Blame view
drivers/hwmon/adm1031.c
31.8 KB
74ba9207e
|
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4c
|
2 |
/* |
fbb6670d9
|
3 4 5 6 7 |
* adm1031.c - Part of lm_sensors, Linux kernel modules for hardware * monitoring * Based on lm75.c and lm85.c * Supports adm1030 / adm1031 * Copyright (C) 2004 Alexandre d'Alton <alex@alexdalton.org> |
7c81c60f3
|
8 |
* Reworked by Jean Delvare <jdelvare@suse.de> |
fbb6670d9
|
9 |
*/ |
1da177e4c
|
10 11 12 13 14 15 |
#include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/jiffies.h> #include <linux/i2c.h> |
943b0830c
|
16 |
#include <linux/hwmon.h> |
c801082d7
|
17 |
#include <linux/hwmon-sysfs.h> |
943b0830c
|
18 |
#include <linux/err.h> |
9a61bf630
|
19 |
#include <linux/mutex.h> |
1da177e4c
|
20 21 22 |
/* Following macros takes channel parameter starting from 0 to 2 */ #define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr)) |
6d6006b8d
|
23 |
#define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr)) |
1da177e4c
|
24 25 |
#define ADM1031_REG_PWM (0x22) #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) |
87c33daad
|
26 |
#define ADM1031_REG_FAN_FILTER (0x23) |
1da177e4c
|
27 |
|
49dc9efed
|
28 |
#define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr)) |
6d6006b8d
|
29 30 31 |
#define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) #define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4 * (nr)) #define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4 * (nr)) |
1da177e4c
|
32 |
|
6d6006b8d
|
33 |
#define ADM1031_REG_TEMP(nr) (0x0a + (nr)) |
1da177e4c
|
34 35 36 |
#define ADM1031_REG_AUTO_TEMP(nr) (0x24 + (nr)) #define ADM1031_REG_STATUS(nr) (0x2 + (nr)) |
6d6006b8d
|
37 38 39 |
#define ADM1031_REG_CONF1 0x00 #define ADM1031_REG_CONF2 0x01 #define ADM1031_REG_EXT_TEMP 0x06 |
1da177e4c
|
40 41 42 43 44 45 46 47 48 49 |
#define ADM1031_CONF1_MONITOR_ENABLE 0x01 /* Monitoring enable */ #define ADM1031_CONF1_PWM_INVERT 0x08 /* PWM Invert */ #define ADM1031_CONF1_AUTO_MODE 0x80 /* Auto FAN */ #define ADM1031_CONF2_PWM1_ENABLE 0x01 #define ADM1031_CONF2_PWM2_ENABLE 0x02 #define ADM1031_CONF2_TACH1_ENABLE 0x04 #define ADM1031_CONF2_TACH2_ENABLE 0x08 #define ADM1031_CONF2_TEMP_ENABLE(chan) (0x10 << (chan)) |
87c33daad
|
50 51 |
#define ADM1031_UPDATE_RATE_MASK 0x1c #define ADM1031_UPDATE_RATE_SHIFT 2 |
1da177e4c
|
52 |
/* Addresses to scan */ |
25e9c86d5
|
53 |
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
1da177e4c
|
54 |
|
e5e9f44c2
|
55 |
enum chips { adm1030, adm1031 }; |
1da177e4c
|
56 57 58 59 60 |
typedef u8 auto_chan_table_t[8][2]; /* Each client has this additional data */ struct adm1031_data { |
b060f3c4a
|
61 62 |
struct i2c_client *client; const struct attribute_group *groups[3]; |
9a61bf630
|
63 |
struct mutex update_lock; |
1da177e4c
|
64 65 66 |
int chip_type; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ |
a51b9944a
|
67 |
unsigned int update_interval; /* In milliseconds */ |
fbb6670d9
|
68 69 |
/* * The chan_select_table contains the possible configurations for |
1da177e4c
|
70 71 |
* auto fan control. */ |
6d6006b8d
|
72 |
const auto_chan_table_t *chan_select_table; |
1da177e4c
|
73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
u16 alarm; u8 conf1; u8 conf2; u8 fan[2]; u8 fan_div[2]; u8 fan_min[2]; u8 pwm[2]; u8 old_pwm[2]; s8 temp[3]; u8 ext_temp[3]; u8 auto_temp[3]; u8 auto_temp_min[3]; u8 auto_temp_off[3]; u8 auto_temp_max[3]; |
49dc9efed
|
87 |
s8 temp_offset[3]; |
1da177e4c
|
88 89 90 91 |
s8 temp_min[3]; s8 temp_max[3]; s8 temp_crit[3]; }; |
1da177e4c
|
92 93 94 95 96 97 98 99 100 101 |
static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) { return i2c_smbus_read_byte_data(client, reg); } static inline int adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value) { return i2c_smbus_write_byte_data(client, reg, value); } |
278ee1c84
|
102 103 |
static struct adm1031_data *adm1031_update_device(struct device *dev) { |
b060f3c4a
|
104 105 |
struct adm1031_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
278ee1c84
|
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
unsigned long next_update; int chan; mutex_lock(&data->update_lock); next_update = data->last_updated + msecs_to_jiffies(data->update_interval); if (time_after(jiffies, next_update) || !data->valid) { dev_dbg(&client->dev, "Starting adm1031 update "); for (chan = 0; chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) { u8 oldh, newh; oldh = adm1031_read_value(client, ADM1031_REG_TEMP(chan)); data->ext_temp[chan] = adm1031_read_value(client, ADM1031_REG_EXT_TEMP); newh = adm1031_read_value(client, ADM1031_REG_TEMP(chan)); if (newh != oldh) { data->ext_temp[chan] = adm1031_read_value(client, ADM1031_REG_EXT_TEMP); #ifdef DEBUG oldh = adm1031_read_value(client, ADM1031_REG_TEMP(chan)); /* oldh is actually newer */ if (newh != oldh) dev_warn(&client->dev, "Remote temperature may be wrong. "); #endif } data->temp[chan] = newh; data->temp_offset[chan] = adm1031_read_value(client, ADM1031_REG_TEMP_OFFSET(chan)); data->temp_min[chan] = adm1031_read_value(client, ADM1031_REG_TEMP_MIN(chan)); data->temp_max[chan] = adm1031_read_value(client, ADM1031_REG_TEMP_MAX(chan)); data->temp_crit[chan] = adm1031_read_value(client, ADM1031_REG_TEMP_CRIT(chan)); data->auto_temp[chan] = adm1031_read_value(client, ADM1031_REG_AUTO_TEMP(chan)); } data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1); data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2); data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0)) | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8); if (data->chip_type == adm1030) data->alarm &= 0xc0ff; for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2); chan++) { data->fan_div[chan] = adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan)); data->fan_min[chan] = adm1031_read_value(client, ADM1031_REG_FAN_MIN(chan)); data->fan[chan] = adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan)); data->pwm[chan] = (adm1031_read_value(client, ADM1031_REG_PWM) >> (4 * chan)) & 0x0f; } data->last_updated = jiffies; data->valid = 1; } mutex_unlock(&data->update_lock); return data; } |
1da177e4c
|
194 195 196 197 198 199 200 |
#define TEMP_TO_REG(val) (((val) < 0 ? ((val - 500) / 1000) : \ ((val + 500) / 1000))) #define TEMP_FROM_REG(val) ((val) * 1000) #define TEMP_FROM_REG_EXT(val, ext) (TEMP_FROM_REG(val) + (ext) * 125) |
49dc9efed
|
201 202 203 |
#define TEMP_OFFSET_TO_REG(val) (TEMP_TO_REG(val) & 0x8f) #define TEMP_OFFSET_FROM_REG(val) TEMP_FROM_REG((val) < 0 ? \ (val) | 0x70 : (val)) |
1c720093f
|
204 205 |
#define FAN_FROM_REG(reg, div) ((reg) ? \ (11250 * 60) / ((reg) * (div)) : 0) |
1da177e4c
|
206 207 208 209 |
static int FAN_TO_REG(int reg, int div) { int tmp; |
2a844c148
|
210 |
tmp = FAN_FROM_REG(clamp_val(reg, 0, 65535), div); |
1da177e4c
|
211 212 213 214 |
return tmp > 255 ? 255 : tmp; } #define FAN_DIV_FROM_REG(reg) (1<<(((reg)&0xc0)>>6)) |
2a844c148
|
215 |
#define PWM_TO_REG(val) (clamp_val((val), 0, 255) >> 4) |
1da177e4c
|
216 217 218 219 220 221 222 |
#define PWM_FROM_REG(val) ((val) << 4) #define FAN_CHAN_FROM_REG(reg) (((reg) >> 5) & 7) #define FAN_CHAN_TO_REG(val, reg) \ (((reg) & 0x1F) | (((val) << 5) & 0xe0)) #define AUTO_TEMP_MIN_TO_REG(val, reg) \ |
1c720093f
|
223 224 |
((((val) / 500) & 0xf8) | ((reg) & 0x7)) #define AUTO_TEMP_RANGE_FROM_REG(reg) (5000 * (1 << ((reg) & 0x7))) |
1da177e4c
|
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
#define AUTO_TEMP_MIN_FROM_REG(reg) (1000 * ((((reg) >> 3) & 0x1f) << 2)) #define AUTO_TEMP_MIN_FROM_REG_DEG(reg) ((((reg) >> 3) & 0x1f) << 2) #define AUTO_TEMP_OFF_FROM_REG(reg) \ (AUTO_TEMP_MIN_FROM_REG(reg) - 5000) #define AUTO_TEMP_MAX_FROM_REG(reg) \ (AUTO_TEMP_RANGE_FROM_REG(reg) + \ AUTO_TEMP_MIN_FROM_REG(reg)) static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm) { int ret; int range = val - AUTO_TEMP_MIN_FROM_REG(reg); range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm); ret = ((reg & 0xf8) | (range < 10000 ? 0 : range < 20000 ? 1 : range < 40000 ? 2 : range < 80000 ? 3 : 4)); return ret; } /* FAN auto control */ #define GET_FAN_AUTO_BITFIELD(data, idx) \ |
1c720093f
|
251 |
(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx % 2] |
1da177e4c
|
252 |
|
fbb6670d9
|
253 254 |
/* * The tables below contains the possible values for the auto fan |
1da177e4c
|
255 256 257 258 |
* control bitfields. the index in the table is the register value. * MSb is the auto fan control enable bit, so the four first entries * in the table disables auto fan control when both bitfields are zero. */ |
6d6006b8d
|
259 260 261 262 263 264 |
static const auto_chan_table_t auto_channel_select_table_adm1031 = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 2 /* 0b010 */ , 4 /* 0b100 */ }, { 2 /* 0b010 */ , 2 /* 0b010 */ }, { 4 /* 0b100 */ , 4 /* 0b100 */ }, { 7 /* 0b111 */ , 7 /* 0b111 */ }, |
1da177e4c
|
265 |
}; |
6d6006b8d
|
266 267 268 269 270 271 |
static const auto_chan_table_t auto_channel_select_table_adm1030 = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 2 /* 0b10 */ , 0 }, { 0xff /* invalid */ , 0 }, { 0xff /* invalid */ , 0 }, { 3 /* 0b11 */ , 0 }, |
1da177e4c
|
272 |
}; |
fbb6670d9
|
273 274 |
/* * That function checks if a bitfield is valid and returns the other bitfield |
1da177e4c
|
275 276 277 |
* nearest match if no exact match where found. */ static int |
ce15a81da
|
278 |
get_fan_auto_nearest(struct adm1031_data *data, int chan, u8 val, u8 reg) |
1da177e4c
|
279 280 281 282 283 |
{ int i; int first_match = -1, exact_match = -1; u8 other_reg_val = (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1]; |
ce15a81da
|
284 |
if (val == 0) |
1da177e4c
|
285 |
return 0; |
1da177e4c
|
286 287 288 289 290 291 292 293 294 295 |
for (i = 0; i < 8; i++) { if ((val == (*data->chan_select_table)[i][chan]) && ((*data->chan_select_table)[i][chan ? 0 : 1] == other_reg_val)) { /* We found an exact match */ exact_match = i; break; } else if (val == (*data->chan_select_table)[i][chan] && first_match == -1) { |
fbb6670d9
|
296 297 |
/* * Save the first match in case of an exact match has |
6d6006b8d
|
298 |
* not been found |
1da177e4c
|
299 300 301 302 |
*/ first_match = i; } } |
1c720093f
|
303 |
if (exact_match >= 0) |
ce15a81da
|
304 |
return exact_match; |
1c720093f
|
305 |
else if (first_match >= 0) |
ce15a81da
|
306 |
return first_match; |
1c720093f
|
307 |
|
ce15a81da
|
308 |
return -EINVAL; |
1da177e4c
|
309 |
} |
8e757e15a
|
310 |
static ssize_t fan_auto_channel_show(struct device *dev, |
c801082d7
|
311 |
struct device_attribute *attr, char *buf) |
1da177e4c
|
312 |
{ |
c801082d7
|
313 |
int nr = to_sensor_dev_attr(attr)->index; |
1da177e4c
|
314 315 316 317 318 319 |
struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d ", GET_FAN_AUTO_BITFIELD(data, nr)); } static ssize_t |
8e757e15a
|
320 321 |
fan_auto_channel_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4c
|
322 |
{ |
b060f3c4a
|
323 324 |
struct adm1031_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
c801082d7
|
325 |
int nr = to_sensor_dev_attr(attr)->index; |
1c720093f
|
326 |
long val; |
1da177e4c
|
327 328 329 |
u8 reg; int ret; u8 old_fan_mode; |
1c720093f
|
330 331 332 |
ret = kstrtol(buf, 10, &val); if (ret) return ret; |
1da177e4c
|
333 |
old_fan_mode = data->conf1; |
9a61bf630
|
334 |
mutex_lock(&data->update_lock); |
6d6006b8d
|
335 |
|
ce15a81da
|
336 337 |
ret = get_fan_auto_nearest(data, nr, val, data->conf1); if (ret < 0) { |
9a61bf630
|
338 |
mutex_unlock(&data->update_lock); |
1da177e4c
|
339 340 |
return ret; } |
ce15a81da
|
341 |
reg = ret; |
6d6006b8d
|
342 343 |
data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^ |
1da177e4c
|
344 |
(old_fan_mode & ADM1031_CONF1_AUTO_MODE)) { |
1c720093f
|
345 |
if (data->conf1 & ADM1031_CONF1_AUTO_MODE) { |
fbb6670d9
|
346 347 |
/* * Switch to Auto Fan Mode |
6d6006b8d
|
348 |
* Save PWM registers |
fbb6670d9
|
349 350 |
* Set PWM registers to 33% Both */ |
1da177e4c
|
351 352 353 354 355 356 357 358 |
data->old_pwm[0] = data->pwm[0]; data->old_pwm[1] = data->pwm[1]; adm1031_write_value(client, ADM1031_REG_PWM, 0x55); } else { /* Switch to Manual Mode */ data->pwm[0] = data->old_pwm[0]; data->pwm[1] = data->old_pwm[1]; /* Restore PWM registers */ |
6d6006b8d
|
359 |
adm1031_write_value(client, ADM1031_REG_PWM, |
1da177e4c
|
360 361 362 363 364 |
data->pwm[0] | (data->pwm[1] << 4)); } } data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1); |
9a61bf630
|
365 |
mutex_unlock(&data->update_lock); |
1da177e4c
|
366 367 |
return count; } |
8e757e15a
|
368 369 |
static SENSOR_DEVICE_ATTR_RW(auto_fan1_channel, fan_auto_channel, 0); static SENSOR_DEVICE_ATTR_RW(auto_fan2_channel, fan_auto_channel, 1); |
1da177e4c
|
370 371 |
/* Auto Temps */ |
8e757e15a
|
372 |
static ssize_t auto_temp_off_show(struct device *dev, |
c801082d7
|
373 |
struct device_attribute *attr, char *buf) |
1da177e4c
|
374 |
{ |
c801082d7
|
375 |
int nr = to_sensor_dev_attr(attr)->index; |
1da177e4c
|
376 |
struct adm1031_data *data = adm1031_update_device(dev); |
6d6006b8d
|
377 378 |
return sprintf(buf, "%d ", |
1da177e4c
|
379 380 |
AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr])); } |
8e757e15a
|
381 |
static ssize_t auto_temp_min_show(struct device *dev, |
c801082d7
|
382 |
struct device_attribute *attr, char *buf) |
1da177e4c
|
383 |
{ |
c801082d7
|
384 |
int nr = to_sensor_dev_attr(attr)->index; |
1da177e4c
|
385 386 387 388 389 390 |
struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d ", AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr])); } static ssize_t |
8e757e15a
|
391 392 |
auto_temp_min_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4c
|
393 |
{ |
b060f3c4a
|
394 395 |
struct adm1031_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
c801082d7
|
396 |
int nr = to_sensor_dev_attr(attr)->index; |
1c720093f
|
397 398 399 400 401 402 |
long val; int ret; ret = kstrtol(buf, 10, &val); if (ret) return ret; |
1da177e4c
|
403 |
|
145e74a4e
|
404 |
val = clamp_val(val, 0, 127000); |
9a61bf630
|
405 |
mutex_lock(&data->update_lock); |
1da177e4c
|
406 407 408 |
data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]); adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), data->auto_temp[nr]); |
9a61bf630
|
409 |
mutex_unlock(&data->update_lock); |
1da177e4c
|
410 411 |
return count; } |
8e757e15a
|
412 |
static ssize_t auto_temp_max_show(struct device *dev, |
c801082d7
|
413 |
struct device_attribute *attr, char *buf) |
1da177e4c
|
414 |
{ |
c801082d7
|
415 |
int nr = to_sensor_dev_attr(attr)->index; |
1da177e4c
|
416 417 418 419 420 421 |
struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d ", AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr])); } static ssize_t |
8e757e15a
|
422 423 |
auto_temp_max_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4c
|
424 |
{ |
b060f3c4a
|
425 426 |
struct adm1031_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
c801082d7
|
427 |
int nr = to_sensor_dev_attr(attr)->index; |
1c720093f
|
428 429 430 431 432 433 |
long val; int ret; ret = kstrtol(buf, 10, &val); if (ret) return ret; |
1da177e4c
|
434 |
|
145e74a4e
|
435 |
val = clamp_val(val, 0, 127000); |
9a61bf630
|
436 |
mutex_lock(&data->update_lock); |
1c720093f
|
437 438 |
data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]); |
1da177e4c
|
439 440 |
adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), data->temp_max[nr]); |
9a61bf630
|
441 |
mutex_unlock(&data->update_lock); |
1da177e4c
|
442 443 |
return count; } |
8e757e15a
|
444 445 446 447 448 449 450 451 452 |
static SENSOR_DEVICE_ATTR_RO(auto_temp1_off, auto_temp_off, 0); static SENSOR_DEVICE_ATTR_RW(auto_temp1_min, auto_temp_min, 0); static SENSOR_DEVICE_ATTR_RW(auto_temp1_max, auto_temp_max, 0); static SENSOR_DEVICE_ATTR_RO(auto_temp2_off, auto_temp_off, 1); static SENSOR_DEVICE_ATTR_RW(auto_temp2_min, auto_temp_min, 1); static SENSOR_DEVICE_ATTR_RW(auto_temp2_max, auto_temp_max, 1); static SENSOR_DEVICE_ATTR_RO(auto_temp3_off, auto_temp_off, 2); static SENSOR_DEVICE_ATTR_RW(auto_temp3_min, auto_temp_min, 2); static SENSOR_DEVICE_ATTR_RW(auto_temp3_max, auto_temp_max, 2); |
1da177e4c
|
453 454 |
/* pwm */ |
8e757e15a
|
455 456 |
static ssize_t pwm_show(struct device *dev, struct device_attribute *attr, char *buf) |
1da177e4c
|
457 |
{ |
c801082d7
|
458 |
int nr = to_sensor_dev_attr(attr)->index; |
1da177e4c
|
459 460 461 462 |
struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d ", PWM_FROM_REG(data->pwm[nr])); } |
8e757e15a
|
463 464 |
static ssize_t pwm_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4c
|
465 |
{ |
b060f3c4a
|
466 467 |
struct adm1031_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
c801082d7
|
468 |
int nr = to_sensor_dev_attr(attr)->index; |
1c720093f
|
469 470 471 472 473 474 |
long val; int ret, reg; ret = kstrtol(buf, 10, &val); if (ret) return ret; |
1da177e4c
|
475 |
|
9a61bf630
|
476 |
mutex_lock(&data->update_lock); |
6d6006b8d
|
477 |
if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && |
1da177e4c
|
478 479 |
(((val>>4) & 0xf) != 5)) { /* In automatic mode, the only PWM accepted is 33% */ |
9a61bf630
|
480 |
mutex_unlock(&data->update_lock); |
1da177e4c
|
481 482 483 484 485 486 487 |
return -EINVAL; } data->pwm[nr] = PWM_TO_REG(val); reg = adm1031_read_value(client, ADM1031_REG_PWM); adm1031_write_value(client, ADM1031_REG_PWM, nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf) : (data->pwm[nr] & 0xf) | (reg & 0xf0)); |
9a61bf630
|
488 |
mutex_unlock(&data->update_lock); |
1da177e4c
|
489 490 |
return count; } |
8e757e15a
|
491 492 493 494 |
static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0); static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1); static SENSOR_DEVICE_ATTR_RW(auto_fan1_min_pwm, pwm, 0); static SENSOR_DEVICE_ATTR_RW(auto_fan2_min_pwm, pwm, 1); |
1da177e4c
|
495 496 497 498 499 |
/* Fans */ /* * That function checks the cases where the fan reading is not |
44bbe87e9
|
500 |
* relevant. It is used to provide 0 as fan reading when the fan is |
1da177e4c
|
501 502 503 504 505 506 507 508 |
* not supposed to run */ static int trust_fan_readings(struct adm1031_data *data, int chan) { int res = 0; if (data->conf1 & ADM1031_CONF1_AUTO_MODE) { switch (data->conf1 & 0x60) { |
1c720093f
|
509 510 511 512 513 |
case 0x00: /* * remote temp1 controls fan1, * remote temp2 controls fan2 */ |
1da177e4c
|
514 |
res = data->temp[chan+1] >= |
1c720093f
|
515 |
AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]); |
1da177e4c
|
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 |
break; case 0x20: /* remote temp1 controls both fans */ res = data->temp[1] >= AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]); break; case 0x40: /* remote temp2 controls both fans */ res = data->temp[2] >= AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]); break; case 0x60: /* max controls both fans */ res = data->temp[0] >= AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0]) || data->temp[1] >= AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]) |
6d6006b8d
|
533 |
|| (data->chip_type == adm1031 |
1da177e4c
|
534 535 536 537 538 539 540 541 542 |
&& data->temp[2] >= AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2])); break; } } else { res = data->pwm[chan] > 0; } return res; } |
8e757e15a
|
543 544 |
static ssize_t fan_show(struct device *dev, struct device_attribute *attr, char *buf) |
1da177e4c
|
545 |
{ |
c801082d7
|
546 |
int nr = to_sensor_dev_attr(attr)->index; |
1da177e4c
|
547 548 549 550 551 552 553 554 |
struct adm1031_data *data = adm1031_update_device(dev); int value; value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr], FAN_DIV_FROM_REG(data->fan_div[nr])) : 0; return sprintf(buf, "%d ", value); } |
8e757e15a
|
555 556 |
static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr, char *buf) |
1da177e4c
|
557 |
{ |
c801082d7
|
558 |
int nr = to_sensor_dev_attr(attr)->index; |
1da177e4c
|
559 560 561 562 |
struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d ", FAN_DIV_FROM_REG(data->fan_div[nr])); } |
8e757e15a
|
563 564 |
static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr, char *buf) |
1da177e4c
|
565 |
{ |
c801082d7
|
566 |
int nr = to_sensor_dev_attr(attr)->index; |
1da177e4c
|
567 568 569 570 571 572 |
struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d ", FAN_FROM_REG(data->fan_min[nr], FAN_DIV_FROM_REG(data->fan_div[nr]))); } |
8e757e15a
|
573 574 575 |
static ssize_t fan_min_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4c
|
576 |
{ |
b060f3c4a
|
577 578 |
struct adm1031_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
c801082d7
|
579 |
int nr = to_sensor_dev_attr(attr)->index; |
1c720093f
|
580 581 582 583 584 585 |
long val; int ret; ret = kstrtol(buf, 10, &val); if (ret) return ret; |
1da177e4c
|
586 |
|
9a61bf630
|
587 |
mutex_lock(&data->update_lock); |
1da177e4c
|
588 |
if (val) { |
6d6006b8d
|
589 |
data->fan_min[nr] = |
1da177e4c
|
590 591 592 593 594 |
FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); } else { data->fan_min[nr] = 0xff; } adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); |
9a61bf630
|
595 |
mutex_unlock(&data->update_lock); |
1da177e4c
|
596 597 |
return count; } |
8e757e15a
|
598 599 600 |
static ssize_t fan_div_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4c
|
601 |
{ |
b060f3c4a
|
602 603 |
struct adm1031_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
c801082d7
|
604 |
int nr = to_sensor_dev_attr(attr)->index; |
1c720093f
|
605 |
long val; |
1da177e4c
|
606 607 608 |
u8 tmp; int old_div; int new_min; |
1c720093f
|
609 610 611 612 613 |
int ret; ret = kstrtol(buf, 10, &val); if (ret) return ret; |
1da177e4c
|
614 615 616 |
tmp = val == 8 ? 0xc0 : val == 4 ? 0x80 : |
6d6006b8d
|
617 618 |
val == 2 ? 0x40 : val == 1 ? 0x00 : |
1da177e4c
|
619 620 621 |
0xff; if (tmp == 0xff) return -EINVAL; |
6d6006b8d
|
622 |
|
9a61bf630
|
623 |
mutex_lock(&data->update_lock); |
38a1f0e9a
|
624 625 626 627 628 629 630 |
/* Get fresh readings */ data->fan_div[nr] = adm1031_read_value(client, ADM1031_REG_FAN_DIV(nr)); data->fan_min[nr] = adm1031_read_value(client, ADM1031_REG_FAN_MIN(nr)); /* Write the new clock divider and fan min */ |
1da177e4c
|
631 |
old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); |
6d6006b8d
|
632 633 |
data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]); new_min = data->fan_min[nr] * old_div / val; |
1da177e4c
|
634 |
data->fan_min[nr] = new_min > 0xff ? 0xff : new_min; |
1da177e4c
|
635 |
|
6d6006b8d
|
636 |
adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr), |
1da177e4c
|
637 |
data->fan_div[nr]); |
6d6006b8d
|
638 |
adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), |
1da177e4c
|
639 |
data->fan_min[nr]); |
38a1f0e9a
|
640 641 642 |
/* Invalidate the cache: fan speed is no longer valid */ data->valid = 0; |
9a61bf630
|
643 |
mutex_unlock(&data->update_lock); |
1da177e4c
|
644 645 |
return count; } |
8e757e15a
|
646 647 648 649 650 651 |
static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0); static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0); static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0); static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1); static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1); static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1); |
1da177e4c
|
652 653 |
/* Temps */ |
8e757e15a
|
654 655 |
static ssize_t temp_show(struct device *dev, struct device_attribute *attr, char *buf) |
1da177e4c
|
656 |
{ |
c801082d7
|
657 |
int nr = to_sensor_dev_attr(attr)->index; |
1da177e4c
|
658 659 660 661 662 663 664 665 |
struct adm1031_data *data = adm1031_update_device(dev); int ext; ext = nr == 0 ? ((data->ext_temp[nr] >> 6) & 0x3) * 2 : (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); return sprintf(buf, "%d ", TEMP_FROM_REG_EXT(data->temp[nr], ext)); } |
8e757e15a
|
666 |
static ssize_t temp_offset_show(struct device *dev, |
49dc9efed
|
667 668 669 670 671 672 673 674 |
struct device_attribute *attr, char *buf) { int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d ", TEMP_OFFSET_FROM_REG(data->temp_offset[nr])); } |
8e757e15a
|
675 |
static ssize_t temp_min_show(struct device *dev, |
c801082d7
|
676 |
struct device_attribute *attr, char *buf) |
1da177e4c
|
677 |
{ |
c801082d7
|
678 |
int nr = to_sensor_dev_attr(attr)->index; |
1da177e4c
|
679 680 681 682 |
struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d ", TEMP_FROM_REG(data->temp_min[nr])); } |
8e757e15a
|
683 |
static ssize_t temp_max_show(struct device *dev, |
c801082d7
|
684 |
struct device_attribute *attr, char *buf) |
1da177e4c
|
685 |
{ |
c801082d7
|
686 |
int nr = to_sensor_dev_attr(attr)->index; |
1da177e4c
|
687 688 689 690 |
struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d ", TEMP_FROM_REG(data->temp_max[nr])); } |
8e757e15a
|
691 |
static ssize_t temp_crit_show(struct device *dev, |
c801082d7
|
692 |
struct device_attribute *attr, char *buf) |
1da177e4c
|
693 |
{ |
c801082d7
|
694 |
int nr = to_sensor_dev_attr(attr)->index; |
1da177e4c
|
695 696 697 698 |
struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d ", TEMP_FROM_REG(data->temp_crit[nr])); } |
8e757e15a
|
699 700 701 |
static ssize_t temp_offset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
49dc9efed
|
702 |
{ |
b060f3c4a
|
703 704 |
struct adm1031_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
49dc9efed
|
705 |
int nr = to_sensor_dev_attr(attr)->index; |
1c720093f
|
706 707 708 709 710 711 |
long val; int ret; ret = kstrtol(buf, 10, &val); if (ret) return ret; |
49dc9efed
|
712 |
|
2a844c148
|
713 |
val = clamp_val(val, -15000, 15000); |
49dc9efed
|
714 715 716 717 718 719 720 |
mutex_lock(&data->update_lock); data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val); adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); mutex_unlock(&data->update_lock); return count; } |
8e757e15a
|
721 722 723 |
static ssize_t temp_min_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4c
|
724 |
{ |
b060f3c4a
|
725 726 |
struct adm1031_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
c801082d7
|
727 |
int nr = to_sensor_dev_attr(attr)->index; |
1c720093f
|
728 729 730 731 732 733 |
long val; int ret; ret = kstrtol(buf, 10, &val); if (ret) return ret; |
1da177e4c
|
734 |
|
145e74a4e
|
735 |
val = clamp_val(val, -55000, 127000); |
9a61bf630
|
736 |
mutex_lock(&data->update_lock); |
1da177e4c
|
737 738 739 |
data->temp_min[nr] = TEMP_TO_REG(val); adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr), data->temp_min[nr]); |
9a61bf630
|
740 |
mutex_unlock(&data->update_lock); |
1da177e4c
|
741 742 |
return count; } |
8e757e15a
|
743 744 745 |
static ssize_t temp_max_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4c
|
746 |
{ |
b060f3c4a
|
747 748 |
struct adm1031_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
c801082d7
|
749 |
int nr = to_sensor_dev_attr(attr)->index; |
1c720093f
|
750 751 752 753 754 755 |
long val; int ret; ret = kstrtol(buf, 10, &val); if (ret) return ret; |
1da177e4c
|
756 |
|
145e74a4e
|
757 |
val = clamp_val(val, -55000, 127000); |
9a61bf630
|
758 |
mutex_lock(&data->update_lock); |
1da177e4c
|
759 760 761 |
data->temp_max[nr] = TEMP_TO_REG(val); adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr), data->temp_max[nr]); |
9a61bf630
|
762 |
mutex_unlock(&data->update_lock); |
1da177e4c
|
763 764 |
return count; } |
8e757e15a
|
765 766 767 |
static ssize_t temp_crit_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1da177e4c
|
768 |
{ |
b060f3c4a
|
769 770 |
struct adm1031_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
c801082d7
|
771 |
int nr = to_sensor_dev_attr(attr)->index; |
1c720093f
|
772 773 774 775 776 777 |
long val; int ret; ret = kstrtol(buf, 10, &val); if (ret) return ret; |
1da177e4c
|
778 |
|
145e74a4e
|
779 |
val = clamp_val(val, -55000, 127000); |
9a61bf630
|
780 |
mutex_lock(&data->update_lock); |
1da177e4c
|
781 782 783 |
data->temp_crit[nr] = TEMP_TO_REG(val); adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr), data->temp_crit[nr]); |
9a61bf630
|
784 |
mutex_unlock(&data->update_lock); |
1da177e4c
|
785 786 |
return count; } |
8e757e15a
|
787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 |
static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0); static SENSOR_DEVICE_ATTR_RW(temp1_offset, temp_offset, 0); static SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0); static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0); static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp_crit, 0); static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1); static SENSOR_DEVICE_ATTR_RW(temp2_offset, temp_offset, 1); static SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1); static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1); static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp_crit, 1); static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2); static SENSOR_DEVICE_ATTR_RW(temp3_offset, temp_offset, 2); static SENSOR_DEVICE_ATTR_RW(temp3_min, temp_min, 2); static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2); static SENSOR_DEVICE_ATTR_RW(temp3_crit, temp_crit, 2); |
1da177e4c
|
802 803 |
/* Alarms */ |
bfb6b1732
|
804 |
static ssize_t alarms_show(struct device *dev, struct device_attribute *attr, |
1c720093f
|
805 |
char *buf) |
1da177e4c
|
806 807 808 809 810 |
{ struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d ", data->alarm); } |
bfb6b1732
|
811 |
static DEVICE_ATTR_RO(alarms); |
1da177e4c
|
812 |
|
8e757e15a
|
813 814 |
static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, char *buf) |
050ab8789
|
815 816 817 818 819 820 |
{ int bitnr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); return sprintf(buf, "%d ", (data->alarm >> bitnr) & 1); } |
8e757e15a
|
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 |
static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 0); static SENSOR_DEVICE_ATTR_RO(fan1_fault, alarm, 1); static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 2); static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, alarm, 3); static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 4); static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 5); static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6); static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 7); static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 8); static SENSOR_DEVICE_ATTR_RO(fan2_fault, alarm, 9); static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, alarm, 10); static SENSOR_DEVICE_ATTR_RO(temp3_min_alarm, alarm, 11); static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, alarm, 12); static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 13); static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 14); |
1da177e4c
|
836 |
|
a51b9944a
|
837 838 |
/* Update Interval */ static const unsigned int update_intervals[] = { |
87c33daad
|
839 840 |
16000, 8000, 4000, 2000, 1000, 500, 250, 125, }; |
bfb6b1732
|
841 |
static ssize_t update_interval_show(struct device *dev, |
a51b9944a
|
842 |
struct device_attribute *attr, char *buf) |
87c33daad
|
843 |
{ |
b060f3c4a
|
844 |
struct adm1031_data *data = dev_get_drvdata(dev); |
87c33daad
|
845 |
|
a51b9944a
|
846 847 |
return sprintf(buf, "%u ", data->update_interval); |
87c33daad
|
848 |
} |
bfb6b1732
|
849 850 851 |
static ssize_t update_interval_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
87c33daad
|
852 |
{ |
b060f3c4a
|
853 854 |
struct adm1031_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
87c33daad
|
855 856 857 |
unsigned long val; int i, err; u8 reg; |
179c4fdb5
|
858 |
err = kstrtoul(buf, 10, &val); |
87c33daad
|
859 860 |
if (err) return err; |
a51b9944a
|
861 862 863 864 865 866 |
/* * Find the nearest update interval from the table. * Use it to determine the matching update rate. */ for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) { if (val >= update_intervals[i]) |
87c33daad
|
867 868 |
break; } |
a51b9944a
|
869 |
/* if not found, we point to the last entry (lowest update interval) */ |
87c33daad
|
870 871 872 873 874 875 876 877 |
/* set the new update rate while preserving other settings */ reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); reg &= ~ADM1031_UPDATE_RATE_MASK; reg |= i << ADM1031_UPDATE_RATE_SHIFT; adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg); mutex_lock(&data->update_lock); |
a51b9944a
|
878 |
data->update_interval = update_intervals[i]; |
87c33daad
|
879 880 881 882 |
mutex_unlock(&data->update_lock); return count; } |
bfb6b1732
|
883 |
static DEVICE_ATTR_RW(update_interval); |
87c33daad
|
884 |
|
681c6f7a6
|
885 |
static struct attribute *adm1031_attributes[] = { |
c801082d7
|
886 887 888 |
&sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, |
050ab8789
|
889 890 |
&sensor_dev_attr_fan1_alarm.dev_attr.attr, &sensor_dev_attr_fan1_fault.dev_attr.attr, |
c801082d7
|
891 892 893 |
&sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_auto_fan1_channel.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, |
49dc9efed
|
894 |
&sensor_dev_attr_temp1_offset.dev_attr.attr, |
c801082d7
|
895 |
&sensor_dev_attr_temp1_min.dev_attr.attr, |
050ab8789
|
896 |
&sensor_dev_attr_temp1_min_alarm.dev_attr.attr, |
c801082d7
|
897 |
&sensor_dev_attr_temp1_max.dev_attr.attr, |
050ab8789
|
898 |
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr, |
c801082d7
|
899 |
&sensor_dev_attr_temp1_crit.dev_attr.attr, |
050ab8789
|
900 |
&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, |
c801082d7
|
901 |
&sensor_dev_attr_temp2_input.dev_attr.attr, |
49dc9efed
|
902 |
&sensor_dev_attr_temp2_offset.dev_attr.attr, |
c801082d7
|
903 |
&sensor_dev_attr_temp2_min.dev_attr.attr, |
050ab8789
|
904 |
&sensor_dev_attr_temp2_min_alarm.dev_attr.attr, |
c801082d7
|
905 |
&sensor_dev_attr_temp2_max.dev_attr.attr, |
050ab8789
|
906 |
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr, |
c801082d7
|
907 |
&sensor_dev_attr_temp2_crit.dev_attr.attr, |
050ab8789
|
908 909 |
&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp2_fault.dev_attr.attr, |
c801082d7
|
910 911 912 913 914 915 916 917 918 919 |
&sensor_dev_attr_auto_temp1_off.dev_attr.attr, &sensor_dev_attr_auto_temp1_min.dev_attr.attr, &sensor_dev_attr_auto_temp1_max.dev_attr.attr, &sensor_dev_attr_auto_temp2_off.dev_attr.attr, &sensor_dev_attr_auto_temp2_min.dev_attr.attr, &sensor_dev_attr_auto_temp2_max.dev_attr.attr, &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr, |
681c6f7a6
|
920 |
|
a51b9944a
|
921 |
&dev_attr_update_interval.attr, |
681c6f7a6
|
922 923 924 925 926 927 928 929 930 931 |
&dev_attr_alarms.attr, NULL }; static const struct attribute_group adm1031_group = { .attrs = adm1031_attributes, }; static struct attribute *adm1031_attributes_opt[] = { |
c801082d7
|
932 933 934 |
&sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, |
050ab8789
|
935 936 |
&sensor_dev_attr_fan2_alarm.dev_attr.attr, &sensor_dev_attr_fan2_fault.dev_attr.attr, |
c801082d7
|
937 938 939 |
&sensor_dev_attr_pwm2.dev_attr.attr, &sensor_dev_attr_auto_fan2_channel.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, |
49dc9efed
|
940 |
&sensor_dev_attr_temp3_offset.dev_attr.attr, |
c801082d7
|
941 |
&sensor_dev_attr_temp3_min.dev_attr.attr, |
050ab8789
|
942 |
&sensor_dev_attr_temp3_min_alarm.dev_attr.attr, |
c801082d7
|
943 |
&sensor_dev_attr_temp3_max.dev_attr.attr, |
050ab8789
|
944 |
&sensor_dev_attr_temp3_max_alarm.dev_attr.attr, |
c801082d7
|
945 |
&sensor_dev_attr_temp3_crit.dev_attr.attr, |
050ab8789
|
946 947 |
&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp3_fault.dev_attr.attr, |
c801082d7
|
948 949 950 951 |
&sensor_dev_attr_auto_temp3_off.dev_attr.attr, &sensor_dev_attr_auto_temp3_min.dev_attr.attr, &sensor_dev_attr_auto_temp3_max.dev_attr.attr, &sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr, |
681c6f7a6
|
952 953 954 955 956 957 |
NULL }; static const struct attribute_group adm1031_group_opt = { .attrs = adm1031_attributes_opt, }; |
af200f881
|
958 |
/* Return 0 if detection is successful, -ENODEV otherwise */ |
310ec7921
|
959 |
static int adm1031_detect(struct i2c_client *client, |
af200f881
|
960 |
struct i2c_board_info *info) |
1da177e4c
|
961 |
{ |
af200f881
|
962 |
struct i2c_adapter *adapter = client->adapter; |
52df6440a
|
963 964 |
const char *name; int id, co; |
1da177e4c
|
965 966 |
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
af200f881
|
967 |
return -ENODEV; |
1da177e4c
|
968 |
|
52df6440a
|
969 970 |
id = i2c_smbus_read_byte_data(client, 0x3d); co = i2c_smbus_read_byte_data(client, 0x3e); |
1da177e4c
|
971 |
|
52df6440a
|
972 973 974 |
if (!((id == 0x31 || id == 0x30) && co == 0x41)) return -ENODEV; name = (id == 0x30) ? "adm1030" : "adm1031"; |
1da177e4c
|
975 |
|
af200f881
|
976 |
strlcpy(info->type, name, I2C_NAME_SIZE); |
1da177e4c
|
977 |
|
af200f881
|
978 979 |
return 0; } |
278ee1c84
|
980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 |
static void adm1031_init_client(struct i2c_client *client) { unsigned int read_val; unsigned int mask; int i; struct adm1031_data *data = i2c_get_clientdata(client); mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE); if (data->chip_type == adm1031) { mask |= (ADM1031_CONF2_PWM2_ENABLE | ADM1031_CONF2_TACH2_ENABLE); } /* Initialize the ADM1031 chip (enables fan speed reading ) */ read_val = adm1031_read_value(client, ADM1031_REG_CONF2); if ((read_val | mask) != read_val) adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask); read_val = adm1031_read_value(client, ADM1031_REG_CONF1); if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) { adm1031_write_value(client, ADM1031_REG_CONF1, read_val | ADM1031_CONF1_MONITOR_ENABLE); } /* Read the chip's update rate */ mask = ADM1031_UPDATE_RATE_MASK; read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT; /* Save it as update interval */ data->update_interval = update_intervals[i]; } |
674870385
|
1010 1011 1012 |
static const struct i2c_device_id adm1031_id[]; static int adm1031_probe(struct i2c_client *client) |
af200f881
|
1013 |
{ |
b060f3c4a
|
1014 1015 |
struct device *dev = &client->dev; struct device *hwmon_dev; |
af200f881
|
1016 |
struct adm1031_data *data; |
af200f881
|
1017 |
|
b060f3c4a
|
1018 |
data = devm_kzalloc(dev, sizeof(struct adm1031_data), GFP_KERNEL); |
dc2fd6632
|
1019 1020 |
if (!data) return -ENOMEM; |
af200f881
|
1021 1022 |
i2c_set_clientdata(client, data); |
b060f3c4a
|
1023 |
data->client = client; |
674870385
|
1024 |
data->chip_type = i2c_match_id(adm1031_id, client)->driver_data; |
9a61bf630
|
1025 |
mutex_init(&data->update_lock); |
1da177e4c
|
1026 |
|
af200f881
|
1027 1028 1029 1030 |
if (data->chip_type == adm1030) data->chan_select_table = &auto_channel_select_table_adm1030; else data->chan_select_table = &auto_channel_select_table_adm1031; |
1da177e4c
|
1031 1032 |
/* Initialize the ADM1031 chip */ |
6d6006b8d
|
1033 |
adm1031_init_client(client); |
1da177e4c
|
1034 |
|
b060f3c4a
|
1035 1036 1037 1038 |
/* sysfs hooks */ data->groups[0] = &adm1031_group; if (data->chip_type == adm1031) data->groups[1] = &adm1031_group_opt; |
1da177e4c
|
1039 |
|
b060f3c4a
|
1040 1041 1042 |
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, data->groups); return PTR_ERR_OR_ZERO(hwmon_dev); |
1da177e4c
|
1043 |
} |
278ee1c84
|
1044 1045 1046 1047 1048 1049 |
static const struct i2c_device_id adm1031_id[] = { { "adm1030", adm1030 }, { "adm1031", adm1031 }, { } }; MODULE_DEVICE_TABLE(i2c, adm1031_id); |
1da177e4c
|
1050 |
|
278ee1c84
|
1051 1052 1053 1054 1055 |
static struct i2c_driver adm1031_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "adm1031", }, |
674870385
|
1056 |
.probe_new = adm1031_probe, |
278ee1c84
|
1057 1058 1059 1060 |
.id_table = adm1031_id, .detect = adm1031_detect, .address_list = normal_i2c, }; |
1da177e4c
|
1061 |
|
f0967eea8
|
1062 |
module_i2c_driver(adm1031_driver); |
1da177e4c
|
1063 1064 1065 1066 |
MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>"); MODULE_DESCRIPTION("ADM1031/ADM1030 driver"); MODULE_LICENSE("GPL"); |