MIPS: Loongson-3: Support 4 packages in CPU Hwmon driver
authorHuacai Chen <chenhc@lemote.com>
Thu, 22 Jun 2017 15:06:51 +0000 (23:06 +0800)
committerRalf Baechle <ralf@linux-mips.org>
Thu, 29 Jun 2017 00:42:22 +0000 (02:42 +0200)
Loongson-3 machines may have as many as 4 physical packages.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Cc: John Crispin <john@phrozen.org>
Cc: Steven J . Hill <Steven.Hill@cavium.com>
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/16588/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
drivers/platform/mips/cpu_hwmon.c

index 46ab7d8..322de58 100644 (file)
@@ -37,6 +37,7 @@ int loongson3_cpu_temp(int cpu)
        return (int)reg * 1000;
 }
 
+static int nr_packages;
 static struct device *cpu_hwmon_dev;
 
 static ssize_t get_hwmon_name(struct device *dev,
@@ -60,88 +61,74 @@ static ssize_t get_hwmon_name(struct device *dev,
        return sprintf(buf, "cpu-hwmon\n");
 }
 
-static ssize_t get_cpu0_temp(struct device *dev,
+static ssize_t get_cpu_temp(struct device *dev,
                        struct device_attribute *attr, char *buf);
-static ssize_t get_cpu1_temp(struct device *dev,
-                       struct device_attribute *attr, char *buf);
-static ssize_t cpu0_temp_label(struct device *dev,
-                       struct device_attribute *attr, char *buf);
-static ssize_t cpu1_temp_label(struct device *dev,
+static ssize_t cpu_temp_label(struct device *dev,
                        struct device_attribute *attr, char *buf);
 
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, get_cpu0_temp, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, cpu0_temp_label, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, get_cpu1_temp, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, cpu1_temp_label, NULL, 2);
-
-static const struct attribute *hwmon_cputemp1[] = {
-       &sensor_dev_attr_temp1_input.dev_attr.attr,
-       &sensor_dev_attr_temp1_label.dev_attr.attr,
-       NULL
-};
-
-static const struct attribute *hwmon_cputemp2[] = {
-       &sensor_dev_attr_temp2_input.dev_attr.attr,
-       &sensor_dev_attr_temp2_label.dev_attr.attr,
-       NULL
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, get_cpu_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, cpu_temp_label, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, get_cpu_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, cpu_temp_label, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, get_cpu_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, cpu_temp_label, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, get_cpu_temp, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, cpu_temp_label, NULL, 4);
+
+static const struct attribute *hwmon_cputemp[4][3] = {
+       {
+               &sensor_dev_attr_temp1_input.dev_attr.attr,
+               &sensor_dev_attr_temp1_label.dev_attr.attr,
+               NULL
+       },
+       {
+               &sensor_dev_attr_temp2_input.dev_attr.attr,
+               &sensor_dev_attr_temp2_label.dev_attr.attr,
+               NULL
+       },
+       {
+               &sensor_dev_attr_temp3_input.dev_attr.attr,
+               &sensor_dev_attr_temp3_label.dev_attr.attr,
+               NULL
+       },
+       {
+               &sensor_dev_attr_temp4_input.dev_attr.attr,
+               &sensor_dev_attr_temp4_label.dev_attr.attr,
+               NULL
+       }
 };
 
-static ssize_t cpu0_temp_label(struct device *dev,
+static ssize_t cpu_temp_label(struct device *dev,
                        struct device_attribute *attr, char *buf)
 {
-       return sprintf(buf, "CPU 0 Temperature\n");
+       int id = (to_sensor_dev_attr(attr))->index - 1;
+       return sprintf(buf, "CPU %d Temperature\n", id);
 }
 
-static ssize_t cpu1_temp_label(struct device *dev,
+static ssize_t get_cpu_temp(struct device *dev,
                        struct device_attribute *attr, char *buf)
 {
-       return sprintf(buf, "CPU 1 Temperature\n");
-}
-
-static ssize_t get_cpu0_temp(struct device *dev,
-                       struct device_attribute *attr, char *buf)
-{
-       int value = loongson3_cpu_temp(0);
-       return sprintf(buf, "%d\n", value);
-}
-
-static ssize_t get_cpu1_temp(struct device *dev,
-                       struct device_attribute *attr, char *buf)
-{
-       int value = loongson3_cpu_temp(1);
+       int id = (to_sensor_dev_attr(attr))->index - 1;
+       int value = loongson3_cpu_temp(id);
        return sprintf(buf, "%d\n", value);
 }
 
 static int create_sysfs_cputemp_files(struct kobject *kobj)
 {
-       int ret;
-
-       ret = sysfs_create_files(kobj, hwmon_cputemp1);
-       if (ret)
-               goto sysfs_create_temp1_fail;
-
-       if (loongson_sysconf.nr_cpus <= loongson_sysconf.cores_per_package)
-               return 0;
-
-       ret = sysfs_create_files(kobj, hwmon_cputemp2);
-       if (ret)
-               goto sysfs_create_temp2_fail;
+       int i, ret = 0;
 
-       return 0;
+       for (i=0; i<nr_packages; i++)
+               ret = sysfs_create_files(kobj, hwmon_cputemp[i]);
 
-sysfs_create_temp2_fail:
-       sysfs_remove_files(kobj, hwmon_cputemp1);
-
-sysfs_create_temp1_fail:
-       return -1;
+       return ret;
 }
 
 static void remove_sysfs_cputemp_files(struct kobject *kobj)
 {
-       sysfs_remove_files(&cpu_hwmon_dev->kobj, hwmon_cputemp1);
+       int i;
 
-       if (loongson_sysconf.nr_cpus > loongson_sysconf.cores_per_package)
-               sysfs_remove_files(&cpu_hwmon_dev->kobj, hwmon_cputemp2);
+       for (i=0; i<nr_packages; i++)
+               sysfs_remove_files(kobj, hwmon_cputemp[i]);
 }
 
 #define CPU_THERMAL_THRESHOLD 90000
@@ -149,8 +136,15 @@ static struct delayed_work thermal_work;
 
 static void do_thermal_timer(struct work_struct *work)
 {
-       int value = loongson3_cpu_temp(0);
-       if (value <= CPU_THERMAL_THRESHOLD)
+       int i, value, temp_max = 0;
+
+       for (i=0; i<nr_packages; i++) {
+               value = loongson3_cpu_temp(i);
+               if (value > temp_max)
+                       temp_max = value;
+       }
+
+       if (temp_max <= CPU_THERMAL_THRESHOLD)
                schedule_delayed_work(&thermal_work, msecs_to_jiffies(5000));
        else
                orderly_poweroff(true);
@@ -169,6 +163,9 @@ static int __init loongson_hwmon_init(void)
                goto fail_hwmon_device_register;
        }
 
+       nr_packages = loongson_sysconf.nr_cpus /
+               loongson_sysconf.cores_per_package;
+
        ret = sysfs_create_group(&cpu_hwmon_dev->kobj,
                                &cpu_hwmon_attribute_group);
        if (ret) {