aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
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
commit7e630bb55a52cfaa35011c0ebc2efc96f13e5135 (patch)
treef3f405eb3d9fd80d8729b62799624072837c15d3 /drivers/hwmon
parent275b7d6ebe9e3599b2d178089171afd63d3fda02 (diff)
hwmon: (w83627ehf) Add support for suspend
On suspend some register values are lost, most notably the Value RAM areas but also other limits and settings. Restore them on resume. Signed-off-by: Jean Delvare <khali@linux-fr.org> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Tested-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/w83627ehf.c95
1 files changed, 94 insertions, 1 deletions
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 55ac41c05561..7fbd0ba0f26f 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * w83627ehf - Driver for the hardware monitoring functionality of 2 * w83627ehf - Driver for the hardware monitoring functionality of
3 * the Winbond W83627EHF Super-I/O chip 3 * the Winbond W83627EHF Super-I/O chip
4 * Copyright (C) 2005-2011 Jean Delvare <khali@linux-fr.org> 4 * Copyright (C) 2005-2012 Jean Delvare <khali@linux-fr.org>
5 * Copyright (C) 2006 Yuan Mu (Winbond), 5 * Copyright (C) 2006 Yuan Mu (Winbond),
6 * Rudolf Marek <r.marek@assembler.cz> 6 * Rudolf Marek <r.marek@assembler.cz>
7 * David Hubbard <david.c.hubbard@gmail.com> 7 * David Hubbard <david.c.hubbard@gmail.com>
@@ -502,6 +502,13 @@ struct w83627ehf_data {
502 u16 have_temp_offset; 502 u16 have_temp_offset;
503 u8 in6_skip:1; 503 u8 in6_skip:1;
504 u8 temp3_val_only:1; 504 u8 temp3_val_only:1;
505
506#ifdef CONFIG_PM
507 /* Remember extra register values over suspend/resume */
508 u8 vbat;
509 u8 fandiv1;
510 u8 fandiv2;
511#endif
505}; 512};
506 513
507struct w83627ehf_sio_data { 514struct w83627ehf_sio_data {
@@ -2608,10 +2615,96 @@ static int w83627ehf_remove(struct platform_device *pdev)
2608 return 0; 2615 return 0;
2609} 2616}
2610 2617
2618#ifdef CONFIG_PM
2619static int w83627ehf_suspend(struct device *dev)
2620{
2621 struct w83627ehf_data *data = w83627ehf_update_device(dev);
2622 struct w83627ehf_sio_data *sio_data = dev->platform_data;
2623
2624 mutex_lock(&data->update_lock);
2625 data->vbat = w83627ehf_read_value(data, W83627EHF_REG_VBAT);
2626 if (sio_data->kind == nct6775) {
2627 data->fandiv1 = w83627ehf_read_value(data, NCT6775_REG_FANDIV1);
2628 data->fandiv2 = w83627ehf_read_value(data, NCT6775_REG_FANDIV2);
2629 }
2630 mutex_unlock(&data->update_lock);
2631
2632 return 0;
2633}
2634
2635static int w83627ehf_resume(struct device *dev)
2636{
2637 struct w83627ehf_data *data = dev_get_drvdata(dev);
2638 struct w83627ehf_sio_data *sio_data = dev->platform_data;
2639 int i;
2640
2641 mutex_lock(&data->update_lock);
2642 data->bank = 0xff; /* Force initial bank selection */
2643
2644 /* Restore limits */
2645 for (i = 0; i < data->in_num; i++) {
2646 if ((i == 6) && data->in6_skip)
2647 continue;
2648
2649 w83627ehf_write_value(data, W83627EHF_REG_IN_MIN(i),
2650 data->in_min[i]);
2651 w83627ehf_write_value(data, W83627EHF_REG_IN_MAX(i),
2652 data->in_max[i]);
2653 }
2654
2655 for (i = 0; i < 5; i++) {
2656 if (!(data->has_fan_min & (1 << i)))
2657 continue;
2658
2659 w83627ehf_write_value(data, data->REG_FAN_MIN[i],
2660 data->fan_min[i]);
2661 }
2662
2663 for (i = 0; i < NUM_REG_TEMP; i++) {
2664 if (!(data->have_temp & (1 << i)))
2665 continue;
2666
2667 if (data->reg_temp_over[i])
2668 w83627ehf_write_temp(data, data->reg_temp_over[i],
2669 data->temp_max[i]);
2670 if (data->reg_temp_hyst[i])
2671 w83627ehf_write_temp(data, data->reg_temp_hyst[i],
2672 data->temp_max_hyst[i]);
2673 if (data->have_temp_offset & (1 << i))
2674 w83627ehf_write_value(data,
2675 W83627EHF_REG_TEMP_OFFSET[i],
2676 data->temp_offset[i]);
2677 }
2678
2679 /* Restore other settings */
2680 w83627ehf_write_value(data, W83627EHF_REG_VBAT, data->vbat);
2681 if (sio_data->kind == nct6775) {
2682 w83627ehf_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
2683 w83627ehf_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
2684 }
2685
2686 /* Force re-reading all values */
2687 data->valid = 0;
2688 mutex_unlock(&data->update_lock);
2689
2690 return 0;
2691}
2692
2693static const struct dev_pm_ops w83627ehf_dev_pm_ops = {
2694 .suspend = w83627ehf_suspend,
2695 .resume = w83627ehf_resume,
2696};
2697
2698#define W83627EHF_DEV_PM_OPS (&w83627ehf_dev_pm_ops)
2699#else
2700#define W83627EHF_DEV_PM_OPS NULL
2701#endif /* CONFIG_PM */
2702
2611static struct platform_driver w83627ehf_driver = { 2703static struct platform_driver w83627ehf_driver = {
2612 .driver = { 2704 .driver = {
2613 .owner = THIS_MODULE, 2705 .owner = THIS_MODULE,
2614 .name = DRVNAME, 2706 .name = DRVNAME,
2707 .pm = W83627EHF_DEV_PM_OPS,
2615 }, 2708 },
2616 .probe = w83627ehf_probe, 2709 .probe = w83627ehf_probe,
2617 .remove = w83627ehf_remove, 2710 .remove = w83627ehf_remove,