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