Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+896
+64
Documentation/devicetree/bindings/i2c/max6697.txt
··· 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 + };
+58
Documentation/hwmon/max6697
··· 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)
+11
drivers/hwmon/Kconfig
··· 854 854 This driver can also be built as a module. If so, the module 855 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 868 config SENSORS_MCP3021 858 869 tristate "Microchip MCP3021 and compatibles" 859 870 depends on I2C
+1
drivers/hwmon/Makefile
··· 99 99 obj-$(CONFIG_SENSORS_MAX6639) += max6639.o 100 100 obj-$(CONFIG_SENSORS_MAX6642) += max6642.o 101 101 obj-$(CONFIG_SENSORS_MAX6650) += max6650.o 102 + obj-$(CONFIG_SENSORS_MAX6697) += max6697.o 102 103 obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o 103 104 obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o 104 105 obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
+726
drivers/hwmon/max6697.c
··· 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");
+36
include/linux/platform_data/max6697.h
··· 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 */