Merge tag 'drm-misc-next-fixes-2020-08-05' of git://anongit.freedesktop.org/drm/drm...
[linux-2.6-microblaze.git] / drivers / hwmon / amd_energy.c
1 // SPDX-License-Identifier: GPL-2.0-only
2
3 /*
4  * Copyright (C) 2020 Advanced Micro Devices, Inc.
5  */
6 #include <asm/cpu_device_id.h>
7
8 #include <linux/bits.h>
9 #include <linux/cpu.h>
10 #include <linux/cpumask.h>
11 #include <linux/delay.h>
12 #include <linux/device.h>
13 #include <linux/hwmon.h>
14 #include <linux/kernel.h>
15 #include <linux/kthread.h>
16 #include <linux/list.h>
17 #include <linux/module.h>
18 #include <linux/mutex.h>
19 #include <linux/processor.h>
20 #include <linux/platform_device.h>
21 #include <linux/sched.h>
22 #include <linux/slab.h>
23 #include <linux/topology.h>
24 #include <linux/types.h>
25
26 #define DRVNAME                 "amd_energy"
27
28 #define ENERGY_PWR_UNIT_MSR     0xC0010299
29 #define ENERGY_CORE_MSR         0xC001029A
30 #define ENERGY_PKG_MSR          0xC001029B
31
32 #define AMD_ENERGY_UNIT_MASK    0x01F00
33 #define AMD_ENERGY_MASK         0xFFFFFFFF
34
35 struct sensor_accumulator {
36         u64 energy_ctr;
37         u64 prev_value;
38         char label[10];
39 };
40
41 struct amd_energy_data {
42         struct hwmon_channel_info energy_info;
43         const struct hwmon_channel_info *info[2];
44         struct hwmon_chip_info chip;
45         struct task_struct *wrap_accumulate;
46         /* Lock around the accumulator */
47         struct mutex lock;
48         /* An accumulator for each core and socket */
49         struct sensor_accumulator *accums;
50         /* Energy Status Units */
51         u64 energy_units;
52         int nr_cpus;
53         int nr_socks;
54         int core_id;
55 };
56
57 static int amd_energy_read_labels(struct device *dev,
58                                   enum hwmon_sensor_types type,
59                                   u32 attr, int channel,
60                                   const char **str)
61 {
62         struct amd_energy_data *data = dev_get_drvdata(dev);
63
64         *str = data->accums[channel].label;
65         return 0;
66 }
67
68 static void get_energy_units(struct amd_energy_data *data)
69 {
70         u64 rapl_units;
71
72         rdmsrl_safe(ENERGY_PWR_UNIT_MSR, &rapl_units);
73         data->energy_units = (rapl_units & AMD_ENERGY_UNIT_MASK) >> 8;
74 }
75
76 static void accumulate_socket_delta(struct amd_energy_data *data,
77                                     int sock, int cpu)
78 {
79         struct sensor_accumulator *s_accum;
80         u64 input;
81
82         mutex_lock(&data->lock);
83         rdmsrl_safe_on_cpu(cpu, ENERGY_PKG_MSR, &input);
84         input &= AMD_ENERGY_MASK;
85
86         s_accum = &data->accums[data->nr_cpus + sock];
87         if (input >= s_accum->prev_value)
88                 s_accum->energy_ctr +=
89                         input - s_accum->prev_value;
90         else
91                 s_accum->energy_ctr += UINT_MAX -
92                         s_accum->prev_value + input;
93
94         s_accum->prev_value = input;
95         mutex_unlock(&data->lock);
96 }
97
98 static void accumulate_core_delta(struct amd_energy_data *data)
99 {
100         struct sensor_accumulator *c_accum;
101         u64 input;
102         int cpu;
103
104         mutex_lock(&data->lock);
105         if (data->core_id >= data->nr_cpus)
106                 data->core_id = 0;
107
108         cpu = data->core_id;
109
110         if (!cpu_online(cpu))
111                 goto out;
112
113         rdmsrl_safe_on_cpu(cpu, ENERGY_CORE_MSR, &input);
114         input &= AMD_ENERGY_MASK;
115
116         c_accum = &data->accums[cpu];
117
118         if (input >= c_accum->prev_value)
119                 c_accum->energy_ctr +=
120                         input - c_accum->prev_value;
121         else
122                 c_accum->energy_ctr += UINT_MAX -
123                         c_accum->prev_value + input;
124
125         c_accum->prev_value = input;
126
127 out:
128         data->core_id++;
129         mutex_unlock(&data->lock);
130 }
131
132 static void read_accumulate(struct amd_energy_data *data)
133 {
134         int sock;
135
136         for (sock = 0; sock < data->nr_socks; sock++) {
137                 int cpu;
138
139                 cpu = cpumask_first_and(cpu_online_mask,
140                                         cpumask_of_node(sock));
141
142                 accumulate_socket_delta(data, sock, cpu);
143         }
144
145         accumulate_core_delta(data);
146 }
147
148 static void amd_add_delta(struct amd_energy_data *data, int ch,
149                           int cpu, long *val, bool is_core)
150 {
151         struct sensor_accumulator *s_accum, *c_accum;
152         u64 input;
153
154         mutex_lock(&data->lock);
155         if (!is_core) {
156                 rdmsrl_safe_on_cpu(cpu, ENERGY_PKG_MSR, &input);
157                 input &= AMD_ENERGY_MASK;
158
159                 s_accum = &data->accums[ch];
160                 if (input >= s_accum->prev_value)
161                         input += s_accum->energy_ctr -
162                                   s_accum->prev_value;
163                 else
164                         input += UINT_MAX - s_accum->prev_value +
165                                   s_accum->energy_ctr;
166         } else {
167                 rdmsrl_safe_on_cpu(cpu, ENERGY_CORE_MSR, &input);
168                 input &= AMD_ENERGY_MASK;
169
170                 c_accum = &data->accums[ch];
171                 if (input >= c_accum->prev_value)
172                         input += c_accum->energy_ctr -
173                                  c_accum->prev_value;
174                 else
175                         input += UINT_MAX - c_accum->prev_value +
176                                  c_accum->energy_ctr;
177         }
178
179         /* Energy consumed = (1/(2^ESU) * RAW * 1000000UL) μJoules */
180         *val = div64_ul(input * 1000000UL, BIT(data->energy_units));
181
182         mutex_unlock(&data->lock);
183 }
184
185 static int amd_energy_read(struct device *dev,
186                            enum hwmon_sensor_types type,
187                            u32 attr, int channel, long *val)
188 {
189         struct amd_energy_data *data = dev_get_drvdata(dev);
190         int cpu;
191
192         if (channel >= data->nr_cpus) {
193                 cpu = cpumask_first_and(cpu_online_mask,
194                                         cpumask_of_node
195                                         (channel - data->nr_cpus));
196                 amd_add_delta(data, channel, cpu, val, false);
197         } else {
198                 cpu = channel;
199                 if (!cpu_online(cpu))
200                         return -ENODEV;
201
202                 amd_add_delta(data, channel, cpu, val, true);
203         }
204
205         return 0;
206 }
207
208 static umode_t amd_energy_is_visible(const void *_data,
209                                      enum hwmon_sensor_types type,
210                                      u32 attr, int channel)
211 {
212         return 0444;
213 }
214
215 static int energy_accumulator(void *p)
216 {
217         struct amd_energy_data *data = (struct amd_energy_data *)p;
218
219         while (!kthread_should_stop()) {
220                 /*
221                  * Ignoring the conditions such as
222                  * cpu being offline or rdmsr failure
223                  */
224                 read_accumulate(data);
225
226                 set_current_state(TASK_INTERRUPTIBLE);
227                 if (kthread_should_stop())
228                         break;
229
230                 /*
231                  * On a 240W system, with default resolution the
232                  * Socket Energy status register may wrap around in
233                  * 2^32*15.3 e-6/240 = 273.8041 secs (~4.5 mins)
234                  *
235                  * let us accumulate for every 100secs
236                  */
237                 schedule_timeout(msecs_to_jiffies(100000));
238         }
239         return 0;
240 }
241
242 static const struct hwmon_ops amd_energy_ops = {
243         .is_visible = amd_energy_is_visible,
244         .read = amd_energy_read,
245         .read_string = amd_energy_read_labels,
246 };
247
248 static int amd_create_sensor(struct device *dev,
249                              struct amd_energy_data *data,
250                              u8 type, u32 config)
251 {
252         struct hwmon_channel_info *info = &data->energy_info;
253         struct sensor_accumulator *accums;
254         int i, num_siblings, cpus, sockets;
255         u32 *s_config;
256
257         /* Identify the number of siblings per core */
258         num_siblings = ((cpuid_ebx(0x8000001e) >> 8) & 0xff) + 1;
259
260         sockets = num_possible_nodes();
261
262         /*
263          * Energy counter register is accessed at core level.
264          * Hence, filterout the siblings.
265          */
266         cpus = num_present_cpus() / num_siblings;
267
268         s_config = devm_kcalloc(dev, cpus + sockets,
269                                 sizeof(u32), GFP_KERNEL);
270         if (!s_config)
271                 return -ENOMEM;
272
273         accums = devm_kcalloc(dev, cpus + sockets,
274                               sizeof(struct sensor_accumulator),
275                               GFP_KERNEL);
276         if (!accums)
277                 return -ENOMEM;
278
279         info->type = type;
280         info->config = s_config;
281
282         data->nr_cpus = cpus;
283         data->nr_socks = sockets;
284         data->accums = accums;
285
286         for (i = 0; i < cpus + sockets; i++) {
287                 s_config[i] = config;
288                 if (i < cpus)
289                         scnprintf(accums[i].label, 10,
290                                   "Ecore%03u", i);
291                 else
292                         scnprintf(accums[i].label, 10,
293                                   "Esocket%u", (i - cpus));
294         }
295
296         return 0;
297 }
298
299 static int amd_energy_probe(struct platform_device *pdev)
300 {
301         struct device *hwmon_dev;
302         struct amd_energy_data *data;
303         struct device *dev = &pdev->dev;
304
305         data = devm_kzalloc(dev,
306                             sizeof(struct amd_energy_data), GFP_KERNEL);
307         if (!data)
308                 return -ENOMEM;
309
310         data->chip.ops = &amd_energy_ops;
311         data->chip.info = data->info;
312
313         dev_set_drvdata(dev, data);
314         /* Populate per-core energy reporting */
315         data->info[0] = &data->energy_info;
316         amd_create_sensor(dev, data, hwmon_energy,
317                           HWMON_E_INPUT | HWMON_E_LABEL);
318
319         mutex_init(&data->lock);
320         get_energy_units(data);
321
322         hwmon_dev = devm_hwmon_device_register_with_info(dev, DRVNAME,
323                                                          data,
324                                                          &data->chip,
325                                                          NULL);
326         if (IS_ERR(hwmon_dev))
327                 return PTR_ERR(hwmon_dev);
328
329         data->wrap_accumulate = kthread_run(energy_accumulator, data,
330                                             "%s", dev_name(hwmon_dev));
331         if (IS_ERR(data->wrap_accumulate))
332                 return PTR_ERR(data->wrap_accumulate);
333
334         return PTR_ERR_OR_ZERO(data->wrap_accumulate);
335 }
336
337 static int amd_energy_remove(struct platform_device *pdev)
338 {
339         struct amd_energy_data *data = dev_get_drvdata(&pdev->dev);
340
341         if (data && data->wrap_accumulate)
342                 kthread_stop(data->wrap_accumulate);
343
344         return 0;
345 }
346
347 static const struct platform_device_id amd_energy_ids[] = {
348         { .name = DRVNAME, },
349         {}
350 };
351 MODULE_DEVICE_TABLE(platform, amd_energy_ids);
352
353 static struct platform_driver amd_energy_driver = {
354         .probe = amd_energy_probe,
355         .remove = amd_energy_remove,
356         .id_table = amd_energy_ids,
357         .driver = {
358                 .name = DRVNAME,
359         },
360 };
361
362 static struct platform_device *amd_energy_platdev;
363
364 static const struct x86_cpu_id cpu_ids[] __initconst = {
365         X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x17, 0x31, NULL),
366         {}
367 };
368 MODULE_DEVICE_TABLE(x86cpu, cpu_ids);
369
370 static int __init amd_energy_init(void)
371 {
372         int ret;
373
374         if (!x86_match_cpu(cpu_ids))
375                 return -ENODEV;
376
377         ret = platform_driver_register(&amd_energy_driver);
378         if (ret)
379                 return ret;
380
381         amd_energy_platdev = platform_device_alloc(DRVNAME, 0);
382         if (!amd_energy_platdev) {
383                 platform_driver_unregister(&amd_energy_driver);
384                 return -ENOMEM;
385         }
386
387         ret = platform_device_add(amd_energy_platdev);
388         if (ret) {
389                 platform_device_put(amd_energy_platdev);
390                 platform_driver_unregister(&amd_energy_driver);
391                 return ret;
392         }
393
394         return ret;
395 }
396
397 static void __exit amd_energy_exit(void)
398 {
399         platform_device_unregister(amd_energy_platdev);
400         platform_driver_unregister(&amd_energy_driver);
401 }
402
403 module_init(amd_energy_init);
404 module_exit(amd_energy_exit);
405
406 MODULE_DESCRIPTION("Driver for AMD Energy reporting from RAPL MSR via HWMON interface");
407 MODULE_AUTHOR("Naveen Krishna Chatradhi <nchatrad@amd.com>");
408 MODULE_LICENSE("GPL");