1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * fan_core.c - ACPI Fan core Driver
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.
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>
22 static const struct acpi_device_id fan_device_ids
[] = {
26 MODULE_DEVICE_TABLE(acpi
, fan_device_ids
);
28 /* thermal cooling device callbacks */
29 static int fan_get_max_state(struct thermal_cooling_device
*cdev
, unsigned long
32 struct acpi_device
*device
= cdev
->devdata
;
33 struct acpi_fan
*fan
= acpi_driver_data(device
);
36 if (fan
->fif
.fine_grain_ctrl
)
37 *state
= 100 / fan
->fif
.step_size
;
39 *state
= fan
->fps_count
- 1;
47 int acpi_fan_get_fst(struct acpi_device
*device
, struct acpi_fan_fst
*fst
)
49 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
50 union acpi_object
*obj
;
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");
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");
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
;
78 static int fan_get_state_acpi4(struct acpi_device
*device
, unsigned long *state
)
80 struct acpi_fan
*fan
= acpi_driver_data(device
);
81 struct acpi_fan_fst fst
;
84 status
= acpi_fan_get_fst(device
, &fst
);
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");
95 *state
= (int) fst
.control
/ fan
->fif
.step_size
;
100 for (i
= 0; i
< fan
->fps_count
; i
++) {
101 if (fst
.control
== fan
->fps
[i
].control
)
104 if (i
== fan
->fps_count
) {
105 dev_dbg(&device
->dev
, "Invalid control value returned\n");
114 static int fan_get_state(struct acpi_device
*device
, unsigned long *state
)
117 int acpi_state
= ACPI_STATE_D0
;
119 result
= acpi_device_update_power(device
, &acpi_state
);
123 *state
= acpi_state
== ACPI_STATE_D3_COLD
124 || acpi_state
== ACPI_STATE_D3_HOT
?
125 0 : (acpi_state
== ACPI_STATE_D0
? 1 : -1);
129 static int fan_get_cur_state(struct thermal_cooling_device
*cdev
, unsigned long
132 struct acpi_device
*device
= cdev
->devdata
;
133 struct acpi_fan
*fan
= acpi_driver_data(device
);
136 return fan_get_state_acpi4(device
, state
);
138 return fan_get_state(device
, state
);
141 static int fan_set_state(struct acpi_device
*device
, unsigned long state
)
143 if (state
!= 0 && state
!= 1)
146 return acpi_device_set_power(device
,
147 state
? ACPI_STATE_D0
: ACPI_STATE_D3_COLD
);
150 static int fan_set_state_acpi4(struct acpi_device
*device
, unsigned long state
)
152 struct acpi_fan
*fan
= acpi_driver_data(device
);
157 if (fan
->fif
.fine_grain_ctrl
)
158 max_state
= 100 / fan
->fif
.step_size
;
160 max_state
= fan
->fps_count
- 1;
162 if (state
> max_state
)
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)
171 value
= fan
->fps
[state
].control
;
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");
184 fan_set_cur_state(struct thermal_cooling_device
*cdev
, unsigned long state
)
186 struct acpi_device
*device
= cdev
->devdata
;
187 struct acpi_fan
*fan
= acpi_driver_data(device
);
190 return fan_set_state_acpi4(device
, state
);
192 return fan_set_state(device
, state
);
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
,
201 /* --------------------------------------------------------------------------
203 * --------------------------------------------------------------------------
206 static bool acpi_fan_is_acpi4(struct acpi_device
*device
)
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");
214 static int acpi_fan_get_fif(struct acpi_device
*device
)
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" };
220 struct acpi_buffer fif
= { sizeof(fields
), fields
};
221 union acpi_object
*obj
;
224 status
= acpi_evaluate_object(device
->handle
, "_FIF", NULL
, &buffer
);
225 if (ACPI_FAILURE(status
))
228 obj
= buffer
.pointer
;
229 if (!obj
|| obj
->type
!= ACPI_TYPE_PACKAGE
) {
230 dev_err(&device
->dev
, "Invalid _FIF data\n");
235 status
= acpi_extract_package(obj
, &format
, &fif
);
236 if (ACPI_FAILURE(status
)) {
237 dev_err(&device
->dev
, "Invalid _FIF element\n");
242 fan
->fif
.revision
= fields
[0];
243 fan
->fif
.fine_grain_ctrl
= fields
[1];
244 fan
->fif
.step_size
= fields
[2];
245 fan
->fif
.low_speed_notification
= fields
[3];
247 /* If there is a bug in step size and set as 0, change to 1 */
248 if (!fan
->fif
.step_size
)
249 fan
->fif
.step_size
= 1;
250 /* If step size > 9, change to 9 (by spec valid values 1-9) */
251 else if (fan
->fif
.step_size
> 9)
252 fan
->fif
.step_size
= 9;
258 static int acpi_fan_speed_cmp(const void *a
, const void *b
)
260 const struct acpi_fan_fps
*fps1
= a
;
261 const struct acpi_fan_fps
*fps2
= b
;
262 return fps1
->speed
- fps2
->speed
;
265 static int acpi_fan_get_fps(struct acpi_device
*device
)
267 struct acpi_fan
*fan
= acpi_driver_data(device
);
268 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
269 union acpi_object
*obj
;
273 status
= acpi_evaluate_object(device
->handle
, "_FPS", NULL
, &buffer
);
274 if (ACPI_FAILURE(status
))
277 obj
= buffer
.pointer
;
278 if (!obj
|| obj
->type
!= ACPI_TYPE_PACKAGE
|| obj
->package
.count
< 2) {
279 dev_err(&device
->dev
, "Invalid _FPS data\n");
284 fan
->fps_count
= obj
->package
.count
- 1; /* minus revision field */
285 fan
->fps
= devm_kcalloc(&device
->dev
,
286 fan
->fps_count
, sizeof(struct acpi_fan_fps
),
289 dev_err(&device
->dev
, "Not enough memory\n");
293 for (i
= 0; i
< fan
->fps_count
; i
++) {
294 struct acpi_buffer format
= { sizeof("NNNNN"), "NNNNN" };
295 struct acpi_buffer fps
= { offsetof(struct acpi_fan_fps
, name
),
297 status
= acpi_extract_package(&obj
->package
.elements
[i
+ 1],
299 if (ACPI_FAILURE(status
)) {
300 dev_err(&device
->dev
, "Invalid _FPS element\n");
305 /* sort the state array according to fan speed in increase order */
306 sort(fan
->fps
, fan
->fps_count
, sizeof(*fan
->fps
),
307 acpi_fan_speed_cmp
, NULL
);
314 static int acpi_fan_probe(struct platform_device
*pdev
)
317 struct thermal_cooling_device
*cdev
;
318 struct acpi_fan
*fan
;
319 struct acpi_device
*device
= ACPI_COMPANION(&pdev
->dev
);
322 fan
= devm_kzalloc(&pdev
->dev
, sizeof(*fan
), GFP_KERNEL
);
324 dev_err(&device
->dev
, "No memory for fan\n");
327 device
->driver_data
= fan
;
328 platform_set_drvdata(pdev
, fan
);
330 if (acpi_fan_is_acpi4(device
)) {
331 result
= acpi_fan_get_fif(device
);
335 result
= acpi_fan_get_fps(device
);
339 result
= devm_acpi_fan_create_hwmon(device
);
343 result
= acpi_fan_create_attributes(device
);
349 result
= acpi_device_update_power(device
, NULL
);
351 dev_err(&device
->dev
, "Failed to set initial power state\n");
356 if (!strncmp(pdev
->name
, "PNP0C0B", strlen("PNP0C0B")))
359 name
= acpi_device_bid(device
);
361 cdev
= thermal_cooling_device_register(name
, device
,
364 result
= PTR_ERR(cdev
);
368 dev_dbg(&pdev
->dev
, "registered as cooling_device%d\n", cdev
->id
);
371 result
= sysfs_create_link(&pdev
->dev
.kobj
,
375 dev_err(&pdev
->dev
, "Failed to create sysfs link 'thermal_cooling'\n");
377 result
= sysfs_create_link(&cdev
->device
.kobj
,
381 dev_err(&pdev
->dev
, "Failed to create sysfs link 'device'\n");
389 acpi_fan_delete_attributes(device
);
394 static void acpi_fan_remove(struct platform_device
*pdev
)
396 struct acpi_fan
*fan
= platform_get_drvdata(pdev
);
399 struct acpi_device
*device
= ACPI_COMPANION(&pdev
->dev
);
401 acpi_fan_delete_attributes(device
);
403 sysfs_remove_link(&pdev
->dev
.kobj
, "thermal_cooling");
404 sysfs_remove_link(&fan
->cdev
->device
.kobj
, "device");
405 thermal_cooling_device_unregister(fan
->cdev
);
408 #ifdef CONFIG_PM_SLEEP
409 static int acpi_fan_suspend(struct device
*dev
)
411 struct acpi_fan
*fan
= dev_get_drvdata(dev
);
415 acpi_device_set_power(ACPI_COMPANION(dev
), ACPI_STATE_D0
);
420 static int acpi_fan_resume(struct device
*dev
)
423 struct acpi_fan
*fan
= dev_get_drvdata(dev
);
428 result
= acpi_device_update_power(ACPI_COMPANION(dev
), NULL
);
430 dev_err(dev
, "Error updating fan power state\n");
435 static const struct dev_pm_ops acpi_fan_pm
= {
436 .resume
= acpi_fan_resume
,
437 .freeze
= acpi_fan_suspend
,
438 .thaw
= acpi_fan_resume
,
439 .restore
= acpi_fan_resume
,
441 #define FAN_PM_OPS_PTR (&acpi_fan_pm)
445 #define FAN_PM_OPS_PTR NULL
449 static struct platform_driver acpi_fan_driver
= {
450 .probe
= acpi_fan_probe
,
451 .remove
= acpi_fan_remove
,
454 .acpi_match_table
= fan_device_ids
,
455 .pm
= FAN_PM_OPS_PTR
,
459 module_platform_driver(acpi_fan_driver
);
461 MODULE_AUTHOR("Paul Diefenbaugh");
462 MODULE_DESCRIPTION("ACPI Fan Driver");
463 MODULE_LICENSE("GPL");