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