Blame view
drivers/hwmon/adm9240.c
23.8 KB
74ba9207e treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
40b5cda28 [PATCH] I2C: add ... |
2 3 |
/* * adm9240.c Part of lm_sensors, Linux kernel modules for hardware |
c387e4eb2 hwmon: (adm9240) ... |
4 |
* monitoring |
40b5cda28 [PATCH] I2C: add ... |
5 6 7 8 |
* * Copyright (C) 1999 Frodo Looijaard <frodol@dds.nl> * Philip Edelbrock <phil@netroedge.com> * Copyright (C) 2003 Michiel Rook <michiel@grendelproject.nl> |
2ca7b961c adm9240: Update G... |
9 |
* Copyright (C) 2005 Grant Coady <gcoady.lk@gmail.com> with valuable |
c387e4eb2 hwmon: (adm9240) ... |
10 |
* guidance from Jean Delvare |
40b5cda28 [PATCH] I2C: add ... |
11 12 13 14 15 16 17 18 19 20 21 22 23 |
* * Driver supports Analog Devices ADM9240 * Dallas Semiconductor DS1780 * National Semiconductor LM81 * * ADM9240 is the reference, DS1780 and LM81 are register compatibles * * Voltage Six inputs are scaled by chip, VID also reported * Temperature Chip temperature to 0.5'C, maximum and max_hysteris * Fans 2 fans, low speed alarm, automatic fan clock divider * Alarms 16-bit map of active alarms * Analog Out 0..1250 mV output * |
0de2b2448 hwmon: (adm9240) ... |
24 |
* Chassis Intrusion: clear CI latch with 'echo 0 > intrusion0_alarm' |
40b5cda28 [PATCH] I2C: add ... |
25 26 27 28 |
* * Test hardware: Intel SE440BX-2 desktop motherboard --Grant * * LM81 extended temp reading not implemented |
40b5cda28 [PATCH] I2C: add ... |
29 30 31 32 33 34 |
*/ #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/i2c.h> |
c7461a665 [PATCH] hwmon: ad... |
35 |
#include <linux/hwmon-sysfs.h> |
943b0830c [PATCH] I2C hwmon... |
36 |
#include <linux/hwmon.h> |
303760b44 [PATCH] hwmon: hw... |
37 |
#include <linux/hwmon-vid.h> |
943b0830c [PATCH] I2C hwmon... |
38 |
#include <linux/err.h> |
9a61bf630 [PATCH] hwmon: Se... |
39 |
#include <linux/mutex.h> |
dcd8f3923 hwmon: Add missin... |
40 |
#include <linux/jiffies.h> |
df885d912 hwmon: (adm9240) ... |
41 |
#include <linux/regmap.h> |
40b5cda28 [PATCH] I2C: add ... |
42 43 |
/* Addresses to scan */ |
25e9c86d5 hwmon: normal_i2c... |
44 |
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, |
40b5cda28 [PATCH] I2C: add ... |
45 |
I2C_CLIENT_END }; |
e5e9f44c2 i2c: Drop I2C_CLI... |
46 |
enum chips { adm9240, ds1780, lm81 }; |
40b5cda28 [PATCH] I2C: add ... |
47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
/* ADM9240 registers */ #define ADM9240_REG_MAN_ID 0x3e #define ADM9240_REG_DIE_REV 0x3f #define ADM9240_REG_CONFIG 0x40 #define ADM9240_REG_IN(nr) (0x20 + (nr)) /* 0..5 */ #define ADM9240_REG_IN_MAX(nr) (0x2b + (nr) * 2) #define ADM9240_REG_IN_MIN(nr) (0x2c + (nr) * 2) #define ADM9240_REG_FAN(nr) (0x28 + (nr)) /* 0..1 */ #define ADM9240_REG_FAN_MIN(nr) (0x3b + (nr)) #define ADM9240_REG_INT(nr) (0x41 + (nr)) #define ADM9240_REG_INT_MASK(nr) (0x43 + (nr)) #define ADM9240_REG_TEMP 0x27 |
c7461a665 [PATCH] hwmon: ad... |
61 |
#define ADM9240_REG_TEMP_MAX(nr) (0x39 + (nr)) /* 0, 1 = high, hyst */ |
40b5cda28 [PATCH] I2C: add ... |
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
#define ADM9240_REG_ANALOG_OUT 0x19 #define ADM9240_REG_CHASSIS_CLEAR 0x46 #define ADM9240_REG_VID_FAN_DIV 0x47 #define ADM9240_REG_I2C_ADDR 0x48 #define ADM9240_REG_VID4 0x49 #define ADM9240_REG_TEMP_CONF 0x4b /* generalised scaling with integer rounding */ static inline int SCALE(long val, int mul, int div) { if (val < 0) return (val * mul - div / 2) / div; else return (val * mul + div / 2) / div; } /* adm9240 internally scales voltage measurements */ static const u16 nom_mv[] = { 2500, 2700, 3300, 5000, 12000, 2700 }; static inline unsigned int IN_FROM_REG(u8 reg, int n) { return SCALE(reg, nom_mv[n], 192); } static inline u8 IN_TO_REG(unsigned long val, int n) { |
0fb620c43 hwmon: (adm9240) ... |
88 89 |
val = clamp_val(val, 0, nom_mv[n] * 255 / 192); return SCALE(val, 192, nom_mv[n]); |
40b5cda28 [PATCH] I2C: add ... |
90 91 92 93 94 |
} /* temperature range: -40..125, 127 disables temperature alarm */ static inline s8 TEMP_TO_REG(long val) { |
0fb620c43 hwmon: (adm9240) ... |
95 96 |
val = clamp_val(val, -40000, 127000); return SCALE(val, 1, 1000); |
40b5cda28 [PATCH] I2C: add ... |
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
} /* two fans, each with low fan speed limit */ static inline unsigned int FAN_FROM_REG(u8 reg, u8 div) { if (!reg) /* error */ return -1; if (reg == 255) return 0; return SCALE(1350000, 1, reg * div); } /* analog out 0..1250mV */ static inline u8 AOUT_TO_REG(unsigned long val) { |
0fb620c43 hwmon: (adm9240) ... |
114 115 |
val = clamp_val(val, 0, 1250); return SCALE(val, 255, 1250); |
40b5cda28 [PATCH] I2C: add ... |
116 117 118 119 120 121 |
} static inline unsigned int AOUT_FROM_REG(u8 reg) { return SCALE(reg, 1250, 255); } |
40b5cda28 [PATCH] I2C: add ... |
122 123 |
/* per client data */ struct adm9240_data { |
715f69bef hwmon: (adm9240) ... |
124 |
struct i2c_client *client; |
df885d912 hwmon: (adm9240) ... |
125 |
struct regmap *regmap; |
9a61bf630 [PATCH] hwmon: Se... |
126 |
struct mutex update_lock; |
40b5cda28 [PATCH] I2C: add ... |
127 128 129 130 131 132 133 134 135 136 137 |
char valid; unsigned long last_updated_measure; unsigned long last_updated_config; u8 in[6]; /* ro in0_input */ u8 in_max[6]; /* rw in0_max */ u8 in_min[6]; /* rw in0_min */ u8 fan[2]; /* ro fan1_input */ u8 fan_min[2]; /* rw fan1_min */ u8 fan_div[2]; /* rw fan1_div, read-only accessor */ s16 temp; /* ro temp1_input, 9-bit sign-extended */ |
c7461a665 [PATCH] hwmon: ad... |
138 |
s8 temp_max[2]; /* rw 0 -> temp_max, 1 -> temp_max_hyst */ |
40b5cda28 [PATCH] I2C: add ... |
139 |
u16 alarms; /* ro alarms */ |
8e8f9289c [PATCH] I2C: adm9... |
140 |
u8 aout; /* rw aout_output */ |
40b5cda28 [PATCH] I2C: add ... |
141 142 143 |
u8 vid; /* ro vid */ u8 vrm; /* -- vrm set on startup, no accessor */ }; |
4341fc3f3 hwmon: (adm9240) ... |
144 |
/* write new fan div, callers must hold data->update_lock */ |
df885d912 hwmon: (adm9240) ... |
145 |
static int adm9240_write_fan_div(struct adm9240_data *data, int nr, |
4341fc3f3 hwmon: (adm9240) ... |
146 147 |
u8 fan_div) { |
df885d912 hwmon: (adm9240) ... |
148 149 |
unsigned int reg, old, shift = (nr + 2) * 2; int err; |
4341fc3f3 hwmon: (adm9240) ... |
150 |
|
df885d912 hwmon: (adm9240) ... |
151 152 153 |
err = regmap_read(data->regmap, ADM9240_REG_VID_FAN_DIV, ®); if (err < 0) return err; |
4341fc3f3 hwmon: (adm9240) ... |
154 155 156 |
old = (reg >> shift) & 3; reg &= ~(3 << shift); reg |= (fan_div << shift); |
df885d912 hwmon: (adm9240) ... |
157 158 159 160 |
err = regmap_write(data->regmap, ADM9240_REG_VID_FAN_DIV, reg); if (err < 0) return err; dev_dbg(&data->client->dev, |
4341fc3f3 hwmon: (adm9240) ... |
161 162 163 |
"fan%d clock divider changed from %u to %u ", nr + 1, 1 << old, 1 << fan_div); |
df885d912 hwmon: (adm9240) ... |
164 165 |
return 0; |
4341fc3f3 hwmon: (adm9240) ... |
166 |
} |
6a8cdd146 hwmon: (adm9240) ... |
167 168 |
static int adm9240_update_measure(struct adm9240_data *data) { |
df885d912 hwmon: (adm9240) ... |
169 170 171 |
unsigned int val; u8 regs[2]; int err; |
6a8cdd146 hwmon: (adm9240) ... |
172 |
int i; |
df885d912 hwmon: (adm9240) ... |
173 174 175 176 177 178 179 180 |
err = regmap_bulk_read(data->regmap, ADM9240_REG_IN(0), &data->in[0], 6); if (err < 0) return err; err = regmap_bulk_read(data->regmap, ADM9240_REG_INT(0), ®s, 2); if (err < 0) return err; data->alarms = regs[0] | regs[1] << 8; |
6a8cdd146 hwmon: (adm9240) ... |
181 182 183 184 185 186 |
/* * read temperature: assume temperature changes less than * 0.5'C per two measurement cycles thus ignore possible * but unlikely aliasing error on lsb reading. --Grant */ |
df885d912 hwmon: (adm9240) ... |
187 188 189 190 191 192 193 194 |
err = regmap_read(data->regmap, ADM9240_REG_TEMP, &val); if (err < 0) return err; data->temp = val << 8; err = regmap_read(data->regmap, ADM9240_REG_TEMP_CONF, &val); if (err < 0) return err; data->temp |= val; |
6a8cdd146 hwmon: (adm9240) ... |
195 |
|
df885d912 hwmon: (adm9240) ... |
196 197 198 199 |
err = regmap_bulk_read(data->regmap, ADM9240_REG_FAN(0), &data->fan[0], 2); if (err < 0) return err; |
6a8cdd146 hwmon: (adm9240) ... |
200 |
|
df885d912 hwmon: (adm9240) ... |
201 |
for (i = 0; i < 2; i++) { /* read fans */ |
6a8cdd146 hwmon: (adm9240) ... |
202 203 204 |
/* adjust fan clock divider on overflow */ if (data->valid && data->fan[i] == 255 && data->fan_div[i] < 3) { |
df885d912 hwmon: (adm9240) ... |
205 |
err = adm9240_write_fan_div(data, i, |
6a8cdd146 hwmon: (adm9240) ... |
206 |
++data->fan_div[i]); |
df885d912 hwmon: (adm9240) ... |
207 208 |
if (err < 0) return err; |
6a8cdd146 hwmon: (adm9240) ... |
209 210 211 212 213 214 215 216 217 218 219 220 |
/* adjust fan_min if active, but not to 0 */ if (data->fan_min[i] < 255 && data->fan_min[i] >= 2) data->fan_min[i] /= 2; } } return 0; } static int adm9240_update_config(struct adm9240_data *data) |
4341fc3f3 hwmon: (adm9240) ... |
221 |
{ |
df885d912 hwmon: (adm9240) ... |
222 |
unsigned int val; |
4341fc3f3 hwmon: (adm9240) ... |
223 |
int i; |
df885d912 hwmon: (adm9240) ... |
224 |
int err; |
4341fc3f3 hwmon: (adm9240) ... |
225 |
|
6a8cdd146 hwmon: (adm9240) ... |
226 |
for (i = 0; i < 6; i++) { |
df885d912 hwmon: (adm9240) ... |
227 228 229 230 231 232 233 234 |
err = regmap_raw_read(data->regmap, ADM9240_REG_IN_MIN(i), &data->in_min[i], 1); if (err < 0) return err; err = regmap_raw_read(data->regmap, ADM9240_REG_IN_MAX(i), &data->in_max[i], 1); if (err < 0) return err; |
6a8cdd146 hwmon: (adm9240) ... |
235 |
} |
df885d912 hwmon: (adm9240) ... |
236 237 238 239 240 241 242 243 |
err = regmap_bulk_read(data->regmap, ADM9240_REG_FAN_MIN(0), &data->fan_min[0], 2); if (err < 0) return err; err = regmap_bulk_read(data->regmap, ADM9240_REG_TEMP_MAX(0), &data->temp_max[0], 2); if (err < 0) return err; |
6a8cdd146 hwmon: (adm9240) ... |
244 245 |
/* read fan divs and 5-bit VID */ |
df885d912 hwmon: (adm9240) ... |
246 247 248 249 250 251 252 253 254 255 |
err = regmap_read(data->regmap, ADM9240_REG_VID_FAN_DIV, &val); if (err < 0) return err; data->fan_div[0] = (val >> 4) & 3; data->fan_div[1] = (val >> 6) & 3; data->vid = val & 0x0f; err = regmap_read(data->regmap, ADM9240_REG_VID4, &val); if (err < 0) return err; data->vid |= (val & 1) << 4; |
6a8cdd146 hwmon: (adm9240) ... |
256 |
/* read analog out */ |
df885d912 hwmon: (adm9240) ... |
257 258 |
err = regmap_raw_read(data->regmap, ADM9240_REG_ANALOG_OUT, &data->aout, 1); |
6a8cdd146 hwmon: (adm9240) ... |
259 |
|
df885d912 hwmon: (adm9240) ... |
260 |
return err; |
6a8cdd146 hwmon: (adm9240) ... |
261 262 263 264 265 266 |
} static struct adm9240_data *adm9240_update_device(struct device *dev) { struct adm9240_data *data = dev_get_drvdata(dev); int err; |
4341fc3f3 hwmon: (adm9240) ... |
267 268 269 270 271 |
mutex_lock(&data->update_lock); /* minimum measurement cycle: 1.75 seconds */ if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4)) || !data->valid) { |
6a8cdd146 hwmon: (adm9240) ... |
272 273 274 275 276 |
err = adm9240_update_measure(data); if (err < 0) { data->valid = 0; mutex_unlock(&data->update_lock); return ERR_PTR(err); |
4341fc3f3 hwmon: (adm9240) ... |
277 278 279 280 281 282 283 |
} data->last_updated_measure = jiffies; } /* minimum config reading cycle: 300 seconds */ if (time_after(jiffies, data->last_updated_config + (HZ * 300)) || !data->valid) { |
6a8cdd146 hwmon: (adm9240) ... |
284 285 286 287 288 |
err = adm9240_update_config(data); if (err < 0) { data->valid = 0; mutex_unlock(&data->update_lock); return ERR_PTR(err); |
4341fc3f3 hwmon: (adm9240) ... |
289 |
} |
4341fc3f3 hwmon: (adm9240) ... |
290 291 292 293 294 295 |
data->last_updated_config = jiffies; data->valid = 1; } mutex_unlock(&data->update_lock); return data; } |
40b5cda28 [PATCH] I2C: add ... |
296 297 298 |
/*** sysfs accessors ***/ /* temperature */ |
b57511165 hwmon: (adm9240) ... |
299 300 |
static ssize_t temp1_input_show(struct device *dev, struct device_attribute *dummy, char *buf) |
c7461a665 [PATCH] hwmon: ad... |
301 302 |
{ struct adm9240_data *data = adm9240_update_device(dev); |
6a8cdd146 hwmon: (adm9240) ... |
303 304 305 |
if (IS_ERR(data)) return PTR_ERR(data); |
667f4bab8 hwmon: (adm9240) ... |
306 307 |
return sprintf(buf, "%d ", data->temp / 128 * 500); /* 9-bit value */ |
c7461a665 [PATCH] hwmon: ad... |
308 |
} |
7352ae8d0 hwmon: (adm9240) ... |
309 310 |
static ssize_t max_show(struct device *dev, struct device_attribute *devattr, char *buf) |
c7461a665 [PATCH] hwmon: ad... |
311 312 313 |
{ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct adm9240_data *data = adm9240_update_device(dev); |
6a8cdd146 hwmon: (adm9240) ... |
314 315 316 |
if (IS_ERR(data)) return PTR_ERR(data); |
c7461a665 [PATCH] hwmon: ad... |
317 318 319 |
return sprintf(buf, "%d ", data->temp_max[attr->index] * 1000); } |
7352ae8d0 hwmon: (adm9240) ... |
320 321 |
static ssize_t max_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) |
c7461a665 [PATCH] hwmon: ad... |
322 323 |
{ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
715f69bef hwmon: (adm9240) ... |
324 |
struct adm9240_data *data = dev_get_drvdata(dev); |
c387e4eb2 hwmon: (adm9240) ... |
325 326 327 328 329 330 |
long val; int err; err = kstrtol(buf, 10, &val); if (err) return err; |
c7461a665 [PATCH] hwmon: ad... |
331 |
|
9a61bf630 [PATCH] hwmon: Se... |
332 |
mutex_lock(&data->update_lock); |
c7461a665 [PATCH] hwmon: ad... |
333 |
data->temp_max[attr->index] = TEMP_TO_REG(val); |
df885d912 hwmon: (adm9240) ... |
334 335 |
err = regmap_write(data->regmap, ADM9240_REG_TEMP_MAX(attr->index), data->temp_max[attr->index]); |
9a61bf630 [PATCH] hwmon: Se... |
336 |
mutex_unlock(&data->update_lock); |
df885d912 hwmon: (adm9240) ... |
337 |
return err < 0 ? err : count; |
c7461a665 [PATCH] hwmon: ad... |
338 |
} |
b57511165 hwmon: (adm9240) ... |
339 |
static DEVICE_ATTR_RO(temp1_input); |
7352ae8d0 hwmon: (adm9240) ... |
340 341 |
static SENSOR_DEVICE_ATTR_RW(temp1_max, max, 0); static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, max, 1); |
40b5cda28 [PATCH] I2C: add ... |
342 343 |
/* voltage */ |
7352ae8d0 hwmon: (adm9240) ... |
344 345 |
static ssize_t in_show(struct device *dev, struct device_attribute *devattr, char *buf) |
40b5cda28 [PATCH] I2C: add ... |
346 |
{ |
c7461a665 [PATCH] hwmon: ad... |
347 |
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
40b5cda28 [PATCH] I2C: add ... |
348 |
struct adm9240_data *data = adm9240_update_device(dev); |
6a8cdd146 hwmon: (adm9240) ... |
349 350 351 |
if (IS_ERR(data)) return PTR_ERR(data); |
c7461a665 [PATCH] hwmon: ad... |
352 353 354 |
return sprintf(buf, "%d ", IN_FROM_REG(data->in[attr->index], attr->index)); |
40b5cda28 [PATCH] I2C: add ... |
355 |
} |
7352ae8d0 hwmon: (adm9240) ... |
356 357 |
static ssize_t in_min_show(struct device *dev, struct device_attribute *devattr, char *buf) |
40b5cda28 [PATCH] I2C: add ... |
358 |
{ |
c7461a665 [PATCH] hwmon: ad... |
359 |
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
40b5cda28 [PATCH] I2C: add ... |
360 |
struct adm9240_data *data = adm9240_update_device(dev); |
6a8cdd146 hwmon: (adm9240) ... |
361 362 363 |
if (IS_ERR(data)) return PTR_ERR(data); |
c7461a665 [PATCH] hwmon: ad... |
364 365 366 |
return sprintf(buf, "%d ", IN_FROM_REG(data->in_min[attr->index], attr->index)); |
40b5cda28 [PATCH] I2C: add ... |
367 |
} |
7352ae8d0 hwmon: (adm9240) ... |
368 369 |
static ssize_t in_max_show(struct device *dev, struct device_attribute *devattr, char *buf) |
40b5cda28 [PATCH] I2C: add ... |
370 |
{ |
c7461a665 [PATCH] hwmon: ad... |
371 |
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
40b5cda28 [PATCH] I2C: add ... |
372 |
struct adm9240_data *data = adm9240_update_device(dev); |
6a8cdd146 hwmon: (adm9240) ... |
373 374 375 |
if (IS_ERR(data)) return PTR_ERR(data); |
c7461a665 [PATCH] hwmon: ad... |
376 377 378 |
return sprintf(buf, "%d ", IN_FROM_REG(data->in_max[attr->index], attr->index)); |
40b5cda28 [PATCH] I2C: add ... |
379 |
} |
7352ae8d0 hwmon: (adm9240) ... |
380 381 382 |
static ssize_t in_min_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) |
40b5cda28 [PATCH] I2C: add ... |
383 |
{ |
c7461a665 [PATCH] hwmon: ad... |
384 |
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
715f69bef hwmon: (adm9240) ... |
385 |
struct adm9240_data *data = dev_get_drvdata(dev); |
c387e4eb2 hwmon: (adm9240) ... |
386 387 388 389 390 391 |
unsigned long val; int err; err = kstrtoul(buf, 10, &val); if (err) return err; |
40b5cda28 [PATCH] I2C: add ... |
392 |
|
9a61bf630 [PATCH] hwmon: Se... |
393 |
mutex_lock(&data->update_lock); |
c7461a665 [PATCH] hwmon: ad... |
394 |
data->in_min[attr->index] = IN_TO_REG(val, attr->index); |
df885d912 hwmon: (adm9240) ... |
395 396 |
err = regmap_write(data->regmap, ADM9240_REG_IN_MIN(attr->index), data->in_min[attr->index]); |
9a61bf630 [PATCH] hwmon: Se... |
397 |
mutex_unlock(&data->update_lock); |
df885d912 hwmon: (adm9240) ... |
398 |
return err < 0 ? err : count; |
40b5cda28 [PATCH] I2C: add ... |
399 |
} |
7352ae8d0 hwmon: (adm9240) ... |
400 401 402 |
static ssize_t in_max_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) |
40b5cda28 [PATCH] I2C: add ... |
403 |
{ |
c7461a665 [PATCH] hwmon: ad... |
404 |
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
715f69bef hwmon: (adm9240) ... |
405 |
struct adm9240_data *data = dev_get_drvdata(dev); |
c387e4eb2 hwmon: (adm9240) ... |
406 407 408 409 410 411 |
unsigned long val; int err; err = kstrtoul(buf, 10, &val); if (err) return err; |
40b5cda28 [PATCH] I2C: add ... |
412 |
|
9a61bf630 [PATCH] hwmon: Se... |
413 |
mutex_lock(&data->update_lock); |
c7461a665 [PATCH] hwmon: ad... |
414 |
data->in_max[attr->index] = IN_TO_REG(val, attr->index); |
df885d912 hwmon: (adm9240) ... |
415 416 |
err = regmap_write(data->regmap, ADM9240_REG_IN_MAX(attr->index), data->in_max[attr->index]); |
9a61bf630 [PATCH] hwmon: Se... |
417 |
mutex_unlock(&data->update_lock); |
df885d912 hwmon: (adm9240) ... |
418 |
return err < 0 ? err : count; |
40b5cda28 [PATCH] I2C: add ... |
419 |
} |
7352ae8d0 hwmon: (adm9240) ... |
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 |
static SENSOR_DEVICE_ATTR_RO(in0_input, in, 0); static SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0); static SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0); static SENSOR_DEVICE_ATTR_RO(in1_input, in, 1); static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1); static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1); static SENSOR_DEVICE_ATTR_RO(in2_input, in, 2); static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2); static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2); static SENSOR_DEVICE_ATTR_RO(in3_input, in, 3); static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3); static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3); static SENSOR_DEVICE_ATTR_RO(in4_input, in, 4); static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4); static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4); static SENSOR_DEVICE_ATTR_RO(in5_input, in, 5); static SENSOR_DEVICE_ATTR_RW(in5_min, in_min, 5); static SENSOR_DEVICE_ATTR_RW(in5_max, in_max, 5); |
40b5cda28 [PATCH] I2C: add ... |
438 439 |
/* fans */ |
7352ae8d0 hwmon: (adm9240) ... |
440 441 |
static ssize_t fan_show(struct device *dev, struct device_attribute *devattr, char *buf) |
40b5cda28 [PATCH] I2C: add ... |
442 |
{ |
c7461a665 [PATCH] hwmon: ad... |
443 |
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
40b5cda28 [PATCH] I2C: add ... |
444 |
struct adm9240_data *data = adm9240_update_device(dev); |
6a8cdd146 hwmon: (adm9240) ... |
445 446 447 |
if (IS_ERR(data)) return PTR_ERR(data); |
c7461a665 [PATCH] hwmon: ad... |
448 449 450 |
return sprintf(buf, "%d ", FAN_FROM_REG(data->fan[attr->index], 1 << data->fan_div[attr->index])); |
40b5cda28 [PATCH] I2C: add ... |
451 |
} |
7352ae8d0 hwmon: (adm9240) ... |
452 453 |
static ssize_t fan_min_show(struct device *dev, struct device_attribute *devattr, char *buf) |
40b5cda28 [PATCH] I2C: add ... |
454 |
{ |
c7461a665 [PATCH] hwmon: ad... |
455 |
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
40b5cda28 [PATCH] I2C: add ... |
456 |
struct adm9240_data *data = adm9240_update_device(dev); |
6a8cdd146 hwmon: (adm9240) ... |
457 458 459 |
if (IS_ERR(data)) return PTR_ERR(data); |
c7461a665 [PATCH] hwmon: ad... |
460 461 462 |
return sprintf(buf, "%d ", FAN_FROM_REG(data->fan_min[attr->index], 1 << data->fan_div[attr->index])); |
40b5cda28 [PATCH] I2C: add ... |
463 |
} |
7352ae8d0 hwmon: (adm9240) ... |
464 465 |
static ssize_t fan_div_show(struct device *dev, struct device_attribute *devattr, char *buf) |
40b5cda28 [PATCH] I2C: add ... |
466 |
{ |
c7461a665 [PATCH] hwmon: ad... |
467 |
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
40b5cda28 [PATCH] I2C: add ... |
468 |
struct adm9240_data *data = adm9240_update_device(dev); |
6a8cdd146 hwmon: (adm9240) ... |
469 470 471 |
if (IS_ERR(data)) return PTR_ERR(data); |
c7461a665 [PATCH] hwmon: ad... |
472 473 |
return sprintf(buf, "%d ", 1 << data->fan_div[attr->index]); |
40b5cda28 [PATCH] I2C: add ... |
474 |
} |
e415e48b6 [PATCH] hwmon: ad... |
475 |
/* |
40b5cda28 [PATCH] I2C: add ... |
476 477 478 479 480 481 482 483 484 485 |
* set fan speed low limit: * * - value is zero: disable fan speed low limit alarm * * - value is below fan speed measurement range: enable fan speed low * limit alarm to be asserted while fan speed too slow to measure * * - otherwise: select fan clock divider to suit fan speed low limit, * measurement code may adjust registers to ensure fan speed reading */ |
7352ae8d0 hwmon: (adm9240) ... |
486 487 488 |
static ssize_t fan_min_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) |
40b5cda28 [PATCH] I2C: add ... |
489 |
{ |
c7461a665 [PATCH] hwmon: ad... |
490 |
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
715f69bef hwmon: (adm9240) ... |
491 492 |
struct adm9240_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; |
c7461a665 [PATCH] hwmon: ad... |
493 |
int nr = attr->index; |
40b5cda28 [PATCH] I2C: add ... |
494 |
u8 new_div; |
c387e4eb2 hwmon: (adm9240) ... |
495 496 497 498 499 500 |
unsigned long val; int err; err = kstrtoul(buf, 10, &val); if (err) return err; |
40b5cda28 [PATCH] I2C: add ... |
501 |
|
9a61bf630 [PATCH] hwmon: Se... |
502 |
mutex_lock(&data->update_lock); |
40b5cda28 [PATCH] I2C: add ... |
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 |
if (!val) { data->fan_min[nr] = 255; new_div = data->fan_div[nr]; dev_dbg(&client->dev, "fan%u low limit set disabled ", nr + 1); } else if (val < 1350000 / (8 * 254)) { new_div = 3; data->fan_min[nr] = 254; dev_dbg(&client->dev, "fan%u low limit set minimum %u ", nr + 1, FAN_FROM_REG(254, 1 << new_div)); } else { unsigned int new_min = 1350000 / val; new_div = 0; while (new_min > 192 && new_div < 3) { new_div++; new_min /= 2; } if (!new_min) /* keep > 0 */ new_min++; data->fan_min[nr] = new_min; dev_dbg(&client->dev, "fan%u low limit set fan speed %u ", nr + 1, FAN_FROM_REG(new_min, 1 << new_div)); } if (new_div != data->fan_div[nr]) { data->fan_div[nr] = new_div; |
df885d912 hwmon: (adm9240) ... |
540 |
adm9240_write_fan_div(data, nr, new_div); |
40b5cda28 [PATCH] I2C: add ... |
541 |
} |
df885d912 hwmon: (adm9240) ... |
542 543 |
err = regmap_write(data->regmap, ADM9240_REG_FAN_MIN(nr), data->fan_min[nr]); |
40b5cda28 [PATCH] I2C: add ... |
544 |
|
9a61bf630 [PATCH] hwmon: Se... |
545 |
mutex_unlock(&data->update_lock); |
df885d912 hwmon: (adm9240) ... |
546 |
return err < 0 ? err : count; |
40b5cda28 [PATCH] I2C: add ... |
547 |
} |
7352ae8d0 hwmon: (adm9240) ... |
548 549 550 551 552 553 |
static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0); static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0); static SENSOR_DEVICE_ATTR_RO(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_RO(fan2_div, fan_div, 1); |
40b5cda28 [PATCH] I2C: add ... |
554 555 |
/* alarms */ |
b57511165 hwmon: (adm9240) ... |
556 |
static ssize_t alarms_show(struct device *dev, |
e415e48b6 [PATCH] hwmon: ad... |
557 |
struct device_attribute *attr, char *buf) |
40b5cda28 [PATCH] I2C: add ... |
558 559 |
{ struct adm9240_data *data = adm9240_update_device(dev); |
6a8cdd146 hwmon: (adm9240) ... |
560 561 562 |
if (IS_ERR(data)) return PTR_ERR(data); |
40b5cda28 [PATCH] I2C: add ... |
563 564 565 |
return sprintf(buf, "%u ", data->alarms); } |
b57511165 hwmon: (adm9240) ... |
566 |
static DEVICE_ATTR_RO(alarms); |
40b5cda28 [PATCH] I2C: add ... |
567 |
|
7352ae8d0 hwmon: (adm9240) ... |
568 569 |
static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, char *buf) |
360f9452d hwmon: (adm9240) ... |
570 571 572 |
{ int bitnr = to_sensor_dev_attr(attr)->index; struct adm9240_data *data = adm9240_update_device(dev); |
6a8cdd146 hwmon: (adm9240) ... |
573 574 575 |
if (IS_ERR(data)) return PTR_ERR(data); |
360f9452d hwmon: (adm9240) ... |
576 577 578 |
return sprintf(buf, "%u ", (data->alarms >> bitnr) & 1); } |
7352ae8d0 hwmon: (adm9240) ... |
579 580 581 582 583 584 585 586 587 |
static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0); static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1); static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2); static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3); static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 8); static SENSOR_DEVICE_ATTR_RO(in5_alarm, alarm, 9); static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 4); static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 6); static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 7); |
360f9452d hwmon: (adm9240) ... |
588 |
|
40b5cda28 [PATCH] I2C: add ... |
589 |
/* vid */ |
b57511165 hwmon: (adm9240) ... |
590 591 |
static ssize_t cpu0_vid_show(struct device *dev, struct device_attribute *attr, char *buf) |
40b5cda28 [PATCH] I2C: add ... |
592 593 |
{ struct adm9240_data *data = adm9240_update_device(dev); |
6a8cdd146 hwmon: (adm9240) ... |
594 595 596 |
if (IS_ERR(data)) return PTR_ERR(data); |
40b5cda28 [PATCH] I2C: add ... |
597 598 599 |
return sprintf(buf, "%d ", vid_from_reg(data->vid, data->vrm)); } |
b57511165 hwmon: (adm9240) ... |
600 |
static DEVICE_ATTR_RO(cpu0_vid); |
40b5cda28 [PATCH] I2C: add ... |
601 602 |
/* analog output */ |
b57511165 hwmon: (adm9240) ... |
603 604 |
static ssize_t aout_output_show(struct device *dev, struct device_attribute *attr, char *buf) |
40b5cda28 [PATCH] I2C: add ... |
605 606 |
{ struct adm9240_data *data = adm9240_update_device(dev); |
6a8cdd146 hwmon: (adm9240) ... |
607 608 609 |
if (IS_ERR(data)) return PTR_ERR(data); |
40b5cda28 [PATCH] I2C: add ... |
610 611 612 |
return sprintf(buf, "%d ", AOUT_FROM_REG(data->aout)); } |
b57511165 hwmon: (adm9240) ... |
613 614 615 |
static ssize_t aout_output_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
40b5cda28 [PATCH] I2C: add ... |
616 |
{ |
715f69bef hwmon: (adm9240) ... |
617 |
struct adm9240_data *data = dev_get_drvdata(dev); |
c387e4eb2 hwmon: (adm9240) ... |
618 619 620 621 622 623 |
long val; int err; err = kstrtol(buf, 10, &val); if (err) return err; |
40b5cda28 [PATCH] I2C: add ... |
624 |
|
9a61bf630 [PATCH] hwmon: Se... |
625 |
mutex_lock(&data->update_lock); |
40b5cda28 [PATCH] I2C: add ... |
626 |
data->aout = AOUT_TO_REG(val); |
df885d912 hwmon: (adm9240) ... |
627 |
err = regmap_write(data->regmap, ADM9240_REG_ANALOG_OUT, data->aout); |
9a61bf630 [PATCH] hwmon: Se... |
628 |
mutex_unlock(&data->update_lock); |
df885d912 hwmon: (adm9240) ... |
629 |
return err < 0 ? err : count; |
40b5cda28 [PATCH] I2C: add ... |
630 |
} |
b57511165 hwmon: (adm9240) ... |
631 |
static DEVICE_ATTR_RW(aout_output); |
40b5cda28 [PATCH] I2C: add ... |
632 |
|
7352ae8d0 hwmon: (adm9240) ... |
633 634 |
static ssize_t alarm_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
0de2b2448 hwmon: (adm9240) ... |
635 |
{ |
715f69bef hwmon: (adm9240) ... |
636 |
struct adm9240_data *data = dev_get_drvdata(dev); |
0de2b2448 hwmon: (adm9240) ... |
637 |
unsigned long val; |
df885d912 hwmon: (adm9240) ... |
638 |
int err; |
0de2b2448 hwmon: (adm9240) ... |
639 |
|
179c4fdb5 hwmon: replaced s... |
640 |
if (kstrtoul(buf, 10, &val) || val != 0) |
0de2b2448 hwmon: (adm9240) ... |
641 642 643 |
return -EINVAL; mutex_lock(&data->update_lock); |
df885d912 hwmon: (adm9240) ... |
644 |
err = regmap_write(data->regmap, ADM9240_REG_CHASSIS_CLEAR, 0x80); |
0de2b2448 hwmon: (adm9240) ... |
645 646 |
data->valid = 0; /* Force cache refresh */ mutex_unlock(&data->update_lock); |
df885d912 hwmon: (adm9240) ... |
647 648 649 650 |
if (err < 0) return err; dev_dbg(&data->client->dev, "chassis intrusion latch cleared "); |
0de2b2448 hwmon: (adm9240) ... |
651 652 653 |
return count; } |
7352ae8d0 hwmon: (adm9240) ... |
654 |
static SENSOR_DEVICE_ATTR_RW(intrusion0_alarm, alarm, 12); |
40b5cda28 [PATCH] I2C: add ... |
655 |
|
715f69bef hwmon: (adm9240) ... |
656 |
static struct attribute *adm9240_attrs[] = { |
681c6f7a6 hwmon: Fix unchec... |
657 658 659 |
&sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in0_max.dev_attr.attr, |
360f9452d hwmon: (adm9240) ... |
660 |
&sensor_dev_attr_in0_alarm.dev_attr.attr, |
681c6f7a6 hwmon: Fix unchec... |
661 662 663 |
&sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr, &sensor_dev_attr_in1_max.dev_attr.attr, |
360f9452d hwmon: (adm9240) ... |
664 |
&sensor_dev_attr_in1_alarm.dev_attr.attr, |
681c6f7a6 hwmon: Fix unchec... |
665 666 667 |
&sensor_dev_attr_in2_input.dev_attr.attr, &sensor_dev_attr_in2_min.dev_attr.attr, &sensor_dev_attr_in2_max.dev_attr.attr, |
360f9452d hwmon: (adm9240) ... |
668 |
&sensor_dev_attr_in2_alarm.dev_attr.attr, |
681c6f7a6 hwmon: Fix unchec... |
669 670 671 |
&sensor_dev_attr_in3_input.dev_attr.attr, &sensor_dev_attr_in3_min.dev_attr.attr, &sensor_dev_attr_in3_max.dev_attr.attr, |
360f9452d hwmon: (adm9240) ... |
672 |
&sensor_dev_attr_in3_alarm.dev_attr.attr, |
681c6f7a6 hwmon: Fix unchec... |
673 674 675 |
&sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, |
360f9452d hwmon: (adm9240) ... |
676 |
&sensor_dev_attr_in4_alarm.dev_attr.attr, |
681c6f7a6 hwmon: Fix unchec... |
677 678 679 |
&sensor_dev_attr_in5_input.dev_attr.attr, &sensor_dev_attr_in5_min.dev_attr.attr, &sensor_dev_attr_in5_max.dev_attr.attr, |
360f9452d hwmon: (adm9240) ... |
680 |
&sensor_dev_attr_in5_alarm.dev_attr.attr, |
681c6f7a6 hwmon: Fix unchec... |
681 682 683 |
&dev_attr_temp1_input.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, |
360f9452d hwmon: (adm9240) ... |
684 |
&sensor_dev_attr_temp1_alarm.dev_attr.attr, |
681c6f7a6 hwmon: Fix unchec... |
685 686 687 |
&sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, |
360f9452d hwmon: (adm9240) ... |
688 |
&sensor_dev_attr_fan1_alarm.dev_attr.attr, |
681c6f7a6 hwmon: Fix unchec... |
689 690 691 |
&sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, |
360f9452d hwmon: (adm9240) ... |
692 |
&sensor_dev_attr_fan2_alarm.dev_attr.attr, |
681c6f7a6 hwmon: Fix unchec... |
693 694 |
&dev_attr_alarms.attr, &dev_attr_aout_output.attr, |
0de2b2448 hwmon: (adm9240) ... |
695 |
&sensor_dev_attr_intrusion0_alarm.dev_attr.attr, |
681c6f7a6 hwmon: Fix unchec... |
696 697 698 |
&dev_attr_cpu0_vid.attr, NULL }; |
715f69bef hwmon: (adm9240) ... |
699 |
ATTRIBUTE_GROUPS(adm9240); |
681c6f7a6 hwmon: Fix unchec... |
700 |
|
40b5cda28 [PATCH] I2C: add ... |
701 |
/*** sensor chip detect and driver install ***/ |
7fae82831 hwmon: (adm9240) ... |
702 |
/* Return 0 if detection is successful, -ENODEV otherwise */ |
310ec7921 i2c: Drop the kin... |
703 |
static int adm9240_detect(struct i2c_client *new_client, |
7fae82831 hwmon: (adm9240) ... |
704 |
struct i2c_board_info *info) |
40b5cda28 [PATCH] I2C: add ... |
705 |
{ |
7fae82831 hwmon: (adm9240) ... |
706 |
struct i2c_adapter *adapter = new_client->adapter; |
40b5cda28 [PATCH] I2C: add ... |
707 |
const char *name = ""; |
7fae82831 hwmon: (adm9240) ... |
708 |
int address = new_client->addr; |
40b5cda28 [PATCH] I2C: add ... |
709 710 711 |
u8 man_id, die_rev; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
7fae82831 hwmon: (adm9240) ... |
712 |
return -ENODEV; |
40b5cda28 [PATCH] I2C: add ... |
713 |
|
52df6440a hwmon: Clean up d... |
714 715 716 717 718 719 720 |
/* verify chip: reg address should match i2c address */ if (i2c_smbus_read_byte_data(new_client, ADM9240_REG_I2C_ADDR) != address) { dev_err(&adapter->dev, "detect fail: address match, 0x%02x ", address); return -ENODEV; |
40b5cda28 [PATCH] I2C: add ... |
721 |
} |
52df6440a hwmon: Clean up d... |
722 723 724 |
/* check known chip manufacturer */ man_id = i2c_smbus_read_byte_data(new_client, ADM9240_REG_MAN_ID); if (man_id == 0x23) { |
40b5cda28 [PATCH] I2C: add ... |
725 |
name = "adm9240"; |
52df6440a hwmon: Clean up d... |
726 |
} else if (man_id == 0xda) { |
40b5cda28 [PATCH] I2C: add ... |
727 |
name = "ds1780"; |
52df6440a hwmon: Clean up d... |
728 |
} else if (man_id == 0x01) { |
40b5cda28 [PATCH] I2C: add ... |
729 |
name = "lm81"; |
52df6440a hwmon: Clean up d... |
730 731 732 733 734 |
} else { dev_err(&adapter->dev, "detect fail: unknown manuf, 0x%02x ", man_id); return -ENODEV; |
40b5cda28 [PATCH] I2C: add ... |
735 |
} |
52df6440a hwmon: Clean up d... |
736 737 738 739 740 741 742 |
/* successful detect, print chip info */ die_rev = i2c_smbus_read_byte_data(new_client, ADM9240_REG_DIE_REV); dev_info(&adapter->dev, "found %s revision %u ", man_id == 0x23 ? "ADM9240" : man_id == 0xda ? "DS1780" : "LM81", die_rev); |
7fae82831 hwmon: (adm9240) ... |
743 |
strlcpy(info->type, name, I2C_NAME_SIZE); |
40b5cda28 [PATCH] I2C: add ... |
744 |
|
7fae82831 hwmon: (adm9240) ... |
745 746 |
return 0; } |
40b5cda28 [PATCH] I2C: add ... |
747 |
|
df885d912 hwmon: (adm9240) ... |
748 |
static int adm9240_init_client(struct i2c_client *client, struct adm9240_data *data) |
40b5cda28 [PATCH] I2C: add ... |
749 |
{ |
df885d912 hwmon: (adm9240) ... |
750 751 752 753 754 755 756 757 758 759 |
u8 conf, mode; int err; err = regmap_raw_read(data->regmap, ADM9240_REG_CONFIG, &conf, 1); if (err < 0) return err; err = regmap_raw_read(data->regmap, ADM9240_REG_TEMP_CONF, &mode, 1); if (err < 0) return err; mode &= 3; |
40b5cda28 [PATCH] I2C: add ... |
760 |
|
303760b44 [PATCH] hwmon: hw... |
761 |
data->vrm = vid_which_vrm(); /* need this to report vid as mV */ |
40b5cda28 [PATCH] I2C: add ... |
762 |
|
8e8f9289c [PATCH] I2C: adm9... |
763 764 765 |
dev_info(&client->dev, "Using VRM: %d.%d ", data->vrm / 10, data->vrm % 10); |
40b5cda28 [PATCH] I2C: add ... |
766 767 768 769 770 771 772 773 |
if (conf & 1) { /* measurement cycle running: report state */ dev_info(&client->dev, "status: config 0x%02x mode %u ", conf, mode); } else { /* cold start: open limits before starting chip */ int i; |
c387e4eb2 hwmon: (adm9240) ... |
774 |
for (i = 0; i < 6; i++) { |
df885d912 hwmon: (adm9240) ... |
775 776 777 778 779 780 781 782 |
err = regmap_write(data->regmap, ADM9240_REG_IN_MIN(i), 0); if (err < 0) return err; err = regmap_write(data->regmap, ADM9240_REG_IN_MAX(i), 255); if (err < 0) return err; |
40b5cda28 [PATCH] I2C: add ... |
783 |
} |
10d097737 hwmon: (adm9240) ... |
784 |
for (i = 0; i < 2; i++) { |
df885d912 hwmon: (adm9240) ... |
785 |
err = regmap_write(data->regmap, |
10d097737 hwmon: (adm9240) ... |
786 |
ADM9240_REG_FAN_MIN(i), 255); |
df885d912 hwmon: (adm9240) ... |
787 788 |
if (err < 0) return err; |
10d097737 hwmon: (adm9240) ... |
789 790 |
} for (i = 0; i < 2; i++) { |
df885d912 hwmon: (adm9240) ... |
791 |
err = regmap_write(data->regmap, |
10d097737 hwmon: (adm9240) ... |
792 |
ADM9240_REG_TEMP_MAX(i), 127); |
df885d912 hwmon: (adm9240) ... |
793 794 |
if (err < 0) return err; |
10d097737 hwmon: (adm9240) ... |
795 |
} |
40b5cda28 [PATCH] I2C: add ... |
796 797 |
/* start measurement cycle */ |
df885d912 hwmon: (adm9240) ... |
798 799 800 |
err = regmap_write(data->regmap, ADM9240_REG_CONFIG, 1); if (err < 0) return err; |
40b5cda28 [PATCH] I2C: add ... |
801 |
|
b55f37572 hwmon: Fix checkp... |
802 803 804 |
dev_info(&client->dev, "cold start: config was 0x%02x mode %u ", conf, mode); |
40b5cda28 [PATCH] I2C: add ... |
805 |
} |
df885d912 hwmon: (adm9240) ... |
806 807 |
return 0; |
40b5cda28 [PATCH] I2C: add ... |
808 |
} |
df885d912 hwmon: (adm9240) ... |
809 810 811 812 813 814 |
static const struct regmap_config adm9240_regmap_config = { .reg_bits = 8, .val_bits = 8, .use_single_read = true, .use_single_write = true, }; |
674870385 hwmon: use simple... |
815 |
static int adm9240_probe(struct i2c_client *new_client) |
40b5cda28 [PATCH] I2C: add ... |
816 |
{ |
715f69bef hwmon: (adm9240) ... |
817 818 |
struct device *dev = &new_client->dev; struct device *hwmon_dev; |
4341fc3f3 hwmon: (adm9240) ... |
819 |
struct adm9240_data *data; |
df885d912 hwmon: (adm9240) ... |
820 |
int err; |
40b5cda28 [PATCH] I2C: add ... |
821 |
|
715f69bef hwmon: (adm9240) ... |
822 |
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); |
4341fc3f3 hwmon: (adm9240) ... |
823 824 |
if (!data) return -ENOMEM; |
40b5cda28 [PATCH] I2C: add ... |
825 |
|
715f69bef hwmon: (adm9240) ... |
826 |
data->client = new_client; |
4341fc3f3 hwmon: (adm9240) ... |
827 |
mutex_init(&data->update_lock); |
df885d912 hwmon: (adm9240) ... |
828 829 830 |
data->regmap = devm_regmap_init_i2c(new_client, &adm9240_regmap_config); if (IS_ERR(data->regmap)) return PTR_ERR(data->regmap); |
40b5cda28 [PATCH] I2C: add ... |
831 |
|
df885d912 hwmon: (adm9240) ... |
832 833 834 |
err = adm9240_init_client(new_client, data); if (err < 0) return err; |
40b5cda28 [PATCH] I2C: add ... |
835 |
|
715f69bef hwmon: (adm9240) ... |
836 837 838 839 840 |
hwmon_dev = devm_hwmon_device_register_with_groups(dev, new_client->name, data, adm9240_groups); return PTR_ERR_OR_ZERO(hwmon_dev); |
4341fc3f3 hwmon: (adm9240) ... |
841 |
} |
40b5cda28 [PATCH] I2C: add ... |
842 |
|
4341fc3f3 hwmon: (adm9240) ... |
843 844 845 846 847 848 849 |
static const struct i2c_device_id adm9240_id[] = { { "adm9240", adm9240 }, { "ds1780", ds1780 }, { "lm81", lm81 }, { } }; MODULE_DEVICE_TABLE(i2c, adm9240_id); |
40b5cda28 [PATCH] I2C: add ... |
850 |
|
4341fc3f3 hwmon: (adm9240) ... |
851 852 853 854 855 |
static struct i2c_driver adm9240_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "adm9240", }, |
674870385 hwmon: use simple... |
856 |
.probe_new = adm9240_probe, |
4341fc3f3 hwmon: (adm9240) ... |
857 858 859 860 |
.id_table = adm9240_id, .detect = adm9240_detect, .address_list = normal_i2c, }; |
40b5cda28 [PATCH] I2C: add ... |
861 |
|
f0967eea8 hwmon: convert dr... |
862 |
module_i2c_driver(adm9240_driver); |
40b5cda28 [PATCH] I2C: add ... |
863 864 |
MODULE_AUTHOR("Michiel Rook <michiel@grendelproject.nl>, " |
2ca7b961c adm9240: Update G... |
865 |
"Grant Coady <gcoady.lk@gmail.com> and others"); |
40b5cda28 [PATCH] I2C: add ... |
866 867 |
MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver"); MODULE_LICENSE("GPL"); |