15812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy/* 2d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * ads7828.c - lm_sensors driver for ads7828 12-bit 8-channel ADC 3d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * (C) 2007 EADS Astrium 4d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * 5d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * This driver is based on the lm75 and other lm_sensors/hwmon drivers 6d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * 7d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * Written by Steve Hardy <shardy@redhat.com> 8d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * 9d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads7828.pdf 10d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * 11d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * This program is free software; you can redistribute it and/or modify 12d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * it under the terms of the GNU General Public License as published by 13d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * the Free Software Foundation; either version 2 of the License, or 14d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * (at your option) any later version. 15d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * 16d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * This program is distributed in the hope that it will be useful, 17d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of 18d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * GNU General Public License for more details. 20d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * 21d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * You should have received a copy of the GNU General Public License 22d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * along with this program; if not, write to the Free Software 23d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck */ 255812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 265812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#include <linux/module.h> 275812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#include <linux/init.h> 285812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#include <linux/slab.h> 295812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#include <linux/jiffies.h> 305812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#include <linux/i2c.h> 315812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#include <linux/hwmon.h> 325812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#include <linux/hwmon-sysfs.h> 335812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#include <linux/err.h> 345812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#include <linux/mutex.h> 355812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 365812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy/* The ADS7828 registers */ 375812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#define ADS7828_NCH 8 /* 8 channels of 12-bit A-D supported */ 385812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#define ADS7828_CMD_SD_SE 0x80 /* Single ended inputs */ 395812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#define ADS7828_CMD_SD_DIFF 0x00 /* Differential inputs */ 405812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#define ADS7828_CMD_PD0 0x0 /* Power Down between A-D conversions */ 415812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#define ADS7828_CMD_PD1 0x04 /* Internal ref OFF && A-D ON */ 425812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#define ADS7828_CMD_PD2 0x08 /* Internal ref ON && A-D OFF */ 435812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#define ADS7828_CMD_PD3 0x0C /* Internal ref ON && A-D ON */ 445812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#define ADS7828_INT_VREF_MV 2500 /* Internal vref is 2.5V, 2500mV */ 455812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 465812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy/* Addresses to scan */ 4725e9c86d5a6d82ea45eb680fc66bf73ac5e50dffMark M. Hoffmanstatic const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 485812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy I2C_CLIENT_END }; 495812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 501f86df49ddfd0067cce941187d57b2fd2f749a9eJean Delvare/* Module parameters */ 5190ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool se_input = 1; /* Default is SE, 0 == diff */ 5290ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool int_vref = 1; /* Default is internal ref ON */ 535812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystatic int vref_mv = ADS7828_INT_VREF_MV; /* set if vref != 2.5V */ 545812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardymodule_param(se_input, bool, S_IRUGO); 555812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardymodule_param(int_vref, bool, S_IRUGO); 565812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardymodule_param(vref_mv, int, S_IRUGO); 575812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 585812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy/* Global Variables */ 595812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystatic u8 ads7828_cmd_byte; /* cmd byte without channel bits */ 605812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystatic unsigned int ads7828_lsb_resol; /* resolution of the ADC sample lsb */ 615812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 625812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy/* Each client has this additional data */ 635812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystruct ads7828_data { 645812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy struct device *hwmon_dev; 655812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy struct mutex update_lock; /* mutex protect updates */ 665812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy char valid; /* !=0 if following fields are valid */ 675812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy unsigned long last_updated; /* In jiffies */ 685812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy u16 adc_input[ADS7828_NCH]; /* ADS7828_NCH 12-bit samples */ 695812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy}; 705812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 715812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy/* Function declaration - necessary due to function dependencies */ 72310ec79210d754afe51e2e4a983e846b60179abdJean Delvarestatic int ads7828_detect(struct i2c_client *client, 737347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare struct i2c_board_info *info); 747347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvarestatic int ads7828_probe(struct i2c_client *client, 757347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare const struct i2c_device_id *id); 765812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 775812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystatic inline u8 channel_cmd_byte(int ch) 785812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy{ 795812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy /* cmd byte C2,C1,C0 - see datasheet */ 805812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy u8 cmd = (((ch>>1) | (ch&0x01)<<2)<<4); 815812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy cmd |= ads7828_cmd_byte; 825812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy return cmd; 835812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy} 845812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 855812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy/* Update data for the device (all 8 channels) */ 865812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystatic struct ads7828_data *ads7828_update_device(struct device *dev) 875812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy{ 885812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy struct i2c_client *client = to_i2c_client(dev); 895812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy struct ads7828_data *data = i2c_get_clientdata(client); 905812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 915812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy mutex_lock(&data->update_lock); 925812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 935812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 945812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy || !data->valid) { 955812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy unsigned int ch; 965812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy dev_dbg(&client->dev, "Starting ads7828 update\n"); 975812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 985812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy for (ch = 0; ch < ADS7828_NCH; ch++) { 995812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy u8 cmd = channel_cmd_byte(ch); 10090f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare data->adc_input[ch] = 10190f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare i2c_smbus_read_word_swapped(client, cmd); 1025812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy } 1035812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy data->last_updated = jiffies; 1045812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy data->valid = 1; 1055812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy } 1065812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 1075812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy mutex_unlock(&data->update_lock); 1085812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 1095812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy return data; 1105812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy} 1115812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 1125812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy/* sysfs callback function */ 1135812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystatic ssize_t show_in(struct device *dev, struct device_attribute *da, 1145812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy char *buf) 1155812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy{ 1165812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 1175812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy struct ads7828_data *data = ads7828_update_device(dev); 1185812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy /* Print value (in mV as specified in sysfs-interface documentation) */ 1195812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy return sprintf(buf, "%d\n", (data->adc_input[attr->index] * 1205812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy ads7828_lsb_resol)/1000); 1215812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy} 1225812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 1235812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy#define in_reg(offset)\ 1245812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,\ 1255812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy NULL, offset) 1265812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 1275812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardyin_reg(0); 1285812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardyin_reg(1); 1295812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardyin_reg(2); 1305812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardyin_reg(3); 1315812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardyin_reg(4); 1325812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardyin_reg(5); 1335812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardyin_reg(6); 1345812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardyin_reg(7); 1355812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 1365812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystatic struct attribute *ads7828_attributes[] = { 1375812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy &sensor_dev_attr_in0_input.dev_attr.attr, 1385812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy &sensor_dev_attr_in1_input.dev_attr.attr, 1395812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy &sensor_dev_attr_in2_input.dev_attr.attr, 1405812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy &sensor_dev_attr_in3_input.dev_attr.attr, 1415812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy &sensor_dev_attr_in4_input.dev_attr.attr, 1425812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy &sensor_dev_attr_in5_input.dev_attr.attr, 1435812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy &sensor_dev_attr_in6_input.dev_attr.attr, 1445812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy &sensor_dev_attr_in7_input.dev_attr.attr, 1455812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy NULL 1465812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy}; 1475812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 1485812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystatic const struct attribute_group ads7828_group = { 1495812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy .attrs = ads7828_attributes, 1505812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy}; 1515812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 1527347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvarestatic int ads7828_remove(struct i2c_client *client) 1535812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy{ 1545812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy struct ads7828_data *data = i2c_get_clientdata(client); 1555812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy hwmon_device_unregister(data->hwmon_dev); 1565812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy sysfs_remove_group(&client->dev.kobj, &ads7828_group); 1575812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy kfree(i2c_get_clientdata(client)); 1585812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy return 0; 1595812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy} 1605812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 1617347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvarestatic const struct i2c_device_id ads7828_id[] = { 1621f86df49ddfd0067cce941187d57b2fd2f749a9eJean Delvare { "ads7828", 0 }, 1637347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare { } 1647347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare}; 1657347cb388e5aecffc4920bd5ea6a61e4a4690baeJean DelvareMODULE_DEVICE_TABLE(i2c, ads7828_id); 1667347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare 1675812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy/* This is the driver that will be inserted */ 1685812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystatic struct i2c_driver ads7828_driver = { 1697347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare .class = I2C_CLASS_HWMON, 1705812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy .driver = { 1715812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy .name = "ads7828", 1725812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy }, 1737347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare .probe = ads7828_probe, 1747347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare .remove = ads7828_remove, 1757347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare .id_table = ads7828_id, 1767347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare .detect = ads7828_detect, 177c3813d6af177fab19e322f3114b1f64fbcf08d71Jean Delvare .address_list = normal_i2c, 1785812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy}; 1795812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 1807347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare/* Return 0 if detection is successful, -ENODEV otherwise */ 181310ec79210d754afe51e2e4a983e846b60179abdJean Delvarestatic int ads7828_detect(struct i2c_client *client, 1827347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare struct i2c_board_info *info) 1835812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy{ 1847347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare struct i2c_adapter *adapter = client->adapter; 18552df6440a29123eed912183fe785bbe174ef14b9Jean Delvare int ch; 1865812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 1875812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy /* Check we have a valid client */ 1885812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) 1897347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare return -ENODEV; 1905812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 191d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck /* 192d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * Now, we do the remaining detection. There is no identification 193d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * dedicated register so attempt to sanity check using knowledge of 194d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * the chip 195d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * - Read from the 8 channel addresses 196d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck * - Check the top 4 bits of each result are not set (12 data bits) 197d13d6232de932f11554119bb0c756798f5039ecdGuenter Roeck */ 19852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare for (ch = 0; ch < ADS7828_NCH; ch++) { 19952df6440a29123eed912183fe785bbe174ef14b9Jean Delvare u16 in_data; 20052df6440a29123eed912183fe785bbe174ef14b9Jean Delvare u8 cmd = channel_cmd_byte(ch); 20190f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare in_data = i2c_smbus_read_word_swapped(client, cmd); 20252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare if (in_data & 0xF000) { 20352df6440a29123eed912183fe785bbe174ef14b9Jean Delvare pr_debug("%s : Doesn't look like an ads7828 device\n", 20452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare __func__); 20552df6440a29123eed912183fe785bbe174ef14b9Jean Delvare return -ENODEV; 2065812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy } 2075812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy } 20852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare 2097347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare strlcpy(info->type, "ads7828", I2C_NAME_SIZE); 2105812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2117347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare return 0; 2127347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare} 2135812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2147347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvarestatic int ads7828_probe(struct i2c_client *client, 2157347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare const struct i2c_device_id *id) 2167347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare{ 2177347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare struct ads7828_data *data; 2187347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare int err; 2195812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2207347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare data = kzalloc(sizeof(struct ads7828_data), GFP_KERNEL); 2217347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare if (!data) { 2227347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare err = -ENOMEM; 2237347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare goto exit; 2247347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare } 2255812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2267347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare i2c_set_clientdata(client, data); 2275812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy mutex_init(&data->update_lock); 2285812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2295812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy /* Register sysfs hooks */ 2305812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy err = sysfs_create_group(&client->dev.kobj, &ads7828_group); 2315812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy if (err) 2327347cb388e5aecffc4920bd5ea6a61e4a4690baeJean Delvare goto exit_free; 2335812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2345812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy data->hwmon_dev = hwmon_device_register(&client->dev); 2355812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy if (IS_ERR(data->hwmon_dev)) { 2365812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy err = PTR_ERR(data->hwmon_dev); 2375812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy goto exit_remove; 2385812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy } 2395812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2405812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy return 0; 2415812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2425812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardyexit_remove: 2435812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy sysfs_remove_group(&client->dev.kobj, &ads7828_group); 2445812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardyexit_free: 2455812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy kfree(data); 2465812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardyexit: 2475812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy return err; 2485812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy} 2495812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2505812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystatic int __init sensors_ads7828_init(void) 2515812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy{ 2525812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy /* Initialize the command byte according to module parameters */ 2535812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy ads7828_cmd_byte = se_input ? 2545812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy ADS7828_CMD_SD_SE : ADS7828_CMD_SD_DIFF; 2555812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy ads7828_cmd_byte |= int_vref ? 2565812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy ADS7828_CMD_PD3 : ADS7828_CMD_PD1; 2575812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2585812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy /* Calculate the LSB resolution */ 2595812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy ads7828_lsb_resol = (vref_mv*1000)/4096; 2605812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2615812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy return i2c_add_driver(&ads7828_driver); 2625812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy} 2635812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2645812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardystatic void __exit sensors_ads7828_exit(void) 2655812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy{ 2665812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy i2c_del_driver(&ads7828_driver); 2675812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy} 2685812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2695d84291da3a594ac391c85296e28f41ff92da0cfSteven HardyMODULE_AUTHOR("Steve Hardy <shardy@redhat.com>"); 2705812f9283e621370a2d65282b7bcc942bf2c3f1cSteve HardyMODULE_DESCRIPTION("ADS7828 driver"); 2715812f9283e621370a2d65282b7bcc942bf2c3f1cSteve HardyMODULE_LICENSE("GPL"); 2725812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardy 2735812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardymodule_init(sensors_ads7828_init); 2745812f9283e621370a2d65282b7bcc942bf2c3f1cSteve Hardymodule_exit(sensors_ads7828_exit); 275