diff options
Diffstat (limited to 'drivers/hwmon/w83627hf.c')
-rw-r--r-- | drivers/hwmon/w83627hf.c | 81 |
1 files changed, 78 insertions, 3 deletions
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 7f68b8309d10..81f486520cea 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Philip Edelbrock <phil@netroedge.com>, | 5 | * Philip Edelbrock <phil@netroedge.com>, |
6 | * and Mark Studebaker <mdsxyz123@yahoo.com> | 6 | * and Mark Studebaker <mdsxyz123@yahoo.com> |
7 | * Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org> | 7 | * Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org> |
8 | * Copyright (c) 2007 Jean Delvare <khali@linux-fr.org> | 8 | * Copyright (c) 2007 - 1012 Jean Delvare <khali@linux-fr.org> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
@@ -389,6 +389,12 @@ struct w83627hf_data { | |||
389 | */ | 389 | */ |
390 | u8 vrm; | 390 | u8 vrm; |
391 | u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ | 391 | u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ |
392 | |||
393 | #ifdef CONFIG_PM | ||
394 | /* Remember extra register values over suspend/resume */ | ||
395 | u8 scfg1; | ||
396 | u8 scfg2; | ||
397 | #endif | ||
392 | }; | 398 | }; |
393 | 399 | ||
394 | 400 | ||
@@ -401,10 +407,77 @@ static void w83627hf_update_fan_div(struct w83627hf_data *data); | |||
401 | static struct w83627hf_data *w83627hf_update_device(struct device *dev); | 407 | static struct w83627hf_data *w83627hf_update_device(struct device *dev); |
402 | static void w83627hf_init_device(struct platform_device *pdev); | 408 | static void w83627hf_init_device(struct platform_device *pdev); |
403 | 409 | ||
410 | #ifdef CONFIG_PM | ||
411 | static int w83627hf_suspend(struct device *dev) | ||
412 | { | ||
413 | struct w83627hf_data *data = w83627hf_update_device(dev); | ||
414 | |||
415 | mutex_lock(&data->update_lock); | ||
416 | data->scfg1 = w83627hf_read_value(data, W83781D_REG_SCFG1); | ||
417 | data->scfg2 = w83627hf_read_value(data, W83781D_REG_SCFG2); | ||
418 | mutex_unlock(&data->update_lock); | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int w83627hf_resume(struct device *dev) | ||
424 | { | ||
425 | struct w83627hf_data *data = dev_get_drvdata(dev); | ||
426 | int i, num_temps = (data->type == w83697hf) ? 2 : 3; | ||
427 | |||
428 | /* Restore limits */ | ||
429 | mutex_lock(&data->update_lock); | ||
430 | for (i = 0; i <= 8; i++) { | ||
431 | /* skip missing sensors */ | ||
432 | if (((data->type == w83697hf) && (i == 1)) || | ||
433 | ((data->type != w83627hf && data->type != w83697hf) | ||
434 | && (i == 5 || i == 6))) | ||
435 | continue; | ||
436 | w83627hf_write_value(data, W83781D_REG_IN_MAX(i), | ||
437 | data->in_max[i]); | ||
438 | w83627hf_write_value(data, W83781D_REG_IN_MIN(i), | ||
439 | data->in_min[i]); | ||
440 | } | ||
441 | for (i = 0; i <= 2; i++) | ||
442 | w83627hf_write_value(data, W83627HF_REG_FAN_MIN(i), | ||
443 | data->fan_min[i]); | ||
444 | for (i = 0; i < num_temps; i++) { | ||
445 | w83627hf_write_value(data, w83627hf_reg_temp_over[i], | ||
446 | data->temp_max[i]); | ||
447 | w83627hf_write_value(data, w83627hf_reg_temp_hyst[i], | ||
448 | data->temp_max_hyst[i]); | ||
449 | } | ||
450 | |||
451 | /* Fixup BIOS bugs */ | ||
452 | if (data->type == w83627thf || data->type == w83637hf || | ||
453 | data->type == w83687thf) | ||
454 | w83627hf_write_value(data, W83627THF_REG_VRM_OVT_CFG, | ||
455 | data->vrm_ovt); | ||
456 | w83627hf_write_value(data, W83781D_REG_SCFG1, data->scfg1); | ||
457 | w83627hf_write_value(data, W83781D_REG_SCFG2, data->scfg2); | ||
458 | |||
459 | /* Force re-reading all values */ | ||
460 | data->valid = 0; | ||
461 | mutex_unlock(&data->update_lock); | ||
462 | |||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static const struct dev_pm_ops w83627hf_dev_pm_ops = { | ||
467 | .suspend = w83627hf_suspend, | ||
468 | .resume = w83627hf_resume, | ||
469 | }; | ||
470 | |||
471 | #define W83627HF_DEV_PM_OPS (&w83627hf_dev_pm_ops) | ||
472 | #else | ||
473 | #define W83627HF_DEV_PM_OPS NULL | ||
474 | #endif /* CONFIG_PM */ | ||
475 | |||
404 | static struct platform_driver w83627hf_driver = { | 476 | static struct platform_driver w83627hf_driver = { |
405 | .driver = { | 477 | .driver = { |
406 | .owner = THIS_MODULE, | 478 | .owner = THIS_MODULE, |
407 | .name = DRVNAME, | 479 | .name = DRVNAME, |
480 | .pm = W83627HF_DEV_PM_OPS, | ||
408 | }, | 481 | }, |
409 | .probe = w83627hf_probe, | 482 | .probe = w83627hf_probe, |
410 | .remove = w83627hf_remove, | 483 | .remove = w83627hf_remove, |
@@ -1659,8 +1732,10 @@ static void w83627hf_init_device(struct platform_device *pdev) | |||
1659 | /* Minimize conflicts with other winbond i2c-only clients... */ | 1732 | /* Minimize conflicts with other winbond i2c-only clients... */ |
1660 | /* disable i2c subclients... how to disable main i2c client?? */ | 1733 | /* disable i2c subclients... how to disable main i2c client?? */ |
1661 | /* force i2c address to relatively uncommon address */ | 1734 | /* force i2c address to relatively uncommon address */ |
1662 | w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89); | 1735 | if (type == w83627hf) { |
1663 | w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c); | 1736 | w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89); |
1737 | w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c); | ||
1738 | } | ||
1664 | 1739 | ||
1665 | /* Read VID only once */ | 1740 | /* Read VID only once */ |
1666 | if (type == w83627hf || type == w83637hf) { | 1741 | if (type == w83627hf || type == w83637hf) { |