Loading drivers/acpi/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o ifdef CONFIG_ACPI_VIDEO acpi-y += video_detect.o endif acpi-y += acpi_lpat.o # These are (potentially) separate modules Loading drivers/acpi/acpi_lpat.c 0 → 100644 +161 −0 Original line number Diff line number Diff line /* * acpi_lpat.c - LPAT table processing functions * * Copyright (C) 2015 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include <linux/module.h> #include <linux/acpi.h> #include <acpi/acpi_lpat.h> /** * acpi_lpat_raw_to_temp(): Return temperature from raw value through * LPAT conversion table * * @lpat_table: the temperature_raw mapping table structure * @raw: the raw value, used as a key to get the temerature from the * above mapping table * * A positive converted temperarure value will be returned on success, * a negative errno will be returned in error cases. */ int acpi_lpat_raw_to_temp(struct acpi_lpat_conversion_table *lpat_table, int raw) { int i, delta_temp, delta_raw, temp; struct acpi_lpat *lpat = lpat_table->lpat; for (i = 0; i < lpat_table->lpat_count - 1; i++) { if ((raw >= lpat[i].raw && raw <= lpat[i+1].raw) || (raw <= lpat[i].raw && raw >= lpat[i+1].raw)) break; } if (i == lpat_table->lpat_count - 1) return -ENOENT; delta_temp = lpat[i+1].temp - lpat[i].temp; delta_raw = lpat[i+1].raw - lpat[i].raw; temp = lpat[i].temp + (raw - lpat[i].raw) * delta_temp / delta_raw; return temp; } EXPORT_SYMBOL_GPL(acpi_lpat_raw_to_temp); /** * acpi_lpat_temp_to_raw(): Return raw value from temperature through * LPAT conversion table * * @lpat: the temperature_raw mapping table * @temp: the temperature, used as a key to get the raw value from the * above mapping table * * A positive converted temperature value will be returned on success, * a negative errno will be returned in error cases. */ int acpi_lpat_temp_to_raw(struct acpi_lpat_conversion_table *lpat_table, int temp) { int i, delta_temp, delta_raw, raw; struct acpi_lpat *lpat = lpat_table->lpat; for (i = 0; i < lpat_table->lpat_count - 1; i++) { if (temp >= lpat[i].temp && temp <= lpat[i+1].temp) break; } if (i == lpat_table->lpat_count - 1) return -ENOENT; delta_temp = lpat[i+1].temp - lpat[i].temp; delta_raw = lpat[i+1].raw - lpat[i].raw; raw = lpat[i].raw + (temp - lpat[i].temp) * delta_raw / delta_temp; return raw; } EXPORT_SYMBOL_GPL(acpi_lpat_temp_to_raw); /** * acpi_lpat_get_conversion_table(): Parse ACPI LPAT table if present. * * @handle: Handle to acpi device * * Parse LPAT table to a struct of type acpi_lpat_table. On success * it returns a pointer to newly allocated table. This table must * be freed by the caller when finished processing, using a call to * acpi_lpat_free_conversion_table. */ struct acpi_lpat_conversion_table *acpi_lpat_get_conversion_table(acpi_handle handle) { struct acpi_lpat_conversion_table *lpat_table = NULL; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj_p, *obj_e; int *lpat, i; acpi_status status; status = acpi_evaluate_object(handle, "LPAT", NULL, &buffer); if (ACPI_FAILURE(status)) return NULL; obj_p = (union acpi_object *)buffer.pointer; if (!obj_p || (obj_p->type != ACPI_TYPE_PACKAGE) || (obj_p->package.count % 2) || (obj_p->package.count < 4)) goto out; lpat = kcalloc(obj_p->package.count, sizeof(int), GFP_KERNEL); if (!lpat) goto out; for (i = 0; i < obj_p->package.count; i++) { obj_e = &obj_p->package.elements[i]; if (obj_e->type != ACPI_TYPE_INTEGER) { kfree(lpat); goto out; } lpat[i] = (s64)obj_e->integer.value; } lpat_table = kzalloc(sizeof(*lpat_table), GFP_KERNEL); if (!lpat_table) { kfree(lpat); goto out; } lpat_table->lpat = (struct acpi_lpat *)lpat; lpat_table->lpat_count = obj_p->package.count / 2; out: kfree(buffer.pointer); return lpat_table; } EXPORT_SYMBOL_GPL(acpi_lpat_get_conversion_table); /** * acpi_lpat_free_conversion_table(): Free LPAT table. * * @lpat_table: the temperature_raw mapping table structure * * Frees the LPAT table previously allocated by a call to * acpi_lpat_get_conversion_table. */ void acpi_lpat_free_conversion_table(struct acpi_lpat_conversion_table *lpat_table) { if (lpat_table) { kfree(lpat_table->lpat); kfree(lpat_table); } } EXPORT_SYMBOL_GPL(acpi_lpat_free_conversion_table); MODULE_LICENSE("GPL"); drivers/acpi/pmic/intel_pmic.c +18 −115 Original line number Diff line number Diff line Loading @@ -16,20 +16,15 @@ #include <linux/module.h> #include <linux/acpi.h> #include <linux/regmap.h> #include <acpi/acpi_lpat.h> #include "intel_pmic.h" #define PMIC_POWER_OPREGION_ID 0x8d #define PMIC_THERMAL_OPREGION_ID 0x8c struct acpi_lpat { int temp; int raw; }; struct intel_pmic_opregion { struct mutex lock; struct acpi_lpat *lpat; int lpat_count; struct acpi_lpat_conversion_table *lpat_table; struct regmap *regmap; struct intel_pmic_opregion_data *data; }; Loading @@ -50,105 +45,6 @@ static int pmic_get_reg_bit(int address, struct pmic_table *table, return -ENOENT; } /** * raw_to_temp(): Return temperature from raw value through LPAT table * * @lpat: the temperature_raw mapping table * @count: the count of the above mapping table * @raw: the raw value, used as a key to get the temerature from the * above mapping table * * A positive value will be returned on success, a negative errno will * be returned in error cases. */ static int raw_to_temp(struct acpi_lpat *lpat, int count, int raw) { int i, delta_temp, delta_raw, temp; for (i = 0; i < count - 1; i++) { if ((raw >= lpat[i].raw && raw <= lpat[i+1].raw) || (raw <= lpat[i].raw && raw >= lpat[i+1].raw)) break; } if (i == count - 1) return -ENOENT; delta_temp = lpat[i+1].temp - lpat[i].temp; delta_raw = lpat[i+1].raw - lpat[i].raw; temp = lpat[i].temp + (raw - lpat[i].raw) * delta_temp / delta_raw; return temp; } /** * temp_to_raw(): Return raw value from temperature through LPAT table * * @lpat: the temperature_raw mapping table * @count: the count of the above mapping table * @temp: the temperature, used as a key to get the raw value from the * above mapping table * * A positive value will be returned on success, a negative errno will * be returned in error cases. */ static int temp_to_raw(struct acpi_lpat *lpat, int count, int temp) { int i, delta_temp, delta_raw, raw; for (i = 0; i < count - 1; i++) { if (temp >= lpat[i].temp && temp <= lpat[i+1].temp) break; } if (i == count - 1) return -ENOENT; delta_temp = lpat[i+1].temp - lpat[i].temp; delta_raw = lpat[i+1].raw - lpat[i].raw; raw = lpat[i].raw + (temp - lpat[i].temp) * delta_raw / delta_temp; return raw; } static void pmic_thermal_lpat(struct intel_pmic_opregion *opregion, acpi_handle handle, struct device *dev) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj_p, *obj_e; int *lpat, i; acpi_status status; status = acpi_evaluate_object(handle, "LPAT", NULL, &buffer); if (ACPI_FAILURE(status)) return; obj_p = (union acpi_object *)buffer.pointer; if (!obj_p || (obj_p->type != ACPI_TYPE_PACKAGE) || (obj_p->package.count % 2) || (obj_p->package.count < 4)) goto out; lpat = devm_kmalloc(dev, sizeof(int) * obj_p->package.count, GFP_KERNEL); if (!lpat) goto out; for (i = 0; i < obj_p->package.count; i++) { obj_e = &obj_p->package.elements[i]; if (obj_e->type != ACPI_TYPE_INTEGER) { devm_kfree(dev, lpat); goto out; } lpat[i] = (s64)obj_e->integer.value; } opregion->lpat = (struct acpi_lpat *)lpat; opregion->lpat_count = obj_p->package.count / 2; out: kfree(buffer.pointer); } static acpi_status intel_pmic_power_handler(u32 function, acpi_physical_address address, u32 bits, u64 *value64, void *handler_context, void *region_context) Loading Loading @@ -192,12 +88,12 @@ static int pmic_read_temp(struct intel_pmic_opregion *opregion, if (raw_temp < 0) return raw_temp; if (!opregion->lpat) { if (!opregion->lpat_table) { *value = raw_temp; return 0; } temp = raw_to_temp(opregion->lpat, opregion->lpat_count, raw_temp); temp = acpi_lpat_raw_to_temp(opregion->lpat_table, raw_temp); if (temp < 0) return temp; Loading @@ -223,9 +119,8 @@ static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg, if (!opregion->data->update_aux) return -ENXIO; if (opregion->lpat) { raw_temp = temp_to_raw(opregion->lpat, opregion->lpat_count, *value); if (opregion->lpat_table) { raw_temp = acpi_lpat_temp_to_raw(opregion->lpat_table, *value); if (raw_temp < 0) return raw_temp; } else { Loading Loading @@ -314,6 +209,7 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, { acpi_status status; struct intel_pmic_opregion *opregion; int ret; if (!dev || !regmap || !d) return -EINVAL; Loading @@ -327,14 +223,16 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, mutex_init(&opregion->lock); opregion->regmap = regmap; pmic_thermal_lpat(opregion, handle, dev); opregion->lpat_table = acpi_lpat_get_conversion_table(handle); status = acpi_install_address_space_handler(handle, PMIC_POWER_OPREGION_ID, intel_pmic_power_handler, NULL, opregion); if (ACPI_FAILURE(status)) return -ENODEV; if (ACPI_FAILURE(status)) { ret = -ENODEV; goto out_error; } status = acpi_install_address_space_handler(handle, PMIC_THERMAL_OPREGION_ID, Loading @@ -343,11 +241,16 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, if (ACPI_FAILURE(status)) { acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID, intel_pmic_power_handler); return -ENODEV; ret = -ENODEV; goto out_error; } opregion->data = d; return 0; out_error: acpi_lpat_free_conversion_table(opregion->lpat_table); return ret; } EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler); Loading drivers/thermal/int340x_thermal/Makefile +1 −0 Original line number Diff line number Diff line obj-$(CONFIG_INT340X_THERMAL) += int3400_thermal.o obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal_zone.o obj-$(CONFIG_INT340X_THERMAL) += int3402_thermal.o obj-$(CONFIG_INT340X_THERMAL) += int3403_thermal.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device.o Loading drivers/thermal/int340x_thermal/int3402_thermal.c +37 −171 Original line number Diff line number Diff line Loading @@ -14,152 +14,39 @@ #include <linux/platform_device.h> #include <linux/acpi.h> #include <linux/thermal.h> #include "int340x_thermal_zone.h" #define ACPI_ACTIVE_COOLING_MAX_NR 10 struct active_trip { unsigned long temp; int id; bool valid; }; #define INT3402_PERF_CHANGED_EVENT 0x80 #define INT3402_THERMAL_EVENT 0x90 struct int3402_thermal_data { unsigned long *aux_trips; int aux_trip_nr; unsigned long psv_temp; int psv_trip_id; unsigned long crt_temp; int crt_trip_id; unsigned long hot_temp; int hot_trip_id; struct active_trip act_trips[ACPI_ACTIVE_COOLING_MAX_NR]; acpi_handle *handle; struct int34x_thermal_zone *int340x_zone; }; static int int3402_thermal_get_zone_temp(struct thermal_zone_device *zone, unsigned long *temp) static void int3402_notify(acpi_handle handle, u32 event, void *data) { struct int3402_thermal_data *d = zone->devdata; unsigned long long tmp; acpi_status status; status = acpi_evaluate_integer(d->handle, "_TMP", NULL, &tmp); if (ACPI_FAILURE(status)) return -ENODEV; struct int3402_thermal_data *priv = data; /* _TMP returns the temperature in tenths of degrees Kelvin */ *temp = DECI_KELVIN_TO_MILLICELSIUS(tmp); if (!priv) return; return 0; } static int int3402_thermal_get_trip_temp(struct thermal_zone_device *zone, int trip, unsigned long *temp) { struct int3402_thermal_data *d = zone->devdata; int i; if (trip < d->aux_trip_nr) *temp = d->aux_trips[trip]; else if (trip == d->crt_trip_id) *temp = d->crt_temp; else if (trip == d->psv_trip_id) *temp = d->psv_temp; else if (trip == d->hot_trip_id) *temp = d->hot_temp; else { for (i = 0; i < ACPI_ACTIVE_COOLING_MAX_NR; i++) { if (d->act_trips[i].valid && d->act_trips[i].id == trip) { *temp = d->act_trips[i].temp; switch (event) { case INT3402_PERF_CHANGED_EVENT: break; } } if (i == ACPI_ACTIVE_COOLING_MAX_NR) return -EINVAL; } return 0; } static int int3402_thermal_get_trip_type(struct thermal_zone_device *zone, int trip, enum thermal_trip_type *type) { struct int3402_thermal_data *d = zone->devdata; int i; if (trip < d->aux_trip_nr) *type = THERMAL_TRIP_PASSIVE; else if (trip == d->crt_trip_id) *type = THERMAL_TRIP_CRITICAL; else if (trip == d->hot_trip_id) *type = THERMAL_TRIP_HOT; else if (trip == d->psv_trip_id) *type = THERMAL_TRIP_PASSIVE; else { for (i = 0; i < ACPI_ACTIVE_COOLING_MAX_NR; i++) { if (d->act_trips[i].valid && d->act_trips[i].id == trip) { *type = THERMAL_TRIP_ACTIVE; case INT3402_THERMAL_EVENT: int340x_thermal_zone_device_update(priv->int340x_zone); break; default: break; } } if (i == ACPI_ACTIVE_COOLING_MAX_NR) return -EINVAL; } return 0; } static int int3402_thermal_set_trip_temp(struct thermal_zone_device *zone, int trip, unsigned long temp) { struct int3402_thermal_data *d = zone->devdata; acpi_status status; char name[10]; snprintf(name, sizeof(name), "PAT%d", trip); status = acpi_execute_simple_method(d->handle, name, MILLICELSIUS_TO_DECI_KELVIN(temp)); if (ACPI_FAILURE(status)) return -EIO; d->aux_trips[trip] = temp; return 0; } static struct thermal_zone_device_ops int3402_thermal_zone_ops = { .get_temp = int3402_thermal_get_zone_temp, .get_trip_temp = int3402_thermal_get_trip_temp, .get_trip_type = int3402_thermal_get_trip_type, .set_trip_temp = int3402_thermal_set_trip_temp, }; static struct thermal_zone_params int3402_thermal_params = { .governor_name = "user_space", .no_hwmon = true, }; static int int3402_thermal_get_temp(acpi_handle handle, char *name, unsigned long *temp) { unsigned long long r; acpi_status status; status = acpi_evaluate_integer(handle, name, NULL, &r); if (ACPI_FAILURE(status)) return -EIO; *temp = DECI_KELVIN_TO_MILLICELSIUS(r); return 0; } static int int3402_thermal_probe(struct platform_device *pdev) { struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); struct int3402_thermal_data *d; struct thermal_zone_device *zone; acpi_status status; unsigned long long trip_cnt; int trip_mask = 0, i; int ret; if (!acpi_has_method(adev->handle, "_TMP")) return -ENODEV; Loading @@ -168,54 +55,33 @@ static int int3402_thermal_probe(struct platform_device *pdev) if (!d) return -ENOMEM; status = acpi_evaluate_integer(adev->handle, "PATC", NULL, &trip_cnt); if (ACPI_FAILURE(status)) trip_cnt = 0; else { d->aux_trips = devm_kzalloc(&pdev->dev, sizeof(*d->aux_trips) * trip_cnt, GFP_KERNEL); if (!d->aux_trips) return -ENOMEM; trip_mask = trip_cnt - 1; d->handle = adev->handle; d->aux_trip_nr = trip_cnt; } d->crt_trip_id = -1; if (!int3402_thermal_get_temp(adev->handle, "_CRT", &d->crt_temp)) d->crt_trip_id = trip_cnt++; d->hot_trip_id = -1; if (!int3402_thermal_get_temp(adev->handle, "_HOT", &d->hot_temp)) d->hot_trip_id = trip_cnt++; d->psv_trip_id = -1; if (!int3402_thermal_get_temp(adev->handle, "_PSV", &d->psv_temp)) d->psv_trip_id = trip_cnt++; for (i = 0; i < ACPI_ACTIVE_COOLING_MAX_NR; i++) { char name[5] = { '_', 'A', 'C', '0' + i, '\0' }; if (int3402_thermal_get_temp(adev->handle, name, &d->act_trips[i].temp)) break; d->act_trips[i].id = trip_cnt++; d->act_trips[i].valid = true; d->int340x_zone = int340x_thermal_zone_add(adev, NULL); if (IS_ERR(d->int340x_zone)) return PTR_ERR(d->int340x_zone); ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, int3402_notify, d); if (ret) { int340x_thermal_zone_remove(d->int340x_zone); return ret; } zone = thermal_zone_device_register(acpi_device_bid(adev), trip_cnt, trip_mask, d, &int3402_thermal_zone_ops, &int3402_thermal_params, 0, 0); if (IS_ERR(zone)) return PTR_ERR(zone); platform_set_drvdata(pdev, zone); d->handle = adev->handle; platform_set_drvdata(pdev, d); return 0; } static int int3402_thermal_remove(struct platform_device *pdev) { struct thermal_zone_device *zone = platform_get_drvdata(pdev); struct int3402_thermal_data *d = platform_get_drvdata(pdev); acpi_remove_notify_handler(d->handle, ACPI_DEVICE_NOTIFY, int3402_notify); int340x_thermal_zone_remove(d->int340x_zone); thermal_zone_device_unregister(zone); return 0; } Loading Loading
drivers/acpi/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o ifdef CONFIG_ACPI_VIDEO acpi-y += video_detect.o endif acpi-y += acpi_lpat.o # These are (potentially) separate modules Loading
drivers/acpi/acpi_lpat.c 0 → 100644 +161 −0 Original line number Diff line number Diff line /* * acpi_lpat.c - LPAT table processing functions * * Copyright (C) 2015 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include <linux/module.h> #include <linux/acpi.h> #include <acpi/acpi_lpat.h> /** * acpi_lpat_raw_to_temp(): Return temperature from raw value through * LPAT conversion table * * @lpat_table: the temperature_raw mapping table structure * @raw: the raw value, used as a key to get the temerature from the * above mapping table * * A positive converted temperarure value will be returned on success, * a negative errno will be returned in error cases. */ int acpi_lpat_raw_to_temp(struct acpi_lpat_conversion_table *lpat_table, int raw) { int i, delta_temp, delta_raw, temp; struct acpi_lpat *lpat = lpat_table->lpat; for (i = 0; i < lpat_table->lpat_count - 1; i++) { if ((raw >= lpat[i].raw && raw <= lpat[i+1].raw) || (raw <= lpat[i].raw && raw >= lpat[i+1].raw)) break; } if (i == lpat_table->lpat_count - 1) return -ENOENT; delta_temp = lpat[i+1].temp - lpat[i].temp; delta_raw = lpat[i+1].raw - lpat[i].raw; temp = lpat[i].temp + (raw - lpat[i].raw) * delta_temp / delta_raw; return temp; } EXPORT_SYMBOL_GPL(acpi_lpat_raw_to_temp); /** * acpi_lpat_temp_to_raw(): Return raw value from temperature through * LPAT conversion table * * @lpat: the temperature_raw mapping table * @temp: the temperature, used as a key to get the raw value from the * above mapping table * * A positive converted temperature value will be returned on success, * a negative errno will be returned in error cases. */ int acpi_lpat_temp_to_raw(struct acpi_lpat_conversion_table *lpat_table, int temp) { int i, delta_temp, delta_raw, raw; struct acpi_lpat *lpat = lpat_table->lpat; for (i = 0; i < lpat_table->lpat_count - 1; i++) { if (temp >= lpat[i].temp && temp <= lpat[i+1].temp) break; } if (i == lpat_table->lpat_count - 1) return -ENOENT; delta_temp = lpat[i+1].temp - lpat[i].temp; delta_raw = lpat[i+1].raw - lpat[i].raw; raw = lpat[i].raw + (temp - lpat[i].temp) * delta_raw / delta_temp; return raw; } EXPORT_SYMBOL_GPL(acpi_lpat_temp_to_raw); /** * acpi_lpat_get_conversion_table(): Parse ACPI LPAT table if present. * * @handle: Handle to acpi device * * Parse LPAT table to a struct of type acpi_lpat_table. On success * it returns a pointer to newly allocated table. This table must * be freed by the caller when finished processing, using a call to * acpi_lpat_free_conversion_table. */ struct acpi_lpat_conversion_table *acpi_lpat_get_conversion_table(acpi_handle handle) { struct acpi_lpat_conversion_table *lpat_table = NULL; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj_p, *obj_e; int *lpat, i; acpi_status status; status = acpi_evaluate_object(handle, "LPAT", NULL, &buffer); if (ACPI_FAILURE(status)) return NULL; obj_p = (union acpi_object *)buffer.pointer; if (!obj_p || (obj_p->type != ACPI_TYPE_PACKAGE) || (obj_p->package.count % 2) || (obj_p->package.count < 4)) goto out; lpat = kcalloc(obj_p->package.count, sizeof(int), GFP_KERNEL); if (!lpat) goto out; for (i = 0; i < obj_p->package.count; i++) { obj_e = &obj_p->package.elements[i]; if (obj_e->type != ACPI_TYPE_INTEGER) { kfree(lpat); goto out; } lpat[i] = (s64)obj_e->integer.value; } lpat_table = kzalloc(sizeof(*lpat_table), GFP_KERNEL); if (!lpat_table) { kfree(lpat); goto out; } lpat_table->lpat = (struct acpi_lpat *)lpat; lpat_table->lpat_count = obj_p->package.count / 2; out: kfree(buffer.pointer); return lpat_table; } EXPORT_SYMBOL_GPL(acpi_lpat_get_conversion_table); /** * acpi_lpat_free_conversion_table(): Free LPAT table. * * @lpat_table: the temperature_raw mapping table structure * * Frees the LPAT table previously allocated by a call to * acpi_lpat_get_conversion_table. */ void acpi_lpat_free_conversion_table(struct acpi_lpat_conversion_table *lpat_table) { if (lpat_table) { kfree(lpat_table->lpat); kfree(lpat_table); } } EXPORT_SYMBOL_GPL(acpi_lpat_free_conversion_table); MODULE_LICENSE("GPL");
drivers/acpi/pmic/intel_pmic.c +18 −115 Original line number Diff line number Diff line Loading @@ -16,20 +16,15 @@ #include <linux/module.h> #include <linux/acpi.h> #include <linux/regmap.h> #include <acpi/acpi_lpat.h> #include "intel_pmic.h" #define PMIC_POWER_OPREGION_ID 0x8d #define PMIC_THERMAL_OPREGION_ID 0x8c struct acpi_lpat { int temp; int raw; }; struct intel_pmic_opregion { struct mutex lock; struct acpi_lpat *lpat; int lpat_count; struct acpi_lpat_conversion_table *lpat_table; struct regmap *regmap; struct intel_pmic_opregion_data *data; }; Loading @@ -50,105 +45,6 @@ static int pmic_get_reg_bit(int address, struct pmic_table *table, return -ENOENT; } /** * raw_to_temp(): Return temperature from raw value through LPAT table * * @lpat: the temperature_raw mapping table * @count: the count of the above mapping table * @raw: the raw value, used as a key to get the temerature from the * above mapping table * * A positive value will be returned on success, a negative errno will * be returned in error cases. */ static int raw_to_temp(struct acpi_lpat *lpat, int count, int raw) { int i, delta_temp, delta_raw, temp; for (i = 0; i < count - 1; i++) { if ((raw >= lpat[i].raw && raw <= lpat[i+1].raw) || (raw <= lpat[i].raw && raw >= lpat[i+1].raw)) break; } if (i == count - 1) return -ENOENT; delta_temp = lpat[i+1].temp - lpat[i].temp; delta_raw = lpat[i+1].raw - lpat[i].raw; temp = lpat[i].temp + (raw - lpat[i].raw) * delta_temp / delta_raw; return temp; } /** * temp_to_raw(): Return raw value from temperature through LPAT table * * @lpat: the temperature_raw mapping table * @count: the count of the above mapping table * @temp: the temperature, used as a key to get the raw value from the * above mapping table * * A positive value will be returned on success, a negative errno will * be returned in error cases. */ static int temp_to_raw(struct acpi_lpat *lpat, int count, int temp) { int i, delta_temp, delta_raw, raw; for (i = 0; i < count - 1; i++) { if (temp >= lpat[i].temp && temp <= lpat[i+1].temp) break; } if (i == count - 1) return -ENOENT; delta_temp = lpat[i+1].temp - lpat[i].temp; delta_raw = lpat[i+1].raw - lpat[i].raw; raw = lpat[i].raw + (temp - lpat[i].temp) * delta_raw / delta_temp; return raw; } static void pmic_thermal_lpat(struct intel_pmic_opregion *opregion, acpi_handle handle, struct device *dev) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj_p, *obj_e; int *lpat, i; acpi_status status; status = acpi_evaluate_object(handle, "LPAT", NULL, &buffer); if (ACPI_FAILURE(status)) return; obj_p = (union acpi_object *)buffer.pointer; if (!obj_p || (obj_p->type != ACPI_TYPE_PACKAGE) || (obj_p->package.count % 2) || (obj_p->package.count < 4)) goto out; lpat = devm_kmalloc(dev, sizeof(int) * obj_p->package.count, GFP_KERNEL); if (!lpat) goto out; for (i = 0; i < obj_p->package.count; i++) { obj_e = &obj_p->package.elements[i]; if (obj_e->type != ACPI_TYPE_INTEGER) { devm_kfree(dev, lpat); goto out; } lpat[i] = (s64)obj_e->integer.value; } opregion->lpat = (struct acpi_lpat *)lpat; opregion->lpat_count = obj_p->package.count / 2; out: kfree(buffer.pointer); } static acpi_status intel_pmic_power_handler(u32 function, acpi_physical_address address, u32 bits, u64 *value64, void *handler_context, void *region_context) Loading Loading @@ -192,12 +88,12 @@ static int pmic_read_temp(struct intel_pmic_opregion *opregion, if (raw_temp < 0) return raw_temp; if (!opregion->lpat) { if (!opregion->lpat_table) { *value = raw_temp; return 0; } temp = raw_to_temp(opregion->lpat, opregion->lpat_count, raw_temp); temp = acpi_lpat_raw_to_temp(opregion->lpat_table, raw_temp); if (temp < 0) return temp; Loading @@ -223,9 +119,8 @@ static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg, if (!opregion->data->update_aux) return -ENXIO; if (opregion->lpat) { raw_temp = temp_to_raw(opregion->lpat, opregion->lpat_count, *value); if (opregion->lpat_table) { raw_temp = acpi_lpat_temp_to_raw(opregion->lpat_table, *value); if (raw_temp < 0) return raw_temp; } else { Loading Loading @@ -314,6 +209,7 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, { acpi_status status; struct intel_pmic_opregion *opregion; int ret; if (!dev || !regmap || !d) return -EINVAL; Loading @@ -327,14 +223,16 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, mutex_init(&opregion->lock); opregion->regmap = regmap; pmic_thermal_lpat(opregion, handle, dev); opregion->lpat_table = acpi_lpat_get_conversion_table(handle); status = acpi_install_address_space_handler(handle, PMIC_POWER_OPREGION_ID, intel_pmic_power_handler, NULL, opregion); if (ACPI_FAILURE(status)) return -ENODEV; if (ACPI_FAILURE(status)) { ret = -ENODEV; goto out_error; } status = acpi_install_address_space_handler(handle, PMIC_THERMAL_OPREGION_ID, Loading @@ -343,11 +241,16 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, if (ACPI_FAILURE(status)) { acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID, intel_pmic_power_handler); return -ENODEV; ret = -ENODEV; goto out_error; } opregion->data = d; return 0; out_error: acpi_lpat_free_conversion_table(opregion->lpat_table); return ret; } EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler); Loading
drivers/thermal/int340x_thermal/Makefile +1 −0 Original line number Diff line number Diff line obj-$(CONFIG_INT340X_THERMAL) += int3400_thermal.o obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal_zone.o obj-$(CONFIG_INT340X_THERMAL) += int3402_thermal.o obj-$(CONFIG_INT340X_THERMAL) += int3403_thermal.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device.o Loading
drivers/thermal/int340x_thermal/int3402_thermal.c +37 −171 Original line number Diff line number Diff line Loading @@ -14,152 +14,39 @@ #include <linux/platform_device.h> #include <linux/acpi.h> #include <linux/thermal.h> #include "int340x_thermal_zone.h" #define ACPI_ACTIVE_COOLING_MAX_NR 10 struct active_trip { unsigned long temp; int id; bool valid; }; #define INT3402_PERF_CHANGED_EVENT 0x80 #define INT3402_THERMAL_EVENT 0x90 struct int3402_thermal_data { unsigned long *aux_trips; int aux_trip_nr; unsigned long psv_temp; int psv_trip_id; unsigned long crt_temp; int crt_trip_id; unsigned long hot_temp; int hot_trip_id; struct active_trip act_trips[ACPI_ACTIVE_COOLING_MAX_NR]; acpi_handle *handle; struct int34x_thermal_zone *int340x_zone; }; static int int3402_thermal_get_zone_temp(struct thermal_zone_device *zone, unsigned long *temp) static void int3402_notify(acpi_handle handle, u32 event, void *data) { struct int3402_thermal_data *d = zone->devdata; unsigned long long tmp; acpi_status status; status = acpi_evaluate_integer(d->handle, "_TMP", NULL, &tmp); if (ACPI_FAILURE(status)) return -ENODEV; struct int3402_thermal_data *priv = data; /* _TMP returns the temperature in tenths of degrees Kelvin */ *temp = DECI_KELVIN_TO_MILLICELSIUS(tmp); if (!priv) return; return 0; } static int int3402_thermal_get_trip_temp(struct thermal_zone_device *zone, int trip, unsigned long *temp) { struct int3402_thermal_data *d = zone->devdata; int i; if (trip < d->aux_trip_nr) *temp = d->aux_trips[trip]; else if (trip == d->crt_trip_id) *temp = d->crt_temp; else if (trip == d->psv_trip_id) *temp = d->psv_temp; else if (trip == d->hot_trip_id) *temp = d->hot_temp; else { for (i = 0; i < ACPI_ACTIVE_COOLING_MAX_NR; i++) { if (d->act_trips[i].valid && d->act_trips[i].id == trip) { *temp = d->act_trips[i].temp; switch (event) { case INT3402_PERF_CHANGED_EVENT: break; } } if (i == ACPI_ACTIVE_COOLING_MAX_NR) return -EINVAL; } return 0; } static int int3402_thermal_get_trip_type(struct thermal_zone_device *zone, int trip, enum thermal_trip_type *type) { struct int3402_thermal_data *d = zone->devdata; int i; if (trip < d->aux_trip_nr) *type = THERMAL_TRIP_PASSIVE; else if (trip == d->crt_trip_id) *type = THERMAL_TRIP_CRITICAL; else if (trip == d->hot_trip_id) *type = THERMAL_TRIP_HOT; else if (trip == d->psv_trip_id) *type = THERMAL_TRIP_PASSIVE; else { for (i = 0; i < ACPI_ACTIVE_COOLING_MAX_NR; i++) { if (d->act_trips[i].valid && d->act_trips[i].id == trip) { *type = THERMAL_TRIP_ACTIVE; case INT3402_THERMAL_EVENT: int340x_thermal_zone_device_update(priv->int340x_zone); break; default: break; } } if (i == ACPI_ACTIVE_COOLING_MAX_NR) return -EINVAL; } return 0; } static int int3402_thermal_set_trip_temp(struct thermal_zone_device *zone, int trip, unsigned long temp) { struct int3402_thermal_data *d = zone->devdata; acpi_status status; char name[10]; snprintf(name, sizeof(name), "PAT%d", trip); status = acpi_execute_simple_method(d->handle, name, MILLICELSIUS_TO_DECI_KELVIN(temp)); if (ACPI_FAILURE(status)) return -EIO; d->aux_trips[trip] = temp; return 0; } static struct thermal_zone_device_ops int3402_thermal_zone_ops = { .get_temp = int3402_thermal_get_zone_temp, .get_trip_temp = int3402_thermal_get_trip_temp, .get_trip_type = int3402_thermal_get_trip_type, .set_trip_temp = int3402_thermal_set_trip_temp, }; static struct thermal_zone_params int3402_thermal_params = { .governor_name = "user_space", .no_hwmon = true, }; static int int3402_thermal_get_temp(acpi_handle handle, char *name, unsigned long *temp) { unsigned long long r; acpi_status status; status = acpi_evaluate_integer(handle, name, NULL, &r); if (ACPI_FAILURE(status)) return -EIO; *temp = DECI_KELVIN_TO_MILLICELSIUS(r); return 0; } static int int3402_thermal_probe(struct platform_device *pdev) { struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); struct int3402_thermal_data *d; struct thermal_zone_device *zone; acpi_status status; unsigned long long trip_cnt; int trip_mask = 0, i; int ret; if (!acpi_has_method(adev->handle, "_TMP")) return -ENODEV; Loading @@ -168,54 +55,33 @@ static int int3402_thermal_probe(struct platform_device *pdev) if (!d) return -ENOMEM; status = acpi_evaluate_integer(adev->handle, "PATC", NULL, &trip_cnt); if (ACPI_FAILURE(status)) trip_cnt = 0; else { d->aux_trips = devm_kzalloc(&pdev->dev, sizeof(*d->aux_trips) * trip_cnt, GFP_KERNEL); if (!d->aux_trips) return -ENOMEM; trip_mask = trip_cnt - 1; d->handle = adev->handle; d->aux_trip_nr = trip_cnt; } d->crt_trip_id = -1; if (!int3402_thermal_get_temp(adev->handle, "_CRT", &d->crt_temp)) d->crt_trip_id = trip_cnt++; d->hot_trip_id = -1; if (!int3402_thermal_get_temp(adev->handle, "_HOT", &d->hot_temp)) d->hot_trip_id = trip_cnt++; d->psv_trip_id = -1; if (!int3402_thermal_get_temp(adev->handle, "_PSV", &d->psv_temp)) d->psv_trip_id = trip_cnt++; for (i = 0; i < ACPI_ACTIVE_COOLING_MAX_NR; i++) { char name[5] = { '_', 'A', 'C', '0' + i, '\0' }; if (int3402_thermal_get_temp(adev->handle, name, &d->act_trips[i].temp)) break; d->act_trips[i].id = trip_cnt++; d->act_trips[i].valid = true; d->int340x_zone = int340x_thermal_zone_add(adev, NULL); if (IS_ERR(d->int340x_zone)) return PTR_ERR(d->int340x_zone); ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, int3402_notify, d); if (ret) { int340x_thermal_zone_remove(d->int340x_zone); return ret; } zone = thermal_zone_device_register(acpi_device_bid(adev), trip_cnt, trip_mask, d, &int3402_thermal_zone_ops, &int3402_thermal_params, 0, 0); if (IS_ERR(zone)) return PTR_ERR(zone); platform_set_drvdata(pdev, zone); d->handle = adev->handle; platform_set_drvdata(pdev, d); return 0; } static int int3402_thermal_remove(struct platform_device *pdev) { struct thermal_zone_device *zone = platform_get_drvdata(pdev); struct int3402_thermal_data *d = platform_get_drvdata(pdev); acpi_remove_notify_handler(d->handle, ACPI_DEVICE_NOTIFY, int3402_notify); int340x_thermal_zone_remove(d->int340x_zone); thermal_zone_device_unregister(zone); return 0; } Loading