Merge tag 'sched-core-2022-08-01' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / acpi / fan_core.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  fan_core.c - ACPI Fan core Driver
4  *
5  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
6  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7  *  Copyright (C) 2022 Intel Corporation. All rights reserved.
8  */
9
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/types.h>
14 #include <linux/uaccess.h>
15 #include <linux/thermal.h>
16 #include <linux/acpi.h>
17 #include <linux/platform_device.h>
18 #include <linux/sort.h>
19
20 #include "fan.h"
21
22 MODULE_AUTHOR("Paul Diefenbaugh");
23 MODULE_DESCRIPTION("ACPI Fan Driver");
24 MODULE_LICENSE("GPL");
25
26 static int acpi_fan_probe(struct platform_device *pdev);
27 static int acpi_fan_remove(struct platform_device *pdev);
28
29 static const struct acpi_device_id fan_device_ids[] = {
30         ACPI_FAN_DEVICE_IDS,
31         {"", 0},
32 };
33 MODULE_DEVICE_TABLE(acpi, fan_device_ids);
34
35 #ifdef CONFIG_PM_SLEEP
36 static int acpi_fan_suspend(struct device *dev);
37 static int acpi_fan_resume(struct device *dev);
38 static const struct dev_pm_ops acpi_fan_pm = {
39         .resume = acpi_fan_resume,
40         .freeze = acpi_fan_suspend,
41         .thaw = acpi_fan_resume,
42         .restore = acpi_fan_resume,
43 };
44 #define FAN_PM_OPS_PTR (&acpi_fan_pm)
45 #else
46 #define FAN_PM_OPS_PTR NULL
47 #endif
48
49 static struct platform_driver acpi_fan_driver = {
50         .probe = acpi_fan_probe,
51         .remove = acpi_fan_remove,
52         .driver = {
53                 .name = "acpi-fan",
54                 .acpi_match_table = fan_device_ids,
55                 .pm = FAN_PM_OPS_PTR,
56         },
57 };
58
59 /* thermal cooling device callbacks */
60 static int fan_get_max_state(struct thermal_cooling_device *cdev, unsigned long
61                              *state)
62 {
63         struct acpi_device *device = cdev->devdata;
64         struct acpi_fan *fan = acpi_driver_data(device);
65
66         if (fan->acpi4) {
67                 if (fan->fif.fine_grain_ctrl)
68                         *state = 100 / fan->fif.step_size;
69                 else
70                         *state = fan->fps_count - 1;
71         } else {
72                 *state = 1;
73         }
74
75         return 0;
76 }
77
78 int acpi_fan_get_fst(struct acpi_device *device, struct acpi_fan_fst *fst)
79 {
80         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
81         union acpi_object *obj;
82         acpi_status status;
83         int ret = 0;
84
85         status = acpi_evaluate_object(device->handle, "_FST", NULL, &buffer);
86         if (ACPI_FAILURE(status)) {
87                 dev_err(&device->dev, "Get fan state failed\n");
88                 return -ENODEV;
89         }
90
91         obj = buffer.pointer;
92         if (!obj || obj->type != ACPI_TYPE_PACKAGE ||
93             obj->package.count != 3 ||
94             obj->package.elements[1].type != ACPI_TYPE_INTEGER) {
95                 dev_err(&device->dev, "Invalid _FST data\n");
96                 ret = -EINVAL;
97                 goto err;
98         }
99
100         fst->revision = obj->package.elements[0].integer.value;
101         fst->control = obj->package.elements[1].integer.value;
102         fst->speed = obj->package.elements[2].integer.value;
103
104 err:
105         kfree(obj);
106         return ret;
107 }
108
109 static int fan_get_state_acpi4(struct acpi_device *device, unsigned long *state)
110 {
111         struct acpi_fan *fan = acpi_driver_data(device);
112         struct acpi_fan_fst fst;
113         int status, i;
114
115         status = acpi_fan_get_fst(device, &fst);
116         if (status)
117                 return status;
118
119         if (fan->fif.fine_grain_ctrl) {
120                 /* This control should be same what we set using _FSL by spec */
121                 if (fst.control > 100) {
122                         dev_dbg(&device->dev, "Invalid control value returned\n");
123                         goto match_fps;
124                 }
125
126                 *state = (int) fst.control / fan->fif.step_size;
127                 return 0;
128         }
129
130 match_fps:
131         for (i = 0; i < fan->fps_count; i++) {
132                 if (fst.control == fan->fps[i].control)
133                         break;
134         }
135         if (i == fan->fps_count) {
136                 dev_dbg(&device->dev, "Invalid control value returned\n");
137                 return -EINVAL;
138         }
139
140         *state = i;
141
142         return status;
143 }
144
145 static int fan_get_state(struct acpi_device *device, unsigned long *state)
146 {
147         int result;
148         int acpi_state = ACPI_STATE_D0;
149
150         result = acpi_device_update_power(device, &acpi_state);
151         if (result)
152                 return result;
153
154         *state = acpi_state == ACPI_STATE_D3_COLD
155                         || acpi_state == ACPI_STATE_D3_HOT ?
156                 0 : (acpi_state == ACPI_STATE_D0 ? 1 : -1);
157         return 0;
158 }
159
160 static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
161                              *state)
162 {
163         struct acpi_device *device = cdev->devdata;
164         struct acpi_fan *fan = acpi_driver_data(device);
165
166         if (fan->acpi4)
167                 return fan_get_state_acpi4(device, state);
168         else
169                 return fan_get_state(device, state);
170 }
171
172 static int fan_set_state(struct acpi_device *device, unsigned long state)
173 {
174         if (state != 0 && state != 1)
175                 return -EINVAL;
176
177         return acpi_device_set_power(device,
178                                      state ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
179 }
180
181 static int fan_set_state_acpi4(struct acpi_device *device, unsigned long state)
182 {
183         struct acpi_fan *fan = acpi_driver_data(device);
184         acpi_status status;
185         u64 value = state;
186         int max_state;
187
188         if (fan->fif.fine_grain_ctrl)
189                 max_state = 100 / fan->fif.step_size;
190         else
191                 max_state = fan->fps_count - 1;
192
193         if (state > max_state)
194                 return -EINVAL;
195
196         if (fan->fif.fine_grain_ctrl) {
197                 value *= fan->fif.step_size;
198                 /* Spec allows compensate the last step only */
199                 if (value + fan->fif.step_size > 100)
200                         value = 100;
201         } else {
202                 value = fan->fps[state].control;
203         }
204
205         status = acpi_execute_simple_method(device->handle, "_FSL", value);
206         if (ACPI_FAILURE(status)) {
207                 dev_dbg(&device->dev, "Failed to set state by _FSL\n");
208                 return -ENODEV;
209         }
210
211         return 0;
212 }
213
214 static int
215 fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
216 {
217         struct acpi_device *device = cdev->devdata;
218         struct acpi_fan *fan = acpi_driver_data(device);
219
220         if (fan->acpi4)
221                 return fan_set_state_acpi4(device, state);
222         else
223                 return fan_set_state(device, state);
224 }
225
226 static const struct thermal_cooling_device_ops fan_cooling_ops = {
227         .get_max_state = fan_get_max_state,
228         .get_cur_state = fan_get_cur_state,
229         .set_cur_state = fan_set_cur_state,
230 };
231
232 /* --------------------------------------------------------------------------
233  *                               Driver Interface
234  * --------------------------------------------------------------------------
235 */
236
237 static bool acpi_fan_is_acpi4(struct acpi_device *device)
238 {
239         return acpi_has_method(device->handle, "_FIF") &&
240                acpi_has_method(device->handle, "_FPS") &&
241                acpi_has_method(device->handle, "_FSL") &&
242                acpi_has_method(device->handle, "_FST");
243 }
244
245 static int acpi_fan_get_fif(struct acpi_device *device)
246 {
247         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
248         struct acpi_fan *fan = acpi_driver_data(device);
249         struct acpi_buffer format = { sizeof("NNNN"), "NNNN" };
250         u64 fields[4];
251         struct acpi_buffer fif = { sizeof(fields), fields };
252         union acpi_object *obj;
253         acpi_status status;
254
255         status = acpi_evaluate_object(device->handle, "_FIF", NULL, &buffer);
256         if (ACPI_FAILURE(status))
257                 return status;
258
259         obj = buffer.pointer;
260         if (!obj || obj->type != ACPI_TYPE_PACKAGE) {
261                 dev_err(&device->dev, "Invalid _FIF data\n");
262                 status = -EINVAL;
263                 goto err;
264         }
265
266         status = acpi_extract_package(obj, &format, &fif);
267         if (ACPI_FAILURE(status)) {
268                 dev_err(&device->dev, "Invalid _FIF element\n");
269                 status = -EINVAL;
270         }
271
272         fan->fif.revision = fields[0];
273         fan->fif.fine_grain_ctrl = fields[1];
274         fan->fif.step_size = fields[2];
275         fan->fif.low_speed_notification = fields[3];
276
277         /* If there is a bug in step size and set as 0, change to 1 */
278         if (!fan->fif.step_size)
279                 fan->fif.step_size = 1;
280         /* If step size > 9, change to 9 (by spec valid values 1-9) */
281         else if (fan->fif.step_size > 9)
282                 fan->fif.step_size = 9;
283 err:
284         kfree(obj);
285         return status;
286 }
287
288 static int acpi_fan_speed_cmp(const void *a, const void *b)
289 {
290         const struct acpi_fan_fps *fps1 = a;
291         const struct acpi_fan_fps *fps2 = b;
292         return fps1->speed - fps2->speed;
293 }
294
295 static int acpi_fan_get_fps(struct acpi_device *device)
296 {
297         struct acpi_fan *fan = acpi_driver_data(device);
298         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
299         union acpi_object *obj;
300         acpi_status status;
301         int i;
302
303         status = acpi_evaluate_object(device->handle, "_FPS", NULL, &buffer);
304         if (ACPI_FAILURE(status))
305                 return status;
306
307         obj = buffer.pointer;
308         if (!obj || obj->type != ACPI_TYPE_PACKAGE || obj->package.count < 2) {
309                 dev_err(&device->dev, "Invalid _FPS data\n");
310                 status = -EINVAL;
311                 goto err;
312         }
313
314         fan->fps_count = obj->package.count - 1; /* minus revision field */
315         fan->fps = devm_kcalloc(&device->dev,
316                                 fan->fps_count, sizeof(struct acpi_fan_fps),
317                                 GFP_KERNEL);
318         if (!fan->fps) {
319                 dev_err(&device->dev, "Not enough memory\n");
320                 status = -ENOMEM;
321                 goto err;
322         }
323         for (i = 0; i < fan->fps_count; i++) {
324                 struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
325                 struct acpi_buffer fps = { offsetof(struct acpi_fan_fps, name),
326                                                 &fan->fps[i] };
327                 status = acpi_extract_package(&obj->package.elements[i + 1],
328                                               &format, &fps);
329                 if (ACPI_FAILURE(status)) {
330                         dev_err(&device->dev, "Invalid _FPS element\n");
331                         goto err;
332                 }
333         }
334
335         /* sort the state array according to fan speed in increase order */
336         sort(fan->fps, fan->fps_count, sizeof(*fan->fps),
337              acpi_fan_speed_cmp, NULL);
338
339 err:
340         kfree(obj);
341         return status;
342 }
343
344 static int acpi_fan_probe(struct platform_device *pdev)
345 {
346         int result = 0;
347         struct thermal_cooling_device *cdev;
348         struct acpi_fan *fan;
349         struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
350         char *name;
351
352         fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL);
353         if (!fan) {
354                 dev_err(&device->dev, "No memory for fan\n");
355                 return -ENOMEM;
356         }
357         device->driver_data = fan;
358         platform_set_drvdata(pdev, fan);
359
360         if (acpi_fan_is_acpi4(device)) {
361                 result = acpi_fan_get_fif(device);
362                 if (result)
363                         return result;
364
365                 result = acpi_fan_get_fps(device);
366                 if (result)
367                         return result;
368
369                 result = acpi_fan_create_attributes(device);
370                 if (result)
371                         return result;
372
373                 fan->acpi4 = true;
374         } else {
375                 result = acpi_device_update_power(device, NULL);
376                 if (result) {
377                         dev_err(&device->dev, "Failed to set initial power state\n");
378                         goto err_end;
379                 }
380         }
381
382         if (!strncmp(pdev->name, "PNP0C0B", strlen("PNP0C0B")))
383                 name = "Fan";
384         else
385                 name = acpi_device_bid(device);
386
387         cdev = thermal_cooling_device_register(name, device,
388                                                 &fan_cooling_ops);
389         if (IS_ERR(cdev)) {
390                 result = PTR_ERR(cdev);
391                 goto err_end;
392         }
393
394         dev_dbg(&pdev->dev, "registered as cooling_device%d\n", cdev->id);
395
396         fan->cdev = cdev;
397         result = sysfs_create_link(&pdev->dev.kobj,
398                                    &cdev->device.kobj,
399                                    "thermal_cooling");
400         if (result)
401                 dev_err(&pdev->dev, "Failed to create sysfs link 'thermal_cooling'\n");
402
403         result = sysfs_create_link(&cdev->device.kobj,
404                                    &pdev->dev.kobj,
405                                    "device");
406         if (result) {
407                 dev_err(&pdev->dev, "Failed to create sysfs link 'device'\n");
408                 goto err_end;
409         }
410
411         return 0;
412
413 err_end:
414         if (fan->acpi4)
415                 acpi_fan_delete_attributes(device);
416
417         return result;
418 }
419
420 static int acpi_fan_remove(struct platform_device *pdev)
421 {
422         struct acpi_fan *fan = platform_get_drvdata(pdev);
423
424         if (fan->acpi4) {
425                 struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
426
427                 acpi_fan_delete_attributes(device);
428         }
429         sysfs_remove_link(&pdev->dev.kobj, "thermal_cooling");
430         sysfs_remove_link(&fan->cdev->device.kobj, "device");
431         thermal_cooling_device_unregister(fan->cdev);
432
433         return 0;
434 }
435
436 #ifdef CONFIG_PM_SLEEP
437 static int acpi_fan_suspend(struct device *dev)
438 {
439         struct acpi_fan *fan = dev_get_drvdata(dev);
440         if (fan->acpi4)
441                 return 0;
442
443         acpi_device_set_power(ACPI_COMPANION(dev), ACPI_STATE_D0);
444
445         return AE_OK;
446 }
447
448 static int acpi_fan_resume(struct device *dev)
449 {
450         int result;
451         struct acpi_fan *fan = dev_get_drvdata(dev);
452
453         if (fan->acpi4)
454                 return 0;
455
456         result = acpi_device_update_power(ACPI_COMPANION(dev), NULL);
457         if (result)
458                 dev_err(dev, "Error updating fan power state\n");
459
460         return result;
461 }
462 #endif
463
464 module_platform_driver(acpi_fan_driver);