ads7828.c revision c3813d6af177fab19e322f3114b1f64fbcf08d71
1/* 2 ads7828.c - lm_sensors driver for ads7828 12-bit 8-channel ADC 3 (C) 2007 EADS Astrium 4 5 This driver is based on the lm75 and other lm_sensors/hwmon drivers 6 7 Written by Steve Hardy <steve@linuxrealtime.co.uk> 8 9 Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads7828.pdf 10 11 This program is free software; you can redistribute it and/or modify 12 it under the terms of the GNU General Public License as published by 13 the Free Software Foundation; either version 2 of the License, or 14 (at your option) any later version. 15 16 This program is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 GNU General Public License for more details. 20 21 You should have received a copy of the GNU General Public License 22 along with this program; if not, write to the Free Software 23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24*/ 25 26#include <linux/module.h> 27#include <linux/init.h> 28#include <linux/slab.h> 29#include <linux/jiffies.h> 30#include <linux/i2c.h> 31#include <linux/hwmon.h> 32#include <linux/hwmon-sysfs.h> 33#include <linux/err.h> 34#include <linux/mutex.h> 35 36/* The ADS7828 registers */ 37#define ADS7828_NCH 8 /* 8 channels of 12-bit A-D supported */ 38#define ADS7828_CMD_SD_SE 0x80 /* Single ended inputs */ 39#define ADS7828_CMD_SD_DIFF 0x00 /* Differential inputs */ 40#define ADS7828_CMD_PD0 0x0 /* Power Down between A-D conversions */ 41#define ADS7828_CMD_PD1 0x04 /* Internal ref OFF && A-D ON */ 42#define ADS7828_CMD_PD2 0x08 /* Internal ref ON && A-D OFF */ 43#define ADS7828_CMD_PD3 0x0C /* Internal ref ON && A-D ON */ 44#define ADS7828_INT_VREF_MV 2500 /* Internal vref is 2.5V, 2500mV */ 45 46/* Addresses to scan */ 47static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 48 I2C_CLIENT_END }; 49 50/* Insmod parameters */ 51I2C_CLIENT_INSMOD_1(ads7828); 52 53/* Other module parameters */ 54static int se_input = 1; /* Default is SE, 0 == diff */ 55static int int_vref = 1; /* Default is internal ref ON */ 56static int vref_mv = ADS7828_INT_VREF_MV; /* set if vref != 2.5V */ 57module_param(se_input, bool, S_IRUGO); 58module_param(int_vref, bool, S_IRUGO); 59module_param(vref_mv, int, S_IRUGO); 60 61/* Global Variables */ 62static u8 ads7828_cmd_byte; /* cmd byte without channel bits */ 63static unsigned int ads7828_lsb_resol; /* resolution of the ADC sample lsb */ 64 65/* Each client has this additional data */ 66struct ads7828_data { 67 struct device *hwmon_dev; 68 struct mutex update_lock; /* mutex protect updates */ 69 char valid; /* !=0 if following fields are valid */ 70 unsigned long last_updated; /* In jiffies */ 71 u16 adc_input[ADS7828_NCH]; /* ADS7828_NCH 12-bit samples */ 72}; 73 74/* Function declaration - necessary due to function dependencies */ 75static int ads7828_detect(struct i2c_client *client, 76 struct i2c_board_info *info); 77static int ads7828_probe(struct i2c_client *client, 78 const struct i2c_device_id *id); 79 80/* The ADS7828 returns the 12-bit sample in two bytes, 81 these are read as a word then byte-swapped */ 82static u16 ads7828_read_value(struct i2c_client *client, u8 reg) 83{ 84 return swab16(i2c_smbus_read_word_data(client, reg)); 85} 86 87static inline u8 channel_cmd_byte(int ch) 88{ 89 /* cmd byte C2,C1,C0 - see datasheet */ 90 u8 cmd = (((ch>>1) | (ch&0x01)<<2)<<4); 91 cmd |= ads7828_cmd_byte; 92 return cmd; 93} 94 95/* Update data for the device (all 8 channels) */ 96static struct ads7828_data *ads7828_update_device(struct device *dev) 97{ 98 struct i2c_client *client = to_i2c_client(dev); 99 struct ads7828_data *data = i2c_get_clientdata(client); 100 101 mutex_lock(&data->update_lock); 102 103 if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 104 || !data->valid) { 105 unsigned int ch; 106 dev_dbg(&client->dev, "Starting ads7828 update\n"); 107 108 for (ch = 0; ch < ADS7828_NCH; ch++) { 109 u8 cmd = channel_cmd_byte(ch); 110 data->adc_input[ch] = ads7828_read_value(client, cmd); 111 } 112 data->last_updated = jiffies; 113 data->valid = 1; 114 } 115 116 mutex_unlock(&data->update_lock); 117 118 return data; 119} 120 121/* sysfs callback function */ 122static ssize_t show_in(struct device *dev, struct device_attribute *da, 123 char *buf) 124{ 125 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 126 struct ads7828_data *data = ads7828_update_device(dev); 127 /* Print value (in mV as specified in sysfs-interface documentation) */ 128 return sprintf(buf, "%d\n", (data->adc_input[attr->index] * 129 ads7828_lsb_resol)/1000); 130} 131 132#define in_reg(offset)\ 133static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,\ 134 NULL, offset) 135 136in_reg(0); 137in_reg(1); 138in_reg(2); 139in_reg(3); 140in_reg(4); 141in_reg(5); 142in_reg(6); 143in_reg(7); 144 145static struct attribute *ads7828_attributes[] = { 146 &sensor_dev_attr_in0_input.dev_attr.attr, 147 &sensor_dev_attr_in1_input.dev_attr.attr, 148 &sensor_dev_attr_in2_input.dev_attr.attr, 149 &sensor_dev_attr_in3_input.dev_attr.attr, 150 &sensor_dev_attr_in4_input.dev_attr.attr, 151 &sensor_dev_attr_in5_input.dev_attr.attr, 152 &sensor_dev_attr_in6_input.dev_attr.attr, 153 &sensor_dev_attr_in7_input.dev_attr.attr, 154 NULL 155}; 156 157static const struct attribute_group ads7828_group = { 158 .attrs = ads7828_attributes, 159}; 160 161static int ads7828_remove(struct i2c_client *client) 162{ 163 struct ads7828_data *data = i2c_get_clientdata(client); 164 hwmon_device_unregister(data->hwmon_dev); 165 sysfs_remove_group(&client->dev.kobj, &ads7828_group); 166 kfree(i2c_get_clientdata(client)); 167 return 0; 168} 169 170static const struct i2c_device_id ads7828_id[] = { 171 { "ads7828", ads7828 }, 172 { } 173}; 174MODULE_DEVICE_TABLE(i2c, ads7828_id); 175 176/* This is the driver that will be inserted */ 177static struct i2c_driver ads7828_driver = { 178 .class = I2C_CLASS_HWMON, 179 .driver = { 180 .name = "ads7828", 181 }, 182 .probe = ads7828_probe, 183 .remove = ads7828_remove, 184 .id_table = ads7828_id, 185 .detect = ads7828_detect, 186 .address_list = normal_i2c, 187}; 188 189/* Return 0 if detection is successful, -ENODEV otherwise */ 190static int ads7828_detect(struct i2c_client *client, 191 struct i2c_board_info *info) 192{ 193 struct i2c_adapter *adapter = client->adapter; 194 int ch; 195 196 /* Check we have a valid client */ 197 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) 198 return -ENODEV; 199 200 /* Now, we do the remaining detection. There is no identification 201 dedicated register so attempt to sanity check using knowledge of 202 the chip 203 - Read from the 8 channel addresses 204 - Check the top 4 bits of each result are not set (12 data bits) 205 */ 206 for (ch = 0; ch < ADS7828_NCH; ch++) { 207 u16 in_data; 208 u8 cmd = channel_cmd_byte(ch); 209 in_data = ads7828_read_value(client, cmd); 210 if (in_data & 0xF000) { 211 pr_debug("%s : Doesn't look like an ads7828 device\n", 212 __func__); 213 return -ENODEV; 214 } 215 } 216 217 strlcpy(info->type, "ads7828", I2C_NAME_SIZE); 218 219 return 0; 220} 221 222static int ads7828_probe(struct i2c_client *client, 223 const struct i2c_device_id *id) 224{ 225 struct ads7828_data *data; 226 int err; 227 228 data = kzalloc(sizeof(struct ads7828_data), GFP_KERNEL); 229 if (!data) { 230 err = -ENOMEM; 231 goto exit; 232 } 233 234 i2c_set_clientdata(client, data); 235 mutex_init(&data->update_lock); 236 237 /* Register sysfs hooks */ 238 err = sysfs_create_group(&client->dev.kobj, &ads7828_group); 239 if (err) 240 goto exit_free; 241 242 data->hwmon_dev = hwmon_device_register(&client->dev); 243 if (IS_ERR(data->hwmon_dev)) { 244 err = PTR_ERR(data->hwmon_dev); 245 goto exit_remove; 246 } 247 248 return 0; 249 250exit_remove: 251 sysfs_remove_group(&client->dev.kobj, &ads7828_group); 252exit_free: 253 kfree(data); 254exit: 255 return err; 256} 257 258static int __init sensors_ads7828_init(void) 259{ 260 /* Initialize the command byte according to module parameters */ 261 ads7828_cmd_byte = se_input ? 262 ADS7828_CMD_SD_SE : ADS7828_CMD_SD_DIFF; 263 ads7828_cmd_byte |= int_vref ? 264 ADS7828_CMD_PD3 : ADS7828_CMD_PD1; 265 266 /* Calculate the LSB resolution */ 267 ads7828_lsb_resol = (vref_mv*1000)/4096; 268 269 return i2c_add_driver(&ads7828_driver); 270} 271 272static void __exit sensors_ads7828_exit(void) 273{ 274 i2c_del_driver(&ads7828_driver); 275} 276 277MODULE_AUTHOR("Steve Hardy <steve@linuxrealtime.co.uk>"); 278MODULE_DESCRIPTION("ADS7828 driver"); 279MODULE_LICENSE("GPL"); 280 281module_init(sensors_ads7828_init); 282module_exit(sensors_ads7828_exit); 283