diff options
Diffstat (limited to 'drivers/hwmon/w83627hf.c')
-rw-r--r-- | drivers/hwmon/w83627hf.c | 81 |
1 files changed, 78 insertions, 3 deletions
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 7f68b8309d10..81f486520cea 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -5,7 +5,7 @@ * Philip Edelbrock <phil@netroedge.com>, * and Mark Studebaker <mdsxyz123@yahoo.com> * Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org> - * Copyright (c) 2007 Jean Delvare <khali@linux-fr.org> + * Copyright (c) 2007 - 1012 Jean Delvare <khali@linux-fr.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -389,6 +389,12 @@ struct w83627hf_data { */ u8 vrm; u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ + +#ifdef CONFIG_PM + /* Remember extra register values over suspend/resume */ + u8 scfg1; + u8 scfg2; +#endif }; @@ -401,10 +407,77 @@ static void w83627hf_update_fan_div(struct w83627hf_data *data); static struct w83627hf_data *w83627hf_update_device(struct device *dev); static void w83627hf_init_device(struct platform_device *pdev); +#ifdef CONFIG_PM +static int w83627hf_suspend(struct device *dev) +{ + struct w83627hf_data *data = w83627hf_update_device(dev); + + mutex_lock(&data->update_lock); + data->scfg1 = w83627hf_read_value(data, W83781D_REG_SCFG1); + data->scfg2 = w83627hf_read_value(data, W83781D_REG_SCFG2); + mutex_unlock(&data->update_lock); + + return 0; +} + +static int w83627hf_resume(struct device *dev) +{ + struct w83627hf_data *data = dev_get_drvdata(dev); + int i, num_temps = (data->type == w83697hf) ? 2 : 3; + + /* Restore limits */ + mutex_lock(&data->update_lock); + for (i = 0; i <= 8; i++) { + /* skip missing sensors */ + if (((data->type == w83697hf) && (i == 1)) || + ((data->type != w83627hf && data->type != w83697hf) + && (i == 5 || i == 6))) + continue; + w83627hf_write_value(data, W83781D_REG_IN_MAX(i), + data->in_max[i]); + w83627hf_write_value(data, W83781D_REG_IN_MIN(i), + data->in_min[i]); + } + for (i = 0; i <= 2; i++) + w83627hf_write_value(data, W83627HF_REG_FAN_MIN(i), + data->fan_min[i]); + for (i = 0; i < num_temps; i++) { + w83627hf_write_value(data, w83627hf_reg_temp_over[i], + data->temp_max[i]); + w83627hf_write_value(data, w83627hf_reg_temp_hyst[i], + data->temp_max_hyst[i]); + } + + /* Fixup BIOS bugs */ + if (data->type == w83627thf || data->type == w83637hf || + data->type == w83687thf) + w83627hf_write_value(data, W83627THF_REG_VRM_OVT_CFG, + data->vrm_ovt); + w83627hf_write_value(data, W83781D_REG_SCFG1, data->scfg1); + w83627hf_write_value(data, W83781D_REG_SCFG2, data->scfg2); + + /* Force re-reading all values */ + data->valid = 0; + mutex_unlock(&data->update_lock); + + return 0; +} + +static const struct dev_pm_ops w83627hf_dev_pm_ops = { + .suspend = w83627hf_suspend, + .resume = w83627hf_resume, +}; + +#define W83627HF_DEV_PM_OPS (&w83627hf_dev_pm_ops) +#else +#define W83627HF_DEV_PM_OPS NULL +#endif /* CONFIG_PM */ + static struct platform_driver w83627hf_driver = { .driver = { .owner = THIS_MODULE, .name = DRVNAME, + .pm = W83627HF_DEV_PM_OPS, }, .probe = w83627hf_probe, .remove = w83627hf_remove, @@ -1659,8 +1732,10 @@ static void w83627hf_init_device(struct platform_device *pdev) /* Minimize conflicts with other winbond i2c-only clients... */ /* disable i2c subclients... how to disable main i2c client?? */ /* force i2c address to relatively uncommon address */ - w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89); - w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c); + if (type == w83627hf) { + w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89); + w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c); + } /* Read VID only once */ if (type == w83627hf || type == w83637hf) { |