]> git.sur5r.net Git - groeck-nct6775/blobdiff - nct6775.c
Add support for hibernate
[groeck-nct6775] / nct6775.c
index 64a2362a0e65b6f4c787b0f622875c6c5a7cf538..c970e32e257ed16117ab32e51a6918f5be1cc212 100644 (file)
--- a/nct6775.c
+++ b/nct6775.c
@@ -511,6 +511,13 @@ static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
 
 #define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE    0x28
 
+static const u16 NCT6791_REG_WEIGHT_TEMP_SEL[6] = { 0, 0x239 };
+static const u16 NCT6791_REG_WEIGHT_TEMP_STEP[6] = { 0, 0x23a };
+static const u16 NCT6791_REG_WEIGHT_TEMP_STEP_TOL[6] = { 0, 0x23b };
+static const u16 NCT6791_REG_WEIGHT_DUTY_STEP[6] = { 0, 0x23c };
+static const u16 NCT6791_REG_WEIGHT_TEMP_BASE[6] = { 0, 0x23d };
+static const u16 NCT6791_REG_WEIGHT_DUTY_BASE[6] = { 0, 0x23e };
+
 static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
        0x459, 0x45A, 0x45B, 0x568, 0x45D };
 
@@ -1319,17 +1326,19 @@ static void nct6775_update_pwm(struct device *dev)
                if (reg & 0x80)
                        data->pwm[2][i] = 0;
 
-               reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
-               data->pwm_weight_temp_sel[i] = reg & 0x1f;
-               /* If weight is disabled, report weight source as 0 */
-               if (j == 1 && !(reg & 0x80))
-                       data->pwm_weight_temp_sel[i] = 0;
-
-               /* Weight temp data */
-               for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
-                       data->weight_temp[j][i]
-                         = nct6775_read_value(data,
-                                              data->REG_WEIGHT_TEMP[j][i]);
+               if (data->REG_WEIGHT_TEMP_SEL[i]) {
+                       reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
+                       data->pwm_weight_temp_sel[i] = reg & 0x1f;
+                       /* If weight is disabled, report weight source as 0 */
+                       if (j == 1 && !(reg & 0x80))
+                               data->pwm_weight_temp_sel[i] = 0;
+
+                       /* Weight temp data */
+                       for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
+                               data->weight_temp[j][i]
+                                 = nct6775_read_value(data,
+                                               data->REG_WEIGHT_TEMP[j][i]);
+                       }
                }
        }
 }
@@ -2873,6 +2882,9 @@ static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
        if (!(data->has_pwm & (1 << pwm)))
                return 0;
 
+       if ((nr >= 14 && nr <= 18) || nr == 21)   /* weight */
+               if (!data->REG_WEIGHT_TEMP_SEL[pwm])
+                       return 0;
        if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
                return 0;
        if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
@@ -2966,11 +2978,11 @@ static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
        &sensor_dev_template_pwm_step_down_time,
        &sensor_dev_template_pwm_start,
        &sensor_dev_template_pwm_floor,
-       &sensor_dev_template_pwm_weight_temp_sel,
+       &sensor_dev_template_pwm_weight_temp_sel,       /* 14 */
        &sensor_dev_template_pwm_weight_temp_step,
        &sensor_dev_template_pwm_weight_temp_step_tol,
        &sensor_dev_template_pwm_weight_temp_step_base,
-       &sensor_dev_template_pwm_weight_duty_step,
+       &sensor_dev_template_pwm_weight_duty_step,      /* 18 */
        &sensor_dev_template_pwm_max,                   /* 19 */
        &sensor_dev_template_pwm_step,                  /* 20 */
        &sensor_dev_template_pwm_weight_duty_base,      /* 21 */
@@ -3653,8 +3665,8 @@ static int nct6775_probe(struct platform_device *pdev)
                data->REG_PWM[0] = NCT6775_REG_PWM;
                data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
                data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
-               data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
-               data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
+               data->REG_PWM[5] = NCT6791_REG_WEIGHT_DUTY_STEP;
+               data->REG_PWM[6] = NCT6791_REG_WEIGHT_DUTY_BASE;
                data->REG_PWM_READ = NCT6775_REG_PWM_READ;
                data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
                data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
@@ -3670,10 +3682,10 @@ static int nct6775_probe(struct platform_device *pdev)
                data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
                data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
                data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
-               data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
-               data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
-               data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
-               data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
+               data->REG_WEIGHT_TEMP_SEL = NCT6791_REG_WEIGHT_TEMP_SEL;
+               data->REG_WEIGHT_TEMP[0] = NCT6791_REG_WEIGHT_TEMP_STEP;
+               data->REG_WEIGHT_TEMP[1] = NCT6791_REG_WEIGHT_TEMP_STEP_TOL;
+               data->REG_WEIGHT_TEMP[2] = NCT6791_REG_WEIGHT_TEMP_BASE;
                data->REG_ALARM = NCT6791_REG_ALARM;
                data->REG_BEEP = NCT6776_REG_BEEP;
 
@@ -3985,6 +3997,18 @@ static int nct6775_remove(struct platform_device *pdev)
        return 0;
 }
 
+static void nct6791_enable_io_mapping(int sioaddr)
+{
+       int val;
+
+       val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
+       if (val & 0x10) {
+               pr_info("Enabling hardware monitor logical device mappings.\n");
+               superio_outb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
+                            val & ~0x10);
+       }
+}
+
 #ifdef CONFIG_PM
 static int nct6775_suspend(struct device *dev)
 {
@@ -4004,11 +4028,20 @@ static int nct6775_suspend(struct device *dev)
 static int nct6775_resume(struct device *dev)
 {
        struct nct6775_data *data = dev_get_drvdata(dev);
-       int i, j;
+       int i, j, err = 0;
 
        mutex_lock(&data->update_lock);
        data->bank = 0xff;              /* Force initial bank selection */
 
+       if (data->kind == nct6791) {
+               err = superio_enter(data->sioreg);
+               if (err)
+                       goto abort;
+
+               nct6791_enable_io_mapping(data->sioreg);
+               superio_exit(data->sioreg);
+       }
+
        /* Restore limits */
        for (i = 0; i < data->in_num; i++) {
                if (!(data->have_in & (1 << i)))
@@ -4045,6 +4078,7 @@ static int nct6775_resume(struct device *dev)
                nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
        }
 
+abort:
        /* Force re-reading all values */
        data->valid = false;
        mutex_unlock(&data->update_lock);
@@ -4055,6 +4089,8 @@ static int nct6775_resume(struct device *dev)
 static const struct dev_pm_ops nct6775_dev_pm_ops = {
        .suspend = nct6775_suspend,
        .resume = nct6775_resume,
+       .freeze = nct6775_suspend,
+       .restore = nct6775_resume,
 };
 
 #define NCT6775_DEV_PM_OPS     (&nct6775_dev_pm_ops)
@@ -4136,15 +4172,8 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
                pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
                superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
        }
-       if (sio_data->kind == nct6791) {
-               val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
-               if (val & 0x10) {
-                       pr_info("Enabling hardware monitor logical device mappings.\n");
-                       superio_outb(sioaddr,
-                                    NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
-                                    val & ~0x10);
-               }
-       }
+       if (sio_data->kind == nct6791)
+               nct6791_enable_io_mapping(sioaddr);
 
        superio_exit(sioaddr);
        pr_info("Found %s or compatible chip at %#x:%#x\n",