1 /* 2 * ads7828.c - driver for TI ADS7828 8-channel A/D converter and compatibles 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 <shardy@redhat.com> 8 * 9 * ADS7830 support, by Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> 10 * 11 * For further information, see the Documentation/hwmon/ads7828 file. 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 26 */ 27 28 #include <linux/err.h> 29 #include <linux/hwmon.h> 30 #include <linux/hwmon-sysfs.h> 31 #include <linux/i2c.h> 32 #include <linux/init.h> 33 #include <linux/module.h> 34 #include <linux/platform_data/ads7828.h> 35 #include <linux/regmap.h> 36 #include <linux/slab.h> 37 38 /* The ADS7828 registers */ 39 #define ADS7828_CMD_SD_SE 0x80 /* Single ended inputs */ 40 #define ADS7828_CMD_PD1 0x04 /* Internal vref OFF && A/D ON */ 41 #define ADS7828_CMD_PD3 0x0C /* Internal vref ON && A/D ON */ 42 #define ADS7828_INT_VREF_MV 2500 /* Internal vref is 2.5V, 2500mV */ 43 #define ADS7828_EXT_VREF_MV_MIN 50 /* External vref min value 0.05V */ 44 #define ADS7828_EXT_VREF_MV_MAX 5250 /* External vref max value 5.25V */ 45 46 /* List of supported devices */ 47 enum ads7828_chips { ads7828, ads7830 }; 48 49 /* Client specific data */ 50 struct ads7828_data { 51 struct regmap *regmap; 52 u8 cmd_byte; /* Command byte without channel bits */ 53 unsigned int lsb_resol; /* Resolution of the ADC sample LSB */ 54 }; 55 56 /* Command byte C2,C1,C0 - see datasheet */ 57 static inline u8 ads7828_cmd_byte(u8 cmd, int ch) 58 { 59 return cmd | (((ch >> 1) | (ch & 0x01) << 2) << 4); 60 } 61 62 /* sysfs callback function */ 63 static ssize_t ads7828_show_in(struct device *dev, struct device_attribute *da, 64 char *buf) 65 { 66 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 67 struct ads7828_data *data = dev_get_drvdata(dev); 68 u8 cmd = ads7828_cmd_byte(data->cmd_byte, attr->index); 69 unsigned int regval; 70 int err; 71 72 err = regmap_read(data->regmap, cmd, ®val); 73 if (err < 0) 74 return err; 75 76 return sprintf(buf, "%d\n", 77 DIV_ROUND_CLOSEST(regval * data->lsb_resol, 1000)); 78 } 79 80 static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ads7828_show_in, NULL, 0); 81 static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ads7828_show_in, NULL, 1); 82 static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ads7828_show_in, NULL, 2); 83 static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ads7828_show_in, NULL, 3); 84 static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ads7828_show_in, NULL, 4); 85 static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, ads7828_show_in, NULL, 5); 86 static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, ads7828_show_in, NULL, 6); 87 static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, ads7828_show_in, NULL, 7); 88 89 static struct attribute *ads7828_attrs[] = { 90 &sensor_dev_attr_in0_input.dev_attr.attr, 91 &sensor_dev_attr_in1_input.dev_attr.attr, 92 &sensor_dev_attr_in2_input.dev_attr.attr, 93 &sensor_dev_attr_in3_input.dev_attr.attr, 94 &sensor_dev_attr_in4_input.dev_attr.attr, 95 &sensor_dev_attr_in5_input.dev_attr.attr, 96 &sensor_dev_attr_in6_input.dev_attr.attr, 97 &sensor_dev_attr_in7_input.dev_attr.attr, 98 NULL 99 }; 100 101 ATTRIBUTE_GROUPS(ads7828); 102 103 static const struct regmap_config ads2828_regmap_config = { 104 .reg_bits = 8, 105 .val_bits = 16, 106 }; 107 108 static const struct regmap_config ads2830_regmap_config = { 109 .reg_bits = 8, 110 .val_bits = 8, 111 }; 112 113 static int ads7828_probe(struct i2c_client *client, 114 const struct i2c_device_id *id) 115 { 116 struct device *dev = &client->dev; 117 struct ads7828_platform_data *pdata = dev_get_platdata(dev); 118 struct ads7828_data *data; 119 struct device *hwmon_dev; 120 unsigned int vref_mv = ADS7828_INT_VREF_MV; 121 bool diff_input = false; 122 bool ext_vref = false; 123 unsigned int regval; 124 125 data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL); 126 if (!data) 127 return -ENOMEM; 128 129 if (pdata) { 130 diff_input = pdata->diff_input; 131 ext_vref = pdata->ext_vref; 132 if (ext_vref && pdata->vref_mv) 133 vref_mv = pdata->vref_mv; 134 } 135 136 /* Bound Vref with min/max values */ 137 vref_mv = clamp_val(vref_mv, ADS7828_EXT_VREF_MV_MIN, 138 ADS7828_EXT_VREF_MV_MAX); 139 140 /* ADS7828 uses 12-bit samples, while ADS7830 is 8-bit */ 141 if (id->driver_data == ads7828) { 142 data->lsb_resol = DIV_ROUND_CLOSEST(vref_mv * 1000, 4096); 143 data->regmap = devm_regmap_init_i2c(client, 144 &ads2828_regmap_config); 145 } else { 146 data->lsb_resol = DIV_ROUND_CLOSEST(vref_mv * 1000, 256); 147 data->regmap = devm_regmap_init_i2c(client, 148 &ads2830_regmap_config); 149 } 150 151 if (IS_ERR(data->regmap)) 152 return PTR_ERR(data->regmap); 153 154 data->cmd_byte = ext_vref ? ADS7828_CMD_PD1 : ADS7828_CMD_PD3; 155 if (!diff_input) 156 data->cmd_byte |= ADS7828_CMD_SD_SE; 157 158 /* 159 * Datasheet specifies internal reference voltage is disabled by 160 * default. The internal reference voltage needs to be enabled and 161 * voltage needs to settle before getting valid ADC data. So perform a 162 * dummy read to enable the internal reference voltage. 163 */ 164 if (!ext_vref) 165 regmap_read(data->regmap, data->cmd_byte, ®val); 166 167 hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, 168 data, 169 ads7828_groups); 170 return PTR_ERR_OR_ZERO(hwmon_dev); 171 } 172 173 static const struct i2c_device_id ads7828_device_ids[] = { 174 { "ads7828", ads7828 }, 175 { "ads7830", ads7830 }, 176 { } 177 }; 178 MODULE_DEVICE_TABLE(i2c, ads7828_device_ids); 179 180 static struct i2c_driver ads7828_driver = { 181 .driver = { 182 .name = "ads7828", 183 }, 184 185 .id_table = ads7828_device_ids, 186 .probe = ads7828_probe, 187 }; 188 189 module_i2c_driver(ads7828_driver); 190 191 MODULE_LICENSE("GPL"); 192 MODULE_AUTHOR("Steve Hardy <shardy@redhat.com>"); 193 MODULE_DESCRIPTION("Driver for TI ADS7828 A/D converter and compatibles"); 194