]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
thermal: tegra: support hw and sw shutdown
authorSrikar Srimath Tirumala <srikars@nvidia.com>
Wed, 5 Apr 2017 17:29:06 +0000 (10:29 -0700)
committermobile promotions <svcmobile_promotions@nvidia.com>
Mon, 17 Apr 2017 19:29:59 +0000 (12:29 -0700)
Currently the critical trip points in thermal framework are the only
way to specify a temperature at which HW should shutdown. This is
insufficient for certain platforms which would want an orderly
software shutdown in addition to HW shutdown.

This change allows soctherm DT to specify thermtrip temperatures so
that critical trip points framework can be used for doing software
shutdown.

Bug 200233003

Change-Id: I62cac336b87a6a4cce3c1a6f2d2cb3edcb8102b3
Signed-off-by: Srikar Srimath Tirumala <srikars@nvidia.com>
Reviewed-on: http://git-master/r/1456368
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
(cherry picked from commit 043c82eeae796b2bea922af998c9639042fea800)
Reviewed-on: http://git-master/r/1462734
GVS: Gerrit_Virtual_Submit
Reviewed-by: Jon Mayo <jmayo@nvidia.com>
Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt
drivers/thermal/tegra/soctherm.c
drivers/thermal/tegra/soctherm.h
drivers/thermal/tegra/tegra210-soctherm.c

index afc736ffd839b4b0a8f8b7ac352a427452b7a682..a26c128e49ea15cbe4e073e9c3bcc61470876d0c 100644 (file)
@@ -42,6 +42,12 @@ Required properties :
     soctherm hardware after offsetting has been applied.
   Offsets are disabled if one or more elements of a triplet are missing or
   incorrect.
+- nvidia, thermtrips : When present, this property specifies the temperature at
+  which the soctherm hardware will assert the thermal trigger signal to the
+  Power Management IC, which can be configured to reset or shutdown the device.
+  It is an array of pairs where each pair represents a tsensor id followed by a
+  temperature in milli Celcius. In the absence of this property the critical
+  trip point will be used for thermtrip temperature.
 - throttle-cfgs: A sub-node which is a container of configuration for each
     hardware throttle events. These events can be set as cooling devices.
   * throttle events: Sub-nodes must be named as "light", "heavy", "oc1" - "oc5".
@@ -90,9 +96,10 @@ Required properties :
         is 0.
 
 Note:
-- the "critical" type trip points will be set to SOC_THERM hardware as the
-shut down temperature. Once the temperature of this thermal zone is higher
-than it, the system will be shutdown or reset by hardware.
+- the "critical" type trip points will be used to set the temperature at which
+the SOC_THERM hardware will assert a thermal trigger if the thermtrips property
+is missing. When the thermtrips property is present the breach of a critical
+trip point is reported back to the thermal framework.
 - the "hot" type trip points will be set to SOC_THERM hardware as the throttle
 temperature. Once the the temperature of this thermal zone is higher
 than it, it will trigger the HW throttle event.
index 12b75528785c99793106ac4daa6e3d04178412f1..485e5ebeb23d576f5a53b1d4e72ab5b2f7850cfd 100644 (file)
@@ -552,6 +552,21 @@ find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name)
        return NULL;
 }
 
+static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id)
+{
+       int i, temp = min_low_temp;
+       struct tsensor_group_thermtrips *tt = ts->soc->thermtrips;
+
+       if (tt) {
+               for (i = 0; i < ts->soc->num_ttgs; i++) {
+                       if (tt[i].id == id)
+                               return tt[i].temp;
+               }
+       }
+
+       return temp;
+}
+
 static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
 {
        struct tegra_thermctl_zone *zone = data;
@@ -570,7 +585,11 @@ static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
                return ret;
 
        if (type == THERMAL_TRIP_CRITICAL) {
-               return thermtrip_program(dev, sg, temp);
+               /* dont allow if soctherm has thermtrips property in DT */
+               if (min_low_temp == tsensor_group_thermtrip_get(ts, sg->id))
+                       return thermtrip_program(dev, sg, temp);
+               else
+                       return 0;
        } else if (type == THERMAL_TRIP_HOT) {
                int i;
 
@@ -736,28 +755,22 @@ static int tegra_soctherm_set_hwtrips(struct device *dev,
 {
        struct tegra_soctherm *ts = dev_get_drvdata(dev);
        struct soctherm_throt_cfg *stc;
-       int i, trip, temperature;
-       int ret;
+       int i, trip, temperature, ret;
 
-       ret = tz->ops->get_crit_temp(tz, &temperature);
-       if (ret) {
-               dev_info(dev, "thermtrip: %s: missing critical temperature\n",
-                        sg->name);
-               goto set_throttle;
-       }
+       temperature = tsensor_group_thermtrip_get(ts, sg->id);
+       if (min_low_temp == temperature)
+               if (tz->ops->get_crit_temp(tz, &temperature))
+                       temperature = max_high_temp;
+
+       dev_info(dev, "thermtrip: will shut down when %s reaches %d mC\n",
+                sg->name, temperature);
 
        ret = thermtrip_program(dev, sg, temperature);
        if (ret) {
-               dev_err(dev, "thermtrip: %s: error during enable\n",
-                       sg->name);
+               dev_err(dev, "thermtrip: %s: error during enable\n", sg->name);
                return ret;
        }
 
-       dev_info(dev,
-                "thermtrip: will shut down when %s reaches %d mC\n",
-                sg->name, temperature);
-
-set_throttle:
        if (ts->soc->use_ccroc)
                return 0;
 
@@ -1843,6 +1856,44 @@ static struct thermal_cooling_device_ops throt_cooling_ops = {
        .set_cur_state = throt_set_cdev_state,
 };
 
+static int soctherm_thermtrips_parse(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct tegra_soctherm *ts = dev_get_drvdata(dev);
+       struct tsensor_group_thermtrips *tt = ts->soc->thermtrips;
+       const int max_num_prop = ts->soc->num_ttgs * 2;
+       int i = 0, j = 0, r, n;
+       u32 off[max_num_prop];
+
+       if (!tt)
+               return 0;
+
+       n = of_property_count_u32_elems(dev->of_node, "nvidia,thermtrips");
+       if (n <= 0) {
+               dev_err(dev, "invalid dt prop: thermtrips:%d\n", n);
+               return n;
+       }
+
+       n = min(max_num_prop, n);
+       r = of_property_read_u32_array(dev->of_node, "nvidia,thermtrips",
+                                       off, n);
+       if (r) {
+               dev_err(dev, "invalid num ele: thermtrips:%d\n", r);
+               return r;
+       }
+
+       for (j = 0; j < n; j = j + 2) {
+               if (off[j] >= TEGRA124_SOCTHERM_SENSOR_NUM)
+                       continue;
+
+               tt[i].id = off[j];
+               tt[i].temp = off[j+1];
+               i++;
+       }
+
+       return 0;
+}
+
 static int soctherm_hw_pllx_offsets_parse(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -2426,6 +2477,7 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
        if (!tegra->soc->use_ccroc)
                soctherm_init_hw_throt_cdev(pdev);
 
+       soctherm_thermtrips_parse(pdev);
        soctherm_hw_pllx_offsets_parse(pdev);
        soctherm_init(pdev);
        soctherm_debug_init(pdev);
index 8f49214d427c39ba7cc1133d8757d768248fcbfa..c670ea8711dc95a596e15b140b46dde3fa3363f0 100644 (file)
@@ -117,6 +117,11 @@ struct tsensor_group_offsets {
        const struct tegra_tsensor_group *ttg;
 };
 
+struct tsensor_group_thermtrips {
+       u8 id;
+       u32 temp;
+};
+
 struct tegra_soctherm_soc {
        const struct tegra_tsensor *tsensors;
        const unsigned int num_tsensors;
@@ -127,6 +132,7 @@ struct tegra_soctherm_soc {
        const int thresh_grain;
        const unsigned int bptt;
        const bool use_ccroc;
+       struct tsensor_group_thermtrips *thermtrips;
 };
 
 #ifdef CONFIG_ARCH_TEGRA_124_SOC
index 0a79a39cbd8fcd936066893ca6a37b79e80eeb33..bad4fe93b9d5dfd8e28e0c077b3af27f11a07939 100644 (file)
@@ -136,6 +136,13 @@ struct tsensor_group_offsets tegra210_tsensor_group_offsets[] = {
        {.ttg = &tegra210_tsensor_group_pll,},
 };
 
+struct tsensor_group_thermtrips tegra210_tsensor_thermtrips[] = {
+       {.id = TEGRA124_SOCTHERM_SENSOR_NUM},
+       {.id = TEGRA124_SOCTHERM_SENSOR_NUM},
+       {.id = TEGRA124_SOCTHERM_SENSOR_NUM},
+       {.id = TEGRA124_SOCTHERM_SENSOR_NUM},
+};
+
 static const struct tegra_tsensor tegra210_tsensors[] = {
        {
                .name = "cpu0",
@@ -245,4 +252,5 @@ const struct tegra_soctherm_soc tegra210_soctherm = {
        .thresh_grain = TEGRA210_THRESH_GRAIN,
        .bptt = TEGRA210_BPTT,
        .use_ccroc = false,
+       .thermtrips = tegra210_tsensor_thermtrips,
 };