Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  Intel menlow Driver for thermal management extension
0004  *
0005  *  Copyright (C) 2008 Intel Corp
0006  *  Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
0007  *  Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
0008  *
0009  *  This driver creates the sys I/F for programming the sensors.
0010  *  It also implements the driver for intel menlow memory controller (hardware
0011  *  id is INT0002) which makes use of the platform specific ACPI methods
0012  *  to get/set bandwidth.
0013  */
0014 
0015 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0016 
0017 #include <linux/acpi.h>
0018 #include <linux/kernel.h>
0019 #include <linux/module.h>
0020 #include <linux/pci.h>
0021 #include <linux/pm.h>
0022 #include <linux/slab.h>
0023 #include <linux/thermal.h>
0024 #include <linux/types.h>
0025 #include <linux/units.h>
0026 
0027 MODULE_AUTHOR("Thomas Sujith");
0028 MODULE_AUTHOR("Zhang Rui");
0029 MODULE_DESCRIPTION("Intel Menlow platform specific driver");
0030 MODULE_LICENSE("GPL v2");
0031 
0032 /*
0033  * Memory controller device control
0034  */
0035 
0036 #define MEMORY_GET_BANDWIDTH "GTHS"
0037 #define MEMORY_SET_BANDWIDTH "STHS"
0038 #define MEMORY_ARG_CUR_BANDWIDTH 1
0039 #define MEMORY_ARG_MAX_BANDWIDTH 0
0040 
0041 static void intel_menlow_unregister_sensor(void);
0042 
0043 /*
0044  * GTHS returning 'n' would mean that [0,n-1] states are supported
0045  * In that case max_cstate would be n-1
0046  * GTHS returning '0' would mean that no bandwidth control states are supported
0047  */
0048 static int memory_get_max_bandwidth(struct thermal_cooling_device *cdev,
0049                     unsigned long *max_state)
0050 {
0051     struct acpi_device *device = cdev->devdata;
0052     acpi_handle handle = device->handle;
0053     unsigned long long value;
0054     struct acpi_object_list arg_list;
0055     union acpi_object arg;
0056     acpi_status status = AE_OK;
0057 
0058     arg_list.count = 1;
0059     arg_list.pointer = &arg;
0060     arg.type = ACPI_TYPE_INTEGER;
0061     arg.integer.value = MEMORY_ARG_MAX_BANDWIDTH;
0062     status = acpi_evaluate_integer(handle, MEMORY_GET_BANDWIDTH,
0063                        &arg_list, &value);
0064     if (ACPI_FAILURE(status))
0065         return -EFAULT;
0066 
0067     if (!value)
0068         return -EINVAL;
0069 
0070     *max_state = value - 1;
0071     return 0;
0072 }
0073 
0074 static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev,
0075                     unsigned long *value)
0076 {
0077     struct acpi_device *device = cdev->devdata;
0078     acpi_handle handle = device->handle;
0079     unsigned long long result;
0080     struct acpi_object_list arg_list;
0081     union acpi_object arg;
0082     acpi_status status = AE_OK;
0083 
0084     arg_list.count = 1;
0085     arg_list.pointer = &arg;
0086     arg.type = ACPI_TYPE_INTEGER;
0087     arg.integer.value = MEMORY_ARG_CUR_BANDWIDTH;
0088     status = acpi_evaluate_integer(handle, MEMORY_GET_BANDWIDTH,
0089                        &arg_list, &result);
0090     if (ACPI_FAILURE(status))
0091         return -EFAULT;
0092 
0093     *value = result;
0094     return 0;
0095 }
0096 
0097 static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
0098                     unsigned long state)
0099 {
0100     struct acpi_device *device = cdev->devdata;
0101     acpi_handle handle = device->handle;
0102     struct acpi_object_list arg_list;
0103     union acpi_object arg;
0104     acpi_status status;
0105     unsigned long long temp;
0106     unsigned long max_state;
0107 
0108     if (memory_get_max_bandwidth(cdev, &max_state))
0109         return -EFAULT;
0110 
0111     if (state > max_state)
0112         return -EINVAL;
0113 
0114     arg_list.count = 1;
0115     arg_list.pointer = &arg;
0116     arg.type = ACPI_TYPE_INTEGER;
0117     arg.integer.value = state;
0118 
0119     status =
0120         acpi_evaluate_integer(handle, MEMORY_SET_BANDWIDTH, &arg_list,
0121                   &temp);
0122 
0123     pr_info("Bandwidth value was %ld: status is %d\n", state, status);
0124     if (ACPI_FAILURE(status))
0125         return -EFAULT;
0126 
0127     return 0;
0128 }
0129 
0130 static const struct thermal_cooling_device_ops memory_cooling_ops = {
0131     .get_max_state = memory_get_max_bandwidth,
0132     .get_cur_state = memory_get_cur_bandwidth,
0133     .set_cur_state = memory_set_cur_bandwidth,
0134 };
0135 
0136 /*
0137  * Memory Device Management
0138  */
0139 static int intel_menlow_memory_add(struct acpi_device *device)
0140 {
0141     int result = -ENODEV;
0142     struct thermal_cooling_device *cdev;
0143 
0144     if (!device)
0145         return -EINVAL;
0146 
0147     if (!acpi_has_method(device->handle, MEMORY_GET_BANDWIDTH))
0148         goto end;
0149 
0150     if (!acpi_has_method(device->handle, MEMORY_SET_BANDWIDTH))
0151         goto end;
0152 
0153     cdev = thermal_cooling_device_register("Memory controller", device,
0154                            &memory_cooling_ops);
0155     if (IS_ERR(cdev)) {
0156         result = PTR_ERR(cdev);
0157         goto end;
0158     }
0159 
0160     device->driver_data = cdev;
0161     result = sysfs_create_link(&device->dev.kobj,
0162                 &cdev->device.kobj, "thermal_cooling");
0163     if (result)
0164         goto unregister;
0165 
0166     result = sysfs_create_link(&cdev->device.kobj,
0167                 &device->dev.kobj, "device");
0168     if (result) {
0169         sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
0170         goto unregister;
0171     }
0172 
0173  end:
0174     return result;
0175 
0176  unregister:
0177     thermal_cooling_device_unregister(cdev);
0178     return result;
0179 
0180 }
0181 
0182 static int intel_menlow_memory_remove(struct acpi_device *device)
0183 {
0184     struct thermal_cooling_device *cdev;
0185 
0186     if (!device)
0187         return -EINVAL;
0188 
0189     cdev = acpi_driver_data(device);
0190     if (!cdev)
0191         return -EINVAL;
0192 
0193     sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
0194     sysfs_remove_link(&cdev->device.kobj, "device");
0195     thermal_cooling_device_unregister(cdev);
0196 
0197     return 0;
0198 }
0199 
0200 static const struct acpi_device_id intel_menlow_memory_ids[] = {
0201     {"INT0002", 0},
0202     {"", 0},
0203 };
0204 
0205 static struct acpi_driver intel_menlow_memory_driver = {
0206     .name = "intel_menlow_thermal_control",
0207     .ids = intel_menlow_memory_ids,
0208     .ops = {
0209         .add = intel_menlow_memory_add,
0210         .remove = intel_menlow_memory_remove,
0211         },
0212 };
0213 
0214 /*
0215  * Sensor control on menlow platform
0216  */
0217 
0218 #define THERMAL_AUX0 0
0219 #define THERMAL_AUX1 1
0220 #define GET_AUX0 "GAX0"
0221 #define GET_AUX1 "GAX1"
0222 #define SET_AUX0 "SAX0"
0223 #define SET_AUX1 "SAX1"
0224 
0225 struct intel_menlow_attribute {
0226     struct device_attribute attr;
0227     struct device *device;
0228     acpi_handle handle;
0229     struct list_head node;
0230 };
0231 
0232 static LIST_HEAD(intel_menlow_attr_list);
0233 static DEFINE_MUTEX(intel_menlow_attr_lock);
0234 
0235 /*
0236  * sensor_get_auxtrip - get the current auxtrip value from sensor
0237  * @name: Thermalzone name
0238  * @auxtype : AUX0/AUX1
0239  * @buf: syfs buffer
0240  */
0241 static int sensor_get_auxtrip(acpi_handle handle, int index,
0242                             unsigned long long *value)
0243 {
0244     acpi_status status;
0245 
0246     if ((index != 0 && index != 1) || !value)
0247         return -EINVAL;
0248 
0249     status = acpi_evaluate_integer(handle, index ? GET_AUX1 : GET_AUX0,
0250                        NULL, value);
0251     if (ACPI_FAILURE(status))
0252         return -EIO;
0253 
0254     return 0;
0255 }
0256 
0257 /*
0258  * sensor_set_auxtrip - set the new auxtrip value to sensor
0259  * @name: Thermalzone name
0260  * @auxtype : AUX0/AUX1
0261  * @buf: syfs buffer
0262  */
0263 static int sensor_set_auxtrip(acpi_handle handle, int index, int value)
0264 {
0265     acpi_status status;
0266     union acpi_object arg = {
0267         ACPI_TYPE_INTEGER
0268     };
0269     struct acpi_object_list args = {
0270         1, &arg
0271     };
0272     unsigned long long temp;
0273 
0274     if (index != 0 && index != 1)
0275         return -EINVAL;
0276 
0277     status = acpi_evaluate_integer(handle, index ? GET_AUX0 : GET_AUX1,
0278                        NULL, &temp);
0279     if (ACPI_FAILURE(status))
0280         return -EIO;
0281     if ((index && value < temp) || (!index && value > temp))
0282         return -EINVAL;
0283 
0284     arg.integer.value = value;
0285     status = acpi_evaluate_integer(handle, index ? SET_AUX1 : SET_AUX0,
0286                        &args, &temp);
0287     if (ACPI_FAILURE(status))
0288         return -EIO;
0289 
0290     /* do we need to check the return value of SAX0/SAX1 ? */
0291 
0292     return 0;
0293 }
0294 
0295 #define to_intel_menlow_attr(_attr) \
0296     container_of(_attr, struct intel_menlow_attribute, attr)
0297 
0298 static ssize_t aux_show(struct device *dev, struct device_attribute *dev_attr,
0299             char *buf, int idx)
0300 {
0301     struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr);
0302     unsigned long long value;
0303     int result;
0304 
0305     result = sensor_get_auxtrip(attr->handle, idx, &value);
0306     if (result)
0307         return result;
0308 
0309     return sprintf(buf, "%lu", deci_kelvin_to_celsius(value));
0310 }
0311 
0312 static ssize_t aux0_show(struct device *dev,
0313              struct device_attribute *dev_attr, char *buf)
0314 {
0315     return aux_show(dev, dev_attr, buf, 0);
0316 }
0317 
0318 static ssize_t aux1_show(struct device *dev,
0319              struct device_attribute *dev_attr, char *buf)
0320 {
0321     return aux_show(dev, dev_attr, buf, 1);
0322 }
0323 
0324 static ssize_t aux_store(struct device *dev, struct device_attribute *dev_attr,
0325              const char *buf, size_t count, int idx)
0326 {
0327     struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr);
0328     int value;
0329     int result;
0330 
0331     /*Sanity check; should be a positive integer */
0332     if (!sscanf(buf, "%d", &value))
0333         return -EINVAL;
0334 
0335     if (value < 0)
0336         return -EINVAL;
0337 
0338     result = sensor_set_auxtrip(attr->handle, idx,
0339                     celsius_to_deci_kelvin(value));
0340     return result ? result : count;
0341 }
0342 
0343 static ssize_t aux0_store(struct device *dev,
0344               struct device_attribute *dev_attr,
0345               const char *buf, size_t count)
0346 {
0347     return aux_store(dev, dev_attr, buf, count, 0);
0348 }
0349 
0350 static ssize_t aux1_store(struct device *dev,
0351               struct device_attribute *dev_attr,
0352               const char *buf, size_t count)
0353 {
0354     return aux_store(dev, dev_attr, buf, count, 1);
0355 }
0356 
0357 /* BIOS can enable/disable the thermal user application in dabney platform */
0358 #define BIOS_ENABLED "\\_TZ.GSTS"
0359 static ssize_t bios_enabled_show(struct device *dev,
0360                  struct device_attribute *attr, char *buf)
0361 {
0362     acpi_status status;
0363     unsigned long long bios_enabled;
0364 
0365     status = acpi_evaluate_integer(NULL, BIOS_ENABLED, NULL, &bios_enabled);
0366     if (ACPI_FAILURE(status))
0367         return -ENODEV;
0368 
0369     return sprintf(buf, "%s\n", bios_enabled ? "enabled" : "disabled");
0370 }
0371 
0372 static int intel_menlow_add_one_attribute(char *name, umode_t mode, void *show,
0373                       void *store, struct device *dev,
0374                       acpi_handle handle)
0375 {
0376     struct intel_menlow_attribute *attr;
0377     int result;
0378 
0379     attr = kzalloc(sizeof(struct intel_menlow_attribute), GFP_KERNEL);
0380     if (!attr)
0381         return -ENOMEM;
0382 
0383     sysfs_attr_init(&attr->attr.attr); /* That is consistent naming :D */
0384     attr->attr.attr.name = name;
0385     attr->attr.attr.mode = mode;
0386     attr->attr.show = show;
0387     attr->attr.store = store;
0388     attr->device = dev;
0389     attr->handle = handle;
0390 
0391     result = device_create_file(dev, &attr->attr);
0392     if (result) {
0393         kfree(attr);
0394         return result;
0395     }
0396 
0397     mutex_lock(&intel_menlow_attr_lock);
0398     list_add_tail(&attr->node, &intel_menlow_attr_list);
0399     mutex_unlock(&intel_menlow_attr_lock);
0400 
0401     return 0;
0402 }
0403 
0404 static acpi_status intel_menlow_register_sensor(acpi_handle handle, u32 lvl,
0405                         void *context, void **rv)
0406 {
0407     acpi_status status;
0408     acpi_handle dummy;
0409     struct thermal_zone_device *thermal;
0410     int result;
0411 
0412     result = acpi_bus_get_private_data(handle, (void **)&thermal);
0413     if (result)
0414         return 0;
0415 
0416     /* _TZ must have the AUX0/1 methods */
0417     status = acpi_get_handle(handle, GET_AUX0, &dummy);
0418     if (ACPI_FAILURE(status))
0419         return (status == AE_NOT_FOUND) ? AE_OK : status;
0420 
0421     status = acpi_get_handle(handle, SET_AUX0, &dummy);
0422     if (ACPI_FAILURE(status))
0423         return (status == AE_NOT_FOUND) ? AE_OK : status;
0424 
0425     result = intel_menlow_add_one_attribute("aux0", 0644,
0426                         aux0_show, aux0_store,
0427                         &thermal->device, handle);
0428     if (result)
0429         return AE_ERROR;
0430 
0431     status = acpi_get_handle(handle, GET_AUX1, &dummy);
0432     if (ACPI_FAILURE(status))
0433         goto aux1_not_found;
0434 
0435     status = acpi_get_handle(handle, SET_AUX1, &dummy);
0436     if (ACPI_FAILURE(status))
0437         goto aux1_not_found;
0438 
0439     result = intel_menlow_add_one_attribute("aux1", 0644,
0440                         aux1_show, aux1_store,
0441                         &thermal->device, handle);
0442     if (result) {
0443         intel_menlow_unregister_sensor();
0444         return AE_ERROR;
0445     }
0446 
0447     /*
0448      * create the "dabney_enabled" attribute which means the user app
0449      * should be loaded or not
0450      */
0451 
0452     result = intel_menlow_add_one_attribute("bios_enabled", 0444,
0453                         bios_enabled_show, NULL,
0454                         &thermal->device, handle);
0455     if (result) {
0456         intel_menlow_unregister_sensor();
0457         return AE_ERROR;
0458     }
0459 
0460     return AE_OK;
0461 
0462  aux1_not_found:
0463     if (status == AE_NOT_FOUND)
0464         return AE_OK;
0465 
0466     intel_menlow_unregister_sensor();
0467     return status;
0468 }
0469 
0470 static void intel_menlow_unregister_sensor(void)
0471 {
0472     struct intel_menlow_attribute *pos, *next;
0473 
0474     mutex_lock(&intel_menlow_attr_lock);
0475     list_for_each_entry_safe(pos, next, &intel_menlow_attr_list, node) {
0476         list_del(&pos->node);
0477         device_remove_file(pos->device, &pos->attr);
0478         kfree(pos);
0479     }
0480     mutex_unlock(&intel_menlow_attr_lock);
0481 
0482     return;
0483 }
0484 
0485 static int __init intel_menlow_module_init(void)
0486 {
0487     int result = -ENODEV;
0488     acpi_status status;
0489     unsigned long long enable;
0490 
0491     if (acpi_disabled)
0492         return result;
0493 
0494     /* Looking for the \_TZ.GSTS method */
0495     status = acpi_evaluate_integer(NULL, BIOS_ENABLED, NULL, &enable);
0496     if (ACPI_FAILURE(status) || !enable)
0497         return -ENODEV;
0498 
0499     /* Looking for ACPI device MEM0 with hardware id INT0002 */
0500     result = acpi_bus_register_driver(&intel_menlow_memory_driver);
0501     if (result)
0502         return result;
0503 
0504     /* Looking for sensors in each ACPI thermal zone */
0505     status = acpi_walk_namespace(ACPI_TYPE_THERMAL, ACPI_ROOT_OBJECT,
0506                      ACPI_UINT32_MAX,
0507                      intel_menlow_register_sensor, NULL, NULL, NULL);
0508     if (ACPI_FAILURE(status)) {
0509         acpi_bus_unregister_driver(&intel_menlow_memory_driver);
0510         return -ENODEV;
0511     }
0512 
0513     return 0;
0514 }
0515 
0516 static void __exit intel_menlow_module_exit(void)
0517 {
0518     acpi_bus_unregister_driver(&intel_menlow_memory_driver);
0519     intel_menlow_unregister_sensor();
0520 }
0521 
0522 module_init(intel_menlow_module_init);
0523 module_exit(intel_menlow_module_exit);