From 5fcdeb20df2085580819c665ae50f7dae964c27d Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 30 May 2014 12:10:32 -0700 Subject: [PATCH] Thermal: int3403: Add CRT and PSV trip The ACPI object definition can contain passive and critical trip temperature. Export them via thermal sysfs. Signed-off-by: Srinivas Pandruvada Signed-off-by: Zhang Rui --- drivers/thermal/int3403_thermal.c | 67 +++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/drivers/thermal/int3403_thermal.c b/drivers/thermal/int3403_thermal.c index e93f0253f6ed..17554eeb3953 100644 --- a/drivers/thermal/int3403_thermal.c +++ b/drivers/thermal/int3403_thermal.c @@ -33,6 +33,10 @@ struct int3403_sensor { struct thermal_zone_device *tzone; unsigned long *thresholds; + unsigned long crit_temp; + int crit_trip_id; + unsigned long psv_temp; + int psv_trip_id; }; static int sys_get_curr_temp(struct thermal_zone_device *tzone, @@ -79,12 +83,18 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzone, struct acpi_device *device = tzone->devdata; struct int3403_sensor *obj = acpi_driver_data(device); - /* - * get_trip_temp is a mandatory callback but - * PATx method doesn't return any value, so return - * cached value, which was last set from user space. - */ - *temp = obj->thresholds[trip]; + if (trip == obj->crit_trip_id) + *temp = obj->crit_temp; + else if (trip == obj->psv_trip_id) + *temp = obj->psv_temp; + else { + /* + * get_trip_temp is a mandatory callback but + * PATx method doesn't return any value, so return + * cached value, which was last set from user space. + */ + *temp = obj->thresholds[trip]; + } return 0; } @@ -92,8 +102,14 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzone, static int sys_get_trip_type(struct thermal_zone_device *thermal, int trip, enum thermal_trip_type *type) { + struct acpi_device *device = thermal->devdata; + struct int3403_sensor *obj = acpi_driver_data(device); + /* Mandatory callback, may not mean much here */ - *type = THERMAL_TRIP_PASSIVE; + if (trip == obj->crit_trip_id) + *type = THERMAL_TRIP_CRITICAL; + else + *type = THERMAL_TRIP_PASSIVE; return 0; } @@ -155,6 +171,34 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event) } } +static int sys_get_trip_crt(struct acpi_device *device, unsigned long *temp) +{ + unsigned long long crt; + acpi_status status; + + status = acpi_evaluate_integer(device->handle, "_CRT", NULL, &crt); + if (ACPI_FAILURE(status)) + return -EIO; + + *temp = DECI_KELVIN_TO_MILLI_CELSIUS(crt, KELVIN_OFFSET); + + return 0; +} + +static int sys_get_trip_psv(struct acpi_device *device, unsigned long *temp) +{ + unsigned long long psv; + acpi_status status; + + status = acpi_evaluate_integer(device->handle, "_PSV", NULL, &psv); + if (ACPI_FAILURE(status)) + return -EIO; + + *temp = DECI_KELVIN_TO_MILLI_CELSIUS(psv, KELVIN_OFFSET); + + return 0; +} + static int acpi_int3403_add(struct acpi_device *device) { int result = 0; @@ -194,6 +238,15 @@ static int acpi_int3403_add(struct acpi_device *device) return -ENOMEM; trip_mask = BIT(trip_cnt) - 1; } + + obj->psv_trip_id = -1; + if (!sys_get_trip_psv(device, &obj->psv_temp)) + obj->psv_trip_id = trip_cnt++; + + obj->crit_trip_id = -1; + if (!sys_get_trip_crt(device, &obj->crit_temp)) + obj->crit_trip_id = trip_cnt++; + obj->tzone = thermal_zone_device_register(acpi_device_bid(device), trip_cnt, trip_mask, device, &tzone_ops, NULL, 0, 0);