thermal: tegra: add set_trips functionality
authorWei Ni <wni@nvidia.com>
Thu, 21 Feb 2019 10:18:43 +0000 (18:18 +0800)
committerEduardo Valentin <edubezval@gmail.com>
Tue, 14 May 2019 03:35:33 +0000 (20:35 -0700)
Implement set_trips ops to set passive trip points.

Signed-off-by: Wei Ni <wni@nvidia.com>
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
drivers/thermal/tegra/soctherm.c
drivers/thermal/tegra/soctherm.h
drivers/thermal/tegra/tegra124-soctherm.c
drivers/thermal/tegra/tegra132-soctherm.c
drivers/thermal/tegra/tegra210-soctherm.c

index 6301b9e160e015dd74b84ba066f76fb984268146..9e66ea730098c2b2adc936eba480c07988f35390 100644 (file)
@@ -87,8 +87,6 @@
 #define THERMCTL_LVL0_DN_STATS                 0x14
 
 #define THERMCTL_INTR_STATUS                   0x84
-#define THERMCTL_INTR_ENABLE                   0x88
-#define THERMCTL_INTR_DISABLE                  0x8c
 
 #define TH_INTR_MD0_MASK                       BIT(25)
 #define TH_INTR_MU0_MASK                       BIT(24)
@@ -265,6 +263,8 @@ struct tegra_soctherm {
        struct soctherm_throt_cfg throt_cfgs[THROTTLE_SIZE];
 
        struct dentry *debugfs_dir;
+
+       struct mutex thermctl_lock;
 };
 
 /**
@@ -573,10 +573,60 @@ static int tegra_thermctl_get_trend(void *data, int trip,
        return 0;
 }
 
+static void thermal_irq_enable(struct tegra_thermctl_zone *zn)
+{
+       u32 r;
+
+       /* multiple zones could be handling and setting trips at once */
+       mutex_lock(&zn->ts->thermctl_lock);
+       r = readl(zn->ts->regs + THERMCTL_INTR_ENABLE);
+       r = REG_SET_MASK(r, zn->sg->thermctl_isr_mask, TH_INTR_UP_DN_EN);
+       writel(r, zn->ts->regs + THERMCTL_INTR_ENABLE);
+       mutex_unlock(&zn->ts->thermctl_lock);
+}
+
+static void thermal_irq_disable(struct tegra_thermctl_zone *zn)
+{
+       u32 r;
+
+       /* multiple zones could be handling and setting trips at once */
+       mutex_lock(&zn->ts->thermctl_lock);
+       r = readl(zn->ts->regs + THERMCTL_INTR_DISABLE);
+       r = REG_SET_MASK(r, zn->sg->thermctl_isr_mask, 0);
+       writel(r, zn->ts->regs + THERMCTL_INTR_DISABLE);
+       mutex_unlock(&zn->ts->thermctl_lock);
+}
+
+static int tegra_thermctl_set_trips(void *data, int lo, int hi)
+{
+       struct tegra_thermctl_zone *zone = data;
+       u32 r;
+
+       thermal_irq_disable(zone);
+
+       r = readl(zone->ts->regs + zone->sg->thermctl_lvl0_offset);
+       r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 0);
+       writel(r, zone->ts->regs + zone->sg->thermctl_lvl0_offset);
+
+       lo = enforce_temp_range(zone->dev, lo) / zone->ts->soc->thresh_grain;
+       hi = enforce_temp_range(zone->dev, hi) / zone->ts->soc->thresh_grain;
+       dev_dbg(zone->dev, "%s hi:%d, lo:%d\n", __func__, hi, lo);
+
+       r = REG_SET_MASK(r, zone->sg->thermctl_lvl0_up_thresh_mask, hi);
+       r = REG_SET_MASK(r, zone->sg->thermctl_lvl0_dn_thresh_mask, lo);
+       r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 1);
+       writel(r, zone->ts->regs + zone->sg->thermctl_lvl0_offset);
+
+       thermal_irq_enable(zone);
+
+       return 0;
+}
+
 static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = {
        .get_temp = tegra_thermctl_get_temp,
        .set_trip_temp = tegra_thermctl_set_trip_temp,
        .get_trend = tegra_thermctl_get_trend,
+       .set_trips = tegra_thermctl_set_trips,
 };
 
 static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp)
@@ -693,6 +743,15 @@ static irqreturn_t soctherm_thermal_isr(int irq, void *dev_id)
        struct tegra_soctherm *ts = dev_id;
        u32 r;
 
+       /* Case for no lock:
+        * Although interrupts are enabled in set_trips, there is still no need
+        * to lock here because the interrupts are disabled before programming
+        * new trip points. Hence there cant be a interrupt on the same sensor.
+        * An interrupt can however occur on a sensor while trips are being
+        * programmed on a different one. This beign a LEVEL interrupt won't
+        * cause a new interrupt but this is taken care of by the re-reading of
+        * the STATUS register in the thread function.
+        */
        r = readl(ts->regs + THERMCTL_INTR_STATUS);
        writel(r, ts->regs + THERMCTL_INTR_DISABLE);
 
@@ -1545,6 +1604,7 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
        if (!tegra)
                return -ENOMEM;
 
+       mutex_init(&tegra->thermctl_lock);
        dev_set_drvdata(&pdev->dev, tegra);
 
        tegra->soc = soc;
index c05c7e37e9684c68e78139ddca26cff493afb227..70501e73d586230d3caca8dea0966afd7f23142a 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
  *
 #define THERMCTL_THERMTRIP_CTL                 0x80
 /* BITs are defined in device file */
 
+#define THERMCTL_INTR_ENABLE                   0x88
+#define THERMCTL_INTR_DISABLE                  0x8c
+#define TH_INTR_UP_DN_EN                       0x3
+#define THERM_IRQ_MEM_MASK                     (TH_INTR_UP_DN_EN << 24)
+#define THERM_IRQ_GPU_MASK                     (TH_INTR_UP_DN_EN << 16)
+#define THERM_IRQ_CPU_MASK                     (TH_INTR_UP_DN_EN << 8)
+#define THERM_IRQ_TSENSE_MASK                  (TH_INTR_UP_DN_EN << 0)
+
 #define SENSOR_PDIV                            0x1c0
 #define SENSOR_PDIV_CPU_MASK                   (0xf << 12)
 #define SENSOR_PDIV_GPU_MASK                   (0xf << 8)
@@ -70,6 +79,7 @@ struct tegra_tsensor_group {
        u32 thermtrip_enable_mask;
        u32 thermtrip_any_en_mask;
        u32 thermtrip_threshold_mask;
+       u32 thermctl_isr_mask;
        u16 thermctl_lvl0_offset;
        u32 thermctl_lvl0_up_thresh_mask;
        u32 thermctl_lvl0_dn_thresh_mask;
index 36768630f78c9f435a8961d74a3125dd6dec2a1f..20ad27f4d1a161d419a19f3406a494d08b31542d 100644 (file)
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2018, NVIDIA CORPORATION.  All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -55,6 +56,7 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_cpu = {
        .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA124_THERMTRIP_CPU_EN_MASK,
        .thermtrip_threshold_mask = TEGRA124_THERMTRIP_CPU_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_CPU_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
        .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -73,6 +75,7 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_gpu = {
        .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA124_THERMTRIP_GPU_EN_MASK,
        .thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_GPU_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
        .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -89,6 +92,7 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_pll = {
        .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA124_THERMTRIP_TSENSE_EN_MASK,
        .thermtrip_threshold_mask = TEGRA124_THERMTRIP_TSENSE_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_TSENSE_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
        .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -107,6 +111,7 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_mem = {
        .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA124_THERMTRIP_MEM_EN_MASK,
        .thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_MEM_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
        .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
index 97fa30501eb19eeec32c05c7365e4f7ab9a8af3f..b76308fdad9e26820261e0f62c56a357d1f576fb 100644 (file)
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2018, NVIDIA CORPORATION.  All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -55,6 +56,7 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_cpu = {
        .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA132_THERMTRIP_CPU_EN_MASK,
        .thermtrip_threshold_mask = TEGRA132_THERMTRIP_CPU_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_CPU_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
        .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -73,6 +75,7 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_gpu = {
        .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA132_THERMTRIP_GPU_EN_MASK,
        .thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_GPU_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
        .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -89,6 +92,7 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_pll = {
        .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA132_THERMTRIP_TSENSE_EN_MASK,
        .thermtrip_threshold_mask = TEGRA132_THERMTRIP_TSENSE_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_TSENSE_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
        .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -107,6 +111,7 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_mem = {
        .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA132_THERMTRIP_MEM_EN_MASK,
        .thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_MEM_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
        .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
index 0a0c3cec7134e1358276847c1ae17e065405cb24..d31b50050faa0d107d20d9e282f0accc72a3db45 100644 (file)
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2018, NVIDIA CORPORATION.  All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -56,6 +57,7 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_cpu = {
        .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA210_THERMTRIP_CPU_EN_MASK,
        .thermtrip_threshold_mask = TEGRA210_THERMTRIP_CPU_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_CPU_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
        .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -74,6 +76,7 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_gpu = {
        .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA210_THERMTRIP_GPU_EN_MASK,
        .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_GPU_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
        .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -90,6 +93,7 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_pll = {
        .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA210_THERMTRIP_TSENSE_EN_MASK,
        .thermtrip_threshold_mask = TEGRA210_THERMTRIP_TSENSE_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_TSENSE_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
        .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -108,6 +112,7 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_mem = {
        .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA210_THERMTRIP_MEM_EN_MASK,
        .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_MEM_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
        .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,