1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * asc7621.c - Part of lm_sensors, Linux kernel modules for hardware monitoring |
4 | * Copyright (c) 2007, 2010 George Joseph <george.joseph@fairview5.com> |
5 | */ |
6 | |
7 | #include <linux/module.h> |
8 | #include <linux/init.h> |
9 | #include <linux/slab.h> |
10 | #include <linux/jiffies.h> |
11 | #include <linux/i2c.h> |
12 | #include <linux/hwmon.h> |
13 | #include <linux/hwmon-sysfs.h> |
14 | #include <linux/err.h> |
15 | #include <linux/mutex.h> |
16 | |
17 | /* Addresses to scan */ |
18 | static const unsigned short normal_i2c[] = { |
19 | 0x2c, 0x2d, 0x2e, I2C_CLIENT_END |
20 | }; |
21 | |
22 | enum asc7621_type { |
23 | asc7621, |
24 | asc7621a |
25 | }; |
26 | |
27 | #define INTERVAL_HIGH (HZ + HZ / 2) |
28 | #define INTERVAL_LOW (1 * 60 * HZ) |
29 | #define PRI_NONE 0 |
30 | #define PRI_LOW 1 |
31 | #define PRI_HIGH 2 |
32 | #define FIRST_CHIP asc7621 |
33 | #define LAST_CHIP asc7621a |
34 | |
35 | struct asc7621_chip { |
36 | char *name; |
37 | enum asc7621_type chip_type; |
38 | u8 company_reg; |
39 | u8 company_id; |
40 | u8 verstep_reg; |
41 | u8 verstep_id; |
42 | const unsigned short *addresses; |
43 | }; |
44 | |
45 | static struct asc7621_chip asc7621_chips[] = { |
46 | { |
47 | .name = "asc7621" , |
48 | .chip_type = asc7621, |
49 | .company_reg = 0x3e, |
50 | .company_id = 0x61, |
51 | .verstep_reg = 0x3f, |
52 | .verstep_id = 0x6c, |
53 | .addresses = normal_i2c, |
54 | }, |
55 | { |
56 | .name = "asc7621a" , |
57 | .chip_type = asc7621a, |
58 | .company_reg = 0x3e, |
59 | .company_id = 0x61, |
60 | .verstep_reg = 0x3f, |
61 | .verstep_id = 0x6d, |
62 | .addresses = normal_i2c, |
63 | }, |
64 | }; |
65 | |
66 | /* |
67 | * Defines the highest register to be used, not the count. |
68 | * The actual count will probably be smaller because of gaps |
69 | * in the implementation (unused register locations). |
70 | * This define will safely set the array size of both the parameter |
71 | * and data arrays. |
72 | * This comes from the data sheet register description table. |
73 | */ |
74 | #define LAST_REGISTER 0xff |
75 | |
76 | struct asc7621_data { |
77 | struct i2c_client client; |
78 | struct device *class_dev; |
79 | struct mutex update_lock; |
80 | bool valid; /* true if following fields are valid */ |
81 | unsigned long last_high_reading; /* In jiffies */ |
82 | unsigned long last_low_reading; /* In jiffies */ |
83 | /* |
84 | * Registers we care about occupy the corresponding index |
85 | * in the array. Registers we don't care about are left |
86 | * at 0. |
87 | */ |
88 | u8 reg[LAST_REGISTER + 1]; |
89 | }; |
90 | |
91 | /* |
92 | * Macro to get the parent asc7621_param structure |
93 | * from a sensor_device_attribute passed into the |
94 | * show/store functions. |
95 | */ |
96 | #define to_asc7621_param(_sda) \ |
97 | container_of(_sda, struct asc7621_param, sda) |
98 | |
99 | /* |
100 | * Each parameter to be retrieved needs an asc7621_param structure |
101 | * allocated. It contains the sensor_device_attribute structure |
102 | * and the control info needed to retrieve the value from the register map. |
103 | */ |
104 | struct asc7621_param { |
105 | struct sensor_device_attribute sda; |
106 | u8 priority; |
107 | u8 msb[3]; |
108 | u8 lsb[3]; |
109 | u8 mask[3]; |
110 | u8 shift[3]; |
111 | }; |
112 | |
113 | /* |
114 | * This is the map that ultimately indicates whether we'll be |
115 | * retrieving a register value or not, and at what frequency. |
116 | */ |
117 | static u8 asc7621_register_priorities[255]; |
118 | |
119 | static struct asc7621_data *asc7621_update_device(struct device *dev); |
120 | |
121 | static inline u8 read_byte(struct i2c_client *client, u8 reg) |
122 | { |
123 | int res = i2c_smbus_read_byte_data(client, command: reg); |
124 | if (res < 0) { |
125 | dev_err(&client->dev, |
126 | "Unable to read from register 0x%02x.\n" , reg); |
127 | return 0; |
128 | } |
129 | return res & 0xff; |
130 | } |
131 | |
132 | static inline int write_byte(struct i2c_client *client, u8 reg, u8 data) |
133 | { |
134 | int res = i2c_smbus_write_byte_data(client, command: reg, value: data); |
135 | if (res < 0) { |
136 | dev_err(&client->dev, |
137 | "Unable to write value 0x%02x to register 0x%02x.\n" , |
138 | data, reg); |
139 | } |
140 | return res; |
141 | } |
142 | |
143 | /* |
144 | * Data Handlers |
145 | * Each function handles the formatting, storage |
146 | * and retrieval of like parameters. |
147 | */ |
148 | |
149 | #define SETUP_SHOW_DATA_PARAM(d, a) \ |
150 | struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \ |
151 | struct asc7621_data *data = asc7621_update_device(d); \ |
152 | struct asc7621_param *param = to_asc7621_param(sda) |
153 | |
154 | #define SETUP_STORE_DATA_PARAM(d, a) \ |
155 | struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \ |
156 | struct i2c_client *client = to_i2c_client(d); \ |
157 | struct asc7621_data *data = i2c_get_clientdata(client); \ |
158 | struct asc7621_param *param = to_asc7621_param(sda) |
159 | |
160 | /* |
161 | * u8 is just what it sounds like...an unsigned byte with no |
162 | * special formatting. |
163 | */ |
164 | static ssize_t show_u8(struct device *dev, struct device_attribute *attr, |
165 | char *buf) |
166 | { |
167 | SETUP_SHOW_DATA_PARAM(dev, attr); |
168 | |
169 | return sprintf(buf, fmt: "%u\n" , data->reg[param->msb[0]]); |
170 | } |
171 | |
172 | static ssize_t store_u8(struct device *dev, struct device_attribute *attr, |
173 | const char *buf, size_t count) |
174 | { |
175 | SETUP_STORE_DATA_PARAM(dev, attr); |
176 | long reqval; |
177 | |
178 | if (kstrtol(s: buf, base: 10, res: &reqval)) |
179 | return -EINVAL; |
180 | |
181 | reqval = clamp_val(reqval, 0, 255); |
182 | |
183 | mutex_lock(&data->update_lock); |
184 | data->reg[param->msb[0]] = reqval; |
185 | write_byte(client, reg: param->msb[0], data: reqval); |
186 | mutex_unlock(lock: &data->update_lock); |
187 | return count; |
188 | } |
189 | |
190 | /* |
191 | * Many of the config values occupy only a few bits of a register. |
192 | */ |
193 | static ssize_t show_bitmask(struct device *dev, |
194 | struct device_attribute *attr, char *buf) |
195 | { |
196 | SETUP_SHOW_DATA_PARAM(dev, attr); |
197 | |
198 | return sprintf(buf, fmt: "%u\n" , |
199 | (data->reg[param->msb[0]] >> param-> |
200 | shift[0]) & param->mask[0]); |
201 | } |
202 | |
203 | static ssize_t store_bitmask(struct device *dev, |
204 | struct device_attribute *attr, |
205 | const char *buf, size_t count) |
206 | { |
207 | SETUP_STORE_DATA_PARAM(dev, attr); |
208 | long reqval; |
209 | u8 currval; |
210 | |
211 | if (kstrtol(s: buf, base: 10, res: &reqval)) |
212 | return -EINVAL; |
213 | |
214 | reqval = clamp_val(reqval, 0, param->mask[0]); |
215 | |
216 | reqval = (reqval & param->mask[0]) << param->shift[0]; |
217 | |
218 | mutex_lock(&data->update_lock); |
219 | currval = read_byte(client, reg: param->msb[0]); |
220 | reqval |= (currval & ~(param->mask[0] << param->shift[0])); |
221 | data->reg[param->msb[0]] = reqval; |
222 | write_byte(client, reg: param->msb[0], data: reqval); |
223 | mutex_unlock(lock: &data->update_lock); |
224 | return count; |
225 | } |
226 | |
227 | /* |
228 | * 16 bit fan rpm values |
229 | * reported by the device as the number of 11.111us periods (90khz) |
230 | * between full fan rotations. Therefore... |
231 | * RPM = (90000 * 60) / register value |
232 | */ |
233 | static ssize_t show_fan16(struct device *dev, |
234 | struct device_attribute *attr, char *buf) |
235 | { |
236 | SETUP_SHOW_DATA_PARAM(dev, attr); |
237 | u16 regval; |
238 | |
239 | mutex_lock(&data->update_lock); |
240 | regval = (data->reg[param->msb[0]] << 8) | data->reg[param->lsb[0]]; |
241 | mutex_unlock(lock: &data->update_lock); |
242 | |
243 | return sprintf(buf, fmt: "%u\n" , |
244 | (regval == 0 ? -1 : (regval) == |
245 | 0xffff ? 0 : 5400000 / regval)); |
246 | } |
247 | |
248 | static ssize_t store_fan16(struct device *dev, |
249 | struct device_attribute *attr, const char *buf, |
250 | size_t count) |
251 | { |
252 | SETUP_STORE_DATA_PARAM(dev, attr); |
253 | long reqval; |
254 | |
255 | if (kstrtol(s: buf, base: 10, res: &reqval)) |
256 | return -EINVAL; |
257 | |
258 | /* |
259 | * If a minimum RPM of zero is requested, then we set the register to |
260 | * 0xffff. This value allows the fan to be stopped completely without |
261 | * generating an alarm. |
262 | */ |
263 | reqval = |
264 | (reqval <= 0 ? 0xffff : clamp_val(5400000 / reqval, 0, 0xfffe)); |
265 | |
266 | mutex_lock(&data->update_lock); |
267 | data->reg[param->msb[0]] = (reqval >> 8) & 0xff; |
268 | data->reg[param->lsb[0]] = reqval & 0xff; |
269 | write_byte(client, reg: param->msb[0], data: data->reg[param->msb[0]]); |
270 | write_byte(client, reg: param->lsb[0], data: data->reg[param->lsb[0]]); |
271 | mutex_unlock(lock: &data->update_lock); |
272 | |
273 | return count; |
274 | } |
275 | |
276 | /* |
277 | * Voltages are scaled in the device so that the nominal voltage |
278 | * is 3/4ths of the 0-255 range (i.e. 192). |
279 | * If all voltages are 'normal' then all voltage registers will |
280 | * read 0xC0. |
281 | * |
282 | * The data sheet provides us with the 3/4 scale value for each voltage |
283 | * which is stored in in_scaling. The sda->index parameter value provides |
284 | * the index into in_scaling. |
285 | * |
286 | * NOTE: The chip expects the first 2 inputs be 2.5 and 2.25 volts |
287 | * respectively. That doesn't mean that's what the motherboard provides. :) |
288 | */ |
289 | |
290 | static const int asc7621_in_scaling[] = { |
291 | 2500, 2250, 3300, 5000, 12000 |
292 | }; |
293 | |
294 | static ssize_t show_in10(struct device *dev, struct device_attribute *attr, |
295 | char *buf) |
296 | { |
297 | SETUP_SHOW_DATA_PARAM(dev, attr); |
298 | u16 regval; |
299 | u8 nr = sda->index; |
300 | |
301 | mutex_lock(&data->update_lock); |
302 | regval = (data->reg[param->msb[0]] << 8) | (data->reg[param->lsb[0]]); |
303 | mutex_unlock(lock: &data->update_lock); |
304 | |
305 | /* The LSB value is a 2-bit scaling of the MSB's LSbit value. */ |
306 | regval = (regval >> 6) * asc7621_in_scaling[nr] / (0xc0 << 2); |
307 | |
308 | return sprintf(buf, fmt: "%u\n" , regval); |
309 | } |
310 | |
311 | /* 8 bit voltage values (the mins and maxs) */ |
312 | static ssize_t show_in8(struct device *dev, struct device_attribute *attr, |
313 | char *buf) |
314 | { |
315 | SETUP_SHOW_DATA_PARAM(dev, attr); |
316 | u8 nr = sda->index; |
317 | |
318 | return sprintf(buf, fmt: "%u\n" , |
319 | ((data->reg[param->msb[0]] * |
320 | asc7621_in_scaling[nr]) / 0xc0)); |
321 | } |
322 | |
323 | static ssize_t store_in8(struct device *dev, struct device_attribute *attr, |
324 | const char *buf, size_t count) |
325 | { |
326 | SETUP_STORE_DATA_PARAM(dev, attr); |
327 | long reqval; |
328 | u8 nr = sda->index; |
329 | |
330 | if (kstrtol(s: buf, base: 10, res: &reqval)) |
331 | return -EINVAL; |
332 | |
333 | reqval = clamp_val(reqval, 0, 0xffff); |
334 | |
335 | reqval = reqval * 0xc0 / asc7621_in_scaling[nr]; |
336 | |
337 | reqval = clamp_val(reqval, 0, 0xff); |
338 | |
339 | mutex_lock(&data->update_lock); |
340 | data->reg[param->msb[0]] = reqval; |
341 | write_byte(client, reg: param->msb[0], data: reqval); |
342 | mutex_unlock(lock: &data->update_lock); |
343 | |
344 | return count; |
345 | } |
346 | |
347 | static ssize_t show_temp8(struct device *dev, |
348 | struct device_attribute *attr, char *buf) |
349 | { |
350 | SETUP_SHOW_DATA_PARAM(dev, attr); |
351 | |
352 | return sprintf(buf, fmt: "%d\n" , ((s8) data->reg[param->msb[0]]) * 1000); |
353 | } |
354 | |
355 | static ssize_t store_temp8(struct device *dev, |
356 | struct device_attribute *attr, const char *buf, |
357 | size_t count) |
358 | { |
359 | SETUP_STORE_DATA_PARAM(dev, attr); |
360 | long reqval; |
361 | s8 temp; |
362 | |
363 | if (kstrtol(s: buf, base: 10, res: &reqval)) |
364 | return -EINVAL; |
365 | |
366 | reqval = clamp_val(reqval, -127000, 127000); |
367 | |
368 | temp = reqval / 1000; |
369 | |
370 | mutex_lock(&data->update_lock); |
371 | data->reg[param->msb[0]] = temp; |
372 | write_byte(client, reg: param->msb[0], data: temp); |
373 | mutex_unlock(lock: &data->update_lock); |
374 | return count; |
375 | } |
376 | |
377 | /* |
378 | * Temperatures that occupy 2 bytes always have the whole |
379 | * number of degrees in the MSB with some part of the LSB |
380 | * indicating fractional degrees. |
381 | */ |
382 | |
383 | /* mmmmmmmm.llxxxxxx */ |
384 | static ssize_t show_temp10(struct device *dev, |
385 | struct device_attribute *attr, char *buf) |
386 | { |
387 | SETUP_SHOW_DATA_PARAM(dev, attr); |
388 | u8 msb, lsb; |
389 | int temp; |
390 | |
391 | mutex_lock(&data->update_lock); |
392 | msb = data->reg[param->msb[0]]; |
393 | lsb = (data->reg[param->lsb[0]] >> 6) & 0x03; |
394 | temp = (((s8) msb) * 1000) + (lsb * 250); |
395 | mutex_unlock(lock: &data->update_lock); |
396 | |
397 | return sprintf(buf, fmt: "%d\n" , temp); |
398 | } |
399 | |
400 | /* mmmmmm.ll */ |
401 | static ssize_t show_temp62(struct device *dev, |
402 | struct device_attribute *attr, char *buf) |
403 | { |
404 | SETUP_SHOW_DATA_PARAM(dev, attr); |
405 | u8 regval = data->reg[param->msb[0]]; |
406 | int temp = ((s8) (regval & 0xfc) * 1000) + ((regval & 0x03) * 250); |
407 | |
408 | return sprintf(buf, fmt: "%d\n" , temp); |
409 | } |
410 | |
411 | static ssize_t store_temp62(struct device *dev, |
412 | struct device_attribute *attr, const char *buf, |
413 | size_t count) |
414 | { |
415 | SETUP_STORE_DATA_PARAM(dev, attr); |
416 | long reqval, i, f; |
417 | s8 temp; |
418 | |
419 | if (kstrtol(s: buf, base: 10, res: &reqval)) |
420 | return -EINVAL; |
421 | |
422 | reqval = clamp_val(reqval, -32000, 31750); |
423 | i = reqval / 1000; |
424 | f = reqval - (i * 1000); |
425 | temp = i << 2; |
426 | temp |= f / 250; |
427 | |
428 | mutex_lock(&data->update_lock); |
429 | data->reg[param->msb[0]] = temp; |
430 | write_byte(client, reg: param->msb[0], data: temp); |
431 | mutex_unlock(lock: &data->update_lock); |
432 | return count; |
433 | } |
434 | |
435 | /* |
436 | * The aSC7621 doesn't provide an "auto_point2". Instead, you |
437 | * specify the auto_point1 and a range. To keep with the sysfs |
438 | * hwmon specs, we synthesize the auto_point_2 from them. |
439 | */ |
440 | |
441 | static const u32 asc7621_range_map[] = { |
442 | 2000, 2500, 3330, 4000, 5000, 6670, 8000, 10000, |
443 | 13330, 16000, 20000, 26670, 32000, 40000, 53330, 80000, |
444 | }; |
445 | |
446 | static ssize_t show_ap2_temp(struct device *dev, |
447 | struct device_attribute *attr, char *buf) |
448 | { |
449 | SETUP_SHOW_DATA_PARAM(dev, attr); |
450 | long auto_point1; |
451 | u8 regval; |
452 | int temp; |
453 | |
454 | mutex_lock(&data->update_lock); |
455 | auto_point1 = ((s8) data->reg[param->msb[1]]) * 1000; |
456 | regval = |
457 | ((data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]); |
458 | temp = auto_point1 + asc7621_range_map[clamp_val(regval, 0, 15)]; |
459 | mutex_unlock(lock: &data->update_lock); |
460 | |
461 | return sprintf(buf, fmt: "%d\n" , temp); |
462 | |
463 | } |
464 | |
465 | static ssize_t store_ap2_temp(struct device *dev, |
466 | struct device_attribute *attr, |
467 | const char *buf, size_t count) |
468 | { |
469 | SETUP_STORE_DATA_PARAM(dev, attr); |
470 | long reqval, auto_point1; |
471 | int i; |
472 | u8 currval, newval = 0; |
473 | |
474 | if (kstrtol(s: buf, base: 10, res: &reqval)) |
475 | return -EINVAL; |
476 | |
477 | mutex_lock(&data->update_lock); |
478 | auto_point1 = data->reg[param->msb[1]] * 1000; |
479 | reqval = clamp_val(reqval, auto_point1 + 2000, auto_point1 + 80000); |
480 | |
481 | for (i = ARRAY_SIZE(asc7621_range_map) - 1; i >= 0; i--) { |
482 | if (reqval >= auto_point1 + asc7621_range_map[i]) { |
483 | newval = i; |
484 | break; |
485 | } |
486 | } |
487 | |
488 | newval = (newval & param->mask[0]) << param->shift[0]; |
489 | currval = read_byte(client, reg: param->msb[0]); |
490 | newval |= (currval & ~(param->mask[0] << param->shift[0])); |
491 | data->reg[param->msb[0]] = newval; |
492 | write_byte(client, reg: param->msb[0], data: newval); |
493 | mutex_unlock(lock: &data->update_lock); |
494 | return count; |
495 | } |
496 | |
497 | static ssize_t show_pwm_ac(struct device *dev, |
498 | struct device_attribute *attr, char *buf) |
499 | { |
500 | SETUP_SHOW_DATA_PARAM(dev, attr); |
501 | u8 config, altbit, regval; |
502 | static const u8 map[] = { |
503 | 0x01, 0x02, 0x04, 0x1f, 0x00, 0x06, 0x07, 0x10, |
504 | 0x08, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f |
505 | }; |
506 | |
507 | mutex_lock(&data->update_lock); |
508 | config = (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; |
509 | altbit = (data->reg[param->msb[1]] >> param->shift[1]) & param->mask[1]; |
510 | regval = config | (altbit << 3); |
511 | mutex_unlock(lock: &data->update_lock); |
512 | |
513 | return sprintf(buf, fmt: "%u\n" , map[clamp_val(regval, 0, 15)]); |
514 | } |
515 | |
516 | static ssize_t store_pwm_ac(struct device *dev, |
517 | struct device_attribute *attr, |
518 | const char *buf, size_t count) |
519 | { |
520 | SETUP_STORE_DATA_PARAM(dev, attr); |
521 | unsigned long reqval; |
522 | u8 currval, config, altbit, newval; |
523 | static const u16 map[] = { |
524 | 0x04, 0x00, 0x01, 0xff, 0x02, 0xff, 0x05, 0x06, |
525 | 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, |
526 | 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
527 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, |
528 | }; |
529 | |
530 | if (kstrtoul(s: buf, base: 10, res: &reqval)) |
531 | return -EINVAL; |
532 | |
533 | if (reqval > 31) |
534 | return -EINVAL; |
535 | |
536 | reqval = map[reqval]; |
537 | if (reqval == 0xff) |
538 | return -EINVAL; |
539 | |
540 | config = reqval & 0x07; |
541 | altbit = (reqval >> 3) & 0x01; |
542 | |
543 | config = (config & param->mask[0]) << param->shift[0]; |
544 | altbit = (altbit & param->mask[1]) << param->shift[1]; |
545 | |
546 | mutex_lock(&data->update_lock); |
547 | currval = read_byte(client, reg: param->msb[0]); |
548 | newval = config | (currval & ~(param->mask[0] << param->shift[0])); |
549 | newval = altbit | (newval & ~(param->mask[1] << param->shift[1])); |
550 | data->reg[param->msb[0]] = newval; |
551 | write_byte(client, reg: param->msb[0], data: newval); |
552 | mutex_unlock(lock: &data->update_lock); |
553 | return count; |
554 | } |
555 | |
556 | static ssize_t show_pwm_enable(struct device *dev, |
557 | struct device_attribute *attr, char *buf) |
558 | { |
559 | SETUP_SHOW_DATA_PARAM(dev, attr); |
560 | u8 config, altbit, minoff, val, newval; |
561 | |
562 | mutex_lock(&data->update_lock); |
563 | config = (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; |
564 | altbit = (data->reg[param->msb[1]] >> param->shift[1]) & param->mask[1]; |
565 | minoff = (data->reg[param->msb[2]] >> param->shift[2]) & param->mask[2]; |
566 | mutex_unlock(lock: &data->update_lock); |
567 | |
568 | val = config | (altbit << 3); |
569 | |
570 | if (val == 3 || val >= 10) |
571 | newval = 255; |
572 | else if (val == 4) |
573 | newval = 0; |
574 | else if (val == 7) |
575 | newval = 1; |
576 | else if (minoff == 1) |
577 | newval = 2; |
578 | else |
579 | newval = 3; |
580 | |
581 | return sprintf(buf, fmt: "%u\n" , newval); |
582 | } |
583 | |
584 | static ssize_t store_pwm_enable(struct device *dev, |
585 | struct device_attribute *attr, |
586 | const char *buf, size_t count) |
587 | { |
588 | SETUP_STORE_DATA_PARAM(dev, attr); |
589 | long reqval; |
590 | u8 currval, config, altbit, newval, minoff = 255; |
591 | |
592 | if (kstrtol(s: buf, base: 10, res: &reqval)) |
593 | return -EINVAL; |
594 | |
595 | switch (reqval) { |
596 | case 0: |
597 | newval = 0x04; |
598 | break; |
599 | case 1: |
600 | newval = 0x07; |
601 | break; |
602 | case 2: |
603 | newval = 0x00; |
604 | minoff = 1; |
605 | break; |
606 | case 3: |
607 | newval = 0x00; |
608 | minoff = 0; |
609 | break; |
610 | case 255: |
611 | newval = 0x03; |
612 | break; |
613 | default: |
614 | return -EINVAL; |
615 | } |
616 | |
617 | config = newval & 0x07; |
618 | altbit = (newval >> 3) & 0x01; |
619 | |
620 | mutex_lock(&data->update_lock); |
621 | config = (config & param->mask[0]) << param->shift[0]; |
622 | altbit = (altbit & param->mask[1]) << param->shift[1]; |
623 | currval = read_byte(client, reg: param->msb[0]); |
624 | newval = config | (currval & ~(param->mask[0] << param->shift[0])); |
625 | newval = altbit | (newval & ~(param->mask[1] << param->shift[1])); |
626 | data->reg[param->msb[0]] = newval; |
627 | write_byte(client, reg: param->msb[0], data: newval); |
628 | if (minoff < 255) { |
629 | minoff = (minoff & param->mask[2]) << param->shift[2]; |
630 | currval = read_byte(client, reg: param->msb[2]); |
631 | newval = |
632 | minoff | (currval & ~(param->mask[2] << param->shift[2])); |
633 | data->reg[param->msb[2]] = newval; |
634 | write_byte(client, reg: param->msb[2], data: newval); |
635 | } |
636 | mutex_unlock(lock: &data->update_lock); |
637 | return count; |
638 | } |
639 | |
640 | static const u32 asc7621_pwm_freq_map[] = { |
641 | 10, 15, 23, 30, 38, 47, 62, 94, |
642 | 23000, 24000, 25000, 26000, 27000, 28000, 29000, 30000 |
643 | }; |
644 | |
645 | static ssize_t show_pwm_freq(struct device *dev, |
646 | struct device_attribute *attr, char *buf) |
647 | { |
648 | SETUP_SHOW_DATA_PARAM(dev, attr); |
649 | u8 regval = |
650 | (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; |
651 | |
652 | regval = clamp_val(regval, 0, 15); |
653 | |
654 | return sprintf(buf, fmt: "%u\n" , asc7621_pwm_freq_map[regval]); |
655 | } |
656 | |
657 | static ssize_t store_pwm_freq(struct device *dev, |
658 | struct device_attribute *attr, |
659 | const char *buf, size_t count) |
660 | { |
661 | SETUP_STORE_DATA_PARAM(dev, attr); |
662 | unsigned long reqval; |
663 | u8 currval, newval = 255; |
664 | int i; |
665 | |
666 | if (kstrtoul(s: buf, base: 10, res: &reqval)) |
667 | return -EINVAL; |
668 | |
669 | for (i = 0; i < ARRAY_SIZE(asc7621_pwm_freq_map); i++) { |
670 | if (reqval == asc7621_pwm_freq_map[i]) { |
671 | newval = i; |
672 | break; |
673 | } |
674 | } |
675 | if (newval == 255) |
676 | return -EINVAL; |
677 | |
678 | newval = (newval & param->mask[0]) << param->shift[0]; |
679 | |
680 | mutex_lock(&data->update_lock); |
681 | currval = read_byte(client, reg: param->msb[0]); |
682 | newval |= (currval & ~(param->mask[0] << param->shift[0])); |
683 | data->reg[param->msb[0]] = newval; |
684 | write_byte(client, reg: param->msb[0], data: newval); |
685 | mutex_unlock(lock: &data->update_lock); |
686 | return count; |
687 | } |
688 | |
689 | static const u32 asc7621_pwm_auto_spinup_map[] = { |
690 | 0, 100, 250, 400, 700, 1000, 2000, 4000 |
691 | }; |
692 | |
693 | static ssize_t show_pwm_ast(struct device *dev, |
694 | struct device_attribute *attr, char *buf) |
695 | { |
696 | SETUP_SHOW_DATA_PARAM(dev, attr); |
697 | u8 regval = |
698 | (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; |
699 | |
700 | regval = clamp_val(regval, 0, 7); |
701 | |
702 | return sprintf(buf, fmt: "%u\n" , asc7621_pwm_auto_spinup_map[regval]); |
703 | |
704 | } |
705 | |
706 | static ssize_t store_pwm_ast(struct device *dev, |
707 | struct device_attribute *attr, |
708 | const char *buf, size_t count) |
709 | { |
710 | SETUP_STORE_DATA_PARAM(dev, attr); |
711 | long reqval; |
712 | u8 currval, newval = 255; |
713 | u32 i; |
714 | |
715 | if (kstrtol(s: buf, base: 10, res: &reqval)) |
716 | return -EINVAL; |
717 | |
718 | for (i = 0; i < ARRAY_SIZE(asc7621_pwm_auto_spinup_map); i++) { |
719 | if (reqval == asc7621_pwm_auto_spinup_map[i]) { |
720 | newval = i; |
721 | break; |
722 | } |
723 | } |
724 | if (newval == 255) |
725 | return -EINVAL; |
726 | |
727 | newval = (newval & param->mask[0]) << param->shift[0]; |
728 | |
729 | mutex_lock(&data->update_lock); |
730 | currval = read_byte(client, reg: param->msb[0]); |
731 | newval |= (currval & ~(param->mask[0] << param->shift[0])); |
732 | data->reg[param->msb[0]] = newval; |
733 | write_byte(client, reg: param->msb[0], data: newval); |
734 | mutex_unlock(lock: &data->update_lock); |
735 | return count; |
736 | } |
737 | |
738 | static const u32 asc7621_temp_smoothing_time_map[] = { |
739 | 35000, 17600, 11800, 7000, 4400, 3000, 1600, 800 |
740 | }; |
741 | |
742 | static ssize_t show_temp_st(struct device *dev, |
743 | struct device_attribute *attr, char *buf) |
744 | { |
745 | SETUP_SHOW_DATA_PARAM(dev, attr); |
746 | u8 regval = |
747 | (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; |
748 | regval = clamp_val(regval, 0, 7); |
749 | |
750 | return sprintf(buf, fmt: "%u\n" , asc7621_temp_smoothing_time_map[regval]); |
751 | } |
752 | |
753 | static ssize_t store_temp_st(struct device *dev, |
754 | struct device_attribute *attr, |
755 | const char *buf, size_t count) |
756 | { |
757 | SETUP_STORE_DATA_PARAM(dev, attr); |
758 | long reqval; |
759 | u8 currval, newval = 255; |
760 | u32 i; |
761 | |
762 | if (kstrtol(s: buf, base: 10, res: &reqval)) |
763 | return -EINVAL; |
764 | |
765 | for (i = 0; i < ARRAY_SIZE(asc7621_temp_smoothing_time_map); i++) { |
766 | if (reqval == asc7621_temp_smoothing_time_map[i]) { |
767 | newval = i; |
768 | break; |
769 | } |
770 | } |
771 | |
772 | if (newval == 255) |
773 | return -EINVAL; |
774 | |
775 | newval = (newval & param->mask[0]) << param->shift[0]; |
776 | |
777 | mutex_lock(&data->update_lock); |
778 | currval = read_byte(client, reg: param->msb[0]); |
779 | newval |= (currval & ~(param->mask[0] << param->shift[0])); |
780 | data->reg[param->msb[0]] = newval; |
781 | write_byte(client, reg: param->msb[0], data: newval); |
782 | mutex_unlock(lock: &data->update_lock); |
783 | return count; |
784 | } |
785 | |
786 | /* |
787 | * End of data handlers |
788 | * |
789 | * These defines do nothing more than make the table easier |
790 | * to read when wrapped at column 80. |
791 | */ |
792 | |
793 | /* |
794 | * Creates a variable length array inititalizer. |
795 | * VAA(1,3,5,7) would produce {1,3,5,7} |
796 | */ |
797 | #define VAA(args...) {args} |
798 | |
799 | #define PREAD(name, n, pri, rm, rl, m, s, r) \ |
800 | {.sda = SENSOR_ATTR(name, S_IRUGO, show_##r, NULL, n), \ |
801 | .priority = pri, .msb[0] = rm, .lsb[0] = rl, .mask[0] = m, \ |
802 | .shift[0] = s,} |
803 | |
804 | #define PWRITE(name, n, pri, rm, rl, m, s, r) \ |
805 | {.sda = SENSOR_ATTR(name, S_IRUGO | S_IWUSR, show_##r, store_##r, n), \ |
806 | .priority = pri, .msb[0] = rm, .lsb[0] = rl, .mask[0] = m, \ |
807 | .shift[0] = s,} |
808 | |
809 | /* |
810 | * PWRITEM assumes that the initializers for the .msb, .lsb, .mask and .shift |
811 | * were created using the VAA macro. |
812 | */ |
813 | #define PWRITEM(name, n, pri, rm, rl, m, s, r) \ |
814 | {.sda = SENSOR_ATTR(name, S_IRUGO | S_IWUSR, show_##r, store_##r, n), \ |
815 | .priority = pri, .msb = rm, .lsb = rl, .mask = m, .shift = s,} |
816 | |
817 | static struct asc7621_param asc7621_params[] = { |
818 | PREAD(in0_input, 0, PRI_HIGH, 0x20, 0x13, 0, 0, in10), |
819 | PREAD(in1_input, 1, PRI_HIGH, 0x21, 0x18, 0, 0, in10), |
820 | PREAD(in2_input, 2, PRI_HIGH, 0x22, 0x11, 0, 0, in10), |
821 | PREAD(in3_input, 3, PRI_HIGH, 0x23, 0x12, 0, 0, in10), |
822 | PREAD(in4_input, 4, PRI_HIGH, 0x24, 0x14, 0, 0, in10), |
823 | |
824 | PWRITE(in0_min, 0, PRI_LOW, 0x44, 0, 0, 0, in8), |
825 | PWRITE(in1_min, 1, PRI_LOW, 0x46, 0, 0, 0, in8), |
826 | PWRITE(in2_min, 2, PRI_LOW, 0x48, 0, 0, 0, in8), |
827 | PWRITE(in3_min, 3, PRI_LOW, 0x4a, 0, 0, 0, in8), |
828 | PWRITE(in4_min, 4, PRI_LOW, 0x4c, 0, 0, 0, in8), |
829 | |
830 | PWRITE(in0_max, 0, PRI_LOW, 0x45, 0, 0, 0, in8), |
831 | PWRITE(in1_max, 1, PRI_LOW, 0x47, 0, 0, 0, in8), |
832 | PWRITE(in2_max, 2, PRI_LOW, 0x49, 0, 0, 0, in8), |
833 | PWRITE(in3_max, 3, PRI_LOW, 0x4b, 0, 0, 0, in8), |
834 | PWRITE(in4_max, 4, PRI_LOW, 0x4d, 0, 0, 0, in8), |
835 | |
836 | PREAD(in0_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 0, bitmask), |
837 | PREAD(in1_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 1, bitmask), |
838 | PREAD(in2_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 2, bitmask), |
839 | PREAD(in3_alarm, 3, PRI_HIGH, 0x41, 0, 0x01, 3, bitmask), |
840 | PREAD(in4_alarm, 4, PRI_HIGH, 0x42, 0, 0x01, 0, bitmask), |
841 | |
842 | PREAD(fan1_input, 0, PRI_HIGH, 0x29, 0x28, 0, 0, fan16), |
843 | PREAD(fan2_input, 1, PRI_HIGH, 0x2b, 0x2a, 0, 0, fan16), |
844 | PREAD(fan3_input, 2, PRI_HIGH, 0x2d, 0x2c, 0, 0, fan16), |
845 | PREAD(fan4_input, 3, PRI_HIGH, 0x2f, 0x2e, 0, 0, fan16), |
846 | |
847 | PWRITE(fan1_min, 0, PRI_LOW, 0x55, 0x54, 0, 0, fan16), |
848 | PWRITE(fan2_min, 1, PRI_LOW, 0x57, 0x56, 0, 0, fan16), |
849 | PWRITE(fan3_min, 2, PRI_LOW, 0x59, 0x58, 0, 0, fan16), |
850 | PWRITE(fan4_min, 3, PRI_LOW, 0x5b, 0x5a, 0, 0, fan16), |
851 | |
852 | PREAD(fan1_alarm, 0, PRI_HIGH, 0x42, 0, 0x01, 2, bitmask), |
853 | PREAD(fan2_alarm, 1, PRI_HIGH, 0x42, 0, 0x01, 3, bitmask), |
854 | PREAD(fan3_alarm, 2, PRI_HIGH, 0x42, 0, 0x01, 4, bitmask), |
855 | PREAD(fan4_alarm, 3, PRI_HIGH, 0x42, 0, 0x01, 5, bitmask), |
856 | |
857 | PREAD(temp1_input, 0, PRI_HIGH, 0x25, 0x10, 0, 0, temp10), |
858 | PREAD(temp2_input, 1, PRI_HIGH, 0x26, 0x15, 0, 0, temp10), |
859 | PREAD(temp3_input, 2, PRI_HIGH, 0x27, 0x16, 0, 0, temp10), |
860 | PREAD(temp4_input, 3, PRI_HIGH, 0x33, 0x17, 0, 0, temp10), |
861 | PREAD(temp5_input, 4, PRI_HIGH, 0xf7, 0xf6, 0, 0, temp10), |
862 | PREAD(temp6_input, 5, PRI_HIGH, 0xf9, 0xf8, 0, 0, temp10), |
863 | PREAD(temp7_input, 6, PRI_HIGH, 0xfb, 0xfa, 0, 0, temp10), |
864 | PREAD(temp8_input, 7, PRI_HIGH, 0xfd, 0xfc, 0, 0, temp10), |
865 | |
866 | PWRITE(temp1_min, 0, PRI_LOW, 0x4e, 0, 0, 0, temp8), |
867 | PWRITE(temp2_min, 1, PRI_LOW, 0x50, 0, 0, 0, temp8), |
868 | PWRITE(temp3_min, 2, PRI_LOW, 0x52, 0, 0, 0, temp8), |
869 | PWRITE(temp4_min, 3, PRI_LOW, 0x34, 0, 0, 0, temp8), |
870 | |
871 | PWRITE(temp1_max, 0, PRI_LOW, 0x4f, 0, 0, 0, temp8), |
872 | PWRITE(temp2_max, 1, PRI_LOW, 0x51, 0, 0, 0, temp8), |
873 | PWRITE(temp3_max, 2, PRI_LOW, 0x53, 0, 0, 0, temp8), |
874 | PWRITE(temp4_max, 3, PRI_LOW, 0x35, 0, 0, 0, temp8), |
875 | |
876 | PREAD(temp1_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 4, bitmask), |
877 | PREAD(temp2_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 5, bitmask), |
878 | PREAD(temp3_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 6, bitmask), |
879 | PREAD(temp4_alarm, 3, PRI_HIGH, 0x43, 0, 0x01, 0, bitmask), |
880 | |
881 | PWRITE(temp1_source, 0, PRI_LOW, 0x02, 0, 0x07, 4, bitmask), |
882 | PWRITE(temp2_source, 1, PRI_LOW, 0x02, 0, 0x07, 0, bitmask), |
883 | PWRITE(temp3_source, 2, PRI_LOW, 0x03, 0, 0x07, 4, bitmask), |
884 | PWRITE(temp4_source, 3, PRI_LOW, 0x03, 0, 0x07, 0, bitmask), |
885 | |
886 | PWRITE(temp1_smoothing_enable, 0, PRI_LOW, 0x62, 0, 0x01, 3, bitmask), |
887 | PWRITE(temp2_smoothing_enable, 1, PRI_LOW, 0x63, 0, 0x01, 7, bitmask), |
888 | PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x63, 0, 0x01, 3, bitmask), |
889 | PWRITE(temp4_smoothing_enable, 3, PRI_LOW, 0x3c, 0, 0x01, 3, bitmask), |
890 | |
891 | PWRITE(temp1_smoothing_time, 0, PRI_LOW, 0x62, 0, 0x07, 0, temp_st), |
892 | PWRITE(temp2_smoothing_time, 1, PRI_LOW, 0x63, 0, 0x07, 4, temp_st), |
893 | PWRITE(temp3_smoothing_time, 2, PRI_LOW, 0x63, 0, 0x07, 0, temp_st), |
894 | PWRITE(temp4_smoothing_time, 3, PRI_LOW, 0x3c, 0, 0x07, 0, temp_st), |
895 | |
896 | PWRITE(temp1_auto_point1_temp_hyst, 0, PRI_LOW, 0x6d, 0, 0x0f, 4, |
897 | bitmask), |
898 | PWRITE(temp2_auto_point1_temp_hyst, 1, PRI_LOW, 0x6d, 0, 0x0f, 0, |
899 | bitmask), |
900 | PWRITE(temp3_auto_point1_temp_hyst, 2, PRI_LOW, 0x6e, 0, 0x0f, 4, |
901 | bitmask), |
902 | PWRITE(temp4_auto_point1_temp_hyst, 3, PRI_LOW, 0x6e, 0, 0x0f, 0, |
903 | bitmask), |
904 | |
905 | PREAD(temp1_auto_point2_temp_hyst, 0, PRI_LOW, 0x6d, 0, 0x0f, 4, |
906 | bitmask), |
907 | PREAD(temp2_auto_point2_temp_hyst, 1, PRI_LOW, 0x6d, 0, 0x0f, 0, |
908 | bitmask), |
909 | PREAD(temp3_auto_point2_temp_hyst, 2, PRI_LOW, 0x6e, 0, 0x0f, 4, |
910 | bitmask), |
911 | PREAD(temp4_auto_point2_temp_hyst, 3, PRI_LOW, 0x6e, 0, 0x0f, 0, |
912 | bitmask), |
913 | |
914 | PWRITE(temp1_auto_point1_temp, 0, PRI_LOW, 0x67, 0, 0, 0, temp8), |
915 | PWRITE(temp2_auto_point1_temp, 1, PRI_LOW, 0x68, 0, 0, 0, temp8), |
916 | PWRITE(temp3_auto_point1_temp, 2, PRI_LOW, 0x69, 0, 0, 0, temp8), |
917 | PWRITE(temp4_auto_point1_temp, 3, PRI_LOW, 0x3b, 0, 0, 0, temp8), |
918 | |
919 | PWRITEM(temp1_auto_point2_temp, 0, PRI_LOW, VAA(0x5f, 0x67), VAA(0), |
920 | VAA(0x0f), VAA(4), ap2_temp), |
921 | PWRITEM(temp2_auto_point2_temp, 1, PRI_LOW, VAA(0x60, 0x68), VAA(0), |
922 | VAA(0x0f), VAA(4), ap2_temp), |
923 | PWRITEM(temp3_auto_point2_temp, 2, PRI_LOW, VAA(0x61, 0x69), VAA(0), |
924 | VAA(0x0f), VAA(4), ap2_temp), |
925 | PWRITEM(temp4_auto_point2_temp, 3, PRI_LOW, VAA(0x3c, 0x3b), VAA(0), |
926 | VAA(0x0f), VAA(4), ap2_temp), |
927 | |
928 | PWRITE(temp1_crit, 0, PRI_LOW, 0x6a, 0, 0, 0, temp8), |
929 | PWRITE(temp2_crit, 1, PRI_LOW, 0x6b, 0, 0, 0, temp8), |
930 | PWRITE(temp3_crit, 2, PRI_LOW, 0x6c, 0, 0, 0, temp8), |
931 | PWRITE(temp4_crit, 3, PRI_LOW, 0x3d, 0, 0, 0, temp8), |
932 | |
933 | PWRITE(temp5_enable, 4, PRI_LOW, 0x0e, 0, 0x01, 0, bitmask), |
934 | PWRITE(temp6_enable, 5, PRI_LOW, 0x0e, 0, 0x01, 1, bitmask), |
935 | PWRITE(temp7_enable, 6, PRI_LOW, 0x0e, 0, 0x01, 2, bitmask), |
936 | PWRITE(temp8_enable, 7, PRI_LOW, 0x0e, 0, 0x01, 3, bitmask), |
937 | |
938 | PWRITE(remote1_offset, 0, PRI_LOW, 0x1c, 0, 0, 0, temp62), |
939 | PWRITE(remote2_offset, 1, PRI_LOW, 0x1d, 0, 0, 0, temp62), |
940 | |
941 | PWRITE(pwm1, 0, PRI_HIGH, 0x30, 0, 0, 0, u8), |
942 | PWRITE(pwm2, 1, PRI_HIGH, 0x31, 0, 0, 0, u8), |
943 | PWRITE(pwm3, 2, PRI_HIGH, 0x32, 0, 0, 0, u8), |
944 | |
945 | PWRITE(pwm1_invert, 0, PRI_LOW, 0x5c, 0, 0x01, 4, bitmask), |
946 | PWRITE(pwm2_invert, 1, PRI_LOW, 0x5d, 0, 0x01, 4, bitmask), |
947 | PWRITE(pwm3_invert, 2, PRI_LOW, 0x5e, 0, 0x01, 4, bitmask), |
948 | |
949 | PWRITEM(pwm1_enable, 0, PRI_LOW, VAA(0x5c, 0x5c, 0x62), VAA(0, 0, 0), |
950 | VAA(0x07, 0x01, 0x01), VAA(5, 3, 5), pwm_enable), |
951 | PWRITEM(pwm2_enable, 1, PRI_LOW, VAA(0x5d, 0x5d, 0x62), VAA(0, 0, 0), |
952 | VAA(0x07, 0x01, 0x01), VAA(5, 3, 6), pwm_enable), |
953 | PWRITEM(pwm3_enable, 2, PRI_LOW, VAA(0x5e, 0x5e, 0x62), VAA(0, 0, 0), |
954 | VAA(0x07, 0x01, 0x01), VAA(5, 3, 7), pwm_enable), |
955 | |
956 | PWRITEM(pwm1_auto_channels, 0, PRI_LOW, VAA(0x5c, 0x5c), VAA(0, 0), |
957 | VAA(0x07, 0x01), VAA(5, 3), pwm_ac), |
958 | PWRITEM(pwm2_auto_channels, 1, PRI_LOW, VAA(0x5d, 0x5d), VAA(0, 0), |
959 | VAA(0x07, 0x01), VAA(5, 3), pwm_ac), |
960 | PWRITEM(pwm3_auto_channels, 2, PRI_LOW, VAA(0x5e, 0x5e), VAA(0, 0), |
961 | VAA(0x07, 0x01), VAA(5, 3), pwm_ac), |
962 | |
963 | PWRITE(pwm1_auto_point1_pwm, 0, PRI_LOW, 0x64, 0, 0, 0, u8), |
964 | PWRITE(pwm2_auto_point1_pwm, 1, PRI_LOW, 0x65, 0, 0, 0, u8), |
965 | PWRITE(pwm3_auto_point1_pwm, 2, PRI_LOW, 0x66, 0, 0, 0, u8), |
966 | |
967 | PWRITE(pwm1_auto_point2_pwm, 0, PRI_LOW, 0x38, 0, 0, 0, u8), |
968 | PWRITE(pwm2_auto_point2_pwm, 1, PRI_LOW, 0x39, 0, 0, 0, u8), |
969 | PWRITE(pwm3_auto_point2_pwm, 2, PRI_LOW, 0x3a, 0, 0, 0, u8), |
970 | |
971 | PWRITE(pwm1_freq, 0, PRI_LOW, 0x5f, 0, 0x0f, 0, pwm_freq), |
972 | PWRITE(pwm2_freq, 1, PRI_LOW, 0x60, 0, 0x0f, 0, pwm_freq), |
973 | PWRITE(pwm3_freq, 2, PRI_LOW, 0x61, 0, 0x0f, 0, pwm_freq), |
974 | |
975 | PREAD(pwm1_auto_zone_assigned, 0, PRI_LOW, 0, 0, 0x03, 2, bitmask), |
976 | PREAD(pwm2_auto_zone_assigned, 1, PRI_LOW, 0, 0, 0x03, 4, bitmask), |
977 | PREAD(pwm3_auto_zone_assigned, 2, PRI_LOW, 0, 0, 0x03, 6, bitmask), |
978 | |
979 | PWRITE(pwm1_auto_spinup_time, 0, PRI_LOW, 0x5c, 0, 0x07, 0, pwm_ast), |
980 | PWRITE(pwm2_auto_spinup_time, 1, PRI_LOW, 0x5d, 0, 0x07, 0, pwm_ast), |
981 | PWRITE(pwm3_auto_spinup_time, 2, PRI_LOW, 0x5e, 0, 0x07, 0, pwm_ast), |
982 | |
983 | PWRITE(peci_enable, 0, PRI_LOW, 0x40, 0, 0x01, 4, bitmask), |
984 | PWRITE(peci_avg, 0, PRI_LOW, 0x36, 0, 0x07, 0, bitmask), |
985 | PWRITE(peci_domain, 0, PRI_LOW, 0x36, 0, 0x01, 3, bitmask), |
986 | PWRITE(peci_legacy, 0, PRI_LOW, 0x36, 0, 0x01, 4, bitmask), |
987 | PWRITE(peci_diode, 0, PRI_LOW, 0x0e, 0, 0x07, 4, bitmask), |
988 | PWRITE(peci_4domain, 0, PRI_LOW, 0x0e, 0, 0x01, 4, bitmask), |
989 | |
990 | }; |
991 | |
992 | static struct asc7621_data *asc7621_update_device(struct device *dev) |
993 | { |
994 | struct i2c_client *client = to_i2c_client(dev); |
995 | struct asc7621_data *data = i2c_get_clientdata(client); |
996 | int i; |
997 | |
998 | /* |
999 | * The asc7621 chips guarantee consistent reads of multi-byte values |
1000 | * regardless of the order of the reads. No special logic is needed |
1001 | * so we can just read the registers in whatever order they appear |
1002 | * in the asc7621_params array. |
1003 | */ |
1004 | |
1005 | mutex_lock(&data->update_lock); |
1006 | |
1007 | /* Read all the high priority registers */ |
1008 | |
1009 | if (!data->valid || |
1010 | time_after(jiffies, data->last_high_reading + INTERVAL_HIGH)) { |
1011 | |
1012 | for (i = 0; i < ARRAY_SIZE(asc7621_register_priorities); i++) { |
1013 | if (asc7621_register_priorities[i] == PRI_HIGH) { |
1014 | data->reg[i] = |
1015 | i2c_smbus_read_byte_data(client, command: i) & 0xff; |
1016 | } |
1017 | } |
1018 | data->last_high_reading = jiffies; |
1019 | } /* last_reading */ |
1020 | |
1021 | /* Read all the low priority registers. */ |
1022 | |
1023 | if (!data->valid || |
1024 | time_after(jiffies, data->last_low_reading + INTERVAL_LOW)) { |
1025 | |
1026 | for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { |
1027 | if (asc7621_register_priorities[i] == PRI_LOW) { |
1028 | data->reg[i] = |
1029 | i2c_smbus_read_byte_data(client, command: i) & 0xff; |
1030 | } |
1031 | } |
1032 | data->last_low_reading = jiffies; |
1033 | } /* last_reading */ |
1034 | |
1035 | data->valid = true; |
1036 | |
1037 | mutex_unlock(lock: &data->update_lock); |
1038 | |
1039 | return data; |
1040 | } |
1041 | |
1042 | /* |
1043 | * Standard detection and initialization below |
1044 | * |
1045 | * Helper function that checks if an address is valid |
1046 | * for a particular chip. |
1047 | */ |
1048 | |
1049 | static inline int valid_address_for_chip(int chip_type, int address) |
1050 | { |
1051 | int i; |
1052 | |
1053 | for (i = 0; asc7621_chips[chip_type].addresses[i] != I2C_CLIENT_END; |
1054 | i++) { |
1055 | if (asc7621_chips[chip_type].addresses[i] == address) |
1056 | return 1; |
1057 | } |
1058 | return 0; |
1059 | } |
1060 | |
1061 | static void asc7621_init_client(struct i2c_client *client) |
1062 | { |
1063 | int value; |
1064 | |
1065 | /* Warn if part was not "READY" */ |
1066 | |
1067 | value = read_byte(client, reg: 0x40); |
1068 | |
1069 | if (value & 0x02) { |
1070 | dev_err(&client->dev, |
1071 | "Client (%d,0x%02x) config is locked.\n" , |
1072 | i2c_adapter_id(client->adapter), client->addr); |
1073 | } |
1074 | if (!(value & 0x04)) { |
1075 | dev_err(&client->dev, "Client (%d,0x%02x) is not ready.\n" , |
1076 | i2c_adapter_id(client->adapter), client->addr); |
1077 | } |
1078 | |
1079 | /* |
1080 | * Start monitoring |
1081 | * |
1082 | * Try to clear LOCK, Set START, save everything else |
1083 | */ |
1084 | value = (value & ~0x02) | 0x01; |
1085 | write_byte(client, reg: 0x40, data: value & 0xff); |
1086 | |
1087 | } |
1088 | |
1089 | static int |
1090 | asc7621_probe(struct i2c_client *client) |
1091 | { |
1092 | struct asc7621_data *data; |
1093 | int i, err; |
1094 | |
1095 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
1096 | return -EIO; |
1097 | |
1098 | data = devm_kzalloc(dev: &client->dev, size: sizeof(struct asc7621_data), |
1099 | GFP_KERNEL); |
1100 | if (data == NULL) |
1101 | return -ENOMEM; |
1102 | |
1103 | i2c_set_clientdata(client, data); |
1104 | mutex_init(&data->update_lock); |
1105 | |
1106 | /* Initialize the asc7621 chip */ |
1107 | asc7621_init_client(client); |
1108 | |
1109 | /* Create the sysfs entries */ |
1110 | for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { |
1111 | err = |
1112 | device_create_file(device: &client->dev, |
1113 | entry: &(asc7621_params[i].sda.dev_attr)); |
1114 | if (err) |
1115 | goto exit_remove; |
1116 | } |
1117 | |
1118 | data->class_dev = hwmon_device_register(dev: &client->dev); |
1119 | if (IS_ERR(ptr: data->class_dev)) { |
1120 | err = PTR_ERR(ptr: data->class_dev); |
1121 | goto exit_remove; |
1122 | } |
1123 | |
1124 | return 0; |
1125 | |
1126 | exit_remove: |
1127 | for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { |
1128 | device_remove_file(dev: &client->dev, |
1129 | attr: &(asc7621_params[i].sda.dev_attr)); |
1130 | } |
1131 | |
1132 | return err; |
1133 | } |
1134 | |
1135 | static int asc7621_detect(struct i2c_client *client, |
1136 | struct i2c_board_info *info) |
1137 | { |
1138 | struct i2c_adapter *adapter = client->adapter; |
1139 | int company, verstep, chip_index; |
1140 | |
1141 | if (!i2c_check_functionality(adap: adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
1142 | return -ENODEV; |
1143 | |
1144 | for (chip_index = FIRST_CHIP; chip_index <= LAST_CHIP; chip_index++) { |
1145 | |
1146 | if (!valid_address_for_chip(chip_type: chip_index, address: client->addr)) |
1147 | continue; |
1148 | |
1149 | company = read_byte(client, |
1150 | reg: asc7621_chips[chip_index].company_reg); |
1151 | verstep = read_byte(client, |
1152 | reg: asc7621_chips[chip_index].verstep_reg); |
1153 | |
1154 | if (company == asc7621_chips[chip_index].company_id && |
1155 | verstep == asc7621_chips[chip_index].verstep_id) { |
1156 | strscpy(info->type, asc7621_chips[chip_index].name, |
1157 | I2C_NAME_SIZE); |
1158 | |
1159 | dev_info(&adapter->dev, "Matched %s at 0x%02x\n" , |
1160 | asc7621_chips[chip_index].name, client->addr); |
1161 | return 0; |
1162 | } |
1163 | } |
1164 | |
1165 | return -ENODEV; |
1166 | } |
1167 | |
1168 | static void asc7621_remove(struct i2c_client *client) |
1169 | { |
1170 | struct asc7621_data *data = i2c_get_clientdata(client); |
1171 | int i; |
1172 | |
1173 | hwmon_device_unregister(dev: data->class_dev); |
1174 | |
1175 | for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { |
1176 | device_remove_file(dev: &client->dev, |
1177 | attr: &(asc7621_params[i].sda.dev_attr)); |
1178 | } |
1179 | } |
1180 | |
1181 | static const struct i2c_device_id asc7621_id[] = { |
1182 | {"asc7621" , asc7621}, |
1183 | {"asc7621a" , asc7621a}, |
1184 | {}, |
1185 | }; |
1186 | |
1187 | MODULE_DEVICE_TABLE(i2c, asc7621_id); |
1188 | |
1189 | static struct i2c_driver asc7621_driver = { |
1190 | .class = I2C_CLASS_HWMON, |
1191 | .driver = { |
1192 | .name = "asc7621" , |
1193 | }, |
1194 | .probe = asc7621_probe, |
1195 | .remove = asc7621_remove, |
1196 | .id_table = asc7621_id, |
1197 | .detect = asc7621_detect, |
1198 | .address_list = normal_i2c, |
1199 | }; |
1200 | |
1201 | static int __init sm_asc7621_init(void) |
1202 | { |
1203 | int i, j; |
1204 | /* |
1205 | * Collect all the registers needed into a single array. |
1206 | * This way, if a register isn't actually used for anything, |
1207 | * we don't retrieve it. |
1208 | */ |
1209 | |
1210 | for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { |
1211 | for (j = 0; j < ARRAY_SIZE(asc7621_params[i].msb); j++) |
1212 | asc7621_register_priorities[asc7621_params[i].msb[j]] = |
1213 | asc7621_params[i].priority; |
1214 | for (j = 0; j < ARRAY_SIZE(asc7621_params[i].lsb); j++) |
1215 | asc7621_register_priorities[asc7621_params[i].lsb[j]] = |
1216 | asc7621_params[i].priority; |
1217 | } |
1218 | return i2c_add_driver(&asc7621_driver); |
1219 | } |
1220 | |
1221 | static void __exit sm_asc7621_exit(void) |
1222 | { |
1223 | i2c_del_driver(driver: &asc7621_driver); |
1224 | } |
1225 | |
1226 | MODULE_LICENSE("GPL" ); |
1227 | MODULE_AUTHOR("George Joseph" ); |
1228 | MODULE_DESCRIPTION("Andigilog aSC7621 and aSC7621a driver" ); |
1229 | |
1230 | module_init(sm_asc7621_init); |
1231 | module_exit(sm_asc7621_exit); |
1232 | |