12d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo/* 22d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo * An hwmon driver for the Analog Devices AD7416/17/18 32d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo * Copyright (C) 2006-07 Tower Technologies 42d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo * 52d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo * Author: Alessandro Zummo <a.zummo@towertech.it> 62d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo * 72d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo * Based on lm75.c 82d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo * Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl> 92d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo * 102d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo * This program is free software; you can redistribute it and/or modify 112d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo * it under the terms of the GNU General Public License, 122d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo * as published by the Free Software Foundation - version 2. 132d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo */ 142d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 152d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#include <linux/module.h> 162d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#include <linux/jiffies.h> 172d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#include <linux/i2c.h> 182d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#include <linux/hwmon.h> 192d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#include <linux/hwmon-sysfs.h> 202d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#include <linux/err.h> 212d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#include <linux/mutex.h> 222d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#include <linux/delay.h> 235a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 242d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 252d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#include "lm75.h" 262d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 27369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare#define DRV_VERSION "0.4" 282d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 29369932f6f840aedfbc717dd156bba7668a11d916Jean Delvareenum chips { ad7416, ad7417, ad7418 }; 302d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 312d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo/* AD7418 registers */ 322d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#define AD7418_REG_TEMP_IN 0x00 332d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#define AD7418_REG_CONF 0x01 342d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#define AD7418_REG_TEMP_HYST 0x02 352d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#define AD7418_REG_TEMP_OS 0x03 362d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#define AD7418_REG_ADC 0x04 372d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#define AD7418_REG_CONF2 0x05 382d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 392d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#define AD7418_REG_ADC_CH(x) ((x) << 5) 402d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo#define AD7418_CH_TEMP AD7418_REG_ADC_CH(0) 412d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 422d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN, 432d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo AD7418_REG_TEMP_HYST, 442d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo AD7418_REG_TEMP_OS }; 452d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 462d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostruct ad7418_data { 471beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones struct device *hwmon_dev; 482d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct attribute_group attrs; 492d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo enum chips type; 502d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct mutex lock; 512d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo int adc_max; /* number of ADC channels */ 522d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo char valid; 532d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo unsigned long last_updated; /* In jiffies */ 542d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo s16 temp[3]; /* Register values */ 552d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo u16 in[4]; 562d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo}; 572d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 58369932f6f840aedfbc717dd156bba7668a11d916Jean Delvarestatic int ad7418_probe(struct i2c_client *client, 59369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare const struct i2c_device_id *id); 60369932f6f840aedfbc717dd156bba7668a11d916Jean Delvarestatic int ad7418_remove(struct i2c_client *client); 61369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare 62369932f6f840aedfbc717dd156bba7668a11d916Jean Delvarestatic const struct i2c_device_id ad7418_id[] = { 63369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare { "ad7416", ad7416 }, 64369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare { "ad7417", ad7417 }, 65369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare { "ad7418", ad7418 }, 66369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare { } 67369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare}; 68369932f6f840aedfbc717dd156bba7668a11d916Jean DelvareMODULE_DEVICE_TABLE(i2c, ad7418_id); 692d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 702d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic struct i2c_driver ad7418_driver = { 712d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo .driver = { 722d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo .name = "ad7418", 732d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo }, 74369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare .probe = ad7418_probe, 75369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare .remove = ad7418_remove, 76369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare .id_table = ad7418_id, 772d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo}; 782d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 792d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic void ad7418_init_client(struct i2c_client *client) 802d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo{ 812d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct ad7418_data *data = i2c_get_clientdata(client); 822d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 832d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF); 842d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo if (reg < 0) { 852d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo dev_err(&client->dev, "cannot read configuration register\n"); 862d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo } else { 872d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo dev_info(&client->dev, "configuring for mode 1\n"); 882d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe); 892d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 902d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo if (data->type == ad7417 || data->type == ad7418) 912d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo i2c_smbus_write_byte_data(client, 922d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo AD7418_REG_CONF2, 0x00); 932d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo } 942d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo} 952d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 962d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic struct ad7418_data *ad7418_update_device(struct device *dev) 972d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo{ 982d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct i2c_client *client = to_i2c_client(dev); 992d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct ad7418_data *data = i2c_get_clientdata(client); 1002d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1012d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo mutex_lock(&data->lock); 1022d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1032d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 1042d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo || !data->valid) { 1052d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo u8 cfg; 1062d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo int i, ch; 1072d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1082d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo /* read config register and clear channel bits */ 1092d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo cfg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF); 1102d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo cfg &= 0x1F; 1112d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1122d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo i2c_smbus_write_byte_data(client, AD7418_REG_CONF, 1132d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo cfg | AD7418_CH_TEMP); 1142d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo udelay(30); 1152d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1162d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo for (i = 0; i < 3; i++) { 11790f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare data->temp[i] = 11890f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare i2c_smbus_read_word_swapped(client, 11990f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare AD7418_REG_TEMP[i]); 1202d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo } 1212d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1222d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo for (i = 0, ch = 4; i < data->adc_max; i++, ch--) { 1232d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo i2c_smbus_write_byte_data(client, 1242d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo AD7418_REG_CONF, 1252d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo cfg | AD7418_REG_ADC_CH(ch)); 1262d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1272d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo udelay(15); 1282d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo data->in[data->adc_max - 1 - i] = 12990f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare i2c_smbus_read_word_swapped(client, 13090f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare AD7418_REG_ADC); 1312d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo } 1322d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1332d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo /* restore old configuration value */ 13490f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare i2c_smbus_write_word_swapped(client, AD7418_REG_CONF, cfg); 1352d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1362d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo data->last_updated = jiffies; 1372d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo data->valid = 1; 1382d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo } 1392d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1402d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo mutex_unlock(&data->lock); 1412d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1422d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo return data; 1432d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo} 1442d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1452d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic ssize_t show_temp(struct device *dev, struct device_attribute *devattr, 1462d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo char *buf) 1472d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo{ 1482d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1492d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct ad7418_data *data = ad7418_update_device(dev); 1502d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo return sprintf(buf, "%d\n", 1512d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo LM75_TEMP_FROM_REG(data->temp[attr->index])); 1522d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo} 1532d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1542d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic ssize_t show_adc(struct device *dev, struct device_attribute *devattr, 1552d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo char *buf) 1562d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo{ 1572d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1582d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct ad7418_data *data = ad7418_update_device(dev); 1592d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1602d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo return sprintf(buf, "%d\n", 1612d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo ((data->in[attr->index] >> 6) * 2500 + 512) / 1024); 1622d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo} 1632d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1642d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic ssize_t set_temp(struct device *dev, struct device_attribute *devattr, 1652d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo const char *buf, size_t count) 1662d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo{ 1672d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1682d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct i2c_client *client = to_i2c_client(dev); 1692d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct ad7418_data *data = i2c_get_clientdata(client); 170e91aef22cdb9ca12099d6d21f88de5036fe26fb5Frans Meulenbroeks long temp; 171e91aef22cdb9ca12099d6d21f88de5036fe26fb5Frans Meulenbroeks int ret = kstrtol(buf, 10, &temp); 172e91aef22cdb9ca12099d6d21f88de5036fe26fb5Frans Meulenbroeks 173e91aef22cdb9ca12099d6d21f88de5036fe26fb5Frans Meulenbroeks if (ret < 0) 174e91aef22cdb9ca12099d6d21f88de5036fe26fb5Frans Meulenbroeks return ret; 1752d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1762d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo mutex_lock(&data->lock); 1772d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo data->temp[attr->index] = LM75_TEMP_TO_REG(temp); 17890f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare i2c_smbus_write_word_swapped(client, 17990f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare AD7418_REG_TEMP[attr->index], 18090f4102ce59226954edbe960b2434d8b3da5f086Jean Delvare data->temp[attr->index]); 1812d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo mutex_unlock(&data->lock); 1822d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo return count; 1832d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo} 1842d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1852d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); 1862d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, 1872d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo show_temp, set_temp, 1); 1882d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, 1892d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo show_temp, set_temp, 2); 1902d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1912d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_adc, NULL, 0); 1922d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 1); 1932d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 2); 1942d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 3); 1952d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 1962d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic struct attribute *ad7416_attributes[] = { 1972d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_temp1_max.dev_attr.attr, 1982d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, 1992d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_temp1_input.dev_attr.attr, 2002d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo NULL 2012d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo}; 2022d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2032d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic struct attribute *ad7417_attributes[] = { 2042d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_temp1_max.dev_attr.attr, 2052d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, 2062d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_temp1_input.dev_attr.attr, 2072d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_in1_input.dev_attr.attr, 2082d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_in2_input.dev_attr.attr, 2092d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_in3_input.dev_attr.attr, 2102d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_in4_input.dev_attr.attr, 2112d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo NULL 2122d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo}; 2132d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2142d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummostatic struct attribute *ad7418_attributes[] = { 2152d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_temp1_max.dev_attr.attr, 2162d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, 2172d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_temp1_input.dev_attr.attr, 2182d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo &sensor_dev_attr_in1_input.dev_attr.attr, 2192d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo NULL 2202d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo}; 2212d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 222369932f6f840aedfbc717dd156bba7668a11d916Jean Delvarestatic int ad7418_probe(struct i2c_client *client, 223369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare const struct i2c_device_id *id) 2242d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo{ 225369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare struct i2c_adapter *adapter = client->adapter; 2262d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct ad7418_data *data; 227369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare int err; 2282d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2292d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | 230369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare I2C_FUNC_SMBUS_WORD_DATA)) { 231369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare err = -EOPNOTSUPP; 2322d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo goto exit; 233369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare } 2342d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 235e91aef22cdb9ca12099d6d21f88de5036fe26fb5Frans Meulenbroeks data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL); 236e91aef22cdb9ca12099d6d21f88de5036fe26fb5Frans Meulenbroeks if (!data) { 2372d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo err = -ENOMEM; 2382d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo goto exit; 2392d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo } 2402d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2412d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo i2c_set_clientdata(client, data); 2422d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2432d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo mutex_init(&data->lock); 244369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare data->type = id->driver_data; 2452d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2462d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo switch (data->type) { 2472d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo case ad7416: 2482d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo data->adc_max = 0; 2492d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo data->attrs.attrs = ad7416_attributes; 2502d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo break; 2512d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2522d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo case ad7417: 2532d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo data->adc_max = 4; 2542d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo data->attrs.attrs = ad7417_attributes; 2552d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo break; 2562d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2572d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo case ad7418: 2582d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo data->adc_max = 1; 2592d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo data->attrs.attrs = ad7418_attributes; 2602d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo break; 2612d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo } 2622d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2632d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo dev_info(&client->dev, "%s chip found\n", client->name); 2642d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2652d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo /* Initialize the AD7418 chip */ 2662d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo ad7418_init_client(client); 2672d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2682d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo /* Register sysfs hooks */ 269e91aef22cdb9ca12099d6d21f88de5036fe26fb5Frans Meulenbroeks err = sysfs_create_group(&client->dev.kobj, &data->attrs); 270e91aef22cdb9ca12099d6d21f88de5036fe26fb5Frans Meulenbroeks if (err) 271369932f6f840aedfbc717dd156bba7668a11d916Jean Delvare goto exit_free; 2722d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2731beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones data->hwmon_dev = hwmon_device_register(&client->dev); 2741beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones if (IS_ERR(data->hwmon_dev)) { 2751beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones err = PTR_ERR(data->hwmon_dev); 2762d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo goto exit_remove; 2772d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo } 2782d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2792d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo return 0; 2802d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 2812d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummoexit_remove: 2822d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo sysfs_remove_group(&client->dev.kobj, &data->attrs); 2832d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummoexit_free: 2842d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo kfree(data); 2852d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummoexit: 2862d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo return err; 2872d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo} 2882d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 289369932f6f840aedfbc717dd156bba7668a11d916Jean Delvarestatic int ad7418_remove(struct i2c_client *client) 2902d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo{ 2912d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo struct ad7418_data *data = i2c_get_clientdata(client); 2921beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones hwmon_device_unregister(data->hwmon_dev); 2932d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo sysfs_remove_group(&client->dev.kobj, &data->attrs); 2942d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo kfree(data); 2952d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo return 0; 2962d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo} 2972d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 298f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(ad7418_driver); 2992d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro Zummo 3002d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro ZummoMODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); 3012d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro ZummoMODULE_DESCRIPTION("AD7416/17/18 driver"); 3022d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro ZummoMODULE_LICENSE("GPL"); 3032d8dd65fc14287f2c004dd755e517ba0f45d446eAlessandro ZummoMODULE_VERSION(DRV_VERSION); 304