aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <guenter.roeck@ericsson.com>2010-08-09 20:21:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-09 23:45:10 -0400
commit4453d7364d3b1f92475f104d4625abee36a7733d (patch)
tree4bd0ffc39d5d0ca38447e62d956cee60fe15ee1f
parent920fa1ffce48d36d7e7bc54eb38c58313bc0a667 (diff)
hwmon: add support for JEDEC JC 42.4 compliant temperature sensors
[akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Cc: Jean Delvare <khali@linux-fr.org> Cc: Randy Dunlap <rdunlap@xenotime.net> Cc: Hans de Goede <hdegoede@redhat.com> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/hwmon/jc4297
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/hwmon/Kconfig11
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/jc42.c593
5 files changed, 709 insertions, 0 deletions
diff --git a/Documentation/hwmon/jc42 b/Documentation/hwmon/jc42
new file mode 100644
index 000000000000..0e76ef12e4c6
--- /dev/null
+++ b/Documentation/hwmon/jc42
@@ -0,0 +1,97 @@
1Kernel driver jc42
2==================
3
4Supported chips:
5 * Analog Devices ADT7408
6 Prefix: 'adt7408'
7 Addresses scanned: I2C 0x18 - 0x1f
8 Datasheets:
9 http://www.analog.com/static/imported-files/data_sheets/ADT7408.pdf
10 * IDT TSE2002B3, TS3000B3
11 Prefix: 'tse2002b3', 'ts3000b3'
12 Addresses scanned: I2C 0x18 - 0x1f
13 Datasheets:
14 http://www.idt.com/products/getdoc.cfm?docid=18715691
15 http://www.idt.com/products/getdoc.cfm?docid=18715692
16 * Maxim MAX6604
17 Prefix: 'max6604'
18 Addresses scanned: I2C 0x18 - 0x1f
19 Datasheets:
20 http://datasheets.maxim-ic.com/en/ds/MAX6604.pdf
21 * Microchip MCP9805, MCP98242, MCP98243, MCP9843
22 Prefixes: 'mcp9805', 'mcp98242', 'mcp98243', 'mcp9843'
23 Addresses scanned: I2C 0x18 - 0x1f
24 Datasheets:
25 http://ww1.microchip.com/downloads/en/DeviceDoc/21977b.pdf
26 http://ww1.microchip.com/downloads/en/DeviceDoc/21996a.pdf
27 http://ww1.microchip.com/downloads/en/DeviceDoc/22153c.pdf
28 * NXP Semiconductors SE97, SE97B
29 Prefix: 'se97'
30 Addresses scanned: I2C 0x18 - 0x1f
31 Datasheets:
32 http://www.nxp.com/documents/data_sheet/SE97.pdf
33 http://www.nxp.com/documents/data_sheet/SE97B.pdf
34 * NXP Semiconductors SE98
35 Prefix: 'se98'
36 Addresses scanned: I2C 0x18 - 0x1f
37 Datasheets:
38 http://www.nxp.com/documents/data_sheet/SE98.pdf
39 * ON Semiconductor CAT34TS02, CAT6095
40 Prefix: 'cat34ts02', 'cat6095'
41 Addresses scanned: I2C 0x18 - 0x1f
42 Datasheet:
43 http://www.onsemi.com/pub_link/Collateral/CAT34TS02-D.PDF
44 http://www.onsemi.com/pub/Collateral/CAT6095-D.PDF
45 * ST Microelectronics STTS424, STTS424E02
46 Prefix: 'stts424'
47 Addresses scanned: I2C 0x18 - 0x1f
48 Datasheets:
49 http://www.st.com/stonline/products/literature/ds/13447/stts424.pdf
50 http://www.st.com/stonline/products/literature/ds/13448/stts424e02.pdf
51 * JEDEC JC 42.4 compliant temperature sensor chips
52 Prefix: 'jc42'
53 Addresses scanned: I2C 0x18 - 0x1f
54 Datasheet: -
55
56Author:
57 Guenter Roeck <guenter.roeck@ericsson.com>
58
59
60Description
61-----------
62
63This driver implements support for JEDEC JC 42.4 compliant temperature sensors.
64The driver auto-detects the chips listed above, but can be manually instantiated
65to support other JC 42.4 compliant chips.
66
67Example: the following will load the driver for a generic JC 42.4 compliant
68temperature sensor at address 0x18 on I2C bus #1:
69
70# modprobe jc42
71# echo jc42 0x18 > /sys/bus/i2c/devices/i2c-1/new_device
72
73A JC 42.4 compliant chip supports a single temperature sensor. Minimum, maximum,
74and critical temperature can be configured. There are alarms for high, low,
75and critical thresholds.
76
77There is also an hysteresis to control the thresholds for resetting alarms.
78Per JC 42.4 specification, the hysteresis threshold can be configured to 0, 1.5,
793.0, and 6.0 degrees C. Configured hysteresis values will be rounded to those
80limits. The chip supports only a single register to configure the hysteresis,
81which applies to all limits. This register can be written by writing into
82temp1_crit_hyst. Other hysteresis attributes are read-only.
83
84Sysfs entries
85-------------
86
87temp1_input Temperature (RO)
88temp1_min Minimum temperature (RW)
89temp1_max Maximum temperature (RW)
90temp1_crit Critical high temperature (RW)
91
92temp1_crit_hyst Critical hysteresis temperature (RW)
93temp1_max_hyst Maximum hysteresis temperature (RO)
94
95temp1_min_alarm Temperature low alarm
96temp1_max_alarm Temperature high alarm
97temp1_crit_alarm Temperature critical alarm
diff --git a/MAINTAINERS b/MAINTAINERS
index caacbcc3b64f..c8a0a39d74a6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3211,6 +3211,13 @@ F: Documentation/video4linux/*.ivtv
3211F: drivers/media/video/ivtv/ 3211F: drivers/media/video/ivtv/
3212F: include/linux/ivtv* 3212F: include/linux/ivtv*
3213 3213
3214JC42.4 TEMPERATURE SENSOR DRIVER
3215M: Guenter Roeck <linux@roeck-us.net>
3216L: lm-sensors@lm-sensors.org
3217S: Maintained
3218F: drivers/hwmon/jc42.c
3219F: Documentation/hwmon/jc42
3220
3214JFS FILESYSTEM 3221JFS FILESYSTEM
3215M: Dave Kleikamp <shaggy@linux.vnet.ibm.com> 3222M: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
3216L: jfs-discussion@lists.sourceforge.net 3223L: jfs-discussion@lists.sourceforge.net
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c80ba4943b81..b0de75cf74dc 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -463,6 +463,17 @@ config SENSORS_JZ4740
463 This driver can also be build as a module. If so, the module will be 463 This driver can also be build as a module. If so, the module will be
464 called jz4740-hwmon. 464 called jz4740-hwmon.
465 465
466config SENSORS_JC42
467 tristate "JEDEC JC42.4 compliant temperature sensors"
468 help
469 If you say yes here you get support for Jedec JC42.4 compliant
470 temperature sensors. Support will include, but not be limited to,
471 ADT7408, CAT34TS02,, CAT6095, MAX6604, MCP9805, MCP98242, MCP98243,
472 MCP9843, SE97, SE98, STTS424, TSE2002B3, and TS3000B3.
473
474 This driver can also be built as a module. If so, the module
475 will be called jc42.
476
466config SENSORS_LM63 477config SENSORS_LM63
467 tristate "National Semiconductor LM63 and LM64" 478 tristate "National Semiconductor LM63 and LM64"
468 depends on I2C 479 depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index db24fa1aa8b7..13d913e34dbf 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
56obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o 56obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
57obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o 57obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
58obj-$(CONFIG_SENSORS_IT87) += it87.o 58obj-$(CONFIG_SENSORS_IT87) += it87.o
59obj-$(CONFIG_SENSORS_JC42) += jc42.o
59obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o 60obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o
60obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o 61obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
61obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o 62obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c
new file mode 100644
index 000000000000..340fc78c8dde
--- /dev/null
+++ b/drivers/hwmon/jc42.c
@@ -0,0 +1,593 @@
1/*
2 * jc42.c - driver for Jedec JC42.4 compliant temperature sensors
3 *
4 * Copyright (c) 2010 Ericsson AB.
5 *
6 * Derived from lm77.c by Andras BALI <drewie@freemail.hu>.
7 *
8 * JC42.4 compliant temperature sensors are typically used on memory modules.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/slab.h>
28#include <linux/jiffies.h>
29#include <linux/i2c.h>
30#include <linux/hwmon.h>
31#include <linux/hwmon-sysfs.h>
32#include <linux/err.h>
33#include <linux/mutex.h>
34
35/* Addresses to scan */
36static const unsigned short normal_i2c[] = {
37 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, I2C_CLIENT_END };
38
39/* JC42 registers. All registers are 16 bit. */
40#define JC42_REG_CAP 0x00
41#define JC42_REG_CONFIG 0x01
42#define JC42_REG_TEMP_UPPER 0x02
43#define JC42_REG_TEMP_LOWER 0x03
44#define JC42_REG_TEMP_CRITICAL 0x04
45#define JC42_REG_TEMP 0x05
46#define JC42_REG_MANID 0x06
47#define JC42_REG_DEVICEID 0x07
48
49/* Status bits in temperature register */
50#define JC42_ALARM_CRIT_BIT 15
51#define JC42_ALARM_MAX_BIT 14
52#define JC42_ALARM_MIN_BIT 13
53
54/* Configuration register defines */
55#define JC42_CFG_CRIT_ONLY (1 << 2)
56#define JC42_CFG_SHUTDOWN (1 << 8)
57#define JC42_CFG_HYST_SHIFT 9
58#define JC42_CFG_HYST_MASK 0x03
59
60/* Capabilities */
61#define JC42_CAP_RANGE (1 << 2)
62
63/* Manufacturer IDs */
64#define ADT_MANID 0x11d4 /* Analog Devices */
65#define MAX_MANID 0x004d /* Maxim */
66#define IDT_MANID 0x00b3 /* IDT */
67#define MCP_MANID 0x0054 /* Microchip */
68#define NXP_MANID 0x1131 /* NXP Semiconductors */
69#define ONS_MANID 0x1b09 /* ON Semiconductor */
70#define STM_MANID 0x104a /* ST Microelectronics */
71
72/* Supported chips */
73
74/* Analog Devices */
75#define ADT7408_DEVID 0x0801
76#define ADT7408_DEVID_MASK 0xffff
77
78/* IDT */
79#define TS3000B3_DEVID 0x2903 /* Also matches TSE2002B3 */
80#define TS3000B3_DEVID_MASK 0xffff
81
82/* Maxim */
83#define MAX6604_DEVID 0x3e00
84#define MAX6604_DEVID_MASK 0xffff
85
86/* Microchip */
87#define MCP98242_DEVID 0x2000
88#define MCP98242_DEVID_MASK 0xfffc
89
90#define MCP98243_DEVID 0x2100
91#define MCP98243_DEVID_MASK 0xfffc
92
93#define MCP9843_DEVID 0x0000 /* Also matches mcp9805 */
94#define MCP9843_DEVID_MASK 0xfffe
95
96/* NXP */
97#define SE97_DEVID 0xa200
98#define SE97_DEVID_MASK 0xfffc
99
100#define SE98_DEVID 0xa100
101#define SE98_DEVID_MASK 0xfffc
102
103/* ON Semiconductor */
104#define CAT6095_DEVID 0x0800 /* Also matches CAT34TS02 */
105#define CAT6095_DEVID_MASK 0xffe0
106
107/* ST Microelectronics */
108#define STTS424_DEVID 0x0101
109#define STTS424_DEVID_MASK 0xffff
110
111#define STTS424E_DEVID 0x0000
112#define STTS424E_DEVID_MASK 0xfffe
113
114static u16 jc42_hysteresis[] = { 0, 1500, 3000, 6000 };
115
116struct jc42_chips {
117 u16 manid;
118 u16 devid;
119 u16 devid_mask;
120};
121
122static struct jc42_chips jc42_chips[] = {
123 { ADT_MANID, ADT7408_DEVID, ADT7408_DEVID_MASK },
124 { IDT_MANID, TS3000B3_DEVID, TS3000B3_DEVID_MASK },
125 { MAX_MANID, MAX6604_DEVID, MAX6604_DEVID_MASK },
126 { MCP_MANID, MCP98242_DEVID, MCP98242_DEVID_MASK },
127 { MCP_MANID, MCP98243_DEVID, MCP98243_DEVID_MASK },
128 { MCP_MANID, MCP9843_DEVID, MCP9843_DEVID_MASK },
129 { NXP_MANID, SE97_DEVID, SE97_DEVID_MASK },
130 { ONS_MANID, CAT6095_DEVID, CAT6095_DEVID_MASK },
131 { NXP_MANID, SE98_DEVID, SE98_DEVID_MASK },
132 { STM_MANID, STTS424_DEVID, STTS424_DEVID_MASK },
133 { STM_MANID, STTS424E_DEVID, STTS424E_DEVID_MASK },
134};
135
136/* Each client has this additional data */
137struct jc42_data {
138 struct device *hwmon_dev;
139 struct mutex update_lock; /* protect register access */
140 bool extended; /* true if extended range supported */
141 bool valid;
142 unsigned long last_updated; /* In jiffies */
143 u16 orig_config; /* original configuration */
144 u16 config; /* current configuration */
145 u16 temp_input; /* Temperatures */
146 u16 temp_crit;
147 u16 temp_min;
148 u16 temp_max;
149};
150
151static int jc42_probe(struct i2c_client *client,
152 const struct i2c_device_id *id);
153static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info);
154static int jc42_remove(struct i2c_client *client);
155static int jc42_read_value(struct i2c_client *client, u8 reg);
156static int jc42_write_value(struct i2c_client *client, u8 reg, u16 value);
157
158static struct jc42_data *jc42_update_device(struct device *dev);
159
160static const struct i2c_device_id jc42_id[] = {
161 { "adt7408", 0 },
162 { "cat94ts02", 0 },
163 { "cat6095", 0 },
164 { "jc42", 0 },
165 { "max6604", 0 },
166 { "mcp9805", 0 },
167 { "mcp98242", 0 },
168 { "mcp98243", 0 },
169 { "mcp9843", 0 },
170 { "se97", 0 },
171 { "se97b", 0 },
172 { "se98", 0 },
173 { "stts424", 0 },
174 { "tse2002b3", 0 },
175 { "ts3000b3", 0 },
176 { }
177};
178MODULE_DEVICE_TABLE(i2c, jc42_id);
179
180#ifdef CONFIG_PM
181
182static int jc42_suspend(struct device *dev)
183{
184 struct i2c_client *client = to_i2c_client(dev);
185 struct jc42_data *data = i2c_get_clientdata(client);
186
187 data->config |= JC42_CFG_SHUTDOWN;
188 jc42_write_value(client, JC42_REG_CONFIG, data->config);
189 return 0;
190}
191
192static int jc42_resume(struct device *dev)
193{
194 struct i2c_client *client = to_i2c_client(dev);
195 struct jc42_data *data = i2c_get_clientdata(client);
196
197 data->config &= ~JC42_CFG_SHUTDOWN;
198 jc42_write_value(client, JC42_REG_CONFIG, data->config);
199 return 0;
200}
201
202static const struct dev_pm_ops jc42_dev_pm_ops = {
203 .suspend = jc42_suspend,
204 .resume = jc42_resume,
205};
206
207#define JC42_DEV_PM_OPS (&jc42_dev_pm_ops)
208#else
209#define JC42_DEV_PM_OPS NULL
210#endif /* CONFIG_PM */
211
212/* This is the driver that will be inserted */
213static struct i2c_driver jc42_driver = {
214 .class = I2C_CLASS_HWMON,
215 .driver = {
216 .name = "jc42",
217 .pm = JC42_DEV_PM_OPS,
218 },
219 .probe = jc42_probe,
220 .remove = jc42_remove,
221 .id_table = jc42_id,
222 .detect = jc42_detect,
223 .address_list = normal_i2c,
224};
225
226#define JC42_TEMP_MIN_EXTENDED (-40000)
227#define JC42_TEMP_MIN 0
228#define JC42_TEMP_MAX 125000
229
230static u16 jc42_temp_to_reg(int temp, bool extended)
231{
232 int ntemp = SENSORS_LIMIT(temp,
233 extended ? JC42_TEMP_MIN_EXTENDED :
234 JC42_TEMP_MIN, JC42_TEMP_MAX);
235
236 /* convert from 0.001 to 0.0625 resolution */
237 return (ntemp * 2 / 125) & 0x1fff;
238}
239
240static int jc42_temp_from_reg(s16 reg)
241{
242 reg &= 0x1fff;
243
244 /* sign extend register */
245 if (reg & 0x1000)
246 reg |= 0xf000;
247
248 /* convert from 0.0625 to 0.001 resolution */
249 return reg * 125 / 2;
250}
251
252/* sysfs stuff */
253
254/* read routines for temperature limits */
255#define show(value) \
256static ssize_t show_##value(struct device *dev, \
257 struct device_attribute *attr, \
258 char *buf) \
259{ \
260 struct jc42_data *data = jc42_update_device(dev); \
261 if (IS_ERR(data)) \
262 return PTR_ERR(data); \
263 return sprintf(buf, "%d\n", jc42_temp_from_reg(data->value)); \
264}
265
266show(temp_input);
267show(temp_crit);
268show(temp_min);
269show(temp_max);
270
271/* read routines for hysteresis values */
272static ssize_t show_temp_crit_hyst(struct device *dev,
273 struct device_attribute *attr, char *buf)
274{
275 struct jc42_data *data = jc42_update_device(dev);
276 int temp, hyst;
277
278 if (IS_ERR(data))
279 return PTR_ERR(data);
280
281 temp = jc42_temp_from_reg(data->temp_crit);
282 hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT)
283 & JC42_CFG_HYST_MASK];
284 return sprintf(buf, "%d\n", temp - hyst);
285}
286
287static ssize_t show_temp_max_hyst(struct device *dev,
288 struct device_attribute *attr, char *buf)
289{
290 struct jc42_data *data = jc42_update_device(dev);
291 int temp, hyst;
292
293 if (IS_ERR(data))
294 return PTR_ERR(data);
295
296 temp = jc42_temp_from_reg(data->temp_max);
297 hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT)
298 & JC42_CFG_HYST_MASK];
299 return sprintf(buf, "%d\n", temp - hyst);
300}
301
302/* write routines */
303#define set(value, reg) \
304static ssize_t set_##value(struct device *dev, \
305 struct device_attribute *attr, \
306 const char *buf, size_t count) \
307{ \
308 struct i2c_client *client = to_i2c_client(dev); \
309 struct jc42_data *data = i2c_get_clientdata(client); \
310 int err, ret = count; \
311 long val; \
312 if (strict_strtol(buf, 10, &val) < 0) \
313 return -EINVAL; \
314 mutex_lock(&data->update_lock); \
315 data->value = jc42_temp_to_reg(val, data->extended); \
316 err = jc42_write_value(client, reg, data->value); \
317 if (err < 0) \
318 ret = err; \
319 mutex_unlock(&data->update_lock); \
320 return ret; \
321}
322
323set(temp_min, JC42_REG_TEMP_LOWER);
324set(temp_max, JC42_REG_TEMP_UPPER);
325set(temp_crit, JC42_REG_TEMP_CRITICAL);
326
327/* JC42.4 compliant chips only support four hysteresis values.
328 * Pick best choice and go from there. */
329static ssize_t set_temp_crit_hyst(struct device *dev,
330 struct device_attribute *attr,
331 const char *buf, size_t count)
332{
333 struct i2c_client *client = to_i2c_client(dev);
334 struct jc42_data *data = i2c_get_clientdata(client);
335 long val;
336 int diff, hyst;
337 int err;
338 int ret = count;
339
340 if (strict_strtoul(buf, 10, &val) < 0)
341 return -EINVAL;
342
343 diff = jc42_temp_from_reg(data->temp_crit) - val;
344 hyst = 0;
345 if (diff > 0) {
346 if (diff < 2250)
347 hyst = 1; /* 1.5 degrees C */
348 else if (diff < 4500)
349 hyst = 2; /* 3.0 degrees C */
350 else
351 hyst = 3; /* 6.0 degrees C */
352 }
353
354 mutex_lock(&data->update_lock);
355 data->config = (data->config
356 & ~(JC42_CFG_HYST_MASK << JC42_CFG_HYST_SHIFT))
357 | (hyst << JC42_CFG_HYST_SHIFT);
358 err = jc42_write_value(client, JC42_REG_CONFIG, data->config);
359 if (err < 0)
360 ret = err;
361 mutex_unlock(&data->update_lock);
362 return ret;
363}
364
365static ssize_t show_alarm(struct device *dev,
366 struct device_attribute *attr, char *buf)
367{
368 u16 bit = to_sensor_dev_attr(attr)->index;
369 struct jc42_data *data = jc42_update_device(dev);
370 u16 val;
371
372 if (IS_ERR(data))
373 return PTR_ERR(data);
374
375 val = data->temp_input;
376 if (bit != JC42_ALARM_CRIT_BIT && (data->config & JC42_CFG_CRIT_ONLY))
377 val = 0;
378 return sprintf(buf, "%u\n", (val >> bit) & 1);
379}
380
381static DEVICE_ATTR(temp1_input, S_IRUGO,
382 show_temp_input, NULL);
383static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO,
384 show_temp_crit, set_temp_crit);
385static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
386 show_temp_min, set_temp_min);
387static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
388 show_temp_max, set_temp_max);
389
390static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO,
391 show_temp_crit_hyst, set_temp_crit_hyst);
392static DEVICE_ATTR(temp1_max_hyst, S_IRUGO,
393 show_temp_max_hyst, NULL);
394
395static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL,
396 JC42_ALARM_CRIT_BIT);
397static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL,
398 JC42_ALARM_MIN_BIT);
399static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL,
400 JC42_ALARM_MAX_BIT);
401
402static struct attribute *jc42_attributes[] = {
403 &dev_attr_temp1_input.attr,
404 &dev_attr_temp1_crit.attr,
405 &dev_attr_temp1_min.attr,
406 &dev_attr_temp1_max.attr,
407 &dev_attr_temp1_crit_hyst.attr,
408 &dev_attr_temp1_max_hyst.attr,
409 &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
410 &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
411 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
412 NULL
413};
414
415static const struct attribute_group jc42_group = {
416 .attrs = jc42_attributes,
417};
418
419/* Return 0 if detection is successful, -ENODEV otherwise */
420static int jc42_detect(struct i2c_client *new_client,
421 struct i2c_board_info *info)
422{
423 struct i2c_adapter *adapter = new_client->adapter;
424 int i, config, cap, manid, devid;
425
426 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
427 I2C_FUNC_SMBUS_WORD_DATA))
428 return -ENODEV;
429
430 cap = jc42_read_value(new_client, JC42_REG_CAP);
431 config = jc42_read_value(new_client, JC42_REG_CONFIG);
432 manid = jc42_read_value(new_client, JC42_REG_MANID);
433 devid = jc42_read_value(new_client, JC42_REG_DEVICEID);
434
435 if (cap < 0 || config < 0 || manid < 0 || devid < 0)
436 return -ENODEV;
437
438 if ((cap & 0xff00) || (config & 0xf800))
439 return -ENODEV;
440
441 for (i = 0; i < ARRAY_SIZE(jc42_chips); i++) {
442 struct jc42_chips *chip = &jc42_chips[i];
443 if (manid == chip->manid &&
444 (devid & chip->devid_mask) == chip->devid) {
445 strlcpy(info->type, "jc42", I2C_NAME_SIZE);
446 return 0;
447 }
448 }
449 return -ENODEV;
450}
451
452static int jc42_probe(struct i2c_client *new_client,
453 const struct i2c_device_id *id)
454{
455 struct jc42_data *data;
456 int config, cap, err;
457
458 data = kzalloc(sizeof(struct jc42_data), GFP_KERNEL);
459 if (!data) {
460 err = -ENOMEM;
461 goto exit;
462 }
463
464 i2c_set_clientdata(new_client, data);
465 mutex_init(&data->update_lock);
466
467 cap = jc42_read_value(new_client, JC42_REG_CAP);
468 if (cap < 0) {
469 err = -EINVAL;
470 goto exit_free;
471 }
472 data->extended = !!(cap & JC42_CAP_RANGE);
473
474 config = jc42_read_value(new_client, JC42_REG_CONFIG);
475 if (config < 0) {
476 err = -EINVAL;
477 goto exit_free;
478 }
479 data->orig_config = config;
480 if (config & JC42_CFG_SHUTDOWN) {
481 config &= ~JC42_CFG_SHUTDOWN;
482 jc42_write_value(new_client, JC42_REG_CONFIG, config);
483 }
484 data->config = config;
485
486 /* Register sysfs hooks */
487 err = sysfs_create_group(&new_client->dev.kobj, &jc42_group);
488 if (err)
489 goto exit_free;
490
491 data->hwmon_dev = hwmon_device_register(&new_client->dev);
492 if (IS_ERR(data->hwmon_dev)) {
493 err = PTR_ERR(data->hwmon_dev);
494 goto exit_remove;
495 }
496
497 return 0;
498
499exit_remove:
500 sysfs_remove_group(&new_client->dev.kobj, &jc42_group);
501exit_free:
502 kfree(data);
503exit:
504 return err;
505}
506
507static int jc42_remove(struct i2c_client *client)
508{
509 struct jc42_data *data = i2c_get_clientdata(client);
510 hwmon_device_unregister(data->hwmon_dev);
511 sysfs_remove_group(&client->dev.kobj, &jc42_group);
512 if (data->config != data->orig_config)
513 jc42_write_value(client, JC42_REG_CONFIG, data->orig_config);
514 kfree(data);
515 return 0;
516}
517
518/* All registers are word-sized. */
519static int jc42_read_value(struct i2c_client *client, u8 reg)
520{
521 int ret = i2c_smbus_read_word_data(client, reg);
522 if (ret < 0)
523 return ret;
524 return swab16(ret);
525}
526
527static int jc42_write_value(struct i2c_client *client, u8 reg, u16 value)
528{
529 return i2c_smbus_write_word_data(client, reg, swab16(value));
530}
531
532static struct jc42_data *jc42_update_device(struct device *dev)
533{
534 struct i2c_client *client = to_i2c_client(dev);
535 struct jc42_data *data = i2c_get_clientdata(client);
536 struct jc42_data *ret = data;
537 int val;
538
539 mutex_lock(&data->update_lock);
540
541 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
542 val = jc42_read_value(client, JC42_REG_TEMP);
543 if (val < 0) {
544 ret = ERR_PTR(val);
545 goto abort;
546 }
547 data->temp_input = val;
548
549 val = jc42_read_value(client, JC42_REG_TEMP_CRITICAL);
550 if (val < 0) {
551 ret = ERR_PTR(val);
552 goto abort;
553 }
554 data->temp_crit = val;
555
556 val = jc42_read_value(client, JC42_REG_TEMP_LOWER);
557 if (val < 0) {
558 ret = ERR_PTR(val);
559 goto abort;
560 }
561 data->temp_min = val;
562
563 val = jc42_read_value(client, JC42_REG_TEMP_UPPER);
564 if (val < 0) {
565 ret = ERR_PTR(val);
566 goto abort;
567 }
568 data->temp_max = val;
569
570 data->last_updated = jiffies;
571 data->valid = true;
572 }
573abort:
574 mutex_unlock(&data->update_lock);
575 return ret;
576}
577
578static int __init sensors_jc42_init(void)
579{
580 return i2c_add_driver(&jc42_driver);
581}
582
583static void __exit sensors_jc42_exit(void)
584{
585 i2c_del_driver(&jc42_driver);
586}
587
588MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
589MODULE_DESCRIPTION("JC42 driver");
590MODULE_LICENSE("GPL");
591
592module_init(sensors_jc42_init);
593module_exit(sensors_jc42_exit);