aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <guenter.roeck@ericsson.com>2010-08-09 20:21:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-09 23:45:10 -0400
commit920fa1ffce48d36d7e7bc54eb38c58313bc0a667 (patch)
treeca8105f753fa0e0eae008de6b0d383c2ad1294d0
parentcfa3b24c38b58cb6acabe6441b4668e530e957af (diff)
hwmon: driver for SMM665 Six-Channel Active DC Output Controller/Monitor
This driver adds support for the monitoring features of the Summit Microelectronics SMM665 Six-Channel Active DC Output Controller/Monitor. Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Acked-by: Jonathan Cameron <jic23@cam.ac.uk> Cc: Jean Delvare <khali@linux-fr.org> Cc: Hans de Goede <hdegoede@redhat.com> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com> Cc: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/hwmon/smm665157
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/hwmon/Kconfig15
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/smm665.c743
5 files changed, 923 insertions, 0 deletions
diff --git a/Documentation/hwmon/smm665 b/Documentation/hwmon/smm665
new file mode 100644
index 000000000000..3820fc9ca52d
--- /dev/null
+++ b/Documentation/hwmon/smm665
@@ -0,0 +1,157 @@
1Kernel driver smm665
2====================
3
4Supported chips:
5 * Summit Microelectronics SMM465
6 Prefix: 'smm465'
7 Addresses scanned: -
8 Datasheet:
9 http://www.summitmicro.com/prod_select/summary/SMM465/SMM465DS.pdf
10 * Summit Microelectronics SMM665, SMM665B
11 Prefix: 'smm665'
12 Addresses scanned: -
13 Datasheet:
14 http://www.summitmicro.com/prod_select/summary/SMM665/SMM665B_2089_20.pdf
15 * Summit Microelectronics SMM665C
16 Prefix: 'smm665c'
17 Addresses scanned: -
18 Datasheet:
19 http://www.summitmicro.com/prod_select/summary/SMM665C/SMM665C_2125.pdf
20 * Summit Microelectronics SMM764
21 Prefix: 'smm764'
22 Addresses scanned: -
23 Datasheet:
24 http://www.summitmicro.com/prod_select/summary/SMM764/SMM764_2098.pdf
25 * Summit Microelectronics SMM766, SMM766B
26 Prefix: 'smm766'
27 Addresses scanned: -
28 Datasheets:
29 http://www.summitmicro.com/prod_select/summary/SMM766/SMM766_2086.pdf
30 http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf
31
32Author: Guenter Roeck <guenter.roeck@ericsson.com>
33
34
35Module Parameters
36-----------------
37
38* vref: int
39 Default: 1250 (mV)
40 Reference voltage on VREF_ADC pin in mV. It should not be necessary to set
41 this parameter unless a non-default reference voltage is used.
42
43
44Description
45-----------
46
47[From datasheet] The SMM665 is an Active DC Output power supply Controller
48that monitors, margins and cascade sequences power. The part monitors six
49power supply channels as well as VDD, 12V input, two general-purpose analog
50inputs and an internal temperature sensor using a 10-bit ADC.
51
52Each monitored channel has its own high and low limits, plus a critical
53limit.
54
55Support for SMM465, SMM764, and SMM766 has been implemented but is untested.
56
57
58Usage Notes
59-----------
60
61This driver does not probe for devices, since there is no register which
62can be safely used to identify the chip. You will have to instantiate
63the devices explicitly. When instantiating the device, you have to specify
64its configuration register address.
65
66Example: the following will load the driver for an SMM665 at address 0x57
67on I2C bus #1:
68$ modprobe smm665
69$ echo smm665 0x57 > /sys/bus/i2c/devices/i2c-1/new_device
70
71
72Sysfs entries
73-------------
74
75This driver uses the values in the datasheet to convert ADC register values
76into the values specified in the sysfs-interface document. All attributes are
77read only.
78
79Min, max, lcrit, and crit values are used by the chip to trigger external signals
80and/or other activity. Triggered signals can include HEALTHY, RST, Power Off,
81or Fault depending on the chip configuration. The driver reports values as lcrit
82or crit if exceeding the limits triggers RST, Power Off, or Fault, and as min or
83max otherwise. For details please see the SMM665 datasheet.
84
85For SMM465 and SMM764, values for Channel E and F are reported but undefined.
86
87in1_input 12V input voltage (mV)
88in2_input 3.3V (VDD) input voltage (mV)
89in3_input Channel A voltage (mV)
90in4_input Channel B voltage (mV)
91in5_input Channel C voltage (mV)
92in6_input Channel D voltage (mV)
93in7_input Channel E voltage (mV)
94in8_input Channel F voltage (mV)
95in9_input AIN1 voltage (mV)
96in10_input AIN2 voltage (mV)
97
98in1_min 12v input minimum voltage (mV)
99in2_min 3.3V (VDD) input minimum voltage (mV)
100in3_min Channel A minimum voltage (mV)
101in4_min Channel B minimum voltage (mV)
102in5_min Channel C minimum voltage (mV)
103in6_min Channel D minimum voltage (mV)
104in7_min Channel E minimum voltage (mV)
105in8_min Channel F minimum voltage (mV)
106in9_min AIN1 minimum voltage (mV)
107in10_min AIN2 minimum voltage (mV)
108
109in1_max 12v input maximum voltage (mV)
110in2_max 3.3V (VDD) input maximum voltage (mV)
111in3_max Channel A maximum voltage (mV)
112in4_max Channel B maximum voltage (mV)
113in5_max Channel C maximum voltage (mV)
114in6_max Channel D maximum voltage (mV)
115in7_max Channel E maximum voltage (mV)
116in8_max Channel F maximum voltage (mV)
117in9_max AIN1 maximum voltage (mV)
118in10_max AIN2 maximum voltage (mV)
119
120in1_lcrit 12v input critical minimum voltage (mV)
121in2_lcrit 3.3V (VDD) input critical minimum voltage (mV)
122in3_lcrit Channel A critical minimum voltage (mV)
123in4_lcrit Channel B critical minimum voltage (mV)
124in5_lcrit Channel C critical minimum voltage (mV)
125in6_lcrit Channel D critical minimum voltage (mV)
126in7_lcrit Channel E critical minimum voltage (mV)
127in8_lcrit Channel F critical minimum voltage (mV)
128in9_lcrit AIN1 critical minimum voltage (mV)
129in10_lcrit AIN2 critical minimum voltage (mV)
130
131in1_crit 12v input critical maximum voltage (mV)
132in2_crit 3.3V (VDD) input critical maximum voltage (mV)
133in3_crit Channel A critical maximum voltage (mV)
134in4_crit Channel B critical maximum voltage (mV)
135in5_crit Channel C critical maximum voltage (mV)
136in6_crit Channel D critical maximum voltage (mV)
137in7_crit Channel E critical maximum voltage (mV)
138in8_crit Channel F critical maximum voltage (mV)
139in9_crit AIN1 critical maximum voltage (mV)
140in10_crit AIN2 critical maximum voltage (mV)
141
142in1_crit_alarm 12v input critical alarm
143in2_crit_alarm 3.3V (VDD) input critical alarm
144in3_crit_alarm Channel A critical alarm
145in4_crit_alarm Channel B critical alarm
146in5_crit_alarm Channel C critical alarm
147in6_crit_alarm Channel D critical alarm
148in7_crit_alarm Channel E critical alarm
149in8_crit_alarm Channel F critical alarm
150in9_crit_alarm AIN1 critical alarm
151in10_crit_alarm AIN2 critical alarm
152
153temp1_input Chip tempererature
154temp1_min Mimimum chip tempererature
155temp1_max Maximum chip tempererature
156temp1_crit Critical chip tempererature
157temp1_crit_alarm Temperature critical alarm
diff --git a/MAINTAINERS b/MAINTAINERS
index c71d2c5bffa6..caacbcc3b64f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5251,6 +5251,13 @@ M: Nicolas Pitre <nico@fluxnic.net>
5251S: Odd Fixes 5251S: Odd Fixes
5252F: drivers/net/smc91x.* 5252F: drivers/net/smc91x.*
5253 5253
5254SMM665 HARDWARE MONITOR DRIVER
5255M: Guenter Roeck <linux@roeck-us.net>
5256L: lm-sensors@lm-sensors.org
5257S: Maintained
5258F: Documentation/hwmon/smm665
5259F: drivers/hwmon/smm665.c
5260
5254SMSC47B397 HARDWARE MONITOR DRIVER 5261SMSC47B397 HARDWARE MONITOR DRIVER
5255M: "Mark M. Hoffman" <mhoffman@lightlink.com> 5262M: "Mark M. Hoffman" <mhoffman@lightlink.com>
5256L: lm-sensors@lm-sensors.org 5263L: lm-sensors@lm-sensors.org
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 4d382ae53092..c80ba4943b81 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -756,6 +756,21 @@ config SENSORS_SIS5595
756 This driver can also be built as a module. If so, the module 756 This driver can also be built as a module. If so, the module
757 will be called sis5595. 757 will be called sis5595.
758 758
759config SENSORS_SMM665
760 tristate "Summit Microelectronics SMM665"
761 depends on I2C && EXPERIMENTAL
762 default n
763 help
764 If you say yes here you get support for the hardware monitoring
765 features of the Summit Microelectronics SMM665/SMM665B Six-Channel
766 Active DC Output Controller / Monitor.
767
768 Other supported chips are SMM465, SMM665C, SMM764, and SMM766.
769 Support for those chips is untested.
770
771 This driver can also be built as a module. If so, the module will
772 be called smm665.
773
759config SENSORS_DME1737 774config SENSORS_DME1737
760 tristate "SMSC DME1737, SCH311x and compatibles" 775 tristate "SMSC DME1737, SCH311x and compatibles"
761 depends on I2C && EXPERIMENTAL 776 depends on I2C && EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 9103bd6ea73a..db24fa1aa8b7 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
88obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o 88obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
89obj-$(CONFIG_SENSORS_SHT15) += sht15.o 89obj-$(CONFIG_SENSORS_SHT15) += sht15.o
90obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o 90obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
91obj-$(CONFIG_SENSORS_SMM665) += smm665.o
91obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o 92obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
92obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o 93obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
93obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o 94obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c
new file mode 100644
index 000000000000..425df5bccd45
--- /dev/null
+++ b/drivers/hwmon/smm665.c
@@ -0,0 +1,743 @@
1/*
2 * Driver for SMM665 Power Controller / Monitor
3 *
4 * Copyright (C) 2010 Ericsson AB.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This driver should also work for SMM465, SMM764, and SMM766, but is untested
11 * for those chips. Only monitoring functionality is implemented.
12 *
13 * Datasheets:
14 * http://www.summitmicro.com/prod_select/summary/SMM665/SMM665B_2089_20.pdf
15 * http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/err.h>
22#include <linux/slab.h>
23#include <linux/i2c.h>
24#include <linux/hwmon.h>
25#include <linux/hwmon-sysfs.h>
26#include <linux/delay.h>
27
28/* Internal reference voltage (VREF, x 1000 */
29#define SMM665_VREF_ADC_X1000 1250
30
31/* module parameters */
32static int vref = SMM665_VREF_ADC_X1000;
33module_param(vref, int, 0);
34MODULE_PARM_DESC(vref, "Reference voltage in mV");
35
36enum chips { smm465, smm665, smm665c, smm764, smm766 };
37
38/*
39 * ADC channel addresses
40 */
41#define SMM665_MISC16_ADC_DATA_A 0x00
42#define SMM665_MISC16_ADC_DATA_B 0x01
43#define SMM665_MISC16_ADC_DATA_C 0x02
44#define SMM665_MISC16_ADC_DATA_D 0x03
45#define SMM665_MISC16_ADC_DATA_E 0x04
46#define SMM665_MISC16_ADC_DATA_F 0x05
47#define SMM665_MISC16_ADC_DATA_VDD 0x06
48#define SMM665_MISC16_ADC_DATA_12V 0x07
49#define SMM665_MISC16_ADC_DATA_INT_TEMP 0x08
50#define SMM665_MISC16_ADC_DATA_AIN1 0x09
51#define SMM665_MISC16_ADC_DATA_AIN2 0x0a
52
53/*
54 * Command registers
55 */
56#define SMM665_MISC8_CMD_STS 0x80
57#define SMM665_MISC8_STATUS1 0x81
58#define SMM665_MISC8_STATUSS2 0x82
59#define SMM665_MISC8_IO_POLARITY 0x83
60#define SMM665_MISC8_PUP_POLARITY 0x84
61#define SMM665_MISC8_ADOC_STATUS1 0x85
62#define SMM665_MISC8_ADOC_STATUS2 0x86
63#define SMM665_MISC8_WRITE_PROT 0x87
64#define SMM665_MISC8_STS_TRACK 0x88
65
66/*
67 * Configuration registers and register groups
68 */
69#define SMM665_ADOC_ENABLE 0x0d
70#define SMM665_LIMIT_BASE 0x80 /* First limit register */
71
72/*
73 * Limit register bit masks
74 */
75#define SMM665_TRIGGER_RST 0x8000
76#define SMM665_TRIGGER_HEALTHY 0x4000
77#define SMM665_TRIGGER_POWEROFF 0x2000
78#define SMM665_TRIGGER_SHUTDOWN 0x1000
79#define SMM665_ADC_MASK 0x03ff
80
81#define smm665_is_critical(lim) ((lim) & (SMM665_TRIGGER_RST \
82 | SMM665_TRIGGER_POWEROFF \
83 | SMM665_TRIGGER_SHUTDOWN))
84/*
85 * Fault register bit definitions
86 * Values are merged from status registers 1/2,
87 * with status register 1 providing the upper 8 bits.
88 */
89#define SMM665_FAULT_A 0x0001
90#define SMM665_FAULT_B 0x0002
91#define SMM665_FAULT_C 0x0004
92#define SMM665_FAULT_D 0x0008
93#define SMM665_FAULT_E 0x0010
94#define SMM665_FAULT_F 0x0020
95#define SMM665_FAULT_VDD 0x0040
96#define SMM665_FAULT_12V 0x0080
97#define SMM665_FAULT_TEMP 0x0100
98#define SMM665_FAULT_AIN1 0x0200
99#define SMM665_FAULT_AIN2 0x0400
100
101/*
102 * I2C Register addresses
103 *
104 * The configuration register needs to be the configured base register.
105 * The command/status register address is derived from it.
106 */
107#define SMM665_REGMASK 0x78
108#define SMM665_CMDREG_BASE 0x48
109#define SMM665_CONFREG_BASE 0x50
110
111/*
112 * Equations given by chip manufacturer to calculate voltage/temperature values
113 * vref = Reference voltage on VREF_ADC pin (module parameter)
114 * adc = 10bit ADC value read back from registers
115 */
116
117/* Voltage A-F and VDD */
118#define SMM665_VMON_ADC_TO_VOLTS(adc) ((adc) * vref / 256)
119
120/* Voltage 12VIN */
121#define SMM665_12VIN_ADC_TO_VOLTS(adc) ((adc) * vref * 3 / 256)
122
123/* Voltage AIN1, AIN2 */
124#define SMM665_AIN_ADC_TO_VOLTS(adc) ((adc) * vref / 512)
125
126/* Temp Sensor */
127#define SMM665_TEMP_ADC_TO_CELSIUS(adc) ((adc) <= 511) ? \
128 ((int)(adc) * 1000 / 4) : \
129 (((int)(adc) - 0x400) * 1000 / 4)
130
131#define SMM665_NUM_ADC 11
132
133/*
134 * Chip dependent ADC conversion time, in uS
135 */
136#define SMM665_ADC_WAIT_SMM665 70
137#define SMM665_ADC_WAIT_SMM766 185
138
139struct smm665_data {
140 enum chips type;
141 int conversion_time; /* ADC conversion time */
142 struct device *hwmon_dev;
143 struct mutex update_lock;
144 bool valid;
145 unsigned long last_updated; /* in jiffies */
146 u16 adc[SMM665_NUM_ADC]; /* adc values (raw) */
147 u16 faults; /* fault status */
148 /* The following values are in mV */
149 int critical_min_limit[SMM665_NUM_ADC];
150 int alarm_min_limit[SMM665_NUM_ADC];
151 int critical_max_limit[SMM665_NUM_ADC];
152 int alarm_max_limit[SMM665_NUM_ADC];
153 struct i2c_client *cmdreg;
154};
155
156/*
157 * smm665_read16()
158 *
159 * Read 16 bit value from <reg>, <reg+1>. Upper 8 bits are in <reg>.
160 */
161static int smm665_read16(struct i2c_client *client, int reg)
162{
163 int rv, val;
164
165 rv = i2c_smbus_read_byte_data(client, reg);
166 if (rv < 0)
167 return rv;
168 val = rv << 8;
169 rv = i2c_smbus_read_byte_data(client, reg + 1);
170 if (rv < 0)
171 return rv;
172 val |= rv;
173 return val;
174}
175
176/*
177 * Read adc value.
178 */
179static int smm665_read_adc(struct smm665_data *data, int adc)
180{
181 struct i2c_client *client = data->cmdreg;
182 int rv;
183 int radc;
184
185 /*
186 * Algorithm for reading ADC, per SMM665 datasheet
187 *
188 * {[S][addr][W][Ack]} {[offset][Ack]} {[S][addr][R][Nack]}
189 * [wait conversion time]
190 * {[S][addr][R][Ack]} {[datahi][Ack]} {[datalo][Ack][P]}
191 *
192 * To implement the first part of this exchange,
193 * do a full read transaction and expect a failure/Nack.
194 * This sets up the address pointer on the SMM665
195 * and starts the ADC conversion.
196 * Then do a two-byte read transaction.
197 */
198 rv = i2c_smbus_read_byte_data(client, adc << 3);
199 if (rv != -ENXIO) {
200 /*
201 * We expect ENXIO to reflect NACK
202 * (per Documentation/i2c/fault-codes).
203 * Everything else is an error.
204 */
205 dev_dbg(&client->dev,
206 "Unexpected return code %d when setting ADC index", rv);
207 return (rv < 0) ? rv : -EIO;
208 }
209
210 udelay(data->conversion_time);
211
212 /*
213 * Now read two bytes.
214 *
215 * Neither i2c_smbus_read_byte() nor
216 * i2c_smbus_read_block_data() worked here,
217 * so use i2c_smbus_read_word_data() instead.
218 * We could also try to use i2c_master_recv(),
219 * but that is not always supported.
220 */
221 rv = i2c_smbus_read_word_data(client, 0);
222 if (rv < 0) {
223 dev_dbg(&client->dev, "Failed to read ADC value: error %d", rv);
224 return -1;
225 }
226 /*
227 * Validate/verify readback adc channel (in bit 11..14).
228 * High byte is in lower 8 bit of rv, so only shift by 3.
229 */
230 radc = (rv >> 3) & 0x0f;
231 if (radc != adc) {
232 dev_dbg(&client->dev, "Unexpected RADC: Expected %d got %d",
233 adc, radc);
234 return -EIO;
235 }
236 /*
237 * Chip replies with H/L, while SMBus expects L/H.
238 * Thus, byte order is reversed, and we have to swap
239 * the result.
240 */
241 rv = swab16(rv) & SMM665_ADC_MASK;
242
243 return rv;
244}
245
246static struct smm665_data *smm665_update_device(struct device *dev)
247{
248 struct i2c_client *client = to_i2c_client(dev);
249 struct smm665_data *data = i2c_get_clientdata(client);
250 struct smm665_data *ret = data;
251
252 mutex_lock(&data->update_lock);
253
254 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
255 int i, val;
256
257 /*
258 * read status registers
259 */
260 val = smm665_read16(client, SMM665_MISC8_STATUS1);
261 if (unlikely(val < 0)) {
262 ret = ERR_PTR(val);
263 goto abort;
264 }
265 data->faults = val;
266
267 /* Read adc registers */
268 for (i = 0; i < SMM665_NUM_ADC; i++) {
269 val = smm665_read_adc(data, i);
270 if (unlikely(val < 0)) {
271 ret = ERR_PTR(val);
272 goto abort;
273 }
274 data->adc[i] = val;
275 }
276 data->last_updated = jiffies;
277 data->valid = 1;
278 }
279abort:
280 mutex_unlock(&data->update_lock);
281 return ret;
282}
283
284/* Return converted value from given adc */
285static int smm665_convert(u16 adcval, int index)
286{
287 int val = 0;
288
289 switch (index) {
290 case SMM665_MISC16_ADC_DATA_12V:
291 val = SMM665_12VIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK);
292 break;
293
294 case SMM665_MISC16_ADC_DATA_VDD:
295 case SMM665_MISC16_ADC_DATA_A:
296 case SMM665_MISC16_ADC_DATA_B:
297 case SMM665_MISC16_ADC_DATA_C:
298 case SMM665_MISC16_ADC_DATA_D:
299 case SMM665_MISC16_ADC_DATA_E:
300 case SMM665_MISC16_ADC_DATA_F:
301 val = SMM665_VMON_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK);
302 break;
303
304 case SMM665_MISC16_ADC_DATA_AIN1:
305 case SMM665_MISC16_ADC_DATA_AIN2:
306 val = SMM665_AIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK);
307 break;
308
309 case SMM665_MISC16_ADC_DATA_INT_TEMP:
310 val = SMM665_TEMP_ADC_TO_CELSIUS(adcval & SMM665_ADC_MASK);
311 break;
312
313 default:
314 /* If we get here, the developer messed up */
315 WARN_ON_ONCE(1);
316 break;
317 }
318
319 return val;
320}
321
322static int smm665_get_min(struct device *dev, int index)
323{
324 struct i2c_client *client = to_i2c_client(dev);
325 struct smm665_data *data = i2c_get_clientdata(client);
326
327 return data->alarm_min_limit[index];
328}
329
330static int smm665_get_max(struct device *dev, int index)
331{
332 struct i2c_client *client = to_i2c_client(dev);
333 struct smm665_data *data = i2c_get_clientdata(client);
334
335 return data->alarm_max_limit[index];
336}
337
338static int smm665_get_lcrit(struct device *dev, int index)
339{
340 struct i2c_client *client = to_i2c_client(dev);
341 struct smm665_data *data = i2c_get_clientdata(client);
342
343 return data->critical_min_limit[index];
344}
345
346static int smm665_get_crit(struct device *dev, int index)
347{
348 struct i2c_client *client = to_i2c_client(dev);
349 struct smm665_data *data = i2c_get_clientdata(client);
350
351 return data->critical_max_limit[index];
352}
353
354static ssize_t smm665_show_crit_alarm(struct device *dev,
355 struct device_attribute *da, char *buf)
356{
357 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
358 struct smm665_data *data = smm665_update_device(dev);
359 int val = 0;
360
361 if (IS_ERR(data))
362 return PTR_ERR(data);
363
364 if (data->faults & (1 << attr->index))
365 val = 1;
366
367 return snprintf(buf, PAGE_SIZE, "%d\n", val);
368}
369
370static ssize_t smm665_show_input(struct device *dev,
371 struct device_attribute *da, char *buf)
372{
373 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
374 struct smm665_data *data = smm665_update_device(dev);
375 int adc = attr->index;
376 int val;
377
378 if (IS_ERR(data))
379 return PTR_ERR(data);
380
381 val = smm665_convert(data->adc[adc], adc);
382 return snprintf(buf, PAGE_SIZE, "%d\n", val);
383}
384
385#define SMM665_SHOW(what) \
386 static ssize_t smm665_show_##what(struct device *dev, \
387 struct device_attribute *da, char *buf) \
388{ \
389 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
390 const int val = smm665_get_##what(dev, attr->index); \
391 return snprintf(buf, PAGE_SIZE, "%d\n", val); \
392}
393
394SMM665_SHOW(min);
395SMM665_SHOW(max);
396SMM665_SHOW(lcrit);
397SMM665_SHOW(crit);
398
399/* These macros are used below in constructing device attribute objects
400 * for use with sysfs_create_group() to make a sysfs device file
401 * for each register.
402 */
403
404#define SMM665_ATTR(name, type, cmd_idx) \
405 static SENSOR_DEVICE_ATTR(name##_##type, S_IRUGO, \
406 smm665_show_##type, NULL, cmd_idx)
407
408/* Construct a sensor_device_attribute structure for each register */
409
410/* Input voltages */
411SMM665_ATTR(in1, input, SMM665_MISC16_ADC_DATA_12V);
412SMM665_ATTR(in2, input, SMM665_MISC16_ADC_DATA_VDD);
413SMM665_ATTR(in3, input, SMM665_MISC16_ADC_DATA_A);
414SMM665_ATTR(in4, input, SMM665_MISC16_ADC_DATA_B);
415SMM665_ATTR(in5, input, SMM665_MISC16_ADC_DATA_C);
416SMM665_ATTR(in6, input, SMM665_MISC16_ADC_DATA_D);
417SMM665_ATTR(in7, input, SMM665_MISC16_ADC_DATA_E);
418SMM665_ATTR(in8, input, SMM665_MISC16_ADC_DATA_F);
419SMM665_ATTR(in9, input, SMM665_MISC16_ADC_DATA_AIN1);
420SMM665_ATTR(in10, input, SMM665_MISC16_ADC_DATA_AIN2);
421
422/* Input voltages min */
423SMM665_ATTR(in1, min, SMM665_MISC16_ADC_DATA_12V);
424SMM665_ATTR(in2, min, SMM665_MISC16_ADC_DATA_VDD);
425SMM665_ATTR(in3, min, SMM665_MISC16_ADC_DATA_A);
426SMM665_ATTR(in4, min, SMM665_MISC16_ADC_DATA_B);
427SMM665_ATTR(in5, min, SMM665_MISC16_ADC_DATA_C);
428SMM665_ATTR(in6, min, SMM665_MISC16_ADC_DATA_D);
429SMM665_ATTR(in7, min, SMM665_MISC16_ADC_DATA_E);
430SMM665_ATTR(in8, min, SMM665_MISC16_ADC_DATA_F);
431SMM665_ATTR(in9, min, SMM665_MISC16_ADC_DATA_AIN1);
432SMM665_ATTR(in10, min, SMM665_MISC16_ADC_DATA_AIN2);
433
434/* Input voltages max */
435SMM665_ATTR(in1, max, SMM665_MISC16_ADC_DATA_12V);
436SMM665_ATTR(in2, max, SMM665_MISC16_ADC_DATA_VDD);
437SMM665_ATTR(in3, max, SMM665_MISC16_ADC_DATA_A);
438SMM665_ATTR(in4, max, SMM665_MISC16_ADC_DATA_B);
439SMM665_ATTR(in5, max, SMM665_MISC16_ADC_DATA_C);
440SMM665_ATTR(in6, max, SMM665_MISC16_ADC_DATA_D);
441SMM665_ATTR(in7, max, SMM665_MISC16_ADC_DATA_E);
442SMM665_ATTR(in8, max, SMM665_MISC16_ADC_DATA_F);
443SMM665_ATTR(in9, max, SMM665_MISC16_ADC_DATA_AIN1);
444SMM665_ATTR(in10, max, SMM665_MISC16_ADC_DATA_AIN2);
445
446/* Input voltages lcrit */
447SMM665_ATTR(in1, lcrit, SMM665_MISC16_ADC_DATA_12V);
448SMM665_ATTR(in2, lcrit, SMM665_MISC16_ADC_DATA_VDD);
449SMM665_ATTR(in3, lcrit, SMM665_MISC16_ADC_DATA_A);
450SMM665_ATTR(in4, lcrit, SMM665_MISC16_ADC_DATA_B);
451SMM665_ATTR(in5, lcrit, SMM665_MISC16_ADC_DATA_C);
452SMM665_ATTR(in6, lcrit, SMM665_MISC16_ADC_DATA_D);
453SMM665_ATTR(in7, lcrit, SMM665_MISC16_ADC_DATA_E);
454SMM665_ATTR(in8, lcrit, SMM665_MISC16_ADC_DATA_F);
455SMM665_ATTR(in9, lcrit, SMM665_MISC16_ADC_DATA_AIN1);
456SMM665_ATTR(in10, lcrit, SMM665_MISC16_ADC_DATA_AIN2);
457
458/* Input voltages crit */
459SMM665_ATTR(in1, crit, SMM665_MISC16_ADC_DATA_12V);
460SMM665_ATTR(in2, crit, SMM665_MISC16_ADC_DATA_VDD);
461SMM665_ATTR(in3, crit, SMM665_MISC16_ADC_DATA_A);
462SMM665_ATTR(in4, crit, SMM665_MISC16_ADC_DATA_B);
463SMM665_ATTR(in5, crit, SMM665_MISC16_ADC_DATA_C);
464SMM665_ATTR(in6, crit, SMM665_MISC16_ADC_DATA_D);
465SMM665_ATTR(in7, crit, SMM665_MISC16_ADC_DATA_E);
466SMM665_ATTR(in8, crit, SMM665_MISC16_ADC_DATA_F);
467SMM665_ATTR(in9, crit, SMM665_MISC16_ADC_DATA_AIN1);
468SMM665_ATTR(in10, crit, SMM665_MISC16_ADC_DATA_AIN2);
469
470/* critical alarms */
471SMM665_ATTR(in1, crit_alarm, SMM665_FAULT_12V);
472SMM665_ATTR(in2, crit_alarm, SMM665_FAULT_VDD);
473SMM665_ATTR(in3, crit_alarm, SMM665_FAULT_A);
474SMM665_ATTR(in4, crit_alarm, SMM665_FAULT_B);
475SMM665_ATTR(in5, crit_alarm, SMM665_FAULT_C);
476SMM665_ATTR(in6, crit_alarm, SMM665_FAULT_D);
477SMM665_ATTR(in7, crit_alarm, SMM665_FAULT_E);
478SMM665_ATTR(in8, crit_alarm, SMM665_FAULT_F);
479SMM665_ATTR(in9, crit_alarm, SMM665_FAULT_AIN1);
480SMM665_ATTR(in10, crit_alarm, SMM665_FAULT_AIN2);
481
482/* Temperature */
483SMM665_ATTR(temp1, input, SMM665_MISC16_ADC_DATA_INT_TEMP);
484SMM665_ATTR(temp1, min, SMM665_MISC16_ADC_DATA_INT_TEMP);
485SMM665_ATTR(temp1, max, SMM665_MISC16_ADC_DATA_INT_TEMP);
486SMM665_ATTR(temp1, lcrit, SMM665_MISC16_ADC_DATA_INT_TEMP);
487SMM665_ATTR(temp1, crit, SMM665_MISC16_ADC_DATA_INT_TEMP);
488SMM665_ATTR(temp1, crit_alarm, SMM665_FAULT_TEMP);
489
490/*
491 * Finally, construct an array of pointers to members of the above objects,
492 * as required for sysfs_create_group()
493 */
494static struct attribute *smm665_attributes[] = {
495 &sensor_dev_attr_in1_input.dev_attr.attr,
496 &sensor_dev_attr_in1_min.dev_attr.attr,
497 &sensor_dev_attr_in1_max.dev_attr.attr,
498 &sensor_dev_attr_in1_lcrit.dev_attr.attr,
499 &sensor_dev_attr_in1_crit.dev_attr.attr,
500 &sensor_dev_attr_in1_crit_alarm.dev_attr.attr,
501
502 &sensor_dev_attr_in2_input.dev_attr.attr,
503 &sensor_dev_attr_in2_min.dev_attr.attr,
504 &sensor_dev_attr_in2_max.dev_attr.attr,
505 &sensor_dev_attr_in2_lcrit.dev_attr.attr,
506 &sensor_dev_attr_in2_crit.dev_attr.attr,
507 &sensor_dev_attr_in2_crit_alarm.dev_attr.attr,
508
509 &sensor_dev_attr_in3_input.dev_attr.attr,
510 &sensor_dev_attr_in3_min.dev_attr.attr,
511 &sensor_dev_attr_in3_max.dev_attr.attr,
512 &sensor_dev_attr_in3_lcrit.dev_attr.attr,
513 &sensor_dev_attr_in3_crit.dev_attr.attr,
514 &sensor_dev_attr_in3_crit_alarm.dev_attr.attr,
515
516 &sensor_dev_attr_in4_input.dev_attr.attr,
517 &sensor_dev_attr_in4_min.dev_attr.attr,
518 &sensor_dev_attr_in4_max.dev_attr.attr,
519 &sensor_dev_attr_in4_lcrit.dev_attr.attr,
520 &sensor_dev_attr_in4_crit.dev_attr.attr,
521 &sensor_dev_attr_in4_crit_alarm.dev_attr.attr,
522
523 &sensor_dev_attr_in5_input.dev_attr.attr,
524 &sensor_dev_attr_in5_min.dev_attr.attr,
525 &sensor_dev_attr_in5_max.dev_attr.attr,
526 &sensor_dev_attr_in5_lcrit.dev_attr.attr,
527 &sensor_dev_attr_in5_crit.dev_attr.attr,
528 &sensor_dev_attr_in5_crit_alarm.dev_attr.attr,
529
530 &sensor_dev_attr_in6_input.dev_attr.attr,
531 &sensor_dev_attr_in6_min.dev_attr.attr,
532 &sensor_dev_attr_in6_max.dev_attr.attr,
533 &sensor_dev_attr_in6_lcrit.dev_attr.attr,
534 &sensor_dev_attr_in6_crit.dev_attr.attr,
535 &sensor_dev_attr_in6_crit_alarm.dev_attr.attr,
536
537 &sensor_dev_attr_in7_input.dev_attr.attr,
538 &sensor_dev_attr_in7_min.dev_attr.attr,
539 &sensor_dev_attr_in7_max.dev_attr.attr,
540 &sensor_dev_attr_in7_lcrit.dev_attr.attr,
541 &sensor_dev_attr_in7_crit.dev_attr.attr,
542 &sensor_dev_attr_in7_crit_alarm.dev_attr.attr,
543
544 &sensor_dev_attr_in8_input.dev_attr.attr,
545 &sensor_dev_attr_in8_min.dev_attr.attr,
546 &sensor_dev_attr_in8_max.dev_attr.attr,
547 &sensor_dev_attr_in8_lcrit.dev_attr.attr,
548 &sensor_dev_attr_in8_crit.dev_attr.attr,
549 &sensor_dev_attr_in8_crit_alarm.dev_attr.attr,
550
551 &sensor_dev_attr_in9_input.dev_attr.attr,
552 &sensor_dev_attr_in9_min.dev_attr.attr,
553 &sensor_dev_attr_in9_max.dev_attr.attr,
554 &sensor_dev_attr_in9_lcrit.dev_attr.attr,
555 &sensor_dev_attr_in9_crit.dev_attr.attr,
556 &sensor_dev_attr_in9_crit_alarm.dev_attr.attr,
557
558 &sensor_dev_attr_in10_input.dev_attr.attr,
559 &sensor_dev_attr_in10_min.dev_attr.attr,
560 &sensor_dev_attr_in10_max.dev_attr.attr,
561 &sensor_dev_attr_in10_lcrit.dev_attr.attr,
562 &sensor_dev_attr_in10_crit.dev_attr.attr,
563 &sensor_dev_attr_in10_crit_alarm.dev_attr.attr,
564
565 &sensor_dev_attr_temp1_input.dev_attr.attr,
566 &sensor_dev_attr_temp1_min.dev_attr.attr,
567 &sensor_dev_attr_temp1_max.dev_attr.attr,
568 &sensor_dev_attr_temp1_lcrit.dev_attr.attr,
569 &sensor_dev_attr_temp1_crit.dev_attr.attr,
570 &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
571
572 NULL,
573};
574
575static const struct attribute_group smm665_group = {
576 .attrs = smm665_attributes,
577};
578
579static int smm665_probe(struct i2c_client *client,
580 const struct i2c_device_id *id)
581{
582 struct i2c_adapter *adapter = client->adapter;
583 struct smm665_data *data;
584 int i, ret;
585
586 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
587 | I2C_FUNC_SMBUS_WORD_DATA))
588 return -ENODEV;
589
590 if (i2c_smbus_read_byte_data(client, SMM665_ADOC_ENABLE) < 0)
591 return -ENODEV;
592
593 ret = -ENOMEM;
594 data = kzalloc(sizeof(*data), GFP_KERNEL);
595 if (!data)
596 goto out_return;
597
598 i2c_set_clientdata(client, data);
599 mutex_init(&data->update_lock);
600
601 data->type = id->driver_data;
602 data->cmdreg = i2c_new_dummy(adapter, (client->addr & ~SMM665_REGMASK)
603 | SMM665_CMDREG_BASE);
604 if (!data->cmdreg)
605 goto out_kfree;
606
607 switch (data->type) {
608 case smm465:
609 case smm665:
610 data->conversion_time = SMM665_ADC_WAIT_SMM665;
611 break;
612 case smm665c:
613 case smm764:
614 case smm766:
615 data->conversion_time = SMM665_ADC_WAIT_SMM766;
616 break;
617 }
618
619 ret = -ENODEV;
620 if (i2c_smbus_read_byte_data(data->cmdreg, SMM665_MISC8_CMD_STS) < 0)
621 goto out_unregister;
622
623 /*
624 * Read limits.
625 *
626 * Limit registers start with register SMM665_LIMIT_BASE.
627 * Each channel uses 8 registers, providing four limit values
628 * per channel. Each limit value requires two registers, with the
629 * high byte in the first register and the low byte in the second
630 * register. The first two limits are under limit values, followed
631 * by two over limit values.
632 *
633 * Limit register order matches the ADC register order, so we use
634 * ADC register defines throughout the code to index limit registers.
635 *
636 * We save the first retrieved value both as "critical" and "alarm"
637 * value. The second value overwrites either the critical or the
638 * alarm value, depending on its configuration. This ensures that both
639 * critical and alarm values are initialized, even if both registers are
640 * configured as critical or non-critical.
641 */
642 for (i = 0; i < SMM665_NUM_ADC; i++) {
643 int val;
644
645 val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8);
646 if (unlikely(val < 0))
647 goto out_unregister;
648 data->critical_min_limit[i] = data->alarm_min_limit[i]
649 = smm665_convert(val, i);
650 val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 2);
651 if (unlikely(val < 0))
652 goto out_unregister;
653 if (smm665_is_critical(val))
654 data->critical_min_limit[i] = smm665_convert(val, i);
655 else
656 data->alarm_min_limit[i] = smm665_convert(val, i);
657 val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 4);
658 if (unlikely(val < 0))
659 goto out_unregister;
660 data->critical_max_limit[i] = data->alarm_max_limit[i]
661 = smm665_convert(val, i);
662 val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 6);
663 if (unlikely(val < 0))
664 goto out_unregister;
665 if (smm665_is_critical(val))
666 data->critical_max_limit[i] = smm665_convert(val, i);
667 else
668 data->alarm_max_limit[i] = smm665_convert(val, i);
669 }
670
671 /* Register sysfs hooks */
672 ret = sysfs_create_group(&client->dev.kobj, &smm665_group);
673 if (ret)
674 goto out_unregister;
675
676 data->hwmon_dev = hwmon_device_register(&client->dev);
677 if (IS_ERR(data->hwmon_dev)) {
678 ret = PTR_ERR(data->hwmon_dev);
679 goto out_remove_group;
680 }
681
682 return 0;
683
684out_remove_group:
685 sysfs_remove_group(&client->dev.kobj, &smm665_group);
686out_unregister:
687 i2c_unregister_device(data->cmdreg);
688out_kfree:
689 kfree(data);
690out_return:
691 return ret;
692}
693
694static int smm665_remove(struct i2c_client *client)
695{
696 struct smm665_data *data = i2c_get_clientdata(client);
697
698 i2c_unregister_device(data->cmdreg);
699 hwmon_device_unregister(data->hwmon_dev);
700 sysfs_remove_group(&client->dev.kobj, &smm665_group);
701
702 kfree(data);
703
704 return 0;
705}
706
707static const struct i2c_device_id smm665_id[] = {
708 {"smm465", smm465},
709 {"smm665", smm665},
710 {"smm665c", smm665c},
711 {"smm764", smm764},
712 {"smm766", smm766},
713 {}
714};
715
716MODULE_DEVICE_TABLE(i2c, smm665_id);
717
718/* This is the driver that will be inserted */
719static struct i2c_driver smm665_driver = {
720 .driver = {
721 .name = "smm665",
722 },
723 .probe = smm665_probe,
724 .remove = smm665_remove,
725 .id_table = smm665_id,
726};
727
728static int __init smm665_init(void)
729{
730 return i2c_add_driver(&smm665_driver);
731}
732
733static void __exit smm665_exit(void)
734{
735 i2c_del_driver(&smm665_driver);
736}
737
738MODULE_AUTHOR("Guenter Roeck");
739MODULE_DESCRIPTION("SMM665 driver");
740MODULE_LICENSE("GPL");
741
742module_init(smm665_init);
743module_exit(smm665_exit);