Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  fan_core.c - ACPI Fan core Driver
0004  *
0005  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
0006  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
0007  *  Copyright (C) 2022 Intel Corporation. All rights reserved.
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/init.h>
0013 #include <linux/types.h>
0014 #include <linux/uaccess.h>
0015 #include <linux/thermal.h>
0016 #include <linux/acpi.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/sort.h>
0019 
0020 #include "fan.h"
0021 
0022 MODULE_AUTHOR("Paul Diefenbaugh");
0023 MODULE_DESCRIPTION("ACPI Fan Driver");
0024 MODULE_LICENSE("GPL");
0025 
0026 static int acpi_fan_probe(struct platform_device *pdev);
0027 static int acpi_fan_remove(struct platform_device *pdev);
0028 
0029 static const struct acpi_device_id fan_device_ids[] = {
0030     ACPI_FAN_DEVICE_IDS,
0031     {"", 0},
0032 };
0033 MODULE_DEVICE_TABLE(acpi, fan_device_ids);
0034 
0035 #ifdef CONFIG_PM_SLEEP
0036 static int acpi_fan_suspend(struct device *dev);
0037 static int acpi_fan_resume(struct device *dev);
0038 static const struct dev_pm_ops acpi_fan_pm = {
0039     .resume = acpi_fan_resume,
0040     .freeze = acpi_fan_suspend,
0041     .thaw = acpi_fan_resume,
0042     .restore = acpi_fan_resume,
0043 };
0044 #define FAN_PM_OPS_PTR (&acpi_fan_pm)
0045 #else
0046 #define FAN_PM_OPS_PTR NULL
0047 #endif
0048 
0049 static struct platform_driver acpi_fan_driver = {
0050     .probe = acpi_fan_probe,
0051     .remove = acpi_fan_remove,
0052     .driver = {
0053         .name = "acpi-fan",
0054         .acpi_match_table = fan_device_ids,
0055         .pm = FAN_PM_OPS_PTR,
0056     },
0057 };
0058 
0059 /* thermal cooling device callbacks */
0060 static int fan_get_max_state(struct thermal_cooling_device *cdev, unsigned long
0061                  *state)
0062 {
0063     struct acpi_device *device = cdev->devdata;
0064     struct acpi_fan *fan = acpi_driver_data(device);
0065 
0066     if (fan->acpi4) {
0067         if (fan->fif.fine_grain_ctrl)
0068             *state = 100 / fan->fif.step_size;
0069         else
0070             *state = fan->fps_count - 1;
0071     } else {
0072         *state = 1;
0073     }
0074 
0075     return 0;
0076 }
0077 
0078 int acpi_fan_get_fst(struct acpi_device *device, struct acpi_fan_fst *fst)
0079 {
0080     struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
0081     union acpi_object *obj;
0082     acpi_status status;
0083     int ret = 0;
0084 
0085     status = acpi_evaluate_object(device->handle, "_FST", NULL, &buffer);
0086     if (ACPI_FAILURE(status)) {
0087         dev_err(&device->dev, "Get fan state failed\n");
0088         return -ENODEV;
0089     }
0090 
0091     obj = buffer.pointer;
0092     if (!obj || obj->type != ACPI_TYPE_PACKAGE ||
0093         obj->package.count != 3 ||
0094         obj->package.elements[1].type != ACPI_TYPE_INTEGER) {
0095         dev_err(&device->dev, "Invalid _FST data\n");
0096         ret = -EINVAL;
0097         goto err;
0098     }
0099 
0100     fst->revision = obj->package.elements[0].integer.value;
0101     fst->control = obj->package.elements[1].integer.value;
0102     fst->speed = obj->package.elements[2].integer.value;
0103 
0104 err:
0105     kfree(obj);
0106     return ret;
0107 }
0108 
0109 static int fan_get_state_acpi4(struct acpi_device *device, unsigned long *state)
0110 {
0111     struct acpi_fan *fan = acpi_driver_data(device);
0112     struct acpi_fan_fst fst;
0113     int status, i;
0114 
0115     status = acpi_fan_get_fst(device, &fst);
0116     if (status)
0117         return status;
0118 
0119     if (fan->fif.fine_grain_ctrl) {
0120         /* This control should be same what we set using _FSL by spec */
0121         if (fst.control > 100) {
0122             dev_dbg(&device->dev, "Invalid control value returned\n");
0123             goto match_fps;
0124         }
0125 
0126         *state = (int) fst.control / fan->fif.step_size;
0127         return 0;
0128     }
0129 
0130 match_fps:
0131     for (i = 0; i < fan->fps_count; i++) {
0132         if (fst.control == fan->fps[i].control)
0133             break;
0134     }
0135     if (i == fan->fps_count) {
0136         dev_dbg(&device->dev, "Invalid control value returned\n");
0137         return -EINVAL;
0138     }
0139 
0140     *state = i;
0141 
0142     return status;
0143 }
0144 
0145 static int fan_get_state(struct acpi_device *device, unsigned long *state)
0146 {
0147     int result;
0148     int acpi_state = ACPI_STATE_D0;
0149 
0150     result = acpi_device_update_power(device, &acpi_state);
0151     if (result)
0152         return result;
0153 
0154     *state = acpi_state == ACPI_STATE_D3_COLD
0155             || acpi_state == ACPI_STATE_D3_HOT ?
0156         0 : (acpi_state == ACPI_STATE_D0 ? 1 : -1);
0157     return 0;
0158 }
0159 
0160 static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
0161                  *state)
0162 {
0163     struct acpi_device *device = cdev->devdata;
0164     struct acpi_fan *fan = acpi_driver_data(device);
0165 
0166     if (fan->acpi4)
0167         return fan_get_state_acpi4(device, state);
0168     else
0169         return fan_get_state(device, state);
0170 }
0171 
0172 static int fan_set_state(struct acpi_device *device, unsigned long state)
0173 {
0174     if (state != 0 && state != 1)
0175         return -EINVAL;
0176 
0177     return acpi_device_set_power(device,
0178                      state ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
0179 }
0180 
0181 static int fan_set_state_acpi4(struct acpi_device *device, unsigned long state)
0182 {
0183     struct acpi_fan *fan = acpi_driver_data(device);
0184     acpi_status status;
0185     u64 value = state;
0186     int max_state;
0187 
0188     if (fan->fif.fine_grain_ctrl)
0189         max_state = 100 / fan->fif.step_size;
0190     else
0191         max_state = fan->fps_count - 1;
0192 
0193     if (state > max_state)
0194         return -EINVAL;
0195 
0196     if (fan->fif.fine_grain_ctrl) {
0197         value *= fan->fif.step_size;
0198         /* Spec allows compensate the last step only */
0199         if (value + fan->fif.step_size > 100)
0200             value = 100;
0201     } else {
0202         value = fan->fps[state].control;
0203     }
0204 
0205     status = acpi_execute_simple_method(device->handle, "_FSL", value);
0206     if (ACPI_FAILURE(status)) {
0207         dev_dbg(&device->dev, "Failed to set state by _FSL\n");
0208         return -ENODEV;
0209     }
0210 
0211     return 0;
0212 }
0213 
0214 static int
0215 fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
0216 {
0217     struct acpi_device *device = cdev->devdata;
0218     struct acpi_fan *fan = acpi_driver_data(device);
0219 
0220     if (fan->acpi4)
0221         return fan_set_state_acpi4(device, state);
0222     else
0223         return fan_set_state(device, state);
0224 }
0225 
0226 static const struct thermal_cooling_device_ops fan_cooling_ops = {
0227     .get_max_state = fan_get_max_state,
0228     .get_cur_state = fan_get_cur_state,
0229     .set_cur_state = fan_set_cur_state,
0230 };
0231 
0232 /* --------------------------------------------------------------------------
0233  *                               Driver Interface
0234  * --------------------------------------------------------------------------
0235 */
0236 
0237 static bool acpi_fan_is_acpi4(struct acpi_device *device)
0238 {
0239     return acpi_has_method(device->handle, "_FIF") &&
0240            acpi_has_method(device->handle, "_FPS") &&
0241            acpi_has_method(device->handle, "_FSL") &&
0242            acpi_has_method(device->handle, "_FST");
0243 }
0244 
0245 static int acpi_fan_get_fif(struct acpi_device *device)
0246 {
0247     struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
0248     struct acpi_fan *fan = acpi_driver_data(device);
0249     struct acpi_buffer format = { sizeof("NNNN"), "NNNN" };
0250     u64 fields[4];
0251     struct acpi_buffer fif = { sizeof(fields), fields };
0252     union acpi_object *obj;
0253     acpi_status status;
0254 
0255     status = acpi_evaluate_object(device->handle, "_FIF", NULL, &buffer);
0256     if (ACPI_FAILURE(status))
0257         return status;
0258 
0259     obj = buffer.pointer;
0260     if (!obj || obj->type != ACPI_TYPE_PACKAGE) {
0261         dev_err(&device->dev, "Invalid _FIF data\n");
0262         status = -EINVAL;
0263         goto err;
0264     }
0265 
0266     status = acpi_extract_package(obj, &format, &fif);
0267     if (ACPI_FAILURE(status)) {
0268         dev_err(&device->dev, "Invalid _FIF element\n");
0269         status = -EINVAL;
0270     }
0271 
0272     fan->fif.revision = fields[0];
0273     fan->fif.fine_grain_ctrl = fields[1];
0274     fan->fif.step_size = fields[2];
0275     fan->fif.low_speed_notification = fields[3];
0276 
0277     /* If there is a bug in step size and set as 0, change to 1 */
0278     if (!fan->fif.step_size)
0279         fan->fif.step_size = 1;
0280     /* If step size > 9, change to 9 (by spec valid values 1-9) */
0281     else if (fan->fif.step_size > 9)
0282         fan->fif.step_size = 9;
0283 err:
0284     kfree(obj);
0285     return status;
0286 }
0287 
0288 static int acpi_fan_speed_cmp(const void *a, const void *b)
0289 {
0290     const struct acpi_fan_fps *fps1 = a;
0291     const struct acpi_fan_fps *fps2 = b;
0292     return fps1->speed - fps2->speed;
0293 }
0294 
0295 static int acpi_fan_get_fps(struct acpi_device *device)
0296 {
0297     struct acpi_fan *fan = acpi_driver_data(device);
0298     struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
0299     union acpi_object *obj;
0300     acpi_status status;
0301     int i;
0302 
0303     status = acpi_evaluate_object(device->handle, "_FPS", NULL, &buffer);
0304     if (ACPI_FAILURE(status))
0305         return status;
0306 
0307     obj = buffer.pointer;
0308     if (!obj || obj->type != ACPI_TYPE_PACKAGE || obj->package.count < 2) {
0309         dev_err(&device->dev, "Invalid _FPS data\n");
0310         status = -EINVAL;
0311         goto err;
0312     }
0313 
0314     fan->fps_count = obj->package.count - 1; /* minus revision field */
0315     fan->fps = devm_kcalloc(&device->dev,
0316                 fan->fps_count, sizeof(struct acpi_fan_fps),
0317                 GFP_KERNEL);
0318     if (!fan->fps) {
0319         dev_err(&device->dev, "Not enough memory\n");
0320         status = -ENOMEM;
0321         goto err;
0322     }
0323     for (i = 0; i < fan->fps_count; i++) {
0324         struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
0325         struct acpi_buffer fps = { offsetof(struct acpi_fan_fps, name),
0326                         &fan->fps[i] };
0327         status = acpi_extract_package(&obj->package.elements[i + 1],
0328                           &format, &fps);
0329         if (ACPI_FAILURE(status)) {
0330             dev_err(&device->dev, "Invalid _FPS element\n");
0331             goto err;
0332         }
0333     }
0334 
0335     /* sort the state array according to fan speed in increase order */
0336     sort(fan->fps, fan->fps_count, sizeof(*fan->fps),
0337          acpi_fan_speed_cmp, NULL);
0338 
0339 err:
0340     kfree(obj);
0341     return status;
0342 }
0343 
0344 static int acpi_fan_probe(struct platform_device *pdev)
0345 {
0346     int result = 0;
0347     struct thermal_cooling_device *cdev;
0348     struct acpi_fan *fan;
0349     struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
0350     char *name;
0351 
0352     fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL);
0353     if (!fan) {
0354         dev_err(&device->dev, "No memory for fan\n");
0355         return -ENOMEM;
0356     }
0357     device->driver_data = fan;
0358     platform_set_drvdata(pdev, fan);
0359 
0360     if (acpi_fan_is_acpi4(device)) {
0361         result = acpi_fan_get_fif(device);
0362         if (result)
0363             return result;
0364 
0365         result = acpi_fan_get_fps(device);
0366         if (result)
0367             return result;
0368 
0369         result = acpi_fan_create_attributes(device);
0370         if (result)
0371             return result;
0372 
0373         fan->acpi4 = true;
0374     } else {
0375         result = acpi_device_update_power(device, NULL);
0376         if (result) {
0377             dev_err(&device->dev, "Failed to set initial power state\n");
0378             goto err_end;
0379         }
0380     }
0381 
0382     if (!strncmp(pdev->name, "PNP0C0B", strlen("PNP0C0B")))
0383         name = "Fan";
0384     else
0385         name = acpi_device_bid(device);
0386 
0387     cdev = thermal_cooling_device_register(name, device,
0388                         &fan_cooling_ops);
0389     if (IS_ERR(cdev)) {
0390         result = PTR_ERR(cdev);
0391         goto err_end;
0392     }
0393 
0394     dev_dbg(&pdev->dev, "registered as cooling_device%d\n", cdev->id);
0395 
0396     fan->cdev = cdev;
0397     result = sysfs_create_link(&pdev->dev.kobj,
0398                    &cdev->device.kobj,
0399                    "thermal_cooling");
0400     if (result)
0401         dev_err(&pdev->dev, "Failed to create sysfs link 'thermal_cooling'\n");
0402 
0403     result = sysfs_create_link(&cdev->device.kobj,
0404                    &pdev->dev.kobj,
0405                    "device");
0406     if (result) {
0407         dev_err(&pdev->dev, "Failed to create sysfs link 'device'\n");
0408         goto err_end;
0409     }
0410 
0411     return 0;
0412 
0413 err_end:
0414     if (fan->acpi4)
0415         acpi_fan_delete_attributes(device);
0416 
0417     return result;
0418 }
0419 
0420 static int acpi_fan_remove(struct platform_device *pdev)
0421 {
0422     struct acpi_fan *fan = platform_get_drvdata(pdev);
0423 
0424     if (fan->acpi4) {
0425         struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
0426 
0427         acpi_fan_delete_attributes(device);
0428     }
0429     sysfs_remove_link(&pdev->dev.kobj, "thermal_cooling");
0430     sysfs_remove_link(&fan->cdev->device.kobj, "device");
0431     thermal_cooling_device_unregister(fan->cdev);
0432 
0433     return 0;
0434 }
0435 
0436 #ifdef CONFIG_PM_SLEEP
0437 static int acpi_fan_suspend(struct device *dev)
0438 {
0439     struct acpi_fan *fan = dev_get_drvdata(dev);
0440     if (fan->acpi4)
0441         return 0;
0442 
0443     acpi_device_set_power(ACPI_COMPANION(dev), ACPI_STATE_D0);
0444 
0445     return AE_OK;
0446 }
0447 
0448 static int acpi_fan_resume(struct device *dev)
0449 {
0450     int result;
0451     struct acpi_fan *fan = dev_get_drvdata(dev);
0452 
0453     if (fan->acpi4)
0454         return 0;
0455 
0456     result = acpi_device_update_power(ACPI_COMPANION(dev), NULL);
0457     if (result)
0458         dev_err(dev, "Error updating fan power state\n");
0459 
0460     return result;
0461 }
0462 #endif
0463 
0464 module_platform_driver(acpi_fan_driver);