1dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal/* 2dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * emc1403.c - SMSC Thermal Driver 3dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * 4dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * Copyright (C) 2008 Intel Corp 5dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * 6dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * 8dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * This program is free software; you can redistribute it and/or modify 9dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * it under the terms of the GNU General Public License as published by 10dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * the Free Software Foundation; version 2 of the License. 11dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * 12dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * This program is distributed in the hope that it will be useful, but 13dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * WITHOUT ANY WARRANTY; without even the implied warranty of 14dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * General Public License for more details. 16dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * 17dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * You should have received a copy of the GNU General Public License along 18dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * with this program; if not, write to the Free Software Foundation, Inc., 19dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 20dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal */ 22dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 23dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal#include <linux/module.h> 24dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal#include <linux/init.h> 25dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal#include <linux/slab.h> 26dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal#include <linux/i2c.h> 27dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal#include <linux/hwmon.h> 28dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal#include <linux/hwmon-sysfs.h> 29dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal#include <linux/err.h> 30dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal#include <linux/sysfs.h> 31dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal#include <linux/mutex.h> 324cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck#include <linux/regmap.h> 33dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 34dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal#define THERMAL_PID_REG 0xfd 35dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal#define THERMAL_SMSC_ID_REG 0xfe 36dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal#define THERMAL_REVISION_REG 0xff 37dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 38be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusekenum emc1403_chip { emc1402, emc1403, emc1404 }; 39be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek 40dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstruct thermal_data { 414cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck struct regmap *regmap; 42dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal struct mutex mutex; 434cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck const struct attribute_group *groups[4]; 44dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal}; 45dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 46dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic ssize_t show_temp(struct device *dev, 47dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal struct device_attribute *attr, char *buf) 48dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal{ 49dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 50454aee17fd441b8ee8e956196dd3ddc9c8ee96d6Guenter Roeck struct thermal_data *data = dev_get_drvdata(dev); 514cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck unsigned int val; 52454aee17fd441b8ee8e956196dd3ddc9c8ee96d6Guenter Roeck int retval; 53dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 544cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck retval = regmap_read(data->regmap, sda->index, &val); 55dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal if (retval < 0) 56dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return retval; 574cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck return sprintf(buf, "%d000\n", val); 58dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal} 59dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 60dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic ssize_t show_bit(struct device *dev, 61dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal struct device_attribute *attr, char *buf) 62dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal{ 63dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); 64454aee17fd441b8ee8e956196dd3ddc9c8ee96d6Guenter Roeck struct thermal_data *data = dev_get_drvdata(dev); 654cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck unsigned int val; 66454aee17fd441b8ee8e956196dd3ddc9c8ee96d6Guenter Roeck int retval; 67dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 684cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck retval = regmap_read(data->regmap, sda->nr, &val); 69dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal if (retval < 0) 70dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return retval; 714cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck return sprintf(buf, "%d\n", !!(val & sda->index)); 72dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal} 73dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 74dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic ssize_t store_temp(struct device *dev, 75dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal struct device_attribute *attr, const char *buf, size_t count) 76dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal{ 77dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 78454aee17fd441b8ee8e956196dd3ddc9c8ee96d6Guenter Roeck struct thermal_data *data = dev_get_drvdata(dev); 79dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal unsigned long val; 80dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal int retval; 81dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 82179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks if (kstrtoul(buf, 10, &val)) 83dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return -EINVAL; 844cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck retval = regmap_write(data->regmap, sda->index, 854cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck DIV_ROUND_CLOSEST(val, 1000)); 86dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal if (retval < 0) 87dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return retval; 88dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return count; 89dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal} 90dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 91960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Coxstatic ssize_t store_bit(struct device *dev, 92960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox struct device_attribute *attr, const char *buf, size_t count) 93960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox{ 94960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); 95454aee17fd441b8ee8e956196dd3ddc9c8ee96d6Guenter Roeck struct thermal_data *data = dev_get_drvdata(dev); 96960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox unsigned long val; 97960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox int retval; 98960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox 99179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks if (kstrtoul(buf, 10, &val)) 100960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox return -EINVAL; 101960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox 1024cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck retval = regmap_update_bits(data->regmap, sda->nr, sda->index, 1034cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck val ? sda->index : 0); 104960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox if (retval < 0) 1054cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck return retval; 1064cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck return count; 107960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox} 108960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox 10954392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeckstatic ssize_t show_hyst_common(struct device *dev, 11054392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck struct device_attribute *attr, char *buf, 11154392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck bool is_min) 112dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal{ 113dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 114454aee17fd441b8ee8e956196dd3ddc9c8ee96d6Guenter Roeck struct thermal_data *data = dev_get_drvdata(dev); 1154cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck struct regmap *regmap = data->regmap; 1164cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck unsigned int limit; 1174cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck unsigned int hyst; 118dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal int retval; 119dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 1204cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck retval = regmap_read(regmap, sda->index, &limit); 121dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal if (retval < 0) 122dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return retval; 123dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 1244cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck retval = regmap_read(regmap, 0x21, &hyst); 1254cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck if (retval < 0) 1264cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck return retval; 1274cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck 12854392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck return sprintf(buf, "%d000\n", is_min ? limit + hyst : limit - hyst); 12954392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck} 13054392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck 13154392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeckstatic ssize_t show_hyst(struct device *dev, 13254392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck struct device_attribute *attr, char *buf) 13354392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck{ 13454392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck return show_hyst_common(dev, attr, buf, false); 13554392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck} 13654392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck 13754392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeckstatic ssize_t show_min_hyst(struct device *dev, 13854392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck struct device_attribute *attr, char *buf) 13954392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck{ 14054392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck return show_hyst_common(dev, attr, buf, true); 141dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal} 142dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 143dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic ssize_t store_hyst(struct device *dev, 144dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal struct device_attribute *attr, const char *buf, size_t count) 145dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal{ 146dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 147454aee17fd441b8ee8e956196dd3ddc9c8ee96d6Guenter Roeck struct thermal_data *data = dev_get_drvdata(dev); 1484cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck struct regmap *regmap = data->regmap; 1494cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck unsigned int limit; 150dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal int retval; 151dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal int hyst; 152dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal unsigned long val; 153dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 154179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks if (kstrtoul(buf, 10, &val)) 155dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return -EINVAL; 156dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 157dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal mutex_lock(&data->mutex); 1584cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck retval = regmap_read(regmap, sda->index, &limit); 159dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal if (retval < 0) 160dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal goto fail; 161dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 1624cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck hyst = limit * 1000 - val; 163ceeaa70c0fa7fbf30a0c7a2b07dc895de22583c9Guenter Roeck hyst = clamp_val(DIV_ROUND_CLOSEST(hyst, 1000), 0, 255); 1644cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck retval = regmap_write(regmap, 0x21, hyst); 1654cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck if (retval == 0) 166dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal retval = count; 167dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalfail: 168dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal mutex_unlock(&data->mutex); 169dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return retval; 170dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal} 171dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 172dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal/* 173dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal * Sensors. We pass the actual i2c register to the methods. 174dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal */ 175dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 176dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, 177dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_temp, store_temp, 0x06); 178dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, 179dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_temp, store_temp, 0x05); 180dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, 181dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_temp, store_temp, 0x20); 182dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0x00); 183dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR_2(temp1_min_alarm, S_IRUGO, 184dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_bit, NULL, 0x36, 0x01); 185dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR_2(temp1_max_alarm, S_IRUGO, 186dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_bit, NULL, 0x35, 0x01); 187dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO, 188dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_bit, NULL, 0x37, 0x01); 18954392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO, show_min_hyst, NULL, 0x06); 190a9a74006867e23ad310c6a0dd5cb8fdec5ae3520Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_hyst, NULL, 0x05); 191dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO | S_IWUSR, 192dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_hyst, store_hyst, 0x20); 193dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 194dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, 195dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_temp, store_temp, 0x08); 196dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, 197dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_temp, store_temp, 0x07); 198dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO | S_IWUSR, 199dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_temp, store_temp, 0x19); 200dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0x01); 201d8850c19b589bd364d3c7cd1273193e6dfe83fd9Guenter Roeckstatic SENSOR_DEVICE_ATTR_2(temp2_fault, S_IRUGO, show_bit, NULL, 0x1b, 0x02); 202dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR_2(temp2_min_alarm, S_IRUGO, 203dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_bit, NULL, 0x36, 0x02); 204dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR_2(temp2_max_alarm, S_IRUGO, 205dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_bit, NULL, 0x35, 0x02); 206dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR_2(temp2_crit_alarm, S_IRUGO, 207dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_bit, NULL, 0x37, 0x02); 20854392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp2_min_hyst, S_IRUGO, show_min_hyst, NULL, 0x08); 209a9a74006867e23ad310c6a0dd5cb8fdec5ae3520Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO, show_hyst, NULL, 0x07); 21084899d394e755989a1cc080083080f7695c36467Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_hyst, NULL, 0x19); 211dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 212dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO | S_IWUSR, 213dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_temp, store_temp, 0x16); 214dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR, 215dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_temp, store_temp, 0x15); 216dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO | S_IWUSR, 217dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_temp, store_temp, 0x1A); 218dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 0x23); 219d8850c19b589bd364d3c7cd1273193e6dfe83fd9Guenter Roeckstatic SENSOR_DEVICE_ATTR_2(temp3_fault, S_IRUGO, show_bit, NULL, 0x1b, 0x04); 220dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR_2(temp3_min_alarm, S_IRUGO, 221dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_bit, NULL, 0x36, 0x04); 222dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR_2(temp3_max_alarm, S_IRUGO, 223dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_bit, NULL, 0x35, 0x04); 224dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic SENSOR_DEVICE_ATTR_2(temp3_crit_alarm, S_IRUGO, 225dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal show_bit, NULL, 0x37, 0x04); 22654392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp3_min_hyst, S_IRUGO, show_min_hyst, NULL, 0x16); 227a9a74006867e23ad310c6a0dd5cb8fdec5ae3520Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO, show_hyst, NULL, 0x15); 22884899d394e755989a1cc080083080f7695c36467Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO, show_hyst, NULL, 0x1A); 229dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 2300011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO | S_IWUSR, 2310011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck show_temp, store_temp, 0x2D); 2320011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO | S_IWUSR, 2330011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck show_temp, store_temp, 0x2C); 2340011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO | S_IWUSR, 2350011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck show_temp, store_temp, 0x30); 2360011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 0x2A); 237d8850c19b589bd364d3c7cd1273193e6dfe83fd9Guenter Roeckstatic SENSOR_DEVICE_ATTR_2(temp4_fault, S_IRUGO, show_bit, NULL, 0x1b, 0x08); 2380011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeckstatic SENSOR_DEVICE_ATTR_2(temp4_min_alarm, S_IRUGO, 2390011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck show_bit, NULL, 0x36, 0x08); 2400011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeckstatic SENSOR_DEVICE_ATTR_2(temp4_max_alarm, S_IRUGO, 2410011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck show_bit, NULL, 0x35, 0x08); 2420011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeckstatic SENSOR_DEVICE_ATTR_2(temp4_crit_alarm, S_IRUGO, 2430011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck show_bit, NULL, 0x37, 0x08); 24454392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp4_min_hyst, S_IRUGO, show_min_hyst, NULL, 0x2D); 245a9a74006867e23ad310c6a0dd5cb8fdec5ae3520Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp4_max_hyst, S_IRUGO, show_hyst, NULL, 0x2C); 24684899d394e755989a1cc080083080f7695c36467Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp4_crit_hyst, S_IRUGO, show_hyst, NULL, 0x30); 2470011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck 248960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Coxstatic SENSOR_DEVICE_ATTR_2(power_state, S_IRUGO | S_IWUSR, 249960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox show_bit, store_bit, 0x03, 0x40); 250960f12f4d1eb5ba3c76dc6b57a909a65dd59e1c2Alan Cox 251be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusekstatic struct attribute *emc1402_attrs[] = { 252dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp1_min.dev_attr.attr, 253dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp1_max.dev_attr.attr, 254dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp1_crit.dev_attr.attr, 255dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp1_input.dev_attr.attr, 25654392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, 257a9a74006867e23ad310c6a0dd5cb8fdec5ae3520Guenter Roeck &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, 258dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, 259be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek 260dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp2_min.dev_attr.attr, 261dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp2_max.dev_attr.attr, 262dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp2_crit.dev_attr.attr, 263dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp2_input.dev_attr.attr, 26454392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck &sensor_dev_attr_temp2_min_hyst.dev_attr.attr, 265a9a74006867e23ad310c6a0dd5cb8fdec5ae3520Guenter Roeck &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, 266be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, 267be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek 268be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek &sensor_dev_attr_power_state.dev_attr.attr, 269be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek NULL 270be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek}; 271be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek 272be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusekstatic const struct attribute_group emc1402_group = { 273be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek .attrs = emc1402_attrs, 274be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek}; 275be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek 276be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusekstatic struct attribute *emc1403_attrs[] = { 277be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, 278be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 279be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, 280be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek 281d8850c19b589bd364d3c7cd1273193e6dfe83fd9Guenter Roeck &sensor_dev_attr_temp2_fault.dev_attr.attr, 282dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, 283dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, 284dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, 285be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek 286dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp3_min.dev_attr.attr, 287dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp3_max.dev_attr.attr, 288dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp3_crit.dev_attr.attr, 289dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp3_input.dev_attr.attr, 290d8850c19b589bd364d3c7cd1273193e6dfe83fd9Guenter Roeck &sensor_dev_attr_temp3_fault.dev_attr.attr, 291dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, 292dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, 293dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, 29454392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck &sensor_dev_attr_temp3_min_hyst.dev_attr.attr, 295a9a74006867e23ad310c6a0dd5cb8fdec5ae3520Guenter Roeck &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, 296dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, 297dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal NULL 298dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal}; 2990011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck 3000011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeckstatic const struct attribute_group emc1403_group = { 3010011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck .attrs = emc1403_attrs, 3020011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck}; 3030011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck 3040011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeckstatic struct attribute *emc1404_attrs[] = { 3050011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck &sensor_dev_attr_temp4_min.dev_attr.attr, 3060011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck &sensor_dev_attr_temp4_max.dev_attr.attr, 3070011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck &sensor_dev_attr_temp4_crit.dev_attr.attr, 3080011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck &sensor_dev_attr_temp4_input.dev_attr.attr, 309d8850c19b589bd364d3c7cd1273193e6dfe83fd9Guenter Roeck &sensor_dev_attr_temp4_fault.dev_attr.attr, 3100011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, 3110011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, 3120011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, 31354392ce4446e31b4f8a98961ef30bf6397c15266Guenter Roeck &sensor_dev_attr_temp4_min_hyst.dev_attr.attr, 314a9a74006867e23ad310c6a0dd5cb8fdec5ae3520Guenter Roeck &sensor_dev_attr_temp4_max_hyst.dev_attr.attr, 3150011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck &sensor_dev_attr_temp4_crit_hyst.dev_attr.attr, 3160011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck NULL 3170011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck}; 3180011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck 3190011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeckstatic const struct attribute_group emc1404_group = { 3200011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck .attrs = emc1404_attrs, 3210011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck}; 322dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 32303f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck/* 32403f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck * EMC14x2 uses a different register and different bits to report alarm and 32503f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck * fault status. For simplicity, provide a separate attribute group for this 32603f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck * chip series. 32703f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck * Since we can not re-use the same attribute names, create a separate attribute 32803f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck * array. 32903f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck */ 33003f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeckstatic struct sensor_device_attribute_2 emc1402_alarms[] = { 33103f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck SENSOR_ATTR_2(temp1_min_alarm, S_IRUGO, show_bit, NULL, 0x02, 0x20), 33203f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck SENSOR_ATTR_2(temp1_max_alarm, S_IRUGO, show_bit, NULL, 0x02, 0x40), 33303f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_bit, NULL, 0x02, 0x01), 33403f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck 33503f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_bit, NULL, 0x02, 0x04), 33603f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck SENSOR_ATTR_2(temp2_min_alarm, S_IRUGO, show_bit, NULL, 0x02, 0x08), 33703f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck SENSOR_ATTR_2(temp2_max_alarm, S_IRUGO, show_bit, NULL, 0x02, 0x10), 33803f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_bit, NULL, 0x02, 0x02), 33903f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck}; 34003f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck 34103f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeckstatic struct attribute *emc1402_alarm_attrs[] = { 34203f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck &emc1402_alarms[0].dev_attr.attr, 34303f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck &emc1402_alarms[1].dev_attr.attr, 34403f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck &emc1402_alarms[2].dev_attr.attr, 34503f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck &emc1402_alarms[3].dev_attr.attr, 34603f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck &emc1402_alarms[4].dev_attr.attr, 34703f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck &emc1402_alarms[5].dev_attr.attr, 34803f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck &emc1402_alarms[6].dev_attr.attr, 34903f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck NULL, 35003f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck}; 35103f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck 35203f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeckstatic const struct attribute_group emc1402_alarm_group = { 35303f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck .attrs = emc1402_alarm_attrs, 35403f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck}; 35503f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck 356dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic int emc1403_detect(struct i2c_client *client, 357dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal struct i2c_board_info *info) 358dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal{ 359dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal int id; 3607a1b76f2a46016809c7bcacf81e89948cc306703Jekyll Lai /* Check if thermal chip is SMSC and EMC1403 or EMC1423 */ 361dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 362dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal id = i2c_smbus_read_byte_data(client, THERMAL_SMSC_ID_REG); 363dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal if (id != 0x5d) 364dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return -ENODEV; 365dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 3667a1b76f2a46016809c7bcacf81e89948cc306703Jekyll Lai id = i2c_smbus_read_byte_data(client, THERMAL_PID_REG); 3677a1b76f2a46016809c7bcacf81e89948cc306703Jekyll Lai switch (id) { 368be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek case 0x20: 369be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek strlcpy(info->type, "emc1402", I2C_NAME_SIZE); 370be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek break; 3717a1b76f2a46016809c7bcacf81e89948cc306703Jekyll Lai case 0x21: 3727a1b76f2a46016809c7bcacf81e89948cc306703Jekyll Lai strlcpy(info->type, "emc1403", I2C_NAME_SIZE); 3737a1b76f2a46016809c7bcacf81e89948cc306703Jekyll Lai break; 374be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek case 0x22: 375be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek strlcpy(info->type, "emc1422", I2C_NAME_SIZE); 376be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek break; 3777a1b76f2a46016809c7bcacf81e89948cc306703Jekyll Lai case 0x23: 3787a1b76f2a46016809c7bcacf81e89948cc306703Jekyll Lai strlcpy(info->type, "emc1423", I2C_NAME_SIZE); 3797a1b76f2a46016809c7bcacf81e89948cc306703Jekyll Lai break; 3800011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck case 0x25: 3810011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck strlcpy(info->type, "emc1404", I2C_NAME_SIZE); 3820011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck break; 3830011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck case 0x27: 3840011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck strlcpy(info->type, "emc1424", I2C_NAME_SIZE); 3850011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck break; 3867a1b76f2a46016809c7bcacf81e89948cc306703Jekyll Lai default: 387dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return -ENODEV; 3887a1b76f2a46016809c7bcacf81e89948cc306703Jekyll Lai } 389dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 390dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal id = i2c_smbus_read_byte_data(client, THERMAL_REVISION_REG); 3913a18e1398fc2dc9c32bbdc50664da3a77959a8d1Josef Gajdusek if (id < 0x01 || id > 0x04) 392dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return -ENODEV; 393dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 394dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return 0; 395dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal} 396dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 3974cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeckstatic bool emc1403_regmap_is_volatile(struct device *dev, unsigned int reg) 3984cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck{ 3994cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck switch (reg) { 4004cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x00: /* internal diode high byte */ 4014cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x01: /* external diode 1 high byte */ 4024cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x02: /* status */ 4034cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x10: /* external diode 1 low byte */ 4044cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x1b: /* external diode fault */ 4054cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x23: /* external diode 2 high byte */ 4064cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x24: /* external diode 2 low byte */ 4074cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x29: /* internal diode low byte */ 4084cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x2a: /* externl diode 3 high byte */ 4094cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x2b: /* external diode 3 low byte */ 4104cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x35: /* high limit status */ 4114cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x36: /* low limit status */ 4124cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck case 0x37: /* therm limit status */ 4134cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck return true; 4144cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck default: 4154cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck return false; 4164cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck } 4174cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck} 4184cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck 419034b44b4a22371c5bcbfb602a5420f3b75939dd8Axel Linstatic const struct regmap_config emc1403_regmap_config = { 4204cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck .reg_bits = 8, 4214cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck .val_bits = 8, 4224cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck .cache_type = REGCACHE_RBTREE, 4234cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck .volatile_reg = emc1403_regmap_is_volatile, 4244cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck}; 4254cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck 426dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic int emc1403_probe(struct i2c_client *client, 427dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal const struct i2c_device_id *id) 428dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal{ 429dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal struct thermal_data *data; 430454aee17fd441b8ee8e956196dd3ddc9c8ee96d6Guenter Roeck struct device *hwmon_dev; 431dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 4327b52eefe1637cffd449abdb5ce67e7dfbda8b2c1Guenter Roeck data = devm_kzalloc(&client->dev, sizeof(struct thermal_data), 4337b52eefe1637cffd449abdb5ce67e7dfbda8b2c1Guenter Roeck GFP_KERNEL); 4347b52eefe1637cffd449abdb5ce67e7dfbda8b2c1Guenter Roeck if (data == NULL) 435dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return -ENOMEM; 436dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 4374cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck data->regmap = devm_regmap_init_i2c(client, &emc1403_regmap_config); 4384cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck if (IS_ERR(data->regmap)) 4394cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck return PTR_ERR(data->regmap); 4404cab259f866ed33571c5f9e3f4bc2799ab64ba45Guenter Roeck 441dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal mutex_init(&data->mutex); 442dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 443be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek switch (id->driver_data) { 444be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek case emc1404: 445be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek data->groups[2] = &emc1404_group; 446be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek case emc1403: 447be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek data->groups[1] = &emc1403_group; 448be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek case emc1402: 449be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek data->groups[0] = &emc1402_group; 450be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek } 4510011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck 45203f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck if (id->driver_data == emc1402) 45303f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck data->groups[1] = &emc1402_alarm_group; 45403f49f641ab70b2ceea674e666f5b933e3bc5d27Guenter Roeck 4558759f9046550f463098148bf577ccd32cdb895e3Jean Delvare hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, 4568759f9046550f463098148bf577ccd32cdb895e3Jean Delvare client->name, data, 4578759f9046550f463098148bf577ccd32cdb895e3Jean Delvare data->groups); 458454aee17fd441b8ee8e956196dd3ddc9c8ee96d6Guenter Roeck if (IS_ERR(hwmon_dev)) 459454aee17fd441b8ee8e956196dd3ddc9c8ee96d6Guenter Roeck return PTR_ERR(hwmon_dev); 460dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 4610011ddfe6a03279fae60d237f2f4d0d7f7678928Guenter Roeck dev_info(&client->dev, "%s Thermal chip found\n", id->name); 462dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal return 0; 463dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal} 464dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 465dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic const unsigned short emc1403_address_list[] = { 466be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek 0x18, 0x1c, 0x29, 0x4c, 0x4d, 0x5c, I2C_CLIENT_END 467dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal}; 468dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 469be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek/* Last digit of chip name indicates number of channels */ 470dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic const struct i2c_device_id emc1403_idtable[] = { 471be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek { "emc1402", emc1402 }, 472be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek { "emc1403", emc1403 }, 473be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek { "emc1404", emc1404 }, 47451585befb4c3c629980b5b252a0caaeeac3b7d73Guenter Roeck { "emc1412", emc1402 }, 47551585befb4c3c629980b5b252a0caaeeac3b7d73Guenter Roeck { "emc1413", emc1403 }, 47651585befb4c3c629980b5b252a0caaeeac3b7d73Guenter Roeck { "emc1414", emc1404 }, 477be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek { "emc1422", emc1402 }, 478be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek { "emc1423", emc1403 }, 479be7f5c4d48e05cb6753d17eb09bea3c38db2ec6fJosef Gajdusek { "emc1424", emc1404 }, 480dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal { } 481dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal}; 482dac6831e67e90d1cee430a66e7390e753c20d835Kalhan TrisalMODULE_DEVICE_TABLE(i2c, emc1403_idtable); 483dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 484dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisalstatic struct i2c_driver sensor_emc1403 = { 485dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal .class = I2C_CLASS_HWMON, 486dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal .driver = { 487dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal .name = "emc1403", 488dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal }, 489dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal .detect = emc1403_detect, 490dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal .probe = emc1403_probe, 491dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal .id_table = emc1403_idtable, 492dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal .address_list = emc1403_address_list, 493dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal}; 494dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 495f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(sensor_emc1403); 496dac6831e67e90d1cee430a66e7390e753c20d835Kalhan Trisal 497dac6831e67e90d1cee430a66e7390e753c20d835Kalhan TrisalMODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com"); 498dac6831e67e90d1cee430a66e7390e753c20d835Kalhan TrisalMODULE_DESCRIPTION("emc1403 Thermal Driver"); 499dac6831e67e90d1cee430a66e7390e753c20d835Kalhan TrisalMODULE_LICENSE("GPL v2"); 500