.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * max31790.c - Part of lm_sensors, Linux kernel modules for hardware |
---|
3 | 4 | * monitoring. |
---|
4 | 5 | * |
---|
5 | 6 | * (C) 2015 by Il Han <corone.il.han@gmail.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License as published by |
---|
9 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
10 | | - * (at your option) any later version. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that it will be useful, |
---|
13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | | - * GNU General Public License for more details. |
---|
16 | 7 | */ |
---|
17 | 8 | |
---|
18 | 9 | #include <linux/err.h> |
---|
.. | .. |
---|
36 | 27 | |
---|
37 | 28 | /* Fan Config register bits */ |
---|
38 | 29 | #define MAX31790_FAN_CFG_RPM_MODE 0x80 |
---|
| 30 | +#define MAX31790_FAN_CFG_CTRL_MON 0x10 |
---|
39 | 31 | #define MAX31790_FAN_CFG_TACH_INPUT_EN 0x08 |
---|
40 | 32 | #define MAX31790_FAN_CFG_TACH_INPUT 0x01 |
---|
41 | 33 | |
---|
.. | .. |
---|
113 | 105 | data->tach[NR_CHANNEL + i] = rv; |
---|
114 | 106 | } else { |
---|
115 | 107 | rv = i2c_smbus_read_word_swapped(client, |
---|
116 | | - MAX31790_REG_PWMOUT(i)); |
---|
| 108 | + MAX31790_REG_PWM_DUTY_CYCLE(i)); |
---|
117 | 109 | if (rv < 0) |
---|
118 | 110 | goto abort; |
---|
119 | 111 | data->pwm[i] = rv; |
---|
.. | .. |
---|
252 | 244 | case hwmon_fan_fault: |
---|
253 | 245 | if (channel < NR_CHANNEL || |
---|
254 | 246 | (fan_config & MAX31790_FAN_CFG_TACH_INPUT)) |
---|
255 | | - return S_IRUGO; |
---|
| 247 | + return 0444; |
---|
256 | 248 | return 0; |
---|
257 | 249 | case hwmon_fan_target: |
---|
258 | 250 | if (channel < NR_CHANNEL && |
---|
259 | 251 | !(fan_config & MAX31790_FAN_CFG_TACH_INPUT)) |
---|
260 | | - return S_IRUGO | S_IWUSR; |
---|
| 252 | + return 0644; |
---|
261 | 253 | return 0; |
---|
262 | 254 | default: |
---|
263 | 255 | return 0; |
---|
.. | .. |
---|
280 | 272 | *val = data->pwm[channel] >> 8; |
---|
281 | 273 | return 0; |
---|
282 | 274 | case hwmon_pwm_enable: |
---|
283 | | - if (fan_config & MAX31790_FAN_CFG_RPM_MODE) |
---|
284 | | - *val = 2; |
---|
285 | | - else if (fan_config & MAX31790_FAN_CFG_TACH_INPUT_EN) |
---|
286 | | - *val = 1; |
---|
287 | | - else |
---|
| 275 | + if (fan_config & MAX31790_FAN_CFG_CTRL_MON) |
---|
288 | 276 | *val = 0; |
---|
| 277 | + else if (fan_config & MAX31790_FAN_CFG_RPM_MODE) |
---|
| 278 | + *val = 2; |
---|
| 279 | + else |
---|
| 280 | + *val = 1; |
---|
289 | 281 | return 0; |
---|
290 | 282 | default: |
---|
291 | 283 | return -EOPNOTSUPP; |
---|
.. | .. |
---|
308 | 300 | err = -EINVAL; |
---|
309 | 301 | break; |
---|
310 | 302 | } |
---|
311 | | - data->pwm[channel] = val << 8; |
---|
| 303 | + data->valid = false; |
---|
312 | 304 | err = i2c_smbus_write_word_swapped(client, |
---|
313 | 305 | MAX31790_REG_PWMOUT(channel), |
---|
314 | | - data->pwm[channel]); |
---|
| 306 | + val << 8); |
---|
315 | 307 | break; |
---|
316 | 308 | case hwmon_pwm_enable: |
---|
317 | 309 | fan_config = data->fan_config[channel]; |
---|
318 | 310 | if (val == 0) { |
---|
319 | | - fan_config &= ~(MAX31790_FAN_CFG_TACH_INPUT_EN | |
---|
320 | | - MAX31790_FAN_CFG_RPM_MODE); |
---|
| 311 | + fan_config |= MAX31790_FAN_CFG_CTRL_MON; |
---|
| 312 | + /* |
---|
| 313 | + * Disable RPM mode; otherwise disabling fan speed |
---|
| 314 | + * monitoring is not possible. |
---|
| 315 | + */ |
---|
| 316 | + fan_config &= ~MAX31790_FAN_CFG_RPM_MODE; |
---|
321 | 317 | } else if (val == 1) { |
---|
322 | | - fan_config = (fan_config | |
---|
323 | | - MAX31790_FAN_CFG_TACH_INPUT_EN) & |
---|
324 | | - ~MAX31790_FAN_CFG_RPM_MODE; |
---|
| 318 | + fan_config &= ~(MAX31790_FAN_CFG_CTRL_MON | MAX31790_FAN_CFG_RPM_MODE); |
---|
325 | 319 | } else if (val == 2) { |
---|
326 | | - fan_config |= MAX31790_FAN_CFG_TACH_INPUT_EN | |
---|
327 | | - MAX31790_FAN_CFG_RPM_MODE; |
---|
| 320 | + fan_config &= ~MAX31790_FAN_CFG_CTRL_MON; |
---|
| 321 | + /* |
---|
| 322 | + * The chip sets MAX31790_FAN_CFG_TACH_INPUT_EN on its |
---|
| 323 | + * own if MAX31790_FAN_CFG_RPM_MODE is set. |
---|
| 324 | + * Do it here as well to reflect the actual register |
---|
| 325 | + * value in the cache. |
---|
| 326 | + */ |
---|
| 327 | + fan_config |= (MAX31790_FAN_CFG_RPM_MODE | MAX31790_FAN_CFG_TACH_INPUT_EN); |
---|
328 | 328 | } else { |
---|
329 | 329 | err = -EINVAL; |
---|
330 | 330 | break; |
---|
331 | 331 | } |
---|
332 | | - data->fan_config[channel] = fan_config; |
---|
333 | | - err = i2c_smbus_write_byte_data(client, |
---|
334 | | - MAX31790_REG_FAN_CONFIG(channel), |
---|
335 | | - fan_config); |
---|
| 332 | + if (fan_config != data->fan_config[channel]) { |
---|
| 333 | + err = i2c_smbus_write_byte_data(client, MAX31790_REG_FAN_CONFIG(channel), |
---|
| 334 | + fan_config); |
---|
| 335 | + if (!err) |
---|
| 336 | + data->fan_config[channel] = fan_config; |
---|
| 337 | + } |
---|
336 | 338 | break; |
---|
337 | 339 | default: |
---|
338 | 340 | err = -EOPNOTSUPP; |
---|
.. | .. |
---|
353 | 355 | case hwmon_pwm_input: |
---|
354 | 356 | case hwmon_pwm_enable: |
---|
355 | 357 | if (!(fan_config & MAX31790_FAN_CFG_TACH_INPUT)) |
---|
356 | | - return S_IRUGO | S_IWUSR; |
---|
| 358 | + return 0644; |
---|
357 | 359 | return 0; |
---|
358 | 360 | default: |
---|
359 | 361 | return 0; |
---|
.. | .. |
---|
400 | 402 | } |
---|
401 | 403 | } |
---|
402 | 404 | |
---|
403 | | -static const u32 max31790_fan_config[] = { |
---|
404 | | - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, |
---|
405 | | - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, |
---|
406 | | - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, |
---|
407 | | - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, |
---|
408 | | - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, |
---|
409 | | - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, |
---|
410 | | - HWMON_F_INPUT | HWMON_F_FAULT, |
---|
411 | | - HWMON_F_INPUT | HWMON_F_FAULT, |
---|
412 | | - HWMON_F_INPUT | HWMON_F_FAULT, |
---|
413 | | - HWMON_F_INPUT | HWMON_F_FAULT, |
---|
414 | | - HWMON_F_INPUT | HWMON_F_FAULT, |
---|
415 | | - HWMON_F_INPUT | HWMON_F_FAULT, |
---|
416 | | - 0 |
---|
417 | | -}; |
---|
418 | | - |
---|
419 | | -static const struct hwmon_channel_info max31790_fan = { |
---|
420 | | - .type = hwmon_fan, |
---|
421 | | - .config = max31790_fan_config, |
---|
422 | | -}; |
---|
423 | | - |
---|
424 | | -static const u32 max31790_pwm_config[] = { |
---|
425 | | - HWMON_PWM_INPUT | HWMON_PWM_ENABLE, |
---|
426 | | - HWMON_PWM_INPUT | HWMON_PWM_ENABLE, |
---|
427 | | - HWMON_PWM_INPUT | HWMON_PWM_ENABLE, |
---|
428 | | - HWMON_PWM_INPUT | HWMON_PWM_ENABLE, |
---|
429 | | - HWMON_PWM_INPUT | HWMON_PWM_ENABLE, |
---|
430 | | - HWMON_PWM_INPUT | HWMON_PWM_ENABLE, |
---|
431 | | - 0 |
---|
432 | | -}; |
---|
433 | | - |
---|
434 | | -static const struct hwmon_channel_info max31790_pwm = { |
---|
435 | | - .type = hwmon_pwm, |
---|
436 | | - .config = max31790_pwm_config, |
---|
437 | | -}; |
---|
438 | | - |
---|
439 | 405 | static const struct hwmon_channel_info *max31790_info[] = { |
---|
440 | | - &max31790_fan, |
---|
441 | | - &max31790_pwm, |
---|
| 406 | + HWMON_CHANNEL_INFO(fan, |
---|
| 407 | + HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, |
---|
| 408 | + HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, |
---|
| 409 | + HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, |
---|
| 410 | + HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, |
---|
| 411 | + HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, |
---|
| 412 | + HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, |
---|
| 413 | + HWMON_F_INPUT | HWMON_F_FAULT, |
---|
| 414 | + HWMON_F_INPUT | HWMON_F_FAULT, |
---|
| 415 | + HWMON_F_INPUT | HWMON_F_FAULT, |
---|
| 416 | + HWMON_F_INPUT | HWMON_F_FAULT, |
---|
| 417 | + HWMON_F_INPUT | HWMON_F_FAULT, |
---|
| 418 | + HWMON_F_INPUT | HWMON_F_FAULT), |
---|
| 419 | + HWMON_CHANNEL_INFO(pwm, |
---|
| 420 | + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, |
---|
| 421 | + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, |
---|
| 422 | + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, |
---|
| 423 | + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, |
---|
| 424 | + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, |
---|
| 425 | + HWMON_PWM_INPUT | HWMON_PWM_ENABLE), |
---|
442 | 426 | NULL |
---|
443 | 427 | }; |
---|
444 | 428 | |
---|
.. | .. |
---|
475 | 459 | return 0; |
---|
476 | 460 | } |
---|
477 | 461 | |
---|
478 | | -static int max31790_probe(struct i2c_client *client, |
---|
479 | | - const struct i2c_device_id *id) |
---|
| 462 | +static int max31790_probe(struct i2c_client *client) |
---|
480 | 463 | { |
---|
481 | 464 | struct i2c_adapter *adapter = client->adapter; |
---|
482 | 465 | struct device *dev = &client->dev; |
---|
.. | .. |
---|
518 | 501 | |
---|
519 | 502 | static struct i2c_driver max31790_driver = { |
---|
520 | 503 | .class = I2C_CLASS_HWMON, |
---|
521 | | - .probe = max31790_probe, |
---|
| 504 | + .probe_new = max31790_probe, |
---|
522 | 505 | .driver = { |
---|
523 | 506 | .name = "max31790", |
---|
524 | 507 | }, |
---|