diff options
| -rw-r--r-- | drivers/hwmon/w83627ehf.c | 95 |
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 | ||
| 507 | struct w83627ehf_sio_data { | 514 | struct 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 | ||
| 2619 | static 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 | |||
| 2635 | static 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 | |||
| 2693 | static 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 | |||
| 2611 | static struct platform_driver w83627ehf_driver = { | 2703 | static 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, |
