diff options
author | Guenter Roeck <linux@roeck-us.net> | 2012-10-13 02:01:58 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2013-02-06 12:57:56 -0500 |
commit | 5372d2d71c46e5649e5d2edd4514adcd6fe7a085 (patch) | |
tree | a2317c0984ace02ba083f3386ce1ec7a3781b45a | |
parent | 412e29c135c11be6e2e4b22c0691e861b3d946c4 (diff) |
hwmon: Driver for Maxim MAX6697 and compatibles
Add support for MAX6581, MAX6602, MAX6622, MAX6636, MAX6689, MAX6693,
MAX6694, MAX6697, MAX6698, and MAX6699 temperature sensors
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r-- | Documentation/devicetree/bindings/i2c/max6697.txt | 64 | ||||
-rw-r--r-- | Documentation/hwmon/max6697 | 58 | ||||
-rw-r--r-- | drivers/hwmon/Kconfig | 11 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 1 | ||||
-rw-r--r-- | drivers/hwmon/max6697.c | 726 | ||||
-rw-r--r-- | include/linux/platform_data/max6697.h | 36 |
6 files changed, 896 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/i2c/max6697.txt b/Documentation/devicetree/bindings/i2c/max6697.txt new file mode 100644 index 000000000000..5f793998e4a4 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/max6697.txt | |||
@@ -0,0 +1,64 @@ | |||
1 | max6697 properties | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: | ||
5 | Should be one of | ||
6 | maxim,max6581 | ||
7 | maxim,max6602 | ||
8 | maxim,max6622 | ||
9 | maxim,max6636 | ||
10 | maxim,max6689 | ||
11 | maxim,max6693 | ||
12 | maxim,max6694 | ||
13 | maxim,max6697 | ||
14 | maxim,max6698 | ||
15 | maxim,max6699 | ||
16 | - reg: I2C address | ||
17 | |||
18 | Optional properties: | ||
19 | |||
20 | - smbus-timeout-disable | ||
21 | Set to disable SMBus timeout. If not specified, SMBus timeout will be | ||
22 | enabled. | ||
23 | - extended-range-enable | ||
24 | Only valid for MAX6581. Set to enable extended temperature range. | ||
25 | Extended temperature will be disabled if not specified. | ||
26 | - beta-compensation-enable | ||
27 | Only valid for MAX6693 and MX6694. Set to enable beta compensation on | ||
28 | remote temperature channel 1. | ||
29 | Beta compensation will be disabled if not specified. | ||
30 | - alert-mask | ||
31 | Alert bit mask. Alert disabled for bits set. | ||
32 | Select bit 0 for local temperature, bit 1..7 for remote temperatures. | ||
33 | If not specified, alert will be enabled for all channels. | ||
34 | - over-temperature-mask | ||
35 | Over-temperature bit mask. Over-temperature reporting disabled for | ||
36 | bits set. | ||
37 | Select bit 0 for local temperature, bit 1..7 for remote temperatures. | ||
38 | If not specified, over-temperature reporting will be enabled for all | ||
39 | channels. | ||
40 | - resistance-cancellation | ||
41 | Boolean for all chips other than MAX6581. Set to enable resistance | ||
42 | cancellation on remote temperature channel 1. | ||
43 | For MAX6581, resistance cancellation enabled for all channels if | ||
44 | specified as boolean, otherwise as per bit mask specified. | ||
45 | Only supported for remote temperatures (bit 1..7). | ||
46 | If not specified, resistance cancellation will be disabled for all | ||
47 | channels. | ||
48 | - transistor-ideality | ||
49 | For MAX6581 only. Two values; first is bit mask, second is ideality | ||
50 | select value as per MAX6581 data sheet. Select bit 1..7 for remote | ||
51 | channels. | ||
52 | Transistor ideality will be initialized to default (1.008) if not | ||
53 | specified. | ||
54 | |||
55 | Example: | ||
56 | |||
57 | temp-sensor@1a { | ||
58 | compatible = "maxim,max6697"; | ||
59 | reg = <0x1a>; | ||
60 | smbus-timeout-disable; | ||
61 | resistance-cancellation; | ||
62 | alert-mask = <0x72>; | ||
63 | over-temperature-mask = <0x7f>; | ||
64 | }; | ||
diff --git a/Documentation/hwmon/max6697 b/Documentation/hwmon/max6697 new file mode 100644 index 000000000000..6594177ededa --- /dev/null +++ b/Documentation/hwmon/max6697 | |||
@@ -0,0 +1,58 @@ | |||
1 | Kernel driver max6697 | ||
2 | ===================== | ||
3 | |||
4 | Supported chips: | ||
5 | * Maxim MAX6581 | ||
6 | Prefix: 'max6581' | ||
7 | Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6581.pdf | ||
8 | * Maxim MAX6602 | ||
9 | Prefix: 'max6602' | ||
10 | Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6602.pdf | ||
11 | * Maxim MAX6622 | ||
12 | Prefix: 'max6622' | ||
13 | Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6622.pdf | ||
14 | * Maxim MAX6636 | ||
15 | Prefix: 'max6636' | ||
16 | Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6636.pdf | ||
17 | * Maxim MAX6689 | ||
18 | Prefix: 'max6689' | ||
19 | Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6689.pdf | ||
20 | * Maxim MAX6693 | ||
21 | Prefix: 'max6693' | ||
22 | Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6693.pdf | ||
23 | * Maxim MAX6694 | ||
24 | Prefix: 'max6694' | ||
25 | Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6694.pdf | ||
26 | * Maxim MAX6697 | ||
27 | Prefix: 'max6697' | ||
28 | Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6697.pdf | ||
29 | * Maxim MAX6698 | ||
30 | Prefix: 'max6698' | ||
31 | Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6698.pdf | ||
32 | * Maxim MAX6699 | ||
33 | Prefix: 'max6699' | ||
34 | Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6699.pdf | ||
35 | |||
36 | Author: | ||
37 | Guenter Roeck <linux@roeck-us.net> | ||
38 | |||
39 | Description | ||
40 | ----------- | ||
41 | |||
42 | This driver implements support for several MAX6697 compatible temperature sensor | ||
43 | chips. The chips support one local temperature sensor plus four, six, or seven | ||
44 | remote temperature sensors. Remote temperature sensors are diode-connected | ||
45 | thermal transitors, except for MAX6698 which supports three diode-connected | ||
46 | thermal transistors plus three thermistors in addition to the local temperature | ||
47 | sensor. | ||
48 | |||
49 | The driver provides the following sysfs attributes. temp1 is the local (chip) | ||
50 | temperature, temp[2..n] are remote temperatures. The actually supported | ||
51 | per-channel attributes are chip type and channel dependent. | ||
52 | |||
53 | tempX_input RO temperature | ||
54 | tempX_max RW temperature maximum threshold | ||
55 | tempX_max_alarm RO temperature maximum threshold alarm | ||
56 | tempX_crit RW temperature critical threshold | ||
57 | tempX_crit_alarm RO temperature critical threshold alarm | ||
58 | tempX_fault RO temperature diode fault (remote sensors only) | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 32f238f3caea..ef5757265f78 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -854,6 +854,17 @@ config SENSORS_MAX6650 | |||
854 | This driver can also be built as a module. If so, the module | 854 | This driver can also be built as a module. If so, the module |
855 | will be called max6650. | 855 | will be called max6650. |
856 | 856 | ||
857 | config SENSORS_MAX6697 | ||
858 | tristate "Maxim MAX6697 and compatibles" | ||
859 | depends on I2C | ||
860 | help | ||
861 | If you say yes here you get support for MAX6581, MAX6602, MAX6622, | ||
862 | MAX6636, MAX6689, MAX6693, MAX6694, MAX6697, MAX6698, and MAX6699 | ||
863 | temperature sensor chips. | ||
864 | |||
865 | This driver can also be built as a module. If so, the module | ||
866 | will be called max6697. | ||
867 | |||
857 | config SENSORS_MCP3021 | 868 | config SENSORS_MCP3021 |
858 | tristate "Microchip MCP3021 and compatibles" | 869 | tristate "Microchip MCP3021 and compatibles" |
859 | depends on I2C | 870 | depends on I2C |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 5da287443f6c..a37a82c64da2 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -99,6 +99,7 @@ obj-$(CONFIG_SENSORS_MAX197) += max197.o | |||
99 | obj-$(CONFIG_SENSORS_MAX6639) += max6639.o | 99 | obj-$(CONFIG_SENSORS_MAX6639) += max6639.o |
100 | obj-$(CONFIG_SENSORS_MAX6642) += max6642.o | 100 | obj-$(CONFIG_SENSORS_MAX6642) += max6642.o |
101 | obj-$(CONFIG_SENSORS_MAX6650) += max6650.o | 101 | obj-$(CONFIG_SENSORS_MAX6650) += max6650.o |
102 | obj-$(CONFIG_SENSORS_MAX6697) += max6697.o | ||
102 | obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o | 103 | obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o |
103 | obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o | 104 | obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o |
104 | obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o | 105 | obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o |
diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c new file mode 100644 index 000000000000..bf4aa3777fc1 --- /dev/null +++ b/drivers/hwmon/max6697.c | |||
@@ -0,0 +1,726 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Guenter Roeck <linux@roeck-us.net> | ||
3 | * | ||
4 | * based on max1668.c | ||
5 | * Copyright (c) 2011 David George <david.george@ska.ac.za> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/jiffies.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/hwmon.h> | ||
24 | #include <linux/hwmon-sysfs.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/mutex.h> | ||
27 | #include <linux/of.h> | ||
28 | |||
29 | #include <linux/platform_data/max6697.h> | ||
30 | |||
31 | enum chips { max6581, max6602, max6622, max6636, max6689, max6693, max6694, | ||
32 | max6697, max6698, max6699 }; | ||
33 | |||
34 | /* Report local sensor as temp1 */ | ||
35 | |||
36 | static const u8 MAX6697_REG_TEMP[] = { | ||
37 | 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08 }; | ||
38 | static const u8 MAX6697_REG_TEMP_EXT[] = { | ||
39 | 0x57, 0x09, 0x52, 0x53, 0x54, 0x55, 0x56, 0 }; | ||
40 | static const u8 MAX6697_REG_MAX[] = { | ||
41 | 0x17, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x18 }; | ||
42 | static const u8 MAX6697_REG_CRIT[] = { | ||
43 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27 }; | ||
44 | |||
45 | /* | ||
46 | * Map device tree / platform data register bit map to chip bit map. | ||
47 | * Applies to alert register and over-temperature register. | ||
48 | */ | ||
49 | #define MAX6697_MAP_BITS(reg) ((((reg) & 0x7e) >> 1) | \ | ||
50 | (((reg) & 0x01) << 6) | ((reg) & 0x80)) | ||
51 | |||
52 | #define MAX6697_REG_STAT(n) (0x44 + (n)) | ||
53 | |||
54 | #define MAX6697_REG_CONFIG 0x41 | ||
55 | #define MAX6581_CONF_EXTENDED (1 << 1) | ||
56 | #define MAX6693_CONF_BETA (1 << 2) | ||
57 | #define MAX6697_CONF_RESISTANCE (1 << 3) | ||
58 | #define MAX6697_CONF_TIMEOUT (1 << 5) | ||
59 | #define MAX6697_REG_ALERT_MASK 0x42 | ||
60 | #define MAX6697_REG_OVERT_MASK 0x43 | ||
61 | |||
62 | #define MAX6581_REG_RESISTANCE 0x4a | ||
63 | #define MAX6581_REG_IDEALITY 0x4b | ||
64 | #define MAX6581_REG_IDEALITY_SELECT 0x4c | ||
65 | #define MAX6581_REG_OFFSET 0x4d | ||
66 | #define MAX6581_REG_OFFSET_SELECT 0x4e | ||
67 | |||
68 | #define MAX6697_CONV_TIME 156 /* ms per channel, worst case */ | ||
69 | |||
70 | struct max6697_chip_data { | ||
71 | int channels; | ||
72 | u32 have_ext; | ||
73 | u32 have_crit; | ||
74 | u32 have_fault; | ||
75 | u8 valid_conf; | ||
76 | const u8 *alarm_map; | ||
77 | }; | ||
78 | |||
79 | struct max6697_data { | ||
80 | struct device *hwmon_dev; | ||
81 | |||
82 | enum chips type; | ||
83 | const struct max6697_chip_data *chip; | ||
84 | |||
85 | int update_interval; /* in milli-seconds */ | ||
86 | int temp_offset; /* in degrees C */ | ||
87 | |||
88 | struct mutex update_lock; | ||
89 | unsigned long last_updated; /* In jiffies */ | ||
90 | bool valid; /* true if following fields are valid */ | ||
91 | |||
92 | /* 1x local and up to 7x remote */ | ||
93 | u8 temp[8][4]; /* [nr][0]=temp [1]=ext [2]=max [3]=crit */ | ||
94 | #define MAX6697_TEMP_INPUT 0 | ||
95 | #define MAX6697_TEMP_EXT 1 | ||
96 | #define MAX6697_TEMP_MAX 2 | ||
97 | #define MAX6697_TEMP_CRIT 3 | ||
98 | u32 alarms; | ||
99 | }; | ||
100 | |||
101 | /* Diode fault status bits on MAX6581 are right shifted by one bit */ | ||
102 | static const u8 max6581_alarm_map[] = { | ||
103 | 0, 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, | ||
104 | 16, 17, 18, 19, 20, 21, 22, 23 }; | ||
105 | |||
106 | static const struct max6697_chip_data max6697_chip_data[] = { | ||
107 | [max6581] = { | ||
108 | .channels = 8, | ||
109 | .have_crit = 0xff, | ||
110 | .have_ext = 0x7f, | ||
111 | .have_fault = 0xfe, | ||
112 | .valid_conf = MAX6581_CONF_EXTENDED | MAX6697_CONF_TIMEOUT, | ||
113 | .alarm_map = max6581_alarm_map, | ||
114 | }, | ||
115 | [max6602] = { | ||
116 | .channels = 5, | ||
117 | .have_crit = 0x12, | ||
118 | .have_ext = 0x02, | ||
119 | .have_fault = 0x1e, | ||
120 | .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, | ||
121 | }, | ||
122 | [max6622] = { | ||
123 | .channels = 5, | ||
124 | .have_crit = 0x12, | ||
125 | .have_ext = 0x02, | ||
126 | .have_fault = 0x1e, | ||
127 | .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, | ||
128 | }, | ||
129 | [max6636] = { | ||
130 | .channels = 7, | ||
131 | .have_crit = 0x72, | ||
132 | .have_ext = 0x02, | ||
133 | .have_fault = 0x7e, | ||
134 | .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, | ||
135 | }, | ||
136 | [max6689] = { | ||
137 | .channels = 7, | ||
138 | .have_crit = 0x72, | ||
139 | .have_ext = 0x02, | ||
140 | .have_fault = 0x7e, | ||
141 | .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, | ||
142 | }, | ||
143 | [max6693] = { | ||
144 | .channels = 7, | ||
145 | .have_crit = 0x72, | ||
146 | .have_ext = 0x02, | ||
147 | .have_fault = 0x7e, | ||
148 | .valid_conf = MAX6697_CONF_RESISTANCE | MAX6693_CONF_BETA | | ||
149 | MAX6697_CONF_TIMEOUT, | ||
150 | }, | ||
151 | [max6694] = { | ||
152 | .channels = 5, | ||
153 | .have_crit = 0x12, | ||
154 | .have_ext = 0x02, | ||
155 | .have_fault = 0x1e, | ||
156 | .valid_conf = MAX6697_CONF_RESISTANCE | MAX6693_CONF_BETA | | ||
157 | MAX6697_CONF_TIMEOUT, | ||
158 | }, | ||
159 | [max6697] = { | ||
160 | .channels = 7, | ||
161 | .have_crit = 0x72, | ||
162 | .have_ext = 0x02, | ||
163 | .have_fault = 0x7e, | ||
164 | .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, | ||
165 | }, | ||
166 | [max6698] = { | ||
167 | .channels = 7, | ||
168 | .have_crit = 0x72, | ||
169 | .have_ext = 0x02, | ||
170 | .have_fault = 0x0e, | ||
171 | .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, | ||
172 | }, | ||
173 | [max6699] = { | ||
174 | .channels = 5, | ||
175 | .have_crit = 0x12, | ||
176 | .have_ext = 0x02, | ||
177 | .have_fault = 0x1e, | ||
178 | .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, | ||
179 | }, | ||
180 | }; | ||
181 | |||
182 | static struct max6697_data *max6697_update_device(struct device *dev) | ||
183 | { | ||
184 | struct i2c_client *client = to_i2c_client(dev); | ||
185 | struct max6697_data *data = i2c_get_clientdata(client); | ||
186 | struct max6697_data *ret = data; | ||
187 | int val; | ||
188 | int i; | ||
189 | u32 alarms; | ||
190 | |||
191 | mutex_lock(&data->update_lock); | ||
192 | |||
193 | if (data->valid && | ||
194 | !time_after(jiffies, data->last_updated | ||
195 | + msecs_to_jiffies(data->update_interval))) | ||
196 | goto abort; | ||
197 | |||
198 | for (i = 0; i < data->chip->channels; i++) { | ||
199 | if (data->chip->have_ext & (1 << i)) { | ||
200 | val = i2c_smbus_read_byte_data(client, | ||
201 | MAX6697_REG_TEMP_EXT[i]); | ||
202 | if (unlikely(val < 0)) { | ||
203 | ret = ERR_PTR(val); | ||
204 | goto abort; | ||
205 | } | ||
206 | data->temp[i][MAX6697_TEMP_EXT] = val; | ||
207 | } | ||
208 | |||
209 | val = i2c_smbus_read_byte_data(client, MAX6697_REG_TEMP[i]); | ||
210 | if (unlikely(val < 0)) { | ||
211 | ret = ERR_PTR(val); | ||
212 | goto abort; | ||
213 | } | ||
214 | data->temp[i][MAX6697_TEMP_INPUT] = val; | ||
215 | |||
216 | val = i2c_smbus_read_byte_data(client, MAX6697_REG_MAX[i]); | ||
217 | if (unlikely(val < 0)) { | ||
218 | ret = ERR_PTR(val); | ||
219 | goto abort; | ||
220 | } | ||
221 | data->temp[i][MAX6697_TEMP_MAX] = val; | ||
222 | |||
223 | if (data->chip->have_crit & (1 << i)) { | ||
224 | val = i2c_smbus_read_byte_data(client, | ||
225 | MAX6697_REG_CRIT[i]); | ||
226 | if (unlikely(val < 0)) { | ||
227 | ret = ERR_PTR(val); | ||
228 | goto abort; | ||
229 | } | ||
230 | data->temp[i][MAX6697_TEMP_CRIT] = val; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | alarms = 0; | ||
235 | for (i = 0; i < 3; i++) { | ||
236 | val = i2c_smbus_read_byte_data(client, MAX6697_REG_STAT(i)); | ||
237 | if (unlikely(val < 0)) { | ||
238 | ret = ERR_PTR(val); | ||
239 | goto abort; | ||
240 | } | ||
241 | alarms = (alarms << 8) | val; | ||
242 | } | ||
243 | data->alarms = alarms; | ||
244 | data->last_updated = jiffies; | ||
245 | data->valid = true; | ||
246 | abort: | ||
247 | mutex_unlock(&data->update_lock); | ||
248 | |||
249 | return ret; | ||
250 | } | ||
251 | |||
252 | static ssize_t show_temp_input(struct device *dev, | ||
253 | struct device_attribute *devattr, char *buf) | ||
254 | { | ||
255 | int index = to_sensor_dev_attr(devattr)->index; | ||
256 | struct max6697_data *data = max6697_update_device(dev); | ||
257 | int temp; | ||
258 | |||
259 | if (IS_ERR(data)) | ||
260 | return PTR_ERR(data); | ||
261 | |||
262 | temp = (data->temp[index][MAX6697_TEMP_INPUT] - data->temp_offset) << 3; | ||
263 | temp |= data->temp[index][MAX6697_TEMP_EXT] >> 5; | ||
264 | |||
265 | return sprintf(buf, "%d\n", temp * 125); | ||
266 | } | ||
267 | |||
268 | static ssize_t show_temp(struct device *dev, | ||
269 | struct device_attribute *devattr, char *buf) | ||
270 | { | ||
271 | int nr = to_sensor_dev_attr_2(devattr)->nr; | ||
272 | int index = to_sensor_dev_attr_2(devattr)->index; | ||
273 | struct max6697_data *data = max6697_update_device(dev); | ||
274 | int temp; | ||
275 | |||
276 | if (IS_ERR(data)) | ||
277 | return PTR_ERR(data); | ||
278 | |||
279 | temp = data->temp[nr][index]; | ||
280 | temp -= data->temp_offset; | ||
281 | |||
282 | return sprintf(buf, "%d\n", temp * 1000); | ||
283 | } | ||
284 | |||
285 | static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, | ||
286 | char *buf) | ||
287 | { | ||
288 | int index = to_sensor_dev_attr(attr)->index; | ||
289 | struct max6697_data *data = max6697_update_device(dev); | ||
290 | |||
291 | if (IS_ERR(data)) | ||
292 | return PTR_ERR(data); | ||
293 | |||
294 | if (data->chip->alarm_map) | ||
295 | index = data->chip->alarm_map[index]; | ||
296 | |||
297 | return sprintf(buf, "%u\n", (data->alarms >> index) & 0x1); | ||
298 | } | ||
299 | |||
300 | static ssize_t set_temp(struct device *dev, | ||
301 | struct device_attribute *devattr, | ||
302 | const char *buf, size_t count) | ||
303 | { | ||
304 | int nr = to_sensor_dev_attr_2(devattr)->nr; | ||
305 | int index = to_sensor_dev_attr_2(devattr)->index; | ||
306 | struct i2c_client *client = to_i2c_client(dev); | ||
307 | struct max6697_data *data = i2c_get_clientdata(client); | ||
308 | long temp; | ||
309 | int ret; | ||
310 | |||
311 | ret = kstrtol(buf, 10, &temp); | ||
312 | if (ret < 0) | ||
313 | return ret; | ||
314 | |||
315 | mutex_lock(&data->update_lock); | ||
316 | temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset; | ||
317 | temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127); | ||
318 | data->temp[nr][index] = temp; | ||
319 | ret = i2c_smbus_write_byte_data(client, | ||
320 | index == 2 ? MAX6697_REG_MAX[nr] | ||
321 | : MAX6697_REG_CRIT[nr], | ||
322 | temp); | ||
323 | mutex_unlock(&data->update_lock); | ||
324 | |||
325 | return ret < 0 ? ret : count; | ||
326 | } | ||
327 | |||
328 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); | ||
329 | static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
330 | 0, MAX6697_TEMP_MAX); | ||
331 | static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
332 | 0, MAX6697_TEMP_CRIT); | ||
333 | |||
334 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1); | ||
335 | static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
336 | 1, MAX6697_TEMP_MAX); | ||
337 | static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
338 | 1, MAX6697_TEMP_CRIT); | ||
339 | |||
340 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2); | ||
341 | static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
342 | 2, MAX6697_TEMP_MAX); | ||
343 | static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
344 | 2, MAX6697_TEMP_CRIT); | ||
345 | |||
346 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3); | ||
347 | static SENSOR_DEVICE_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
348 | 3, MAX6697_TEMP_MAX); | ||
349 | static SENSOR_DEVICE_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
350 | 3, MAX6697_TEMP_CRIT); | ||
351 | |||
352 | static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4); | ||
353 | static SENSOR_DEVICE_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
354 | 4, MAX6697_TEMP_MAX); | ||
355 | static SENSOR_DEVICE_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
356 | 4, MAX6697_TEMP_CRIT); | ||
357 | |||
358 | static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5); | ||
359 | static SENSOR_DEVICE_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
360 | 5, MAX6697_TEMP_MAX); | ||
361 | static SENSOR_DEVICE_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
362 | 5, MAX6697_TEMP_CRIT); | ||
363 | |||
364 | static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp_input, NULL, 6); | ||
365 | static SENSOR_DEVICE_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
366 | 6, MAX6697_TEMP_MAX); | ||
367 | static SENSOR_DEVICE_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
368 | 6, MAX6697_TEMP_CRIT); | ||
369 | |||
370 | static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp_input, NULL, 7); | ||
371 | static SENSOR_DEVICE_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
372 | 7, MAX6697_TEMP_MAX); | ||
373 | static SENSOR_DEVICE_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
374 | 7, MAX6697_TEMP_CRIT); | ||
375 | |||
376 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 22); | ||
377 | static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 16); | ||
378 | static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 17); | ||
379 | static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 18); | ||
380 | static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL, 19); | ||
381 | static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO, show_alarm, NULL, 20); | ||
382 | static SENSOR_DEVICE_ATTR(temp7_max_alarm, S_IRUGO, show_alarm, NULL, 21); | ||
383 | static SENSOR_DEVICE_ATTR(temp8_max_alarm, S_IRUGO, show_alarm, NULL, 23); | ||
384 | |||
385 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); | ||
386 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8); | ||
387 | static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 9); | ||
388 | static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 10); | ||
389 | static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, show_alarm, NULL, 11); | ||
390 | static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO, show_alarm, NULL, 12); | ||
391 | static SENSOR_DEVICE_ATTR(temp7_crit_alarm, S_IRUGO, show_alarm, NULL, 13); | ||
392 | static SENSOR_DEVICE_ATTR(temp8_crit_alarm, S_IRUGO, show_alarm, NULL, 15); | ||
393 | |||
394 | static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 1); | ||
395 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2); | ||
396 | static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 3); | ||
397 | static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_alarm, NULL, 4); | ||
398 | static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_alarm, NULL, 5); | ||
399 | static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_alarm, NULL, 6); | ||
400 | static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_alarm, NULL, 7); | ||
401 | |||
402 | static struct attribute *max6697_attributes[8][7] = { | ||
403 | { | ||
404 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
405 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
406 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | ||
407 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
408 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | ||
409 | NULL | ||
410 | }, { | ||
411 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
412 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
413 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | ||
414 | &sensor_dev_attr_temp2_crit.dev_attr.attr, | ||
415 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, | ||
416 | &sensor_dev_attr_temp2_fault.dev_attr.attr, | ||
417 | NULL | ||
418 | }, { | ||
419 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
420 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
421 | &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, | ||
422 | &sensor_dev_attr_temp3_crit.dev_attr.attr, | ||
423 | &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, | ||
424 | &sensor_dev_attr_temp3_fault.dev_attr.attr, | ||
425 | NULL | ||
426 | }, { | ||
427 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
428 | &sensor_dev_attr_temp4_max.dev_attr.attr, | ||
429 | &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, | ||
430 | &sensor_dev_attr_temp4_crit.dev_attr.attr, | ||
431 | &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, | ||
432 | &sensor_dev_attr_temp4_fault.dev_attr.attr, | ||
433 | NULL | ||
434 | }, { | ||
435 | &sensor_dev_attr_temp5_input.dev_attr.attr, | ||
436 | &sensor_dev_attr_temp5_max.dev_attr.attr, | ||
437 | &sensor_dev_attr_temp5_max_alarm.dev_attr.attr, | ||
438 | &sensor_dev_attr_temp5_crit.dev_attr.attr, | ||
439 | &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr, | ||
440 | &sensor_dev_attr_temp5_fault.dev_attr.attr, | ||
441 | NULL | ||
442 | }, { | ||
443 | &sensor_dev_attr_temp6_input.dev_attr.attr, | ||
444 | &sensor_dev_attr_temp6_max.dev_attr.attr, | ||
445 | &sensor_dev_attr_temp6_max_alarm.dev_attr.attr, | ||
446 | &sensor_dev_attr_temp6_crit.dev_attr.attr, | ||
447 | &sensor_dev_attr_temp6_crit_alarm.dev_attr.attr, | ||
448 | &sensor_dev_attr_temp6_fault.dev_attr.attr, | ||
449 | NULL | ||
450 | }, { | ||
451 | &sensor_dev_attr_temp7_input.dev_attr.attr, | ||
452 | &sensor_dev_attr_temp7_max.dev_attr.attr, | ||
453 | &sensor_dev_attr_temp7_max_alarm.dev_attr.attr, | ||
454 | &sensor_dev_attr_temp7_crit.dev_attr.attr, | ||
455 | &sensor_dev_attr_temp7_crit_alarm.dev_attr.attr, | ||
456 | &sensor_dev_attr_temp7_fault.dev_attr.attr, | ||
457 | NULL | ||
458 | }, { | ||
459 | &sensor_dev_attr_temp8_input.dev_attr.attr, | ||
460 | &sensor_dev_attr_temp8_max.dev_attr.attr, | ||
461 | &sensor_dev_attr_temp8_max_alarm.dev_attr.attr, | ||
462 | &sensor_dev_attr_temp8_crit.dev_attr.attr, | ||
463 | &sensor_dev_attr_temp8_crit_alarm.dev_attr.attr, | ||
464 | &sensor_dev_attr_temp8_fault.dev_attr.attr, | ||
465 | NULL | ||
466 | } | ||
467 | }; | ||
468 | |||
469 | static const struct attribute_group max6697_group[8] = { | ||
470 | { .attrs = max6697_attributes[0] }, | ||
471 | { .attrs = max6697_attributes[1] }, | ||
472 | { .attrs = max6697_attributes[2] }, | ||
473 | { .attrs = max6697_attributes[3] }, | ||
474 | { .attrs = max6697_attributes[4] }, | ||
475 | { .attrs = max6697_attributes[5] }, | ||
476 | { .attrs = max6697_attributes[6] }, | ||
477 | { .attrs = max6697_attributes[7] }, | ||
478 | }; | ||
479 | |||
480 | static void max6697_get_config_of(struct device_node *node, | ||
481 | struct max6697_platform_data *pdata) | ||
482 | { | ||
483 | int len; | ||
484 | const __be32 *prop; | ||
485 | |||
486 | prop = of_get_property(node, "smbus-timeout-disable", &len); | ||
487 | if (prop) | ||
488 | pdata->smbus_timeout_disable = true; | ||
489 | prop = of_get_property(node, "extended-range-enable", &len); | ||
490 | if (prop) | ||
491 | pdata->extended_range_enable = true; | ||
492 | prop = of_get_property(node, "beta-compensation-enable", &len); | ||
493 | if (prop) | ||
494 | pdata->beta_compensation = true; | ||
495 | prop = of_get_property(node, "alert-mask", &len); | ||
496 | if (prop && len == sizeof(u32)) | ||
497 | pdata->alert_mask = be32_to_cpu(prop[0]); | ||
498 | prop = of_get_property(node, "over-temperature-mask", &len); | ||
499 | if (prop && len == sizeof(u32)) | ||
500 | pdata->over_temperature_mask = be32_to_cpu(prop[0]); | ||
501 | prop = of_get_property(node, "resistance-cancellation", &len); | ||
502 | if (prop) { | ||
503 | if (len == sizeof(u32)) | ||
504 | pdata->resistance_cancellation = be32_to_cpu(prop[0]); | ||
505 | else | ||
506 | pdata->resistance_cancellation = 0xfe; | ||
507 | } | ||
508 | prop = of_get_property(node, "transistor-ideality", &len); | ||
509 | if (prop && len == 2 * sizeof(u32)) { | ||
510 | pdata->ideality_mask = be32_to_cpu(prop[0]); | ||
511 | pdata->ideality_value = be32_to_cpu(prop[1]); | ||
512 | } | ||
513 | } | ||
514 | |||
515 | static int max6697_init_chip(struct i2c_client *client) | ||
516 | { | ||
517 | struct max6697_data *data = i2c_get_clientdata(client); | ||
518 | struct max6697_platform_data *pdata = dev_get_platdata(&client->dev); | ||
519 | struct max6697_platform_data p; | ||
520 | const struct max6697_chip_data *chip = data->chip; | ||
521 | int factor = chip->channels; | ||
522 | int ret, reg; | ||
523 | |||
524 | /* | ||
525 | * Don't touch configuration if neither platform data nor OF | ||
526 | * configuration was specified. If that is the case, use the | ||
527 | * current chip configuration. | ||
528 | */ | ||
529 | if (!pdata && !client->dev.of_node) { | ||
530 | reg = i2c_smbus_read_byte_data(client, MAX6697_REG_CONFIG); | ||
531 | if (reg < 0) | ||
532 | return reg; | ||
533 | if (data->type == max6581) { | ||
534 | if (reg & MAX6581_CONF_EXTENDED) | ||
535 | data->temp_offset = 64; | ||
536 | reg = i2c_smbus_read_byte_data(client, | ||
537 | MAX6581_REG_RESISTANCE); | ||
538 | if (reg < 0) | ||
539 | return reg; | ||
540 | factor += hweight8(reg); | ||
541 | } else { | ||
542 | if (reg & MAX6697_CONF_RESISTANCE) | ||
543 | factor++; | ||
544 | } | ||
545 | goto done; | ||
546 | } | ||
547 | |||
548 | if (client->dev.of_node) { | ||
549 | memset(&p, 0, sizeof(p)); | ||
550 | max6697_get_config_of(client->dev.of_node, &p); | ||
551 | pdata = &p; | ||
552 | } | ||
553 | |||
554 | reg = 0; | ||
555 | if (pdata->smbus_timeout_disable && | ||
556 | (chip->valid_conf & MAX6697_CONF_TIMEOUT)) { | ||
557 | reg |= MAX6697_CONF_TIMEOUT; | ||
558 | } | ||
559 | if (pdata->extended_range_enable && | ||
560 | (chip->valid_conf & MAX6581_CONF_EXTENDED)) { | ||
561 | reg |= MAX6581_CONF_EXTENDED; | ||
562 | data->temp_offset = 64; | ||
563 | } | ||
564 | if (pdata->resistance_cancellation && | ||
565 | (chip->valid_conf & MAX6697_CONF_RESISTANCE)) { | ||
566 | reg |= MAX6697_CONF_RESISTANCE; | ||
567 | factor++; | ||
568 | } | ||
569 | if (pdata->beta_compensation && | ||
570 | (chip->valid_conf & MAX6693_CONF_BETA)) { | ||
571 | reg |= MAX6693_CONF_BETA; | ||
572 | } | ||
573 | |||
574 | ret = i2c_smbus_write_byte_data(client, MAX6697_REG_CONFIG, reg); | ||
575 | if (ret < 0) | ||
576 | return ret; | ||
577 | |||
578 | ret = i2c_smbus_write_byte_data(client, MAX6697_REG_ALERT_MASK, | ||
579 | MAX6697_MAP_BITS(pdata->alert_mask)); | ||
580 | if (ret < 0) | ||
581 | return ret; | ||
582 | |||
583 | ret = i2c_smbus_write_byte_data(client, MAX6697_REG_OVERT_MASK, | ||
584 | MAX6697_MAP_BITS(pdata->over_temperature_mask)); | ||
585 | if (ret < 0) | ||
586 | return ret; | ||
587 | |||
588 | if (data->type == max6581) { | ||
589 | factor += hweight8(pdata->resistance_cancellation >> 1); | ||
590 | ret = i2c_smbus_write_byte_data(client, MAX6581_REG_RESISTANCE, | ||
591 | pdata->resistance_cancellation >> 1); | ||
592 | if (ret < 0) | ||
593 | return ret; | ||
594 | ret = i2c_smbus_write_byte_data(client, MAX6581_REG_IDEALITY, | ||
595 | pdata->ideality_mask >> 1); | ||
596 | if (ret < 0) | ||
597 | return ret; | ||
598 | ret = i2c_smbus_write_byte_data(client, | ||
599 | MAX6581_REG_IDEALITY_SELECT, | ||
600 | pdata->ideality_value); | ||
601 | if (ret < 0) | ||
602 | return ret; | ||
603 | } | ||
604 | done: | ||
605 | data->update_interval = factor * MAX6697_CONV_TIME; | ||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | static void max6697_remove_files(struct i2c_client *client) | ||
610 | { | ||
611 | int i; | ||
612 | |||
613 | for (i = 0; i < ARRAY_SIZE(max6697_group); i++) | ||
614 | sysfs_remove_group(&client->dev.kobj, &max6697_group[i]); | ||
615 | } | ||
616 | |||
617 | static int max6697_probe(struct i2c_client *client, | ||
618 | const struct i2c_device_id *id) | ||
619 | { | ||
620 | struct i2c_adapter *adapter = client->adapter; | ||
621 | struct device *dev = &client->dev; | ||
622 | struct max6697_data *data; | ||
623 | int i, err; | ||
624 | |||
625 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
626 | return -ENODEV; | ||
627 | |||
628 | data = devm_kzalloc(dev, sizeof(struct max6697_data), GFP_KERNEL); | ||
629 | if (!data) | ||
630 | return -ENOMEM; | ||
631 | |||
632 | data->type = id->driver_data; | ||
633 | data->chip = &max6697_chip_data[data->type]; | ||
634 | |||
635 | i2c_set_clientdata(client, data); | ||
636 | mutex_init(&data->update_lock); | ||
637 | |||
638 | err = max6697_init_chip(client); | ||
639 | if (err) | ||
640 | return err; | ||
641 | |||
642 | for (i = 0; i < data->chip->channels; i++) { | ||
643 | err = sysfs_create_file(&dev->kobj, | ||
644 | max6697_attributes[i][0]); | ||
645 | if (err) | ||
646 | goto error; | ||
647 | err = sysfs_create_file(&dev->kobj, | ||
648 | max6697_attributes[i][1]); | ||
649 | if (err) | ||
650 | goto error; | ||
651 | err = sysfs_create_file(&dev->kobj, | ||
652 | max6697_attributes[i][2]); | ||
653 | if (err) | ||
654 | goto error; | ||
655 | |||
656 | if (data->chip->have_crit & (1 << i)) { | ||
657 | err = sysfs_create_file(&dev->kobj, | ||
658 | max6697_attributes[i][3]); | ||
659 | if (err) | ||
660 | goto error; | ||
661 | err = sysfs_create_file(&dev->kobj, | ||
662 | max6697_attributes[i][4]); | ||
663 | if (err) | ||
664 | goto error; | ||
665 | } | ||
666 | if (data->chip->have_fault & (1 << i)) { | ||
667 | err = sysfs_create_file(&dev->kobj, | ||
668 | max6697_attributes[i][5]); | ||
669 | if (err) | ||
670 | goto error; | ||
671 | } | ||
672 | } | ||
673 | |||
674 | data->hwmon_dev = hwmon_device_register(dev); | ||
675 | if (IS_ERR(data->hwmon_dev)) { | ||
676 | err = PTR_ERR(data->hwmon_dev); | ||
677 | goto error; | ||
678 | } | ||
679 | |||
680 | return 0; | ||
681 | |||
682 | error: | ||
683 | max6697_remove_files(client); | ||
684 | return err; | ||
685 | } | ||
686 | |||
687 | static int max6697_remove(struct i2c_client *client) | ||
688 | { | ||
689 | struct max6697_data *data = i2c_get_clientdata(client); | ||
690 | |||
691 | hwmon_device_unregister(data->hwmon_dev); | ||
692 | max6697_remove_files(client); | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static const struct i2c_device_id max6697_id[] = { | ||
698 | { "max6581", max6581 }, | ||
699 | { "max6602", max6602 }, | ||
700 | { "max6622", max6622 }, | ||
701 | { "max6636", max6636 }, | ||
702 | { "max6689", max6689 }, | ||
703 | { "max6693", max6693 }, | ||
704 | { "max6694", max6694 }, | ||
705 | { "max6697", max6697 }, | ||
706 | { "max6698", max6698 }, | ||
707 | { "max6699", max6699 }, | ||
708 | { } | ||
709 | }; | ||
710 | MODULE_DEVICE_TABLE(i2c, max6697_id); | ||
711 | |||
712 | static struct i2c_driver max6697_driver = { | ||
713 | .class = I2C_CLASS_HWMON, | ||
714 | .driver = { | ||
715 | .name = "max6697", | ||
716 | }, | ||
717 | .probe = max6697_probe, | ||
718 | .remove = max6697_remove, | ||
719 | .id_table = max6697_id, | ||
720 | }; | ||
721 | |||
722 | module_i2c_driver(max6697_driver); | ||
723 | |||
724 | MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>"); | ||
725 | MODULE_DESCRIPTION("MAX6697 temperature sensor driver"); | ||
726 | MODULE_LICENSE("GPL"); | ||
diff --git a/include/linux/platform_data/max6697.h b/include/linux/platform_data/max6697.h new file mode 100644 index 000000000000..ed9d3b3daf02 --- /dev/null +++ b/include/linux/platform_data/max6697.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * max6697.h | ||
3 | * Copyright (c) 2012 Guenter Roeck <linux@roeck-us.net> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #ifndef MAX6697_H | ||
11 | #define MAX6697_H | ||
12 | |||
13 | #include <linux/types.h> | ||
14 | |||
15 | /* | ||
16 | * For all bit masks: | ||
17 | * bit 0: local temperature | ||
18 | * bit 1..7: remote temperatures | ||
19 | */ | ||
20 | struct max6697_platform_data { | ||
21 | bool smbus_timeout_disable; /* set to disable SMBus timeouts */ | ||
22 | bool extended_range_enable; /* set to enable extended temp range */ | ||
23 | bool beta_compensation; /* set to enable beta compensation */ | ||
24 | u8 alert_mask; /* set bit to 1 to disable alert */ | ||
25 | u8 over_temperature_mask; /* set bit to 1 to disable */ | ||
26 | u8 resistance_cancellation; /* set bit to 0 to disable | ||
27 | * bit mask for MAX6581, | ||
28 | * boolean for other chips | ||
29 | */ | ||
30 | u8 ideality_mask; /* set bit to 0 to disable */ | ||
31 | u8 ideality_value; /* transistor ideality as per | ||
32 | * MAX6581 datasheet | ||
33 | */ | ||
34 | }; | ||
35 | |||
36 | #endif /* MAX6697_H */ | ||