aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2012-12-19 16:16:59 -0500
committerJean Delvare <khali@endymion.delvare>2012-12-19 16:16:59 -0500
commit275b7d6ebe9e3599b2d178089171afd63d3fda02 (patch)
tree0bede5b9f1f47cc763952817d57fd3b1495a7624
parentd6dab7dd123ba6a737e69d89c8cca9c6d9b75aa9 (diff)
hwmon: (w83627hf) Add support for suspend
On suspend some register values are lost, most notably the Value RAM areas but also other limits. Restore them on resume. On top of that, some fixups are needed to work around BIOS bugs, in particular when the BIOS omits running the same initialization sequence on resume that it does after boot. In that case we have to carry initialization over suspend. Signed-off-by: Jean Delvare <khali@linux-fr.org> Acked-by: Guenter Roeck <linux@roeck-us.net> Tested-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--drivers/hwmon/w83627hf.c75
1 files changed, 74 insertions, 1 deletions
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 7f68b8309d10..9170746e9743 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);
401static struct w83627hf_data *w83627hf_update_device(struct device *dev); 407static struct w83627hf_data *w83627hf_update_device(struct device *dev);
402static void w83627hf_init_device(struct platform_device *pdev); 408static void w83627hf_init_device(struct platform_device *pdev);
403 409
410#ifdef CONFIG_PM
411static 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
423static 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
466static 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
404static struct platform_driver w83627hf_driver = { 476static 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,