hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/platform/mips/cpu_hwmon.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 #include <linux/err.h>
23 #include <linux/module.h>
34 #include <linux/reboot.h>
....@@ -8,6 +9,9 @@
89 #include <loongson.h>
910 #include <boot_param.h>
1011 #include <loongson_hwmon.h>
12
+#include <loongson_regs.h>
13
+
14
+static int csr_temp_enable;
1115
1216 /*
1317 * Loongson-3 series cpu has two sensors inside,
....@@ -19,90 +23,43 @@
1923 {
2024 u32 reg, prid_rev;
2125
26
+ if (csr_temp_enable) {
27
+ reg = (csr_readl(LOONGSON_CSR_CPUTEMP) & 0xff);
28
+ goto out;
29
+ }
30
+
2231 reg = LOONGSON_CHIPTEMP(cpu);
2332 prid_rev = read_c0_prid() & PRID_REV_MASK;
33
+
2434 switch (prid_rev) {
2535 case PRID_REV_LOONGSON3A_R1:
2636 reg = (reg >> 8) & 0xff;
2737 break;
28
- case PRID_REV_LOONGSON3A_R2:
2938 case PRID_REV_LOONGSON3B_R1:
3039 case PRID_REV_LOONGSON3B_R2:
40
+ case PRID_REV_LOONGSON3A_R2_0:
41
+ case PRID_REV_LOONGSON3A_R2_1:
3142 reg = ((reg >> 8) & 0xff) - 100;
3243 break;
3344 case PRID_REV_LOONGSON3A_R3_0:
3445 case PRID_REV_LOONGSON3A_R3_1:
35
- reg = (reg & 0xffff)*731/0x4000 - 273;
46
+ default:
47
+ reg = (reg & 0xffff) * 731 / 0x4000 - 273;
3648 break;
3749 }
50
+
51
+out:
3852 return (int)reg * 1000;
3953 }
4054
4155 static int nr_packages;
4256 static struct device *cpu_hwmon_dev;
4357
44
-static ssize_t get_hwmon_name(struct device *dev,
45
- struct device_attribute *attr, char *buf);
46
-static SENSOR_DEVICE_ATTR(name, S_IRUGO, get_hwmon_name, NULL, 0);
47
-
48
-static struct attribute *cpu_hwmon_attributes[] = {
49
- &sensor_dev_attr_name.dev_attr.attr,
50
- NULL
51
-};
52
-
53
-/* Hwmon device attribute group */
54
-static struct attribute_group cpu_hwmon_attribute_group = {
55
- .attrs = cpu_hwmon_attributes,
56
-};
57
-
58
-/* Hwmon device get name */
59
-static ssize_t get_hwmon_name(struct device *dev,
60
- struct device_attribute *attr, char *buf)
61
-{
62
- return sprintf(buf, "cpu-hwmon\n");
63
-}
64
-
65
-static ssize_t get_cpu_temp(struct device *dev,
66
- struct device_attribute *attr, char *buf);
67
-static ssize_t cpu_temp_label(struct device *dev,
68
- struct device_attribute *attr, char *buf);
69
-
70
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, get_cpu_temp, NULL, 1);
71
-static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, cpu_temp_label, NULL, 1);
72
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, get_cpu_temp, NULL, 2);
73
-static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, cpu_temp_label, NULL, 2);
74
-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, get_cpu_temp, NULL, 3);
75
-static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, cpu_temp_label, NULL, 3);
76
-static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, get_cpu_temp, NULL, 4);
77
-static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, cpu_temp_label, NULL, 4);
78
-
79
-static const struct attribute *hwmon_cputemp[4][3] = {
80
- {
81
- &sensor_dev_attr_temp1_input.dev_attr.attr,
82
- &sensor_dev_attr_temp1_label.dev_attr.attr,
83
- NULL
84
- },
85
- {
86
- &sensor_dev_attr_temp2_input.dev_attr.attr,
87
- &sensor_dev_attr_temp2_label.dev_attr.attr,
88
- NULL
89
- },
90
- {
91
- &sensor_dev_attr_temp3_input.dev_attr.attr,
92
- &sensor_dev_attr_temp3_label.dev_attr.attr,
93
- NULL
94
- },
95
- {
96
- &sensor_dev_attr_temp4_input.dev_attr.attr,
97
- &sensor_dev_attr_temp4_label.dev_attr.attr,
98
- NULL
99
- }
100
-};
101
-
10258 static ssize_t cpu_temp_label(struct device *dev,
10359 struct device_attribute *attr, char *buf)
10460 {
10561 int id = (to_sensor_dev_attr(attr))->index - 1;
62
+
10663 return sprintf(buf, "CPU %d Temperature\n", id);
10764 }
10865
....@@ -111,97 +68,96 @@
11168 {
11269 int id = (to_sensor_dev_attr(attr))->index - 1;
11370 int value = loongson3_cpu_temp(id);
71
+
11472 return sprintf(buf, "%d\n", value);
11573 }
11674
117
-static int create_sysfs_cputemp_files(struct kobject *kobj)
75
+static SENSOR_DEVICE_ATTR(temp1_input, 0444, get_cpu_temp, NULL, 1);
76
+static SENSOR_DEVICE_ATTR(temp1_label, 0444, cpu_temp_label, NULL, 1);
77
+static SENSOR_DEVICE_ATTR(temp2_input, 0444, get_cpu_temp, NULL, 2);
78
+static SENSOR_DEVICE_ATTR(temp2_label, 0444, cpu_temp_label, NULL, 2);
79
+static SENSOR_DEVICE_ATTR(temp3_input, 0444, get_cpu_temp, NULL, 3);
80
+static SENSOR_DEVICE_ATTR(temp3_label, 0444, cpu_temp_label, NULL, 3);
81
+static SENSOR_DEVICE_ATTR(temp4_input, 0444, get_cpu_temp, NULL, 4);
82
+static SENSOR_DEVICE_ATTR(temp4_label, 0444, cpu_temp_label, NULL, 4);
83
+
84
+static struct attribute *cpu_hwmon_attributes[] = {
85
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
86
+ &sensor_dev_attr_temp1_label.dev_attr.attr,
87
+ &sensor_dev_attr_temp2_input.dev_attr.attr,
88
+ &sensor_dev_attr_temp2_label.dev_attr.attr,
89
+ &sensor_dev_attr_temp3_input.dev_attr.attr,
90
+ &sensor_dev_attr_temp3_label.dev_attr.attr,
91
+ &sensor_dev_attr_temp4_input.dev_attr.attr,
92
+ &sensor_dev_attr_temp4_label.dev_attr.attr,
93
+ NULL
94
+};
95
+
96
+static umode_t cpu_hwmon_is_visible(struct kobject *kobj,
97
+ struct attribute *attr, int i)
11898 {
119
- int i, ret = 0;
99
+ int id = i / 2;
120100
121
- for (i=0; i<nr_packages; i++)
122
- ret = sysfs_create_files(kobj, hwmon_cputemp[i]);
123
-
124
- return ret;
101
+ if (id < nr_packages)
102
+ return attr->mode;
103
+ return 0;
125104 }
126105
127
-static void remove_sysfs_cputemp_files(struct kobject *kobj)
128
-{
129
- int i;
106
+static struct attribute_group cpu_hwmon_group = {
107
+ .attrs = cpu_hwmon_attributes,
108
+ .is_visible = cpu_hwmon_is_visible,
109
+};
130110
131
- for (i=0; i<nr_packages; i++)
132
- sysfs_remove_files(kobj, hwmon_cputemp[i]);
133
-}
111
+static const struct attribute_group *cpu_hwmon_groups[] = {
112
+ &cpu_hwmon_group,
113
+ NULL
114
+};
134115
135116 #define CPU_THERMAL_THRESHOLD 90000
136117 static struct delayed_work thermal_work;
137118
138119 static void do_thermal_timer(struct work_struct *work)
139120 {
140
- int i, value, temp_max = 0;
121
+ int i, value;
141122
142
- for (i=0; i<nr_packages; i++) {
123
+ for (i = 0; i < nr_packages; i++) {
143124 value = loongson3_cpu_temp(i);
144
- if (value > temp_max)
145
- temp_max = value;
125
+ if (value > CPU_THERMAL_THRESHOLD) {
126
+ pr_emerg("Power off due to high temp: %d\n", value);
127
+ orderly_poweroff(true);
128
+ }
146129 }
147130
148
- if (temp_max <= CPU_THERMAL_THRESHOLD)
149
- schedule_delayed_work(&thermal_work, msecs_to_jiffies(5000));
150
- else
151
- orderly_poweroff(true);
131
+ schedule_delayed_work(&thermal_work, msecs_to_jiffies(5000));
152132 }
153133
154134 static int __init loongson_hwmon_init(void)
155135 {
156
- int ret;
157
-
158136 pr_info("Loongson Hwmon Enter...\n");
159137
160
- cpu_hwmon_dev = hwmon_device_register(NULL);
161
- if (IS_ERR(cpu_hwmon_dev)) {
162
- ret = PTR_ERR(cpu_hwmon_dev);
163
- pr_err("hwmon_device_register fail!\n");
164
- goto fail_hwmon_device_register;
165
- }
138
+ if (cpu_has_csr())
139
+ csr_temp_enable = csr_readl(LOONGSON_CSR_FEATURES) &
140
+ LOONGSON_CSRF_TEMP;
166141
167142 nr_packages = loongson_sysconf.nr_cpus /
168143 loongson_sysconf.cores_per_package;
169144
170
- ret = sysfs_create_group(&cpu_hwmon_dev->kobj,
171
- &cpu_hwmon_attribute_group);
172
- if (ret) {
173
- pr_err("fail to create loongson hwmon!\n");
174
- goto fail_sysfs_create_group_hwmon;
175
- }
176
-
177
- ret = create_sysfs_cputemp_files(&cpu_hwmon_dev->kobj);
178
- if (ret) {
179
- pr_err("fail to create cpu temperature interface!\n");
180
- goto fail_create_sysfs_cputemp_files;
145
+ cpu_hwmon_dev = hwmon_device_register_with_groups(NULL, "cpu_hwmon",
146
+ NULL, cpu_hwmon_groups);
147
+ if (IS_ERR(cpu_hwmon_dev)) {
148
+ pr_err("hwmon_device_register fail!\n");
149
+ return PTR_ERR(cpu_hwmon_dev);
181150 }
182151
183152 INIT_DEFERRABLE_WORK(&thermal_work, do_thermal_timer);
184153 schedule_delayed_work(&thermal_work, msecs_to_jiffies(20000));
185154
186
- return ret;
187
-
188
-fail_create_sysfs_cputemp_files:
189
- sysfs_remove_group(&cpu_hwmon_dev->kobj,
190
- &cpu_hwmon_attribute_group);
191
-
192
-fail_sysfs_create_group_hwmon:
193
- hwmon_device_unregister(cpu_hwmon_dev);
194
-
195
-fail_hwmon_device_register:
196
- return ret;
155
+ return 0;
197156 }
198157
199158 static void __exit loongson_hwmon_exit(void)
200159 {
201160 cancel_delayed_work_sync(&thermal_work);
202
- remove_sysfs_cputemp_files(&cpu_hwmon_dev->kobj);
203
- sysfs_remove_group(&cpu_hwmon_dev->kobj,
204
- &cpu_hwmon_attribute_group);
205161 hwmon_device_unregister(cpu_hwmon_dev);
206162 }
207163