hwmon: (emc1403) Support 11 bit accuracy
authorGuenter Roeck <linux@roeck-us.net>
Fri, 3 May 2024 04:53:55 +0000 (21:53 -0700)
committerGuenter Roeck <linux@roeck-us.net>
Tue, 7 May 2024 13:23:27 +0000 (06:23 -0700)
Various temperature and limit registers support 11 bit accuracy.
Add support for it.

Cc: Lars Petter Mostad <lars.petter.mostad@appear.net>
Tested-by: Lars Petter Mostad <lars.petter.mostad@appear.net>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/emc1403.c

index e656f0432a572f3d551e27e5844f5045e6c12d02..e53bb4d8bc1bf2f1ac865c6fc4724e4ce2dd311e 100644 (file)
@@ -178,17 +178,52 @@ static u8 emc1403_temp_regs[][4] = {
        },
 };
 
+static s8 emc1403_temp_regs_low[][4] = {
+       [0] = {
+               [temp_min] = -1,
+               [temp_max] = -1,
+               [temp_crit] = -1,
+               [temp_input] = 0x29,
+       },
+       [1] = {
+               [temp_min] = 0x14,
+               [temp_max] = 0x13,
+               [temp_crit] = -1,
+               [temp_input] = 0x10,
+       },
+       [2] = {
+               [temp_min] = 0x18,
+               [temp_max] = 0x17,
+               [temp_crit] = -1,
+               [temp_input] = 0x24,
+       },
+       [3] = {
+               [temp_min] = 0x2f,
+               [temp_max] = 0x2e,
+               [temp_crit] = -1,
+               [temp_input] = 0x2b,
+       },
+};
+
 static int __emc1403_get_temp(struct thermal_data *data, int channel,
                              enum emc1403_reg_map map, long *val)
 {
        unsigned int regval;
        int ret;
+       s8 reg;
 
        ret = regmap_read(data->regmap, emc1403_temp_regs[channel][map], &regval);
        if (ret < 0)
                return ret;
        *val = regval * 1000;
 
+       reg = emc1403_temp_regs_low[channel][map];
+       if (reg >= 0) {
+               ret = regmap_read(data->regmap, reg, &regval);
+               if (ret < 0)
+                       return ret;
+               *val += (regval >> 5) * 125;
+       }
        return 0;
 }
 
@@ -336,12 +371,26 @@ static int emc1403_set_temp(struct thermal_data *data, int channel,
 {
        unsigned int regval;
        int ret;
+       u8 regh;
+       s8 regl;
 
-       val = clamp_val(val, 0, 255000);
+       regh = emc1403_temp_regs[channel][map];
+       regl = emc1403_temp_regs_low[channel][map];
 
        mutex_lock(&data->mutex);
-       regval = DIV_ROUND_CLOSEST(val, 1000);
-       ret = regmap_write(data->regmap, emc1403_temp_regs[channel][map], regval);
+       if (regl >= 0) {
+               val = clamp_val(val, 0, 255875);
+               regval = DIV_ROUND_CLOSEST(val, 125);
+               ret = regmap_write(data->regmap, regh, regval >> 3);
+               if (ret < 0)
+                       goto unlock;
+               ret = regmap_write(data->regmap, regl, (regval & 0x07) << 5);
+       } else {
+               val = clamp_val(val, 0, 255000);
+               regval = DIV_ROUND_CLOSEST(val, 1000);
+               ret = regmap_write(data->regmap, regh, regval);
+       }
+unlock:
        mutex_unlock(&data->mutex);
        return ret;
 }