|
@@ -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) {
|