aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/w83627ehf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/w83627ehf.c')
-rw-r--r--drivers/hwmon/w83627ehf.c112
1 files changed, 105 insertions, 7 deletions
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 1821b7423d5b..0e8ffd6059a0 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 {
@@ -898,6 +905,8 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
898 data->temp_max_hyst[i] 905 data->temp_max_hyst[i]
899 = w83627ehf_read_temp(data, 906 = w83627ehf_read_temp(data,
900 data->reg_temp_hyst[i]); 907 data->reg_temp_hyst[i]);
908 if (i > 2)
909 continue;
901 if (data->have_temp_offset & (1 << i)) 910 if (data->have_temp_offset & (1 << i))
902 data->temp_offset[i] 911 data->temp_offset[i]
903 = w83627ehf_read_value(data, 912 = w83627ehf_read_value(data,
@@ -1866,7 +1875,7 @@ static void w83627ehf_device_remove_files(struct device *dev)
1866} 1875}
1867 1876
1868/* Get the monitoring functions started */ 1877/* Get the monitoring functions started */
1869static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data, 1878static inline void w83627ehf_init_device(struct w83627ehf_data *data,
1870 enum kinds kind) 1879 enum kinds kind)
1871{ 1880{
1872 int i; 1881 int i;
@@ -1952,7 +1961,7 @@ static void w82627ehf_swap_tempreg(struct w83627ehf_data *data,
1952 data->reg_temp_config[r2] = tmp; 1961 data->reg_temp_config[r2] = tmp;
1953} 1962}
1954 1963
1955static void __devinit 1964static void
1956w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp) 1965w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp)
1957{ 1966{
1958 int i; 1967 int i;
@@ -1965,7 +1974,7 @@ w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp)
1965 } 1974 }
1966} 1975}
1967 1976
1968static void __devinit 1977static void
1969w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data, 1978w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
1970 struct w83627ehf_data *data) 1979 struct w83627ehf_data *data)
1971{ 1980{
@@ -2054,7 +2063,7 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
2054 } 2063 }
2055} 2064}
2056 2065
2057static int __devinit w83627ehf_probe(struct platform_device *pdev) 2066static int w83627ehf_probe(struct platform_device *pdev)
2058{ 2067{
2059 struct device *dev = &pdev->dev; 2068 struct device *dev = &pdev->dev;
2060 struct w83627ehf_sio_data *sio_data = dev->platform_data; 2069 struct w83627ehf_sio_data *sio_data = dev->platform_data;
@@ -2083,6 +2092,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
2083 mutex_init(&data->lock); 2092 mutex_init(&data->lock);
2084 mutex_init(&data->update_lock); 2093 mutex_init(&data->update_lock);
2085 data->name = w83627ehf_device_names[sio_data->kind]; 2094 data->name = w83627ehf_device_names[sio_data->kind];
2095 data->bank = 0xff; /* Force initial bank selection */
2086 platform_set_drvdata(pdev, data); 2096 platform_set_drvdata(pdev, data);
2087 2097
2088 /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ 2098 /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
@@ -2595,7 +2605,7 @@ exit:
2595 return err; 2605 return err;
2596} 2606}
2597 2607
2598static int __devexit w83627ehf_remove(struct platform_device *pdev) 2608static int w83627ehf_remove(struct platform_device *pdev)
2599{ 2609{
2600 struct w83627ehf_data *data = platform_get_drvdata(pdev); 2610 struct w83627ehf_data *data = platform_get_drvdata(pdev);
2601 2611
@@ -2607,13 +2617,101 @@ static int __devexit w83627ehf_remove(struct platform_device *pdev)
2607 return 0; 2617 return 0;
2608} 2618}
2609 2619
2620#ifdef CONFIG_PM
2621static int w83627ehf_suspend(struct device *dev)
2622{
2623 struct w83627ehf_data *data = w83627ehf_update_device(dev);
2624 struct w83627ehf_sio_data *sio_data = dev->platform_data;
2625
2626 mutex_lock(&data->update_lock);
2627 data->vbat = w83627ehf_read_value(data, W83627EHF_REG_VBAT);
2628 if (sio_data->kind == nct6775) {
2629 data->fandiv1 = w83627ehf_read_value(data, NCT6775_REG_FANDIV1);
2630 data->fandiv2 = w83627ehf_read_value(data, NCT6775_REG_FANDIV2);
2631 }
2632 mutex_unlock(&data->update_lock);
2633
2634 return 0;
2635}
2636
2637static int w83627ehf_resume(struct device *dev)
2638{
2639 struct w83627ehf_data *data = dev_get_drvdata(dev);
2640 struct w83627ehf_sio_data *sio_data = dev->platform_data;
2641 int i;
2642
2643 mutex_lock(&data->update_lock);
2644 data->bank = 0xff; /* Force initial bank selection */
2645
2646 /* Restore limits */
2647 for (i = 0; i < data->in_num; i++) {
2648 if ((i == 6) && data->in6_skip)
2649 continue;
2650
2651 w83627ehf_write_value(data, W83627EHF_REG_IN_MIN(i),
2652 data->in_min[i]);
2653 w83627ehf_write_value(data, W83627EHF_REG_IN_MAX(i),
2654 data->in_max[i]);
2655 }
2656
2657 for (i = 0; i < 5; i++) {
2658 if (!(data->has_fan_min & (1 << i)))
2659 continue;
2660
2661 w83627ehf_write_value(data, data->REG_FAN_MIN[i],
2662 data->fan_min[i]);
2663 }
2664
2665 for (i = 0; i < NUM_REG_TEMP; i++) {
2666 if (!(data->have_temp & (1 << i)))
2667 continue;
2668
2669 if (data->reg_temp_over[i])
2670 w83627ehf_write_temp(data, data->reg_temp_over[i],
2671 data->temp_max[i]);
2672 if (data->reg_temp_hyst[i])
2673 w83627ehf_write_temp(data, data->reg_temp_hyst[i],
2674 data->temp_max_hyst[i]);
2675 if (i > 2)
2676 continue;
2677 if (data->have_temp_offset & (1 << i))
2678 w83627ehf_write_value(data,
2679 W83627EHF_REG_TEMP_OFFSET[i],
2680 data->temp_offset[i]);
2681 }
2682
2683 /* Restore other settings */
2684 w83627ehf_write_value(data, W83627EHF_REG_VBAT, data->vbat);
2685 if (sio_data->kind == nct6775) {
2686 w83627ehf_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
2687 w83627ehf_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
2688 }
2689
2690 /* Force re-reading all values */
2691 data->valid = 0;
2692 mutex_unlock(&data->update_lock);
2693
2694 return 0;
2695}
2696
2697static const struct dev_pm_ops w83627ehf_dev_pm_ops = {
2698 .suspend = w83627ehf_suspend,
2699 .resume = w83627ehf_resume,
2700};
2701
2702#define W83627EHF_DEV_PM_OPS (&w83627ehf_dev_pm_ops)
2703#else
2704#define W83627EHF_DEV_PM_OPS NULL
2705#endif /* CONFIG_PM */
2706
2610static struct platform_driver w83627ehf_driver = { 2707static struct platform_driver w83627ehf_driver = {
2611 .driver = { 2708 .driver = {
2612 .owner = THIS_MODULE, 2709 .owner = THIS_MODULE,
2613 .name = DRVNAME, 2710 .name = DRVNAME,
2711 .pm = W83627EHF_DEV_PM_OPS,
2614 }, 2712 },
2615 .probe = w83627ehf_probe, 2713 .probe = w83627ehf_probe,
2616 .remove = __devexit_p(w83627ehf_remove), 2714 .remove = w83627ehf_remove,
2617}; 2715};
2618 2716
2619/* w83627ehf_find() looks for a '627 in the Super-I/O config space */ 2717/* w83627ehf_find() looks for a '627 in the Super-I/O config space */