These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / hwmon / f71882fg.c
index 2e5c6f4..cb28e4b 100644 (file)
@@ -51,6 +51,7 @@
 #define SIO_F71808A_ID         0x1001  /* Chipset ID */
 #define SIO_F71858_ID          0x0507  /* Chipset ID */
 #define SIO_F71862_ID          0x0601  /* Chipset ID */
+#define SIO_F71868_ID          0x1106  /* Chipset ID */
 #define SIO_F71869_ID          0x0814  /* Chipset ID */
 #define SIO_F71869A_ID         0x1007  /* Chipset ID */
 #define SIO_F71882_ID          0x0541  /* Chipset ID */
@@ -58,7 +59,9 @@
 #define SIO_F71889E_ID         0x0909  /* Chipset ID */
 #define SIO_F71889A_ID         0x1005  /* Chipset ID */
 #define SIO_F8000_ID           0x0581  /* Chipset ID */
+#define SIO_F81768D_ID         0x1210  /* Chipset ID */
 #define SIO_F81865_ID          0x0704  /* Chipset ID */
+#define SIO_F81866_ID          0x1010  /* Chipset ID */
 
 #define REGION_LENGTH          8
 #define ADDR_REG_OFFSET                5
 #define F71882FG_REG_IN(nr)            (0x20  + (nr))
 #define F71882FG_REG_IN1_HIGH          0x32 /* f7188x only */
 
+#define F81866_REG_IN_STATUS           0x16 /* F81866 only */
+#define F81866_REG_IN_BEEP                     0x17 /* F81866 only */
+#define F81866_REG_IN1_HIGH            0x3a /* F81866 only */
+
 #define F71882FG_REG_FAN(nr)           (0xA0 + (16 * (nr)))
 #define F71882FG_REG_FAN_TARGET(nr)    (0xA2 + (16 * (nr)))
 #define F71882FG_REG_FAN_FULL_SPEED(nr)        (0xA4 + (16 * (nr)))
 
 #define        F71882FG_REG_START              0x01
 
-#define F71882FG_MAX_INS               9
+#define F71882FG_MAX_INS               11
 
 #define FAN_MIN_DETECT                 366 /* Lowest detectable fanspeed */
 
@@ -109,14 +116,16 @@ static unsigned short force_id;
 module_param(force_id, ushort, 0);
 MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
-enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71869a, f71882fg,
-            f71889fg, f71889ed, f71889a, f8000, f81865f };
+enum chips { f71808e, f71808a, f71858fg, f71862fg, f71868a, f71869, f71869a,
+       f71882fg, f71889fg, f71889ed, f71889a, f8000, f81768d, f81865f,
+       f81866a};
 
 static const char *const f71882fg_names[] = {
        "f71808e",
        "f71808a",
        "f71858fg",
        "f71862fg",
+       "f71868a",
        "f71869", /* Both f71869f and f71869e, reg. compatible and same id */
        "f71869a",
        "f71882fg",
@@ -124,22 +133,27 @@ static const char *const f71882fg_names[] = {
        "f71889ed",
        "f71889a",
        "f8000",
+       "f81768d",
        "f81865f",
+       "f81866a",
 };
 
 static const char f71882fg_has_in[][F71882FG_MAX_INS] = {
-       [f71808e]       = { 1, 1, 1, 1, 1, 1, 0, 1, 1 },
-       [f71808a]       = { 1, 1, 1, 1, 0, 0, 0, 1, 1 },
-       [f71858fg]      = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
-       [f71862fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f71869]        = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f71869a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f71882fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f71889fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f71889ed]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f71889a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f8000]         = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
-       [f81865f]       = { 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71808e]       = { 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0 },
+       [f71808a]       = { 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0 },
+       [f71858fg]      = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+       [f71862fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71868a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+       [f71869]        = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71869a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71882fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71889fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71889ed]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71889a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f8000]         = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+       [f81768d]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+       [f81865f]       = { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
+       [f81866a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
 };
 
 static const char f71882fg_has_in1_alarm[] = {
@@ -147,6 +161,7 @@ static const char f71882fg_has_in1_alarm[] = {
        [f71808a]       = 0,
        [f71858fg]      = 0,
        [f71862fg]      = 0,
+       [f71868a]       = 0,
        [f71869]        = 0,
        [f71869a]       = 0,
        [f71882fg]      = 1,
@@ -154,7 +169,9 @@ static const char f71882fg_has_in1_alarm[] = {
        [f71889ed]      = 1,
        [f71889a]       = 1,
        [f8000]         = 0,
+       [f81768d]       = 1,
        [f81865f]       = 1,
+       [f81866a]       = 1,
 };
 
 static const char f71882fg_fan_has_beep[] = {
@@ -162,6 +179,7 @@ static const char f71882fg_fan_has_beep[] = {
        [f71808a]       = 0,
        [f71858fg]      = 0,
        [f71862fg]      = 1,
+       [f71868a]       = 1,
        [f71869]        = 1,
        [f71869a]       = 1,
        [f71882fg]      = 1,
@@ -169,7 +187,9 @@ static const char f71882fg_fan_has_beep[] = {
        [f71889ed]      = 1,
        [f71889a]       = 1,
        [f8000]         = 0,
+       [f81768d]       = 1,
        [f81865f]       = 1,
+       [f81866a]       = 1,
 };
 
 static const char f71882fg_nr_fans[] = {
@@ -177,6 +197,7 @@ static const char f71882fg_nr_fans[] = {
        [f71808a]       = 2, /* +1 fan which is monitor + simple pwm only */
        [f71858fg]      = 3,
        [f71862fg]      = 3,
+       [f71868a]       = 3,
        [f71869]        = 3,
        [f71869a]       = 3,
        [f71882fg]      = 4,
@@ -184,7 +205,9 @@ static const char f71882fg_nr_fans[] = {
        [f71889ed]      = 3,
        [f71889a]       = 3,
        [f8000]         = 3, /* +1 fan which is monitor only */
+       [f81768d]       = 3,
        [f81865f]       = 2,
+       [f81866a]       = 3,
 };
 
 static const char f71882fg_temp_has_beep[] = {
@@ -192,6 +215,7 @@ static const char f71882fg_temp_has_beep[] = {
        [f71808a]       = 1,
        [f71858fg]      = 0,
        [f71862fg]      = 1,
+       [f71868a]       = 1,
        [f71869]        = 1,
        [f71869a]       = 1,
        [f71882fg]      = 1,
@@ -199,7 +223,9 @@ static const char f71882fg_temp_has_beep[] = {
        [f71889ed]      = 1,
        [f71889a]       = 1,
        [f8000]         = 0,
+       [f81768d]       = 1,
        [f81865f]       = 1,
+       [f81866a]       = 1,
 };
 
 static const char f71882fg_nr_temps[] = {
@@ -207,6 +233,7 @@ static const char f71882fg_nr_temps[] = {
        [f71808a]       = 2,
        [f71858fg]      = 3,
        [f71862fg]      = 3,
+       [f71868a]       = 3,
        [f71869]        = 3,
        [f71869a]       = 3,
        [f71882fg]      = 3,
@@ -214,7 +241,9 @@ static const char f71882fg_nr_temps[] = {
        [f71889ed]      = 3,
        [f71889a]       = 3,
        [f8000]         = 3,
+       [f81768d]       = 3,
        [f81865f]       = 2,
+       [f81866a]       = 3,
 };
 
 static struct platform_device *f71882fg_pdev;
@@ -490,6 +519,23 @@ static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {
                store_temp_beep, 0, 7),
 } };
 
+static struct sensor_device_attribute_2 f81866_temp_beep_attr[3][2] = { {
+       SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+               store_temp_beep, 0, 0),
+       SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+               store_temp_beep, 0, 4),
+}, {
+       SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+               store_temp_beep, 0, 1),
+       SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+               store_temp_beep, 0, 5),
+}, {
+       SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+               store_temp_beep, 0, 2),
+       SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+               store_temp_beep, 0, 6),
+} };
+
 /*
  * Temp attr for the f8000
  * Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
@@ -531,6 +577,8 @@ static struct sensor_device_attribute_2 fxxxx_in_attr[] = {
        SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
        SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
        SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
+       SENSOR_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 0, 9),
+       SENSOR_ATTR_2(in10_input, S_IRUGO, show_in, NULL, 0, 10),
 };
 
 /* For models with in1 alarm capability */
@@ -1170,10 +1218,21 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
        if (time_after(jiffies, data->last_limits + 60 * HZ) ||
                        !data->valid) {
                if (f71882fg_has_in1_alarm[data->type]) {
-                       data->in1_max =
-                               f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
-                       data->in_beep =
-                               f71882fg_read8(data, F71882FG_REG_IN_BEEP);
+                       if (data->type == f81866a) {
+                               data->in1_max =
+                                       f71882fg_read8(data,
+                                                      F81866_REG_IN1_HIGH);
+                               data->in_beep =
+                                       f71882fg_read8(data,
+                                                      F81866_REG_IN_BEEP);
+                       } else {
+                               data->in1_max =
+                                       f71882fg_read8(data,
+                                                      F71882FG_REG_IN1_HIGH);
+                               data->in_beep =
+                                       f71882fg_read8(data,
+                                                      F71882FG_REG_IN_BEEP);
+                       }
                }
 
                /* Get High & boundary temps*/
@@ -1297,9 +1356,16 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
                        data->fan[3] = f71882fg_read16(data,
                                                F71882FG_REG_FAN(3));
 
-               if (f71882fg_has_in1_alarm[data->type])
-                       data->in_status = f71882fg_read8(data,
+               if (f71882fg_has_in1_alarm[data->type]) {
+                       if (data->type == f81866a)
+                               data->in_status = f71882fg_read8(data,
+                                               F81866_REG_IN_STATUS);
+
+                       else
+                               data->in_status = f71882fg_read8(data,
                                                F71882FG_REG_IN_STATUS);
+               }
+
                for (nr = 0; nr < F71882FG_MAX_INS; nr++)
                        if (f71882fg_has_in[data->type][nr])
                                data->in[nr] = f71882fg_read8(data,
@@ -1440,7 +1506,10 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute
        val = clamp_val(val, 0, 255);
 
        mutex_lock(&data->update_lock);
-       f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
+       if (data->type == f81866a)
+               f71882fg_write8(data, F81866_REG_IN1_HIGH, val);
+       else
+               f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
        data->in1_max = val;
        mutex_unlock(&data->update_lock);
 
@@ -1471,13 +1540,20 @@ static ssize_t store_in_beep(struct device *dev, struct device_attribute
                return err;
 
        mutex_lock(&data->update_lock);
-       data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
+       if (data->type == f81866a)
+               data->in_beep = f71882fg_read8(data, F81866_REG_IN_BEEP);
+       else
+               data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
+
        if (val)
                data->in_beep |= 1 << nr;
        else
                data->in_beep &= ~(1 << nr);
 
-       f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
+       if (data->type == f81866a)
+               f71882fg_write8(data, F81866_REG_IN_BEEP, data->in_beep);
+       else
+               f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
        mutex_unlock(&data->update_lock);
 
        return count;
@@ -2270,6 +2346,7 @@ static int f71882fg_probe(struct platform_device *pdev)
        int nr_fans = f71882fg_nr_fans[sio_data->type];
        int nr_temps = f71882fg_nr_temps[sio_data->type];
        int err, i;
+       int size;
        u8 start_reg, reg;
 
        data = devm_kzalloc(&pdev->dev, sizeof(struct f71882fg_data),
@@ -2280,7 +2357,8 @@ static int f71882fg_probe(struct platform_device *pdev)
        data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
        data->type = sio_data->type;
        data->temp_start =
-           (data->type == f71858fg || data->type == f8000) ? 0 : 1;
+           (data->type == f71858fg || data->type == f8000 ||
+               data->type == f81866a) ? 0 : 1;
        mutex_init(&data->update_lock);
        platform_set_drvdata(pdev, data);
 
@@ -2322,6 +2400,11 @@ static int f71882fg_probe(struct platform_device *pdev)
                                        f8000_temp_attr,
                                        ARRAY_SIZE(f8000_temp_attr));
                        break;
+               case f81866a:
+                       err = f71882fg_create_sysfs_files(pdev,
+                                       f71858fg_temp_attr,
+                                       ARRAY_SIZE(f71858fg_temp_attr));
+                       break;
                default:
                        err = f71882fg_create_sysfs_files(pdev,
                                &fxxxx_temp_attr[0][0],
@@ -2331,10 +2414,18 @@ static int f71882fg_probe(struct platform_device *pdev)
                        goto exit_unregister_sysfs;
 
                if (f71882fg_temp_has_beep[data->type]) {
-                       err = f71882fg_create_sysfs_files(pdev,
-                                       &fxxxx_temp_beep_attr[0][0],
-                                       ARRAY_SIZE(fxxxx_temp_beep_attr[0])
-                                               * nr_temps);
+                       if (data->type == f81866a) {
+                               size = ARRAY_SIZE(f81866_temp_beep_attr[0]);
+                               err = f71882fg_create_sysfs_files(pdev,
+                                               &f81866_temp_beep_attr[0][0],
+                                               size * nr_temps);
+
+                       } else {
+                               size = ARRAY_SIZE(fxxxx_temp_beep_attr[0]);
+                               err = f71882fg_create_sysfs_files(pdev,
+                                               &fxxxx_temp_beep_attr[0][0],
+                                               size * nr_temps);
+                       }
                        if (err)
                                goto exit_unregister_sysfs;
                }
@@ -2451,15 +2542,27 @@ static int f71882fg_remove(struct platform_device *pdev)
                                        f8000_temp_attr,
                                        ARRAY_SIZE(f8000_temp_attr));
                        break;
+               case f81866a:
+                       f71882fg_remove_sysfs_files(pdev,
+                                       f71858fg_temp_attr,
+                                       ARRAY_SIZE(f71858fg_temp_attr));
+                       break;
                default:
                        f71882fg_remove_sysfs_files(pdev,
                                &fxxxx_temp_attr[0][0],
                                ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
                }
                if (f71882fg_temp_has_beep[data->type]) {
-                       f71882fg_remove_sysfs_files(pdev,
-                              &fxxxx_temp_beep_attr[0][0],
-                              ARRAY_SIZE(fxxxx_temp_beep_attr[0]) * nr_temps);
+                       if (data->type == f81866a)
+                               f71882fg_remove_sysfs_files(pdev,
+                                       &f81866_temp_beep_attr[0][0],
+                                       ARRAY_SIZE(f81866_temp_beep_attr[0])
+                                               * nr_temps);
+                       else
+                               f71882fg_remove_sysfs_files(pdev,
+                                       &fxxxx_temp_beep_attr[0][0],
+                                       ARRAY_SIZE(fxxxx_temp_beep_attr[0])
+                                               * nr_temps);
                }
 
                for (i = 0; i < F71882FG_MAX_INS; i++) {
@@ -2551,6 +2654,9 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data)
        case SIO_F71862_ID:
                sio_data->type = f71862fg;
                break;
+       case SIO_F71868_ID:
+               sio_data->type = f71868a;
+               break;
        case SIO_F71869_ID:
                sio_data->type = f71869;
                break;
@@ -2572,9 +2678,15 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data)
        case SIO_F8000_ID:
                sio_data->type = f8000;
                break;
+       case SIO_F81768D_ID:
+               sio_data->type = f81768d;
+               break;
        case SIO_F81865_ID:
                sio_data->type = f81865f;
                break;
+       case SIO_F81866_ID:
+               sio_data->type = f81866a;
+               break;
        default:
                pr_info("Unsupported Fintek device: %04x\n",
                        (unsigned int)devid);