aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches-4.9/0063-2-tsens-support-configurable-interrupts.patch
diff options
context:
space:
mode:
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.patch474
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);
+ };
+
+ /**