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