diff options
Diffstat (limited to 'drivers/hwmon/w83627ehf.c')
-rw-r--r-- | drivers/hwmon/w83627ehf.c | 112 |
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 | ||
507 | struct w83627ehf_sio_data { | 514 | struct 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 */ |
1869 | static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data, | 1878 | static 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 | ||
1955 | static void __devinit | 1964 | static void |
1956 | w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp) | 1965 | w83627ehf_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 | ||
1968 | static void __devinit | 1977 | static void |
1969 | w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data, | 1978 | w83627ehf_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 | ||
2057 | static int __devinit w83627ehf_probe(struct platform_device *pdev) | 2066 | static 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 | ||
2598 | static int __devexit w83627ehf_remove(struct platform_device *pdev) | 2608 | static 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 | ||
2621 | static 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 | |||
2637 | static 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 | |||
2697 | static 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 | |||
2610 | static struct platform_driver w83627ehf_driver = { | 2707 | static 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 */ |