diff options
Diffstat (limited to 'target/linux/ipq806x/patches-4.9/0063-2-tsens-support-configurable-interrupts.patch')
-rw-r--r-- | target/linux/ipq806x/patches-4.9/0063-2-tsens-support-configurable-interrupts.patch | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/target/linux/ipq806x/patches-4.9/0063-2-tsens-support-configurable-interrupts.patch b/target/linux/ipq806x/patches-4.9/0063-2-tsens-support-configurable-interrupts.patch new file mode 100644 index 0000000000..de9a8f8169 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/0063-2-tsens-support-configurable-interrupts.patch @@ -0,0 +1,474 @@ +From 4e87400732c77765afae2ea89ed43837457aa604 Mon Sep 17 00:00:00 2001 +From: Rajith Cherian <rajith@codeaurora.org> +Date: Wed, 1 Feb 2017 19:00:26 +0530 +Subject: [PATCH] ipq8064: tsens: Support for configurable interrupts + +Provide support for adding configurable high and +configurable low trip temperatures. An interrupts is +also triggerred when these trip points are hit. The +interrupts can be activated or deactivated from sysfs. +This functionality is made available only if +CONFIG_THERMAL_WRITABLE_TRIPS is defined. + +Change-Id: Ib73f3f9459de4fffce7bb985a0312a88291f4934 +Signed-off-by: Rajith Cherian <rajith@codeaurora.org> +--- + .../devicetree/bindings/thermal/qcom-tsens.txt | 4 ++ + drivers/thermal/of-thermal.c | 63 ++++++++++++++++++---- + drivers/thermal/qcom/tsens.c | 43 ++++++++++++--- + drivers/thermal/qcom/tsens.h | 11 ++++ + drivers/thermal/thermal_core.c | 44 ++++++++++++++- + include/linux/thermal.h | 14 +++++ + 6 files changed, 162 insertions(+), 17 deletions(-) + +diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt +index f4a76f6..7c0a6a7 100644 +--- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt ++++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt +@@ -12,11 +12,15 @@ Required properties: + - Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify + nvmem cells + ++Optional properties: ++- interrupts: Interrupt which gets triggered when threshold is hit ++ + Example: + tsens: thermal-sensor@900000 { + compatible = "qcom,msm8916-tsens"; + reg = <0x4a8000 0x2000>; + nvmem-cells = <&tsens_caldata>, <&tsens_calsel>; + nvmem-cell-names = "caldata", "calsel"; ++ interrupts = <0 178 0>; + #thermal-sensor-cells = <1>; + }; +diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c +index d04ec3b..d83697e 100644 +--- a/drivers/thermal/of-thermal.c ++++ b/drivers/thermal/of-thermal.c +@@ -95,7 +95,7 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz, + { + struct __thermal_zone *data = tz->devdata; + +- if (!data->ops->get_temp) ++ if (!data->ops->get_temp || (data->mode == THERMAL_DEVICE_DISABLED)) + return -EINVAL; + + return data->ops->get_temp(data->sensor_data, temp); +@@ -106,7 +106,8 @@ static int of_thermal_set_trips(struct thermal_zone_device *tz, + { + struct __thermal_zone *data = tz->devdata; + +- if (!data->ops || !data->ops->set_trips) ++ if (!data->ops || !data->ops->set_trips ++ || (data->mode == THERMAL_DEVICE_DISABLED)) + return -EINVAL; + + return data->ops->set_trips(data->sensor_data, low, high); +@@ -192,6 +193,9 @@ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz, + { + struct __thermal_zone *data = tz->devdata; + ++ if (data->mode == THERMAL_DEVICE_DISABLED) ++ return -EINVAL; ++ + return data->ops->set_emul_temp(data->sensor_data, temp); + } + +@@ -200,7 +204,7 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip, + { + struct __thermal_zone *data = tz->devdata; + +- if (!data->ops->get_trend) ++ if (!data->ops->get_trend || (data->mode == THERMAL_DEVICE_DISABLED)) + return -EINVAL; + + return data->ops->get_trend(data->sensor_data, trip, trend); +@@ -286,7 +290,9 @@ static int of_thermal_set_mode(struct thermal_zone_device *tz, + mutex_unlock(&tz->lock); + + data->mode = mode; +- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); ++ ++ if (mode == THERMAL_DEVICE_ENABLED) ++ thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); + + return 0; + } +@@ -296,7 +302,8 @@ static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip, + { + struct __thermal_zone *data = tz->devdata; + +- if (trip >= data->ntrips || trip < 0) ++ if (trip >= data->ntrips || trip < 0 ++ || (data->mode == THERMAL_DEVICE_DISABLED)) + return -EDOM; + + *type = data->trips[trip].type; +@@ -304,12 +311,39 @@ static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip, + return 0; + } + ++static int of_thermal_activate_trip_type(struct thermal_zone_device *tz, ++ int trip, enum thermal_trip_activation_mode mode) ++{ ++ struct __thermal_zone *data = tz->devdata; ++ ++ if (trip >= data->ntrips || trip < 0 ++ || (data->mode == THERMAL_DEVICE_DISABLED)) ++ return -EDOM; ++ ++ /* ++ * The configurable_hi and configurable_lo trip points can be ++ * activated and deactivated. ++ */ ++ ++ if (data->ops->set_trip_activate) { ++ int ret; ++ ++ ret = data->ops->set_trip_activate(data->sensor_data, ++ trip, mode); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ + static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip, + int *temp) + { + struct __thermal_zone *data = tz->devdata; + +- if (trip >= data->ntrips || trip < 0) ++ if (trip >= data->ntrips || trip < 0 ++ || (data->mode == THERMAL_DEVICE_DISABLED)) + return -EDOM; + + *temp = data->trips[trip].temperature; +@@ -322,7 +356,8 @@ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip, + { + struct __thermal_zone *data = tz->devdata; + +- if (trip >= data->ntrips || trip < 0) ++ if (trip >= data->ntrips || trip < 0 ++ || (data->mode == THERMAL_DEVICE_DISABLED)) + return -EDOM; + + if (data->ops->set_trip_temp) { +@@ -344,7 +379,8 @@ static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip, + { + struct __thermal_zone *data = tz->devdata; + +- if (trip >= data->ntrips || trip < 0) ++ if (trip >= data->ntrips || trip < 0 ++ || (data->mode == THERMAL_DEVICE_DISABLED)) + return -EDOM; + + *hyst = data->trips[trip].hysteresis; +@@ -357,7 +393,8 @@ static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip, + { + struct __thermal_zone *data = tz->devdata; + +- if (trip >= data->ntrips || trip < 0) ++ if (trip >= data->ntrips || trip < 0 ++ || (data->mode == THERMAL_DEVICE_DISABLED)) + return -EDOM; + + /* thermal framework should take care of data->mask & (1 << trip) */ +@@ -432,6 +469,9 @@ thermal_zone_of_add_sensor(struct device_node *zone, + if (ops->set_emul_temp) + tzd->ops->set_emul_temp = of_thermal_set_emul_temp; + ++ if (ops->set_trip_activate) ++ tzd->ops->set_trip_activate = of_thermal_activate_trip_type; ++ + mutex_unlock(&tzd->lock); + + return tzd; +@@ -726,7 +766,10 @@ static const char * const trip_types[] = { + [THERMAL_TRIP_ACTIVE] = "active", + [THERMAL_TRIP_PASSIVE] = "passive", + [THERMAL_TRIP_HOT] = "hot", +- [THERMAL_TRIP_CRITICAL] = "critical", ++ [THERMAL_TRIP_CRITICAL] = "critical_high", ++ [THERMAL_TRIP_CONFIGURABLE_HI] = "configurable_hi", ++ [THERMAL_TRIP_CONFIGURABLE_LOW] = "configurable_lo", ++ [THERMAL_TRIP_CRITICAL_LOW] = "critical_low", + }; + + /** +diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c +index 2d25593..ac68af3 100644 +--- a/drivers/thermal/qcom/tsens.c ++++ b/drivers/thermal/qcom/tsens.c +@@ -31,7 +31,7 @@ static int tsens_get_temp(void *data, int *temp) + + static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend) + { +- const struct tsens_sensor *s = p; ++ struct tsens_sensor *s = p; + struct tsens_device *tmdev = s->tmdev; + + if (tmdev->ops->get_trend) +@@ -40,9 +40,10 @@ static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend) + return -ENOTSUPP; + } + +-static int __maybe_unused tsens_suspend(struct device *dev) ++static int __maybe_unused tsens_suspend(void *data) + { +- struct tsens_device *tmdev = dev_get_drvdata(dev); ++ struct tsens_sensor *s = data; ++ struct tsens_device *tmdev = s->tmdev; + + if (tmdev->ops && tmdev->ops->suspend) + return tmdev->ops->suspend(tmdev); +@@ -50,9 +51,10 @@ static int __maybe_unused tsens_suspend(struct device *dev) + return 0; + } + +-static int __maybe_unused tsens_resume(struct device *dev) ++static int __maybe_unused tsens_resume(void *data) + { +- struct tsens_device *tmdev = dev_get_drvdata(dev); ++ struct tsens_sensor *s = data; ++ struct tsens_device *tmdev = s->tmdev; + + if (tmdev->ops && tmdev->ops->resume) + return tmdev->ops->resume(tmdev); +@@ -60,6 +62,30 @@ static int __maybe_unused tsens_resume(struct device *dev) + return 0; + } + ++static int __maybe_unused tsens_set_trip_temp(void *data, int trip, int temp) ++{ ++ struct tsens_sensor *s = data; ++ struct tsens_device *tmdev = s->tmdev; ++ ++ if (tmdev->ops && tmdev->ops->set_trip_temp) ++ return tmdev->ops->set_trip_temp(s, trip, temp); ++ ++ return 0; ++} ++ ++static int __maybe_unused tsens_activate_trip_type(void *data, int trip, ++ enum thermal_trip_activation_mode mode) ++{ ++ struct tsens_sensor *s = data; ++ struct tsens_device *tmdev = s->tmdev; ++ ++ if (tmdev->ops && tmdev->ops->set_trip_activate) ++ return tmdev->ops->set_trip_activate(s, trip, mode); ++ ++ return 0; ++} ++ ++ + static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume); + + static const struct of_device_id tsens_table[] = { +@@ -83,6 +109,8 @@ MODULE_DEVICE_TABLE(of, tsens_table); + static const struct thermal_zone_of_device_ops tsens_of_ops = { + .get_temp = tsens_get_temp, + .get_trend = tsens_get_trend, ++ .set_trip_temp = tsens_set_trip_temp, ++ .set_trip_activate = tsens_activate_trip_type, + }; + + static int tsens_register(struct tsens_device *tmdev) +@@ -131,7 +159,7 @@ static int tsens_probe(struct platform_device *pdev) + if (id) + data = id->data; + else +- data = &data_8960; ++ return -EINVAL; + + if (data->num_sensors <= 0) { + dev_err(dev, "invalid number of sensors\n"); +@@ -146,6 +174,9 @@ static int tsens_probe(struct platform_device *pdev) + tmdev->dev = dev; + tmdev->num_sensors = data->num_sensors; + tmdev->ops = data->ops; ++ ++ tmdev->tsens_irq = platform_get_irq(pdev, 0); ++ + for (i = 0; i < tmdev->num_sensors; i++) { + if (data->hw_ids) + tmdev->sensor[i].hw_id = data->hw_ids[i]; +diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h +index 31279a2..54bbdc0 100644 +--- a/drivers/thermal/qcom/tsens.h ++++ b/drivers/thermal/qcom/tsens.h +@@ -24,9 +24,12 @@ struct tsens_device; + struct tsens_sensor { + struct tsens_device *tmdev; + struct thermal_zone_device *tzd; ++ struct work_struct notify_work; + int offset; + int id; + int hw_id; ++ int calib_data; ++ int calib_data_backup; + int slope; + u32 status; + }; +@@ -41,6 +44,9 @@ struct tsens_sensor { + * @suspend: Function to suspend the tsens device + * @resume: Function to resume the tsens device + * @get_trend: Function to get the thermal/temp trend ++ * @set_trip_temp: Function to set trip temp ++ * @get_trip_temp: Function to get trip temp ++ * @set_trip_activate: Function to activate trip points + */ + struct tsens_ops { + /* mandatory callbacks */ +@@ -53,6 +59,9 @@ struct tsens_ops { + int (*suspend)(struct tsens_device *); + int (*resume)(struct tsens_device *); + int (*get_trend)(struct tsens_device *, int, enum thermal_trend *); ++ int (*set_trip_temp)(void *, int, int); ++ int (*set_trip_activate)(void *, int, ++ enum thermal_trip_activation_mode); + }; + + /** +@@ -76,11 +85,13 @@ struct tsens_context { + struct tsens_device { + struct device *dev; + u32 num_sensors; ++ u32 tsens_irq; + struct regmap *map; + struct regmap_field *status_field; + struct tsens_context ctx; + bool trdy; + const struct tsens_ops *ops; ++ struct work_struct tsens_work; + struct tsens_sensor sensor[0]; + }; + +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index 226b0b4..20bd624 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -732,12 +732,48 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr, + return sprintf(buf, "passive\n"); + case THERMAL_TRIP_ACTIVE: + return sprintf(buf, "active\n"); ++ case THERMAL_TRIP_CONFIGURABLE_HI: ++ return sprintf(buf, "configurable_hi\n"); ++ case THERMAL_TRIP_CONFIGURABLE_LOW: ++ return sprintf(buf, "configurable_low\n"); ++ case THERMAL_TRIP_CRITICAL_LOW: ++ return sprintf(buf, "critical_low\n"); + default: + return sprintf(buf, "unknown\n"); + } + } + + static ssize_t ++trip_point_type_activate(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct thermal_zone_device *tz = to_thermal_zone(dev); ++ int trip, ret; ++ char *enabled = "enabled"; ++ char *disabled = "disabled"; ++ ++ if (!tz->ops->set_trip_activate) ++ return -EPERM; ++ ++ if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) ++ return -EINVAL; ++ ++ if (!strncmp(buf, enabled, strlen(enabled))) ++ ret = tz->ops->set_trip_activate(tz, trip, ++ THERMAL_TRIP_ACTIVATION_ENABLED); ++ else if (!strncmp(buf, disabled, strlen(disabled))) ++ ret = tz->ops->set_trip_activate(tz, trip, ++ THERMAL_TRIP_ACTIVATION_DISABLED); ++ else ++ ret = -EINVAL; ++ ++ if (ret) ++ return ret; ++ ++ return count; ++} ++ ++static ssize_t + trip_point_temp_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) + { +@@ -1321,7 +1357,7 @@ thermal_cooling_device_weight_store(struct device *dev, + */ + int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, + int trip, +- struct thermal_cooling_device *cdev, ++ struct thermal_cooling_device *cdev, + unsigned long upper, unsigned long lower, + unsigned int weight) + { +@@ -1772,6 +1808,12 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask) + tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO; + tz->trip_type_attrs[indx].attr.show = trip_point_type_show; + ++ if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS)) { ++ tz->trip_type_attrs[indx].attr.store ++ = trip_point_type_activate; ++ tz->trip_type_attrs[indx].attr.attr.mode |= S_IWUSR; ++ } ++ + device_create_file(&tz->device, + &tz->trip_type_attrs[indx].attr); + +diff --git a/include/linux/thermal.h b/include/linux/thermal.h +index 511182a..510a087 100644 +--- a/include/linux/thermal.h ++++ b/include/linux/thermal.h +@@ -77,11 +77,19 @@ enum thermal_device_mode { + THERMAL_DEVICE_ENABLED, + }; + ++enum thermal_trip_activation_mode { ++ THERMAL_TRIP_ACTIVATION_DISABLED = 0, ++ THERMAL_TRIP_ACTIVATION_ENABLED, ++}; ++ + enum thermal_trip_type { + THERMAL_TRIP_ACTIVE = 0, + THERMAL_TRIP_PASSIVE, + THERMAL_TRIP_HOT, + THERMAL_TRIP_CRITICAL, ++ THERMAL_TRIP_CONFIGURABLE_HI, ++ THERMAL_TRIP_CONFIGURABLE_LOW, ++ THERMAL_TRIP_CRITICAL_LOW, + }; + + enum thermal_trend { +@@ -118,6 +126,8 @@ struct thermal_zone_device_ops { + enum thermal_trip_type *); + int (*get_trip_temp) (struct thermal_zone_device *, int, int *); + int (*set_trip_temp) (struct thermal_zone_device *, int, int); ++ int (*set_trip_activate) (struct thermal_zone_device *, int, ++ enum thermal_trip_activation_mode); + int (*get_trip_hyst) (struct thermal_zone_device *, int, int *); + int (*set_trip_hyst) (struct thermal_zone_device *, int, int); + int (*get_crit_temp) (struct thermal_zone_device *, int *); +@@ -360,6 +370,8 @@ struct thermal_genl_event { + * temperature. + * @set_trip_temp: a pointer to a function that sets the trip temperature on + * hardware. ++ * @activate_trip_type: a pointer to a function to enable/disable trip ++ * temperature interrupts + */ + struct thermal_zone_of_device_ops { + int (*get_temp)(void *, int *); +@@ -367,6 +379,8 @@ struct thermal_zone_of_device_ops { + int (*set_trips)(void *, int, int); + int (*set_emul_temp)(void *, int); + int (*set_trip_temp)(void *, int, int); ++ int (*set_trip_activate)(void *, int, ++ enum thermal_trip_activation_mode); + }; + + /** |