Blame view

drivers/hwmon/lm90.c 45.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * lm90.c - Part of lm_sensors, Linux kernel modules for hardware
   *          monitoring
952383641   Jean Delvare   hwmon: (lm90) Res...
4
   * Copyright (C) 2003-2010  Jean Delvare <khali@linux-fr.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
   *
   * Based on the lm83 driver. The LM90 is a sensor chip made by National
   * Semiconductor. It reports up to two temperatures (its own plus up to
   * one external one) with a 0.125 deg resolution (1 deg for local
a874a10cf   Jean Delvare   hwmon: (lm90) Upd...
9
   * temperature) and a 3-4 deg accuracy.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
14
   *
   * This driver also supports the LM89 and LM99, two other sensor chips
   * made by National Semiconductor. Both have an increased remote
   * temperature measurement accuracy (1 degree), and the LM99
   * additionally shifts remote temperatures (measured and limits) by 16
97ae60bb3   Jean Delvare   hwmon: (lm90) Add...
15
   * degrees, which allows for higher temperatures measurement.
44bbe87e9   Steven Cole   [PATCH] Spelling ...
16
   * Note that there is no way to differentiate between both chips.
97ae60bb3   Jean Delvare   hwmon: (lm90) Add...
17
   * When device is auto-detected, the driver will assume an LM99.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
   *
   * This driver also supports the LM86, another sensor chip made by
   * National Semiconductor. It is exactly similar to the LM90 except it
   * has a higher accuracy.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
   *
   * This driver also supports the ADM1032, a sensor chip made by Analog
   * Devices. That chip is similar to the LM90, with a few differences
a874a10cf   Jean Delvare   hwmon: (lm90) Upd...
25
26
   * that are not handled by this driver. Among others, it has a higher
   * accuracy than the LM90, much like the LM86 does.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
   *
   * This driver also supports the MAX6657, MAX6658 and MAX6659 sensor
a874a10cf   Jean Delvare   hwmon: (lm90) Upd...
29
   * chips made by Maxim. These chips are similar to the LM86.
44bbe87e9   Steven Cole   [PATCH] Spelling ...
30
   * Note that there is no easy way to differentiate between the three
6948708dd   Guenter Roeck   hwmon: (lm90) Add...
31
32
33
34
35
   * variants. We use the device address to detect MAX6659, which will result
   * in a detection as max6657 if it is on address 0x4c. The extra address
   * and features of the MAX6659 are only supported if the chip is configured
   * explicitly as max6659, or if its address is not 0x4c.
   * These chips lack the remote temperature offset feature.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
   *
1a51e068c   Darrick J. Wong   hwmon: (lm90) Doc...
37
38
39
40
   * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and
   * MAX6692 chips made by Maxim.  These are again similar to the LM86,
   * but they use unsigned temperature values and can report temperatures
   * from 0 to 145 degrees.
271dabf5b   Ben Hutchings   hwmon: (lm90) Sup...
41
   *
32c82a934   Rainer Birkenmaier   hwmon/lm90: Add s...
42
43
   * This driver also supports the MAX6680 and MAX6681, two other sensor
   * chips made by Maxim. These are quite similar to the other Maxim
a874a10cf   Jean Delvare   hwmon: (lm90) Upd...
44
45
   * chips. The MAX6680 and MAX6681 only differ in the pinout so they can
   * be treated identically.
32c82a934   Rainer Birkenmaier   hwmon/lm90: Add s...
46
   *
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
47
48
49
50
51
   * This driver also supports the MAX6695 and MAX6696, two other sensor
   * chips made by Maxim. These are also quite similar to other Maxim
   * chips, but support three temperature sensors instead of two. MAX6695
   * and MAX6696 only differ in the pinout so they can be treated identically.
   *
5a4e5e6a7   Guenter Roeck   hwmon: (lm90) Add...
52
53
54
55
   * This driver also supports ADT7461 and ADT7461A from Analog Devices as well as
   * NCT1008 from ON Semiconductor. The chips are supported in both compatibility
   * and extended mode. They are mostly compatible with LM90 except for a data
   * format difference for the temperature value registers.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
   *
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
57
58
59
   * This driver also supports the SA56004 from Philips. This device is
   * pin-compatible with the LM86, the ED/EDP parts are also address-compatible.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
   * Since the LM90 was the first chipset supported by this driver, most
   * comments will refer to this chipset, but are actually general and
   * concern all supported chipsets, unless mentioned otherwise.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
81
82
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/jiffies.h>
  #include <linux/i2c.h>
10c08f810   Jean Delvare   [PATCH] I2C: rena...
83
  #include <linux/hwmon-sysfs.h>
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
84
85
  #include <linux/hwmon.h>
  #include <linux/err.h>
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
86
  #include <linux/mutex.h>
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
87
  #include <linux/sysfs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
91
  
  /*
   * Addresses to scan
   * Address is fully defined internally and cannot be changed except for
32c82a934   Rainer Birkenmaier   hwmon/lm90: Add s...
92
   * MAX6659, MAX6680 and MAX6681.
5a4e5e6a7   Guenter Roeck   hwmon: (lm90) Add...
93
94
95
96
   * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, ADT7461A, MAX6649,
   * MAX6657, MAX6658, NCT1008 and W83L771 have address 0x4c.
   * ADM1032-2, ADT7461-2, ADT7461A-2, LM89-1, LM99-1, MAX6646, and NCT1008D
   * have address 0x4d.
271dabf5b   Ben Hutchings   hwmon: (lm90) Sup...
97
   * MAX6647 has address 0x4e.
13c84951a   Guenter Roeck   hwmon: (lm90) Add...
98
   * MAX6659 can have address 0x4c, 0x4d or 0x4e.
32c82a934   Rainer Birkenmaier   hwmon/lm90: Add s...
99
100
   * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
   * 0x4c, 0x4d or 0x4e.
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
101
   * SA56004 can have address 0x48 through 0x4F.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
   */
25e9c86d5   Mark M. Hoffman   hwmon: normal_i2c...
103
  static const unsigned short normal_i2c[] = {
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
104
105
  	0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
  	0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106

13c84951a   Guenter Roeck   hwmon: (lm90) Add...
107
  enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
108
  	max6646, w83l771, max6696, sa56004 };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  
  /*
   * The LM90 registers
   */
  
  #define LM90_REG_R_MAN_ID		0xFE
  #define LM90_REG_R_CHIP_ID		0xFF
  #define LM90_REG_R_CONFIG1		0x03
  #define LM90_REG_W_CONFIG1		0x09
  #define LM90_REG_R_CONFIG2		0xBF
  #define LM90_REG_W_CONFIG2		0xBF
  #define LM90_REG_R_CONVRATE		0x04
  #define LM90_REG_W_CONVRATE		0x0A
  #define LM90_REG_R_STATUS		0x02
  #define LM90_REG_R_LOCAL_TEMP		0x00
  #define LM90_REG_R_LOCAL_HIGH		0x05
  #define LM90_REG_W_LOCAL_HIGH		0x0B
  #define LM90_REG_R_LOCAL_LOW		0x06
  #define LM90_REG_W_LOCAL_LOW		0x0C
  #define LM90_REG_R_LOCAL_CRIT		0x20
  #define LM90_REG_W_LOCAL_CRIT		0x20
  #define LM90_REG_R_REMOTE_TEMPH		0x01
  #define LM90_REG_R_REMOTE_TEMPL		0x10
  #define LM90_REG_R_REMOTE_OFFSH		0x11
  #define LM90_REG_W_REMOTE_OFFSH		0x11
  #define LM90_REG_R_REMOTE_OFFSL		0x12
  #define LM90_REG_W_REMOTE_OFFSL		0x12
  #define LM90_REG_R_REMOTE_HIGHH		0x07
  #define LM90_REG_W_REMOTE_HIGHH		0x0D
  #define LM90_REG_R_REMOTE_HIGHL		0x13
  #define LM90_REG_W_REMOTE_HIGHL		0x13
  #define LM90_REG_R_REMOTE_LOWH		0x08
  #define LM90_REG_W_REMOTE_LOWH		0x0E
  #define LM90_REG_R_REMOTE_LOWL		0x14
  #define LM90_REG_W_REMOTE_LOWL		0x14
  #define LM90_REG_R_REMOTE_CRIT		0x19
  #define LM90_REG_W_REMOTE_CRIT		0x19
  #define LM90_REG_R_TCRIT_HYST		0x21
  #define LM90_REG_W_TCRIT_HYST		0x21
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
148
  /* MAX6646/6647/6649/6657/6658/6659/6695/6696 registers */
f65e17086   Jean Delvare   hwmon: (lm90) Sup...
149
150
  
  #define MAX6657_REG_R_LOCAL_TEMPL	0x11
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
151
  #define MAX6696_REG_R_STATUS2		0x12
6948708dd   Guenter Roeck   hwmon: (lm90) Add...
152
153
154
155
  #define MAX6659_REG_R_REMOTE_EMERG	0x16
  #define MAX6659_REG_W_REMOTE_EMERG	0x16
  #define MAX6659_REG_R_LOCAL_EMERG	0x17
  #define MAX6659_REG_W_LOCAL_EMERG	0x17
f65e17086   Jean Delvare   hwmon: (lm90) Sup...
156

2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
157
158
159
  /*  SA56004 registers */
  
  #define SA56004_REG_R_LOCAL_TEMPL 0x22
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
160
161
  #define LM90_DEF_CONVRATE_RVAL	6	/* Def conversion rate register value */
  #define LM90_MAX_CONVRATE_MS	16000	/* Maximum conversion rate in ms */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  /*
23b2d4778   Nate Case   hwmon: (lm90) Sup...
163
164
   * Device flags
   */
88073bb1b   Guenter Roeck   hwmon: (lm90) Int...
165
166
167
  #define LM90_FLAG_ADT7461_EXT	(1 << 0) /* ADT7461 extended mode	*/
  /* Device features */
  #define LM90_HAVE_OFFSET	(1 << 1) /* temperature offset register	*/
88073bb1b   Guenter Roeck   hwmon: (lm90) Int...
168
  #define LM90_HAVE_REM_LIMIT_EXT	(1 << 3) /* extended remote limit	*/
6948708dd   Guenter Roeck   hwmon: (lm90) Add...
169
  #define LM90_HAVE_EMERGENCY	(1 << 4) /* 3rd upper (emergency) limit	*/
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
170
171
  #define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm		*/
  #define LM90_HAVE_TEMP3		(1 << 6) /* 3rd temperature sensor	*/
1179324c4   Guenter Roeck   hwmon: (lm90) Int...
172
  #define LM90_HAVE_BROKEN_ALERT	(1 << 7) /* Broken alert		*/
23b2d4778   Nate Case   hwmon: (lm90) Sup...
173
174
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
   * Driver data (common to all clients)
   */
9b0e85269   Jean Delvare   hwmon: (lm90) Con...
177
178
179
  static const struct i2c_device_id lm90_id[] = {
  	{ "adm1032", adm1032 },
  	{ "adt7461", adt7461 },
5a4e5e6a7   Guenter Roeck   hwmon: (lm90) Add...
180
  	{ "adt7461a", adt7461 },
9b0e85269   Jean Delvare   hwmon: (lm90) Con...
181
182
  	{ "lm90", lm90 },
  	{ "lm86", lm86 },
97ae60bb3   Jean Delvare   hwmon: (lm90) Add...
183
184
  	{ "lm89", lm86 },
  	{ "lm99", lm99 },
271dabf5b   Ben Hutchings   hwmon: (lm90) Sup...
185
186
187
  	{ "max6646", max6646 },
  	{ "max6647", max6646 },
  	{ "max6649", max6646 },
9b0e85269   Jean Delvare   hwmon: (lm90) Con...
188
189
  	{ "max6657", max6657 },
  	{ "max6658", max6657 },
13c84951a   Guenter Roeck   hwmon: (lm90) Add...
190
  	{ "max6659", max6659 },
9b0e85269   Jean Delvare   hwmon: (lm90) Con...
191
192
  	{ "max6680", max6680 },
  	{ "max6681", max6680 },
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
193
194
  	{ "max6695", max6696 },
  	{ "max6696", max6696 },
5a4e5e6a7   Guenter Roeck   hwmon: (lm90) Add...
195
  	{ "nct1008", adt7461 },
6771ea1ff   Jean Delvare   hwmon: (lm90) Add...
196
  	{ "w83l771", w83l771 },
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
197
  	{ "sa56004", sa56004 },
9b0e85269   Jean Delvare   hwmon: (lm90) Con...
198
199
200
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, lm90_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  /*
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
202
203
204
205
206
207
   * chip type specific parameters
   */
  struct lm90_params {
  	u32 flags;		/* Capabilities */
  	u16 alert_alarms;	/* Which alarm bits trigger ALERT# */
  				/* Upper 8 bits for max6695/96 */
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
208
  	u8 max_convrate;	/* Maximum conversion rate register value */
a095f687f   Jean Delvare   hwmon: (lm90) Sim...
209
  	u8 reg_local_ext;	/* Extended local temp register (optional) */
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
210
211
212
213
  };
  
  static const struct lm90_params lm90_params[] = {
  	[adm1032] = {
1179324c4   Guenter Roeck   hwmon: (lm90) Int...
214
215
  		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
  		  | LM90_HAVE_BROKEN_ALERT,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
216
  		.alert_alarms = 0x7c,
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
217
  		.max_convrate = 10,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
218
219
  	},
  	[adt7461] = {
1179324c4   Guenter Roeck   hwmon: (lm90) Int...
220
221
  		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
  		  | LM90_HAVE_BROKEN_ALERT,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
222
  		.alert_alarms = 0x7c,
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
223
  		.max_convrate = 10,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
224
225
226
227
  	},
  	[lm86] = {
  		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
  		.alert_alarms = 0x7b,
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
228
  		.max_convrate = 9,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
229
230
231
232
  	},
  	[lm90] = {
  		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
  		.alert_alarms = 0x7b,
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
233
  		.max_convrate = 9,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
234
235
236
237
  	},
  	[lm99] = {
  		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
  		.alert_alarms = 0x7b,
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
238
  		.max_convrate = 9,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
239
240
  	},
  	[max6646] = {
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
241
  		.alert_alarms = 0x7c,
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
242
  		.max_convrate = 6,
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
243
  		.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
244
245
  	},
  	[max6657] = {
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
246
  		.alert_alarms = 0x7c,
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
247
  		.max_convrate = 8,
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
248
  		.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
249
250
  	},
  	[max6659] = {
a095f687f   Jean Delvare   hwmon: (lm90) Sim...
251
  		.flags = LM90_HAVE_EMERGENCY,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
252
  		.alert_alarms = 0x7c,
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
253
  		.max_convrate = 8,
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
254
  		.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
255
256
257
258
  	},
  	[max6680] = {
  		.flags = LM90_HAVE_OFFSET,
  		.alert_alarms = 0x7c,
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
259
  		.max_convrate = 7,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
260
261
  	},
  	[max6696] = {
a095f687f   Jean Delvare   hwmon: (lm90) Sim...
262
  		.flags = LM90_HAVE_EMERGENCY
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
263
264
  		  | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3,
  		.alert_alarms = 0x187c,
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
265
  		.max_convrate = 6,
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
266
  		.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
267
268
269
270
  	},
  	[w83l771] = {
  		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
  		.alert_alarms = 0x7c,
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
271
  		.max_convrate = 8,
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
272
  	},
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
273
  	[sa56004] = {
a095f687f   Jean Delvare   hwmon: (lm90) Sim...
274
  		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
275
276
277
278
  		.alert_alarms = 0x7b,
  		.max_convrate = 9,
  		.reg_local_ext = SA56004_REG_R_LOCAL_TEMPL,
  	},
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
279
280
281
  };
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
285
   * Client data (each client gets its own)
   */
  
  struct lm90_data {
1beeffe43   Tony Jones   hwmon: Convert fr...
286
  	struct device *hwmon_dev;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
287
  	struct mutex update_lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
290
  	char valid; /* zero until following fields are valid */
  	unsigned long last_updated; /* in jiffies */
  	int kind;
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
291
  	u32 flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292

0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
293
  	int update_interval;	/* in milliseconds */
952383641   Jean Delvare   hwmon: (lm90) Res...
294
  	u8 config_orig;		/* Original configuration register value */
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
295
  	u8 convrate_orig;	/* Original conversion rate register value */
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
296
297
  	u16 alert_alarms;	/* Which alarm bits trigger ALERT# */
  				/* Upper 8 bits for max6695/96 */
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
298
  	u8 max_convrate;	/* Maximum conversion rate */
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
299
  	u8 reg_local_ext;	/* local extension register offset */
952383641   Jean Delvare   hwmon: (lm90) Res...
300

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
  	/* registers values */
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
302
  	s8 temp8[8];	/* 0: local low limit
f65e17086   Jean Delvare   hwmon: (lm90) Sup...
303
304
  			   1: local high limit
  			   2: local critical limit
6948708dd   Guenter Roeck   hwmon: (lm90) Add...
305
  			   3: remote critical limit
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
306
307
308
309
310
  			   4: local emergency limit (max6659 and max6695/96)
  			   5: remote emergency limit (max6659 and max6695/96)
  			   6: remote 2 critical limit (max6695/96 only)
  			   7: remote 2 emergency limit (max6695/96 only) */
  	s16 temp11[8];	/* 0: remote input
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
311
  			   1: remote low limit
69f2f96d9   Jean Delvare   hwmon: (lm90) Exp...
312
  			   2: remote high limit
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
313
314
315
316
317
318
  			   3: remote offset (except max6646, max6657/58/59,
  					     and max6695/96)
  			   4: local input
  			   5: remote 2 input (max6695/96 only)
  			   6: remote 2 low limit (max6695/96 only)
  			   7: remote 2 high limit (ma6695/96 only) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
  	u8 temp_hyst;
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
320
  	u16 alarms; /* bitvector (upper 8 bits for max6695/96) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
322
323
  };
  
  /*
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
   * Support functions
   */
  
  /*
   * The ADM1032 supports PEC but not on write byte transactions, so we need
   * to explicitly ask for a transaction without PEC.
   */
  static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value)
  {
  	return i2c_smbus_xfer(client->adapter, client->addr,
  			      client->flags & ~I2C_CLIENT_PEC,
  			      I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
  }
  
  /*
   * It is assumed that client->update_lock is held (unless we are in
   * detection or initialization steps). This matters when PEC is enabled,
   * because we don't want the address pointer to change between the write
   * byte and the read byte transactions.
   */
  static int lm90_read_reg(struct i2c_client *client, u8 reg, u8 *value)
  {
  	int err;
  
  	if (client->flags & I2C_CLIENT_PEC) {
  		err = adm1032_write_byte(client, reg);
  		if (err >= 0)
  			err = i2c_smbus_read_byte(client);
  	} else
  		err = i2c_smbus_read_byte_data(client, reg);
  
  	if (err < 0) {
  		dev_warn(&client->dev, "Register %#02x read failed (%d)
  ",
  			 reg, err);
  		return err;
  	}
  	*value = err;
  
  	return 0;
  }
  
  static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value)
  {
  	int err;
  	u8 oldh, newh, l;
  
  	/*
  	 * There is a trick here. We have to read two registers to have the
  	 * sensor temperature, but we have to beware a conversion could occur
25985edce   Lucas De Marchi   Fix common misspe...
374
  	 * between the readings. The datasheet says we should either use
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
  	 * the one-shot conversion register, which we don't want to do
  	 * (disables hardware monitoring) or monitor the busy bit, which is
  	 * impossible (we can't read the values and monitor that bit at the
  	 * exact same time). So the solution used here is to read the high
  	 * byte once, then the low byte, then the high byte again. If the new
  	 * high byte matches the old one, then we have a valid reading. Else
  	 * we have to read the low byte again, and now we believe we have a
  	 * correct reading.
  	 */
  	if ((err = lm90_read_reg(client, regh, &oldh))
  	 || (err = lm90_read_reg(client, regl, &l))
  	 || (err = lm90_read_reg(client, regh, &newh)))
  		return err;
  	if (oldh != newh) {
  		err = lm90_read_reg(client, regl, &l);
  		if (err)
  			return err;
  	}
  	*value = (newh << 8) | l;
  
  	return 0;
  }
  
  /*
   * client->update_lock must be held when calling this function (unless we are
   * in detection or initialization steps), and while a remote channel other
   * than channel 0 is selected. Also, calling code must make sure to re-select
   * external channel 0 before releasing the lock. This is necessary because
   * various registers have different meanings as a result of selecting a
   * non-default remote channel.
   */
  static inline void lm90_select_remote_channel(struct i2c_client *client,
  					      struct lm90_data *data,
  					      int channel)
  {
  	u8 config;
  
  	if (data->kind == max6696) {
  		lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
  		config &= ~0x08;
  		if (channel)
  			config |= 0x08;
  		i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
  					  config);
  	}
  }
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
  /*
   * Set conversion rate.
   * client->update_lock must be held when calling this function (unless we are
   * in detection or initialization steps).
   */
  static void lm90_set_convrate(struct i2c_client *client, struct lm90_data *data,
  			      unsigned int interval)
  {
  	int i;
  	unsigned int update_interval;
  
  	/* Shift calculations to avoid rounding errors */
  	interval <<= 6;
  
  	/* find the nearest update rate */
  	for (i = 0, update_interval = LM90_MAX_CONVRATE_MS << 6;
  	     i < data->max_convrate; i++, update_interval >>= 1)
  		if (interval >= update_interval * 3 / 4)
  			break;
  
  	i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE, i);
  	data->update_interval = DIV_ROUND_CLOSEST(update_interval, 64);
  }
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
444
445
446
447
  static struct lm90_data *lm90_update_device(struct device *dev)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm90_data *data = i2c_get_clientdata(client);
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
448
  	unsigned long next_update;
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
449
450
  
  	mutex_lock(&data->update_lock);
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
451
452
453
  	next_update = data->last_updated
  	  + msecs_to_jiffies(data->update_interval) + 1;
  	if (time_after(jiffies, next_update) || !data->valid) {
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
454
455
456
457
458
459
460
461
462
463
  		u8 h, l;
  		u8 alarms;
  
  		dev_dbg(&client->dev, "Updating lm90 data.
  ");
  		lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, &data->temp8[0]);
  		lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, &data->temp8[1]);
  		lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, &data->temp8[2]);
  		lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]);
  		lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst);
a095f687f   Jean Delvare   hwmon: (lm90) Sim...
464
  		if (data->reg_local_ext) {
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
465
  			lm90_read16(client, LM90_REG_R_LOCAL_TEMP,
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
466
  				    data->reg_local_ext,
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
  				    &data->temp11[4]);
  		} else {
  			if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP,
  					  &h) == 0)
  				data->temp11[4] = h << 8;
  		}
  		lm90_read16(client, LM90_REG_R_REMOTE_TEMPH,
  			    LM90_REG_R_REMOTE_TEMPL, &data->temp11[0]);
  
  		if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) {
  			data->temp11[1] = h << 8;
  			if ((data->flags & LM90_HAVE_REM_LIMIT_EXT)
  			 && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL,
  					  &l) == 0)
  				data->temp11[1] |= l;
  		}
  		if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) {
  			data->temp11[2] = h << 8;
  			if ((data->flags & LM90_HAVE_REM_LIMIT_EXT)
  			 && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL,
  					  &l) == 0)
  				data->temp11[2] |= l;
  		}
  
  		if (data->flags & LM90_HAVE_OFFSET) {
  			if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH,
  					  &h) == 0
  			 && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL,
  					  &l) == 0)
  				data->temp11[3] = (h << 8) | l;
  		}
  		if (data->flags & LM90_HAVE_EMERGENCY) {
  			lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG,
  				      &data->temp8[4]);
  			lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG,
  				      &data->temp8[5]);
  		}
  		lm90_read_reg(client, LM90_REG_R_STATUS, &alarms);
  		data->alarms = alarms;	/* save as 16 bit value */
  
  		if (data->kind == max6696) {
  			lm90_select_remote_channel(client, data, 1);
  			lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT,
  				      &data->temp8[6]);
  			lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG,
  				      &data->temp8[7]);
  			lm90_read16(client, LM90_REG_R_REMOTE_TEMPH,
  				    LM90_REG_R_REMOTE_TEMPL, &data->temp11[5]);
  			if (!lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h))
  				data->temp11[6] = h << 8;
  			if (!lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h))
  				data->temp11[7] = h << 8;
  			lm90_select_remote_channel(client, data, 0);
  
  			if (!lm90_read_reg(client, MAX6696_REG_R_STATUS2,
  					   &alarms))
  				data->alarms |= alarms << 8;
  		}
  
  		/* Re-enable ALERT# output if it was originally enabled and
  		 * relevant alarms are all clear */
  		if ((data->config_orig & 0x80) == 0
  		 && (data->alarms & data->alert_alarms) == 0) {
  			u8 config;
  
  			lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
  			if (config & 0x80) {
  				dev_dbg(&client->dev, "Re-enabling ALERT#
  ");
  				i2c_smbus_write_byte_data(client,
  							  LM90_REG_W_CONFIG1,
  							  config & ~0x80);
  			}
  		}
  
  		data->last_updated = jiffies;
  		data->valid = 1;
  	}
  
  	mutex_unlock(&data->update_lock);
  
  	return data;
  }
  
  /*
cea50fe2f   Nate Case   hwmon: (lm90) Con...
552
553
554
555
   * Conversions
   * For local temperatures and limits, critical limits and the hysteresis
   * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celsius.
   * For remote temperatures and limits, it uses signed 11-bit values with
271dabf5b   Ben Hutchings   hwmon: (lm90) Sup...
556
557
   * LSB = 0.125 degree Celsius, left-justified in 16-bit registers.  Some
   * Maxim chips use unsigned values.
cea50fe2f   Nate Case   hwmon: (lm90) Con...
558
   */
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
559
  static inline int temp_from_s8(s8 val)
cea50fe2f   Nate Case   hwmon: (lm90) Con...
560
561
562
  {
  	return val * 1000;
  }
271dabf5b   Ben Hutchings   hwmon: (lm90) Sup...
563
564
565
566
  static inline int temp_from_u8(u8 val)
  {
  	return val * 1000;
  }
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
567
  static inline int temp_from_s16(s16 val)
cea50fe2f   Nate Case   hwmon: (lm90) Con...
568
569
570
  {
  	return val / 32 * 125;
  }
271dabf5b   Ben Hutchings   hwmon: (lm90) Sup...
571
572
573
574
  static inline int temp_from_u16(u16 val)
  {
  	return val / 32 * 125;
  }
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
575
  static s8 temp_to_s8(long val)
cea50fe2f   Nate Case   hwmon: (lm90) Con...
576
577
578
579
580
581
582
583
584
  {
  	if (val <= -128000)
  		return -128;
  	if (val >= 127000)
  		return 127;
  	if (val < 0)
  		return (val - 500) / 1000;
  	return (val + 500) / 1000;
  }
271dabf5b   Ben Hutchings   hwmon: (lm90) Sup...
585
586
587
588
589
590
591
592
  static u8 temp_to_u8(long val)
  {
  	if (val <= 0)
  		return 0;
  	if (val >= 255000)
  		return 255;
  	return (val + 500) / 1000;
  }
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
593
  static s16 temp_to_s16(long val)
cea50fe2f   Nate Case   hwmon: (lm90) Con...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
  {
  	if (val <= -128000)
  		return 0x8000;
  	if (val >= 127875)
  		return 0x7FE0;
  	if (val < 0)
  		return (val - 62) / 125 * 32;
  	return (val + 62) / 125 * 32;
  }
  
  static u8 hyst_to_reg(long val)
  {
  	if (val <= 0)
  		return 0;
  	if (val >= 30500)
  		return 31;
  	return (val + 500) / 1000;
  }
  
  /*
23b2d4778   Nate Case   hwmon: (lm90) Sup...
614
615
616
617
618
619
   * ADT7461 in compatibility mode is almost identical to LM90 except that
   * attempts to write values that are outside the range 0 < temp < 127 are
   * treated as the boundary value.
   *
   * ADT7461 in "extended mode" operation uses unsigned integers offset by
   * 64 (e.g., 0 -> -64 degC).  The range is restricted to -64..191 degC.
cea50fe2f   Nate Case   hwmon: (lm90) Con...
620
   */
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
621
  static inline int temp_from_u8_adt7461(struct lm90_data *data, u8 val)
cea50fe2f   Nate Case   hwmon: (lm90) Con...
622
  {
23b2d4778   Nate Case   hwmon: (lm90) Sup...
623
624
625
  	if (data->flags & LM90_FLAG_ADT7461_EXT)
  		return (val - 64) * 1000;
  	else
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
626
  		return temp_from_s8(val);
cea50fe2f   Nate Case   hwmon: (lm90) Con...
627
  }
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
628
  static inline int temp_from_u16_adt7461(struct lm90_data *data, u16 val)
cea50fe2f   Nate Case   hwmon: (lm90) Con...
629
  {
23b2d4778   Nate Case   hwmon: (lm90) Sup...
630
631
632
  	if (data->flags & LM90_FLAG_ADT7461_EXT)
  		return (val - 0x4000) / 64 * 250;
  	else
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
633
  		return temp_from_s16(val);
23b2d4778   Nate Case   hwmon: (lm90) Sup...
634
  }
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
635
  static u8 temp_to_u8_adt7461(struct lm90_data *data, long val)
23b2d4778   Nate Case   hwmon: (lm90) Sup...
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
  {
  	if (data->flags & LM90_FLAG_ADT7461_EXT) {
  		if (val <= -64000)
  			return 0;
  		if (val >= 191000)
  			return 0xFF;
  		return (val + 500 + 64000) / 1000;
  	} else {
  		if (val <= 0)
  			return 0;
  		if (val >= 127000)
  			return 127;
  		return (val + 500) / 1000;
  	}
  }
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
651
  static u16 temp_to_u16_adt7461(struct lm90_data *data, long val)
23b2d4778   Nate Case   hwmon: (lm90) Sup...
652
653
654
655
656
657
658
659
660
661
662
663
664
665
  {
  	if (data->flags & LM90_FLAG_ADT7461_EXT) {
  		if (val <= -64000)
  			return 0;
  		if (val >= 191750)
  			return 0xFFC0;
  		return (val + 64000 + 125) / 250 * 64;
  	} else {
  		if (val <= 0)
  			return 0;
  		if (val >= 127750)
  			return 0x7FC0;
  		return (val + 125) / 250 * 64;
  	}
cea50fe2f   Nate Case   hwmon: (lm90) Con...
666
667
668
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
670
   * Sysfs stuff
   */
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
671
672
673
674
675
  static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
  			  char *buf)
  {
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  	struct lm90_data *data = lm90_update_device(dev);
23b2d4778   Nate Case   hwmon: (lm90) Sup...
676
677
678
  	int temp;
  
  	if (data->kind == adt7461)
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
679
  		temp = temp_from_u8_adt7461(data, data->temp8[attr->index]);
271dabf5b   Ben Hutchings   hwmon: (lm90) Sup...
680
681
  	else if (data->kind == max6646)
  		temp = temp_from_u8(data->temp8[attr->index]);
23b2d4778   Nate Case   hwmon: (lm90) Sup...
682
  	else
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
683
  		temp = temp_from_s8(data->temp8[attr->index]);
23b2d4778   Nate Case   hwmon: (lm90) Sup...
684

97ae60bb3   Jean Delvare   hwmon: (lm90) Add...
685
686
687
  	/* +16 degrees offset for temp2 for the LM99 */
  	if (data->kind == lm99 && attr->index == 3)
  		temp += 16000;
23b2d4778   Nate Case   hwmon: (lm90) Sup...
688
689
  	return sprintf(buf, "%d
  ", temp);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
690
691
692
693
694
  }
  
  static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
  			 const char *buf, size_t count)
  {
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
695
  	static const u8 reg[8] = {
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
696
697
698
699
  		LM90_REG_W_LOCAL_LOW,
  		LM90_REG_W_LOCAL_HIGH,
  		LM90_REG_W_LOCAL_CRIT,
  		LM90_REG_W_REMOTE_CRIT,
6948708dd   Guenter Roeck   hwmon: (lm90) Add...
700
701
  		MAX6659_REG_W_LOCAL_EMERG,
  		MAX6659_REG_W_REMOTE_EMERG,
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
702
703
  		LM90_REG_W_REMOTE_CRIT,
  		MAX6659_REG_W_REMOTE_EMERG,
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
704
705
706
707
708
  	};
  
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm90_data *data = i2c_get_clientdata(client);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
709
  	int nr = attr->index;
11e578129   Guenter Roeck   hwmon: (lm90) Fix...
710
711
  	long val;
  	int err;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
712
  	err = kstrtol(buf, 10, &val);
11e578129   Guenter Roeck   hwmon: (lm90) Fix...
713
714
  	if (err < 0)
  		return err;
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
715

97ae60bb3   Jean Delvare   hwmon: (lm90) Add...
716
717
718
  	/* +16 degrees offset for temp2 for the LM99 */
  	if (data->kind == lm99 && attr->index == 3)
  		val -= 16000;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
719
  	mutex_lock(&data->update_lock);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
720
  	if (data->kind == adt7461)
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
721
  		data->temp8[nr] = temp_to_u8_adt7461(data, val);
271dabf5b   Ben Hutchings   hwmon: (lm90) Sup...
722
723
  	else if (data->kind == max6646)
  		data->temp8[nr] = temp_to_u8(val);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
724
  	else
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
725
  		data->temp8[nr] = temp_to_s8(val);
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
726
727
  
  	lm90_select_remote_channel(client, data, nr >= 6);
f65e17086   Jean Delvare   hwmon: (lm90) Sup...
728
  	i2c_smbus_write_byte_data(client, reg[nr], data->temp8[nr]);
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
729
  	lm90_select_remote_channel(client, data, 0);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
730
  	mutex_unlock(&data->update_lock);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
731
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
  }
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
733
734
735
736
  
  static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
  			   char *buf)
  {
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
737
  	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
738
  	struct lm90_data *data = lm90_update_device(dev);
23b2d4778   Nate Case   hwmon: (lm90) Sup...
739
740
741
  	int temp;
  
  	if (data->kind == adt7461)
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
742
  		temp = temp_from_u16_adt7461(data, data->temp11[attr->index]);
271dabf5b   Ben Hutchings   hwmon: (lm90) Sup...
743
744
  	else if (data->kind == max6646)
  		temp = temp_from_u16(data->temp11[attr->index]);
23b2d4778   Nate Case   hwmon: (lm90) Sup...
745
  	else
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
746
  		temp = temp_from_s16(data->temp11[attr->index]);
23b2d4778   Nate Case   hwmon: (lm90) Sup...
747

97ae60bb3   Jean Delvare   hwmon: (lm90) Add...
748
749
750
  	/* +16 degrees offset for temp2 for the LM99 */
  	if (data->kind == lm99 &&  attr->index <= 2)
  		temp += 16000;
23b2d4778   Nate Case   hwmon: (lm90) Sup...
751
752
  	return sprintf(buf, "%d
  ", temp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
  }
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
754
755
756
757
  
  static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
  			  const char *buf, size_t count)
  {
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
758
759
760
  	struct {
  		u8 high;
  		u8 low;
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
761
762
763
764
765
766
767
  		int channel;
  	} reg[5] = {
  		{ LM90_REG_W_REMOTE_LOWH, LM90_REG_W_REMOTE_LOWL, 0 },
  		{ LM90_REG_W_REMOTE_HIGHH, LM90_REG_W_REMOTE_HIGHL, 0 },
  		{ LM90_REG_W_REMOTE_OFFSH, LM90_REG_W_REMOTE_OFFSL, 0 },
  		{ LM90_REG_W_REMOTE_LOWH, LM90_REG_W_REMOTE_LOWL, 1 },
  		{ LM90_REG_W_REMOTE_HIGHH, LM90_REG_W_REMOTE_HIGHL, 1 }
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
768
  	};
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
769
  	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
770
771
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm90_data *data = i2c_get_clientdata(client);
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
772
773
  	int nr = attr->nr;
  	int index = attr->index;
11e578129   Guenter Roeck   hwmon: (lm90) Fix...
774
775
  	long val;
  	int err;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
776
  	err = kstrtol(buf, 10, &val);
11e578129   Guenter Roeck   hwmon: (lm90) Fix...
777
778
  	if (err < 0)
  		return err;
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
779

97ae60bb3   Jean Delvare   hwmon: (lm90) Add...
780
  	/* +16 degrees offset for temp2 for the LM99 */
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
781
  	if (data->kind == lm99 && index <= 2)
97ae60bb3   Jean Delvare   hwmon: (lm90) Add...
782
  		val -= 16000;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
783
  	mutex_lock(&data->update_lock);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
784
  	if (data->kind == adt7461)
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
785
  		data->temp11[index] = temp_to_u16_adt7461(data, val);
271dabf5b   Ben Hutchings   hwmon: (lm90) Sup...
786
  	else if (data->kind == max6646)
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
787
  		data->temp11[index] = temp_to_u8(val) << 8;
88073bb1b   Guenter Roeck   hwmon: (lm90) Int...
788
  	else if (data->flags & LM90_HAVE_REM_LIMIT_EXT)
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
789
  		data->temp11[index] = temp_to_s16(val);
88073bb1b   Guenter Roeck   hwmon: (lm90) Int...
790
  	else
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
791
  		data->temp11[index] = temp_to_s8(val) << 8;
5f502a834   Jean Delvare   hwmon: (lm90) Don...
792

06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
793
  	lm90_select_remote_channel(client, data, reg[nr].channel);
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
794
795
  	i2c_smbus_write_byte_data(client, reg[nr].high,
  				  data->temp11[index] >> 8);
88073bb1b   Guenter Roeck   hwmon: (lm90) Int...
796
  	if (data->flags & LM90_HAVE_REM_LIMIT_EXT)
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
797
798
  		i2c_smbus_write_byte_data(client, reg[nr].low,
  					  data->temp11[index] & 0xff);
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
799
  	lm90_select_remote_channel(client, data, 0);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
800
  	mutex_unlock(&data->update_lock);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
801
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
  }
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
803

11e578129   Guenter Roeck   hwmon: (lm90) Fix...
804
805
  static ssize_t show_temphyst(struct device *dev,
  			     struct device_attribute *devattr,
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
806
807
808
809
  			     char *buf)
  {
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  	struct lm90_data *data = lm90_update_device(dev);
23b2d4778   Nate Case   hwmon: (lm90) Sup...
810
811
812
  	int temp;
  
  	if (data->kind == adt7461)
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
813
  		temp = temp_from_u8_adt7461(data, data->temp8[attr->index]);
ec38fa2b3   Jean Delvare   hwmon: (lm90) Fix...
814
815
  	else if (data->kind == max6646)
  		temp = temp_from_u8(data->temp8[attr->index]);
23b2d4778   Nate Case   hwmon: (lm90) Sup...
816
  	else
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
817
  		temp = temp_from_s8(data->temp8[attr->index]);
23b2d4778   Nate Case   hwmon: (lm90) Sup...
818

97ae60bb3   Jean Delvare   hwmon: (lm90) Add...
819
820
821
  	/* +16 degrees offset for temp2 for the LM99 */
  	if (data->kind == lm99 && attr->index == 3)
  		temp += 16000;
9d4d38342   Ben Hutchings   hwmon: (lm90) Ren...
822
823
  	return sprintf(buf, "%d
  ", temp - temp_from_s8(data->temp_hyst));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825

30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
826
827
  static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy,
  			    const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
829
830
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm90_data *data = i2c_get_clientdata(client);
11e578129   Guenter Roeck   hwmon: (lm90) Fix...
831
832
  	long val;
  	int err;
ec38fa2b3   Jean Delvare   hwmon: (lm90) Fix...
833
  	int temp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834

179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
835
  	err = kstrtol(buf, 10, &val);
11e578129   Guenter Roeck   hwmon: (lm90) Fix...
836
837
  	if (err < 0)
  		return err;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
838
  	mutex_lock(&data->update_lock);
ec38fa2b3   Jean Delvare   hwmon: (lm90) Fix...
839
840
841
842
843
844
845
846
  	if (data->kind == adt7461)
  		temp = temp_from_u8_adt7461(data, data->temp8[2]);
  	else if (data->kind == max6646)
  		temp = temp_from_u8(data->temp8[2]);
  	else
  		temp = temp_from_s8(data->temp8[2]);
  
  	data->temp_hyst = hyst_to_reg(temp - val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847
  	i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST,
ec38fa2b3   Jean Delvare   hwmon: (lm90) Fix...
848
  				  data->temp_hyst);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
849
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
851
  	return count;
  }
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
852
853
  static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
  			   char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854
855
856
857
858
  {
  	struct lm90_data *data = lm90_update_device(dev);
  	return sprintf(buf, "%d
  ", data->alarms);
  }
2d45771e6   Jean Delvare   hwmon: Add indivi...
859
860
861
862
863
864
865
866
867
868
  static ssize_t show_alarm(struct device *dev, struct device_attribute
  			  *devattr, char *buf)
  {
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  	struct lm90_data *data = lm90_update_device(dev);
  	int bitnr = attr->index;
  
  	return sprintf(buf, "%d
  ", (data->alarms >> bitnr) & 1);
  }
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
  static ssize_t show_update_interval(struct device *dev,
  				    struct device_attribute *attr, char *buf)
  {
  	struct lm90_data *data = dev_get_drvdata(dev);
  
  	return sprintf(buf, "%u
  ", data->update_interval);
  }
  
  static ssize_t set_update_interval(struct device *dev,
  				   struct device_attribute *attr,
  				   const char *buf, size_t count)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct lm90_data *data = i2c_get_clientdata(client);
  	unsigned long val;
  	int err;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
886
  	err = kstrtoul(buf, 10, &val);
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
887
888
889
890
  	if (err)
  		return err;
  
  	mutex_lock(&data->update_lock);
6b101116a   Guenter Roeck   hwmon: (lm90) Add...
891
  	lm90_set_convrate(client, data, SENSORS_LIMIT(val, 0, 100000));
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
892
893
894
895
  	mutex_unlock(&data->update_lock);
  
  	return count;
  }
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
896
897
  static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp11, NULL, 0, 4);
  static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp11, NULL, 0, 0);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
898
  static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8,
f65e17086   Jean Delvare   hwmon: (lm90) Sup...
899
  	set_temp8, 0);
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
900
901
  static SENSOR_DEVICE_ATTR_2(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
  	set_temp11, 0, 1);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
902
  static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8,
f65e17086   Jean Delvare   hwmon: (lm90) Sup...
903
  	set_temp8, 1);
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
904
905
  static SENSOR_DEVICE_ATTR_2(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
  	set_temp11, 1, 2);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
906
  static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8,
f65e17086   Jean Delvare   hwmon: (lm90) Sup...
907
  	set_temp8, 2);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
908
  static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8,
f65e17086   Jean Delvare   hwmon: (lm90) Sup...
909
  	set_temp8, 3);
30d7394b1   Jean Delvare   [PATCH] I2C: lm90...
910
  static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst,
f65e17086   Jean Delvare   hwmon: (lm90) Sup...
911
912
  	set_temphyst, 2);
  static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 3);
96512861c   Guenter Roeck   hwmon: (lm90) Sim...
913
914
  static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IWUSR | S_IRUGO, show_temp11,
  	set_temp11, 2, 3);
2d45771e6   Jean Delvare   hwmon: Add indivi...
915
916
917
918
  
  /* Individual alarm files */
  static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0);
  static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
7817a39e6   Jean Delvare   hwmon: Fault file...
919
  static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);
2d45771e6   Jean Delvare   hwmon: Add indivi...
920
921
922
923
924
  static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
  static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
  static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 5);
  static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
  /* Raw alarm file for compatibility */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925
  static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
926
927
  static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
  		   set_update_interval);
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
928
929
930
931
932
933
934
935
936
937
938
939
940
941
  static struct attribute *lm90_attributes[] = {
  	&sensor_dev_attr_temp1_input.dev_attr.attr,
  	&sensor_dev_attr_temp2_input.dev_attr.attr,
  	&sensor_dev_attr_temp1_min.dev_attr.attr,
  	&sensor_dev_attr_temp2_min.dev_attr.attr,
  	&sensor_dev_attr_temp1_max.dev_attr.attr,
  	&sensor_dev_attr_temp2_max.dev_attr.attr,
  	&sensor_dev_attr_temp1_crit.dev_attr.attr,
  	&sensor_dev_attr_temp2_crit.dev_attr.attr,
  	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
  	&sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
  
  	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
7817a39e6   Jean Delvare   hwmon: Fault file...
942
  	&sensor_dev_attr_temp2_fault.dev_attr.attr,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
943
944
945
946
947
  	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
  	&dev_attr_alarms.attr,
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
948
  	&dev_attr_update_interval.attr,
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
949
950
951
952
953
954
  	NULL
  };
  
  static const struct attribute_group lm90_group = {
  	.attrs = lm90_attributes,
  };
6948708dd   Guenter Roeck   hwmon: (lm90) Add...
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
  /*
   * Additional attributes for devices with emergency sensors
   */
  static SENSOR_DEVICE_ATTR(temp1_emergency, S_IWUSR | S_IRUGO, show_temp8,
  	set_temp8, 4);
  static SENSOR_DEVICE_ATTR(temp2_emergency, S_IWUSR | S_IRUGO, show_temp8,
  	set_temp8, 5);
  static SENSOR_DEVICE_ATTR(temp1_emergency_hyst, S_IRUGO, show_temphyst,
  			  NULL, 4);
  static SENSOR_DEVICE_ATTR(temp2_emergency_hyst, S_IRUGO, show_temphyst,
  			  NULL, 5);
  
  static struct attribute *lm90_emergency_attributes[] = {
  	&sensor_dev_attr_temp1_emergency.dev_attr.attr,
  	&sensor_dev_attr_temp2_emergency.dev_attr.attr,
  	&sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr,
  	&sensor_dev_attr_temp2_emergency_hyst.dev_attr.attr,
  	NULL
  };
  
  static const struct attribute_group lm90_emergency_group = {
  	.attrs = lm90_emergency_attributes,
  };
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
  static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO, show_alarm, NULL, 15);
  static SENSOR_DEVICE_ATTR(temp2_emergency_alarm, S_IRUGO, show_alarm, NULL, 13);
  
  static struct attribute *lm90_emergency_alarm_attributes[] = {
  	&sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp2_emergency_alarm.dev_attr.attr,
  	NULL
  };
  
  static const struct attribute_group lm90_emergency_alarm_group = {
  	.attrs = lm90_emergency_alarm_attributes,
  };
  
  /*
   * Additional attributes for devices with 3 temperature sensors
   */
  static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp11, NULL, 0, 5);
  static SENSOR_DEVICE_ATTR_2(temp3_min, S_IWUSR | S_IRUGO, show_temp11,
  	set_temp11, 3, 6);
  static SENSOR_DEVICE_ATTR_2(temp3_max, S_IWUSR | S_IRUGO, show_temp11,
  	set_temp11, 4, 7);
  static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp8,
  	set_temp8, 6);
  static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO, show_temphyst, NULL, 6);
  static SENSOR_DEVICE_ATTR(temp3_emergency, S_IWUSR | S_IRUGO, show_temp8,
  	set_temp8, 7);
  static SENSOR_DEVICE_ATTR(temp3_emergency_hyst, S_IRUGO, show_temphyst,
  			  NULL, 7);
  
  static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 9);
  static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 10);
  static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 11);
  static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 12);
  static SENSOR_DEVICE_ATTR(temp3_emergency_alarm, S_IRUGO, show_alarm, NULL, 14);
  
  static struct attribute *lm90_temp3_attributes[] = {
  	&sensor_dev_attr_temp3_input.dev_attr.attr,
  	&sensor_dev_attr_temp3_min.dev_attr.attr,
  	&sensor_dev_attr_temp3_max.dev_attr.attr,
  	&sensor_dev_attr_temp3_crit.dev_attr.attr,
  	&sensor_dev_attr_temp3_crit_hyst.dev_attr.attr,
  	&sensor_dev_attr_temp3_emergency.dev_attr.attr,
  	&sensor_dev_attr_temp3_emergency_hyst.dev_attr.attr,
  
  	&sensor_dev_attr_temp3_fault.dev_attr.attr,
  	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp3_emergency_alarm.dev_attr.attr,
  	NULL
  };
  
  static const struct attribute_group lm90_temp3_group = {
  	.attrs = lm90_temp3_attributes,
  };
c3df5806c   Jean Delvare   [PATCH] hwmon: Ad...
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
  /* pec used for ADM1032 only */
  static ssize_t show_pec(struct device *dev, struct device_attribute *dummy,
  			char *buf)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	return sprintf(buf, "%d
  ", !!(client->flags & I2C_CLIENT_PEC));
  }
  
  static ssize_t set_pec(struct device *dev, struct device_attribute *dummy,
  		       const char *buf, size_t count)
  {
  	struct i2c_client *client = to_i2c_client(dev);
11e578129   Guenter Roeck   hwmon: (lm90) Fix...
1046
1047
  	long val;
  	int err;
179c4fdb5   Frans Meulenbroeks   hwmon: replaced s...
1048
  	err = kstrtol(buf, 10, &val);
11e578129   Guenter Roeck   hwmon: (lm90) Fix...
1049
1050
  	if (err < 0)
  		return err;
c3df5806c   Jean Delvare   [PATCH] hwmon: Ad...
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
  
  	switch (val) {
  	case 0:
  		client->flags &= ~I2C_CLIENT_PEC;
  		break;
  	case 1:
  		client->flags |= I2C_CLIENT_PEC;
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	return count;
  }
  
  static DEVICE_ATTR(pec, S_IWUSR | S_IRUGO, show_pec, set_pec);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1067
1068
1069
  /*
   * Real code
   */
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
1070
  /* Return 0 if detection is successful, -ENODEV otherwise */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1071
  static int lm90_detect(struct i2c_client *client,
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
1072
  		       struct i2c_board_info *info)
8256fe0f4   Jean Delvare   [PATCH] hwmon: Se...
1073
  {
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1074
1075
  	struct i2c_adapter *adapter = client->adapter;
  	int address = client->addr;
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
1076
  	const char *name = NULL;
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1077
  	int man_id, chip_id, config1, config2, convrate;
8256fe0f4   Jean Delvare   [PATCH] hwmon: Se...
1078

15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
1079
1080
  	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1081

8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1082
  	/* detection and identification */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1083
1084
1085
1086
1087
  	man_id = i2c_smbus_read_byte_data(client, LM90_REG_R_MAN_ID);
  	chip_id = i2c_smbus_read_byte_data(client, LM90_REG_R_CHIP_ID);
  	config1 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG1);
  	convrate = i2c_smbus_read_byte_data(client, LM90_REG_R_CONVRATE);
  	if (man_id < 0 || chip_id < 0 || config1 < 0 || convrate < 0)
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1088
  		return -ENODEV;
f90be42fb   Jean Delvare   hwmon: (lm90) Ref...
1089
  	if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) {
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1090
1091
  		config2 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG2);
  		if (config2 < 0)
9b0e85269   Jean Delvare   hwmon: (lm90) Con...
1092
  			return -ENODEV;
f90be42fb   Jean Delvare   hwmon: (lm90) Ref...
1093
  	} else
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1094
  		config2 = 0;		/* Make compiler happy */
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1095

f90be42fb   Jean Delvare   hwmon: (lm90) Ref...
1096
1097
  	if ((address == 0x4C || address == 0x4D)
  	 && man_id == 0x01) { /* National Semiconductor */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1098
1099
1100
  		if ((config1 & 0x2A) == 0x00
  		 && (config2 & 0xF8) == 0x00
  		 && convrate <= 0x09) {
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1101
1102
1103
  			if (address == 0x4C
  			 && (chip_id & 0xF0) == 0x20) { /* LM90 */
  				name = "lm90";
32c82a934   Rainer Birkenmaier   hwmon/lm90: Add s...
1104
  			} else
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
  			if ((chip_id & 0xF0) == 0x30) { /* LM89/LM99 */
  				name = "lm99";
  				dev_info(&adapter->dev,
  					 "Assuming LM99 chip at 0x%02x
  ",
  					 address);
  				dev_info(&adapter->dev,
  					 "If it is an LM89, instantiate it "
  					 "with the new_device sysfs "
  					 "interface
  ");
271dabf5b   Ben Hutchings   hwmon: (lm90) Sup...
1116
  			} else
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1117
1118
1119
  			if (address == 0x4C
  			 && (chip_id & 0xF0) == 0x10) { /* LM86 */
  				name = "lm86";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
1121
  			}
  		}
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1122
1123
1124
1125
  	} else
  	if ((address == 0x4C || address == 0x4D)
  	 && man_id == 0x41) { /* Analog Devices */
  		if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1126
1127
  		 && (config1 & 0x3F) == 0x00
  		 && convrate <= 0x0A) {
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1128
1129
1130
1131
1132
1133
1134
1135
  			name = "adm1032";
  			/* The ADM1032 supports PEC, but only if combined
  			   transactions are not used. */
  			if (i2c_check_functionality(adapter,
  						    I2C_FUNC_SMBUS_BYTE))
  				info->flags |= I2C_CLIENT_PEC;
  		} else
  		if (chip_id == 0x51 /* ADT7461 */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1136
1137
  		 && (config1 & 0x1B) == 0x00
  		 && convrate <= 0x0A) {
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1138
  			name = "adt7461";
5a4e5e6a7   Guenter Roeck   hwmon: (lm90) Add...
1139
1140
  		} else
  		if (chip_id == 0x57 /* ADT7461A, NCT1008 */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1141
1142
  		 && (config1 & 0x1B) == 0x00
  		 && convrate <= 0x0A) {
5a4e5e6a7   Guenter Roeck   hwmon: (lm90) Add...
1143
  			name = "adt7461a";
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1144
1145
1146
  		}
  	} else
  	if (man_id == 0x4D) { /* Maxim */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1147
  		int emerg, emerg2, status2;
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1148
1149
1150
1151
1152
1153
1154
  
  		/*
  		 * We read MAX6659_REG_R_REMOTE_EMERG twice, and re-read
  		 * LM90_REG_R_MAN_ID in between. If MAX6659_REG_R_REMOTE_EMERG
  		 * exists, both readings will reflect the same value. Otherwise,
  		 * the readings will be different.
  		 */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1155
1156
1157
  		emerg = i2c_smbus_read_byte_data(client,
  						 MAX6659_REG_R_REMOTE_EMERG);
  		man_id = i2c_smbus_read_byte_data(client,
8dc089d68   Jean Delvare   hwmon: (lm90) Fix...
1158
  						  LM90_REG_R_MAN_ID);
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1159
  		emerg2 = i2c_smbus_read_byte_data(client,
8dc089d68   Jean Delvare   hwmon: (lm90) Fix...
1160
  						  MAX6659_REG_R_REMOTE_EMERG);
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1161
1162
1163
  		status2 = i2c_smbus_read_byte_data(client,
  						   MAX6696_REG_R_STATUS2);
  		if (emerg < 0 || man_id < 0 || emerg2 < 0 || status2 < 0)
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1164
  			return -ENODEV;
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1165
1166
1167
1168
1169
1170
1171
  		/*
  		 * The MAX6657, MAX6658 and MAX6659 do NOT have a chip_id
  		 * register. Reading from that address will return the last
  		 * read value, which in our case is those of the man_id
  		 * register. Likewise, the config1 register seems to lack a
  		 * low nibble, so the value will be those of the previous
  		 * read, so in our case those of the man_id register.
13c84951a   Guenter Roeck   hwmon: (lm90) Add...
1172
1173
1174
1175
1176
  		 * MAX6659 has a third set of upper temperature limit registers.
  		 * Those registers also return values on MAX6657 and MAX6658,
  		 * thus the only way to detect MAX6659 is by its address.
  		 * For this reason it will be mis-detected as MAX6657 if its
  		 * address is 0x4C.
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1177
1178
  		 */
  		if (chip_id == man_id
13c84951a   Guenter Roeck   hwmon: (lm90) Add...
1179
  		 && (address == 0x4C || address == 0x4D || address == 0x4E)
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1180
1181
  		 && (config1 & 0x1F) == (man_id & 0x0F)
  		 && convrate <= 0x09) {
13c84951a   Guenter Roeck   hwmon: (lm90) Add...
1182
1183
1184
1185
  			if (address == 0x4C)
  				name = "max6657";
  			else
  				name = "max6659";
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1186
1187
  		} else
  		/*
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
  		 * Even though MAX6695 and MAX6696 do not have a chip ID
  		 * register, reading it returns 0x01. Bit 4 of the config1
  		 * register is unused and should return zero when read. Bit 0 of
  		 * the status2 register is unused and should return zero when
  		 * read.
  		 *
  		 * MAX6695 and MAX6696 have an additional set of temperature
  		 * limit registers. We can detect those chips by checking if
  		 * one of those registers exists.
  		 */
  		if (chip_id == 0x01
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1199
1200
1201
1202
  		 && (config1 & 0x10) == 0x00
  		 && (status2 & 0x01) == 0x00
  		 && emerg == emerg2
  		 && convrate <= 0x07) {
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1203
1204
1205
  			name = "max6696";
  		} else
  		/*
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1206
1207
1208
1209
1210
1211
  		 * The chip_id register of the MAX6680 and MAX6681 holds the
  		 * revision of the chip. The lowest bit of the config1 register
  		 * is unused and should return zero when read, so should the
  		 * second to last bit of config1 (software reset).
  		 */
  		if (chip_id == 0x01
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1212
1213
  		 && (config1 & 0x03) == 0x00
  		 && convrate <= 0x07) {
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1214
1215
1216
1217
1218
1219
1220
1221
  			name = "max6680";
  		} else
  		/*
  		 * The chip_id register of the MAX6646/6647/6649 holds the
  		 * revision of the chip. The lowest 6 bits of the config1
  		 * register are unused and should return zero when read.
  		 */
  		if (chip_id == 0x59
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1222
1223
  		 && (config1 & 0x3f) == 0x00
  		 && convrate <= 0x07) {
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1224
  			name = "max6646";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225
  		}
6771ea1ff   Jean Delvare   hwmon: (lm90) Add...
1226
1227
1228
  	} else
  	if (address == 0x4C
  	 && man_id == 0x5C) { /* Winbond/Nuvoton */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1229
1230
  		if ((config1 & 0x2A) == 0x00
  		 && (config2 & 0xF8) == 0x00) {
c4f99a2b8   Jean Delvare   hwmon: (lm90) Add...
1231
  			if (chip_id == 0x01 /* W83L771W/G */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1232
  			 && convrate <= 0x09) {
c4f99a2b8   Jean Delvare   hwmon: (lm90) Add...
1233
1234
1235
  				name = "w83l771";
  			} else
  			if ((chip_id & 0xFE) == 0x10 /* W83L771AWG/ASG */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1236
  			 && convrate <= 0x08) {
c4f99a2b8   Jean Delvare   hwmon: (lm90) Add...
1237
1238
  				name = "w83l771";
  			}
6771ea1ff   Jean Delvare   hwmon: (lm90) Add...
1239
  		}
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
1240
  	} else
6d101c588   Jean Delvare   hwmon: (lm90) Mak...
1241
1242
  	if (address >= 0x48 && address <= 0x4F
  	 && man_id == 0xA1) { /*  NXP Semiconductor/Philips */
6d101c588   Jean Delvare   hwmon: (lm90) Mak...
1243
  		if (chip_id == 0x00
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1244
1245
1246
  		 && (config1 & 0x2A) == 0x00
  		 && (config2 & 0xFE) == 0x00
  		 && convrate <= 0x09) {
2ef017935   Stijn Devriendt   hwmon: (lm90) Add...
1247
1248
  			name = "sa56004";
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249
  	}
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1250
1251
1252
1253
1254
1255
  	if (!name) { /* identification failed */
  		dev_dbg(&adapter->dev,
  			"Unsupported chip at 0x%02x (man_id=0x%02X, "
  			"chip_id=0x%02X)
  ", address, man_id, chip_id);
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256
  	}
8f2fa77c5   Jean Delvare   hwmon: (lm90) Cle...
1257

9b0e85269   Jean Delvare   hwmon: (lm90) Con...
1258
1259
1260
1261
  	strlcpy(info->type, name, I2C_NAME_SIZE);
  
  	return 0;
  }
b6fc1bacc   Guenter Roeck   hwmon: (lm90) Int...
1262
1263
  static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data)
  {
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1264
  	struct device *dev = &client->dev;
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1265
  	if (data->flags & LM90_HAVE_TEMP3)
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1266
  		sysfs_remove_group(&dev->kobj, &lm90_temp3_group);
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1267
  	if (data->flags & LM90_HAVE_EMERGENCY_ALARM)
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1268
  		sysfs_remove_group(&dev->kobj, &lm90_emergency_alarm_group);
6948708dd   Guenter Roeck   hwmon: (lm90) Add...
1269
  	if (data->flags & LM90_HAVE_EMERGENCY)
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1270
  		sysfs_remove_group(&dev->kobj, &lm90_emergency_group);
b6fc1bacc   Guenter Roeck   hwmon: (lm90) Int...
1271
  	if (data->flags & LM90_HAVE_OFFSET)
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1272
1273
1274
  		device_remove_file(dev, &sensor_dev_attr_temp2_offset.dev_attr);
  	device_remove_file(dev, &dev_attr_pec);
  	sysfs_remove_group(&dev->kobj, &lm90_group);
b6fc1bacc   Guenter Roeck   hwmon: (lm90) Int...
1275
  }
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
1276
1277
  static void lm90_init_client(struct i2c_client *client)
  {
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
1278
  	u8 config, convrate;
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
1279
  	struct lm90_data *data = i2c_get_clientdata(client);
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
1280
1281
1282
1283
1284
1285
  	if (lm90_read_reg(client, LM90_REG_R_CONVRATE, &convrate) < 0) {
  		dev_warn(&client->dev, "Failed to read convrate register!
  ");
  		convrate = LM90_DEF_CONVRATE_RVAL;
  	}
  	data->convrate_orig = convrate;
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
1286
1287
1288
  	/*
  	 * Start the conversions.
  	 */
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
1289
  	lm90_set_convrate(client, data, 500);	/* 500ms; 2Hz conversion rate */
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
  	if (lm90_read_reg(client, LM90_REG_R_CONFIG1, &config) < 0) {
  		dev_warn(&client->dev, "Initialization failed!
  ");
  		return;
  	}
  	data->config_orig = config;
  
  	/* Check Temperature Range Select */
  	if (data->kind == adt7461) {
  		if (config & 0x04)
  			data->flags |= LM90_FLAG_ADT7461_EXT;
  	}
  
  	/*
  	 * Put MAX6680/MAX8881 into extended resolution (bit 0x10,
  	 * 0.125 degree resolution) and range (0x08, extend range
  	 * to -64 degree) mode for the remote temperature sensor.
  	 */
  	if (data->kind == max6680)
  		config |= 0x18;
  
  	/*
  	 * Select external channel 0 for max6695/96
  	 */
  	if (data->kind == max6696)
  		config &= ~0x08;
  
  	config &= 0xBF;	/* run */
  	if (config != data->config_orig) /* Only write if changed */
  		i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
  }
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1321
  static int lm90_probe(struct i2c_client *client,
9b0e85269   Jean Delvare   hwmon: (lm90) Con...
1322
1323
  		      const struct i2c_device_id *id)
  {
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1324
1325
  	struct device *dev = &client->dev;
  	struct i2c_adapter *adapter = to_i2c_adapter(dev->parent);
9b0e85269   Jean Delvare   hwmon: (lm90) Con...
1326
1327
  	struct lm90_data *data;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1328

9b0e85269   Jean Delvare   hwmon: (lm90) Con...
1329
1330
1331
1332
1333
  	data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL);
  	if (!data) {
  		err = -ENOMEM;
  		goto exit;
  	}
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1334
  	i2c_set_clientdata(client, data);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1335
  	mutex_init(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1336

9b0e85269   Jean Delvare   hwmon: (lm90) Con...
1337
1338
1339
1340
  	/* Set the device type */
  	data->kind = id->driver_data;
  	if (data->kind == adm1032) {
  		if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1341
  			client->flags &= ~I2C_CLIENT_PEC;
9b0e85269   Jean Delvare   hwmon: (lm90) Con...
1342
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1343

53de33427   Jean Delvare   hwmon: (lm90) Add...
1344
1345
  	/* Different devices have different alarm bits triggering the
  	 * ALERT# output */
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
1346
  	data->alert_alarms = lm90_params[data->kind].alert_alarms;
53de33427   Jean Delvare   hwmon: (lm90) Add...
1347

88073bb1b   Guenter Roeck   hwmon: (lm90) Int...
1348
  	/* Set chip capabilities */
4667bcb8d   Guenter Roeck   hwmon: (lm90) Int...
1349
  	data->flags = lm90_params[data->kind].flags;
a095f687f   Jean Delvare   hwmon: (lm90) Sim...
1350
  	data->reg_local_ext = lm90_params[data->kind].reg_local_ext;
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1351

0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
1352
1353
  	/* Set maximum conversion rate */
  	data->max_convrate = lm90_params[data->kind].max_convrate;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1354
  	/* Initialize the LM90 chip */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1355
  	lm90_init_client(client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
1357
  
  	/* Register sysfs hooks */
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1358
  	err = sysfs_create_group(&dev->kobj, &lm90_group);
11e578129   Guenter Roeck   hwmon: (lm90) Fix...
1359
  	if (err)
9b0e85269   Jean Delvare   hwmon: (lm90) Con...
1360
  		goto exit_free;
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1361
1362
  	if (client->flags & I2C_CLIENT_PEC) {
  		err = device_create_file(dev, &dev_attr_pec);
11e578129   Guenter Roeck   hwmon: (lm90) Fix...
1363
  		if (err)
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
1364
1365
  			goto exit_remove_files;
  	}
88073bb1b   Guenter Roeck   hwmon: (lm90) Int...
1366
  	if (data->flags & LM90_HAVE_OFFSET) {
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1367
  		err = device_create_file(dev,
11e578129   Guenter Roeck   hwmon: (lm90) Fix...
1368
1369
  					&sensor_dev_attr_temp2_offset.dev_attr);
  		if (err)
69f2f96d9   Jean Delvare   hwmon: (lm90) Exp...
1370
1371
  			goto exit_remove_files;
  	}
6948708dd   Guenter Roeck   hwmon: (lm90) Add...
1372
  	if (data->flags & LM90_HAVE_EMERGENCY) {
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1373
  		err = sysfs_create_group(&dev->kobj, &lm90_emergency_group);
6948708dd   Guenter Roeck   hwmon: (lm90) Add...
1374
1375
1376
  		if (err)
  			goto exit_remove_files;
  	}
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1377
  	if (data->flags & LM90_HAVE_EMERGENCY_ALARM) {
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1378
  		err = sysfs_create_group(&dev->kobj,
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1379
1380
1381
1382
1383
  					 &lm90_emergency_alarm_group);
  		if (err)
  			goto exit_remove_files;
  	}
  	if (data->flags & LM90_HAVE_TEMP3) {
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1384
  		err = sysfs_create_group(&dev->kobj, &lm90_temp3_group);
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1385
1386
1387
  		if (err)
  			goto exit_remove_files;
  	}
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
1388

b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1389
  	data->hwmon_dev = hwmon_device_register(dev);
1beeffe43   Tony Jones   hwmon: Convert fr...
1390
1391
  	if (IS_ERR(data->hwmon_dev)) {
  		err = PTR_ERR(data->hwmon_dev);
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
1392
  		goto exit_remove_files;
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
1393
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1394
  	return 0;
0e39e01c9   Jean Delvare   hwmon: Fix unchec...
1395
  exit_remove_files:
b2589ab02   Jean Delvare   hwmon: (lm90) Mak...
1396
  	lm90_remove_files(client, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
1398
1399
1400
1401
  exit_free:
  	kfree(data);
  exit:
  	return err;
  }
9b0e85269   Jean Delvare   hwmon: (lm90) Con...
1402
  static int lm90_remove(struct i2c_client *client)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1403
  {
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
1404
  	struct lm90_data *data = i2c_get_clientdata(client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1405

1beeffe43   Tony Jones   hwmon: Convert fr...
1406
  	hwmon_device_unregister(data->hwmon_dev);
b6fc1bacc   Guenter Roeck   hwmon: (lm90) Int...
1407
  	lm90_remove_files(client, data);
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
1408

952383641   Jean Delvare   hwmon: (lm90) Res...
1409
  	/* Restore initial configuration */
0c01b644f   Guenter Roeck   hwmon: (lm90) Add...
1410
1411
  	i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE,
  				  data->convrate_orig);
952383641   Jean Delvare   hwmon: (lm90) Res...
1412
1413
  	i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
  				  data->config_orig);
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
1414
  	kfree(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1415
1416
  	return 0;
  }
53de33427   Jean Delvare   hwmon: (lm90) Add...
1417
1418
1419
  static void lm90_alert(struct i2c_client *client, unsigned int flag)
  {
  	struct lm90_data *data = i2c_get_clientdata(client);
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1420
  	u8 config, alarms, alarms2 = 0;
53de33427   Jean Delvare   hwmon: (lm90) Add...
1421
1422
  
  	lm90_read_reg(client, LM90_REG_R_STATUS, &alarms);
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1423
1424
1425
1426
1427
  
  	if (data->kind == max6696)
  		lm90_read_reg(client, MAX6696_REG_R_STATUS2, &alarms2);
  
  	if ((alarms & 0x7f) == 0 && (alarms2 & 0xfe) == 0) {
53de33427   Jean Delvare   hwmon: (lm90) Add...
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
  		dev_info(&client->dev, "Everything OK
  ");
  	} else {
  		if (alarms & 0x61)
  			dev_warn(&client->dev,
  				 "temp%d out of range, please check!
  ", 1);
  		if (alarms & 0x1a)
  			dev_warn(&client->dev,
  				 "temp%d out of range, please check!
  ", 2);
  		if (alarms & 0x04)
  			dev_warn(&client->dev,
  				 "temp%d diode open, please check!
  ", 2);
06e1c0a21   Guenter Roeck   hwmon: (lm90) Add...
1443
1444
1445
1446
  		if (alarms2 & 0x18)
  			dev_warn(&client->dev,
  				 "temp%d out of range, please check!
  ", 3);
53de33427   Jean Delvare   hwmon: (lm90) Add...
1447
1448
1449
  		/* Disable ALERT# output, because these chips don't implement
  		  SMBus alert correctly; they should only hold the alert line
  		  low briefly. */
1179324c4   Guenter Roeck   hwmon: (lm90) Int...
1450
  		if ((data->flags & LM90_HAVE_BROKEN_ALERT)
53de33427   Jean Delvare   hwmon: (lm90) Add...
1451
1452
1453
1454
1455
1456
1457
1458
1459
  		 && (alarms & data->alert_alarms)) {
  			dev_dbg(&client->dev, "Disabling ALERT#
  ");
  			lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
  			i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
  						  config | 0x80);
  		}
  	}
  }
15b66ab69   Guenter Roeck   hwmon: (lm90) Rea...
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
  static struct i2c_driver lm90_driver = {
  	.class		= I2C_CLASS_HWMON,
  	.driver = {
  		.name	= "lm90",
  	},
  	.probe		= lm90_probe,
  	.remove		= lm90_remove,
  	.alert		= lm90_alert,
  	.id_table	= lm90_id,
  	.detect		= lm90_detect,
  	.address_list	= normal_i2c,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
  
  static int __init sensors_lm90_init(void)
  {
  	return i2c_add_driver(&lm90_driver);
  }
  
  static void __exit sensors_lm90_exit(void)
  {
  	i2c_del_driver(&lm90_driver);
  }
  
  MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
  MODULE_DESCRIPTION("LM90/ADM1032 driver");
  MODULE_LICENSE("GPL");
  
  module_init(sensors_lm90_init);
  module_exit(sensors_lm90_exit);