From 5c9d6ac23170e672101bce965a8180af24c40adb Mon Sep 17 00:00:00 2001 From: Wei Ni Date: Thu, 21 Feb 2019 18:18:43 +0800 Subject: thermal: tegra: add set_trips functionality Implement set_trips ops to set passive trip points. Signed-off-by: Wei Ni Signed-off-by: Eduardo Valentin --- drivers/thermal/tegra/soctherm.c | 64 ++++++++++++++++++++++++++++++- drivers/thermal/tegra/soctherm.h | 10 +++++ drivers/thermal/tegra/tegra124-soctherm.c | 7 +++- drivers/thermal/tegra/tegra132-soctherm.c | 7 +++- drivers/thermal/tegra/tegra210-soctherm.c | 7 +++- 5 files changed, 90 insertions(+), 5 deletions(-) diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 6301b9e160e0..9e66ea730098 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c @@ -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; diff --git a/drivers/thermal/tegra/soctherm.h b/drivers/thermal/tegra/soctherm.h index c05c7e37e968..70501e73d586 100644 --- a/drivers/thermal/tegra/soctherm.h +++ b/drivers/thermal/tegra/soctherm.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. * @@ -29,6 +30,14 @@ #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; diff --git a/drivers/thermal/tegra/tegra124-soctherm.c b/drivers/thermal/tegra/tegra124-soctherm.c index 36768630f78c..20ad27f4d1a1 100644 --- a/drivers/thermal/tegra/tegra124-soctherm.c +++ b/drivers/thermal/tegra/tegra124-soctherm.c @@ -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, diff --git a/drivers/thermal/tegra/tegra132-soctherm.c b/drivers/thermal/tegra/tegra132-soctherm.c index 97fa30501eb1..b76308fdad9e 100644 --- a/drivers/thermal/tegra/tegra132-soctherm.c +++ b/drivers/thermal/tegra/tegra132-soctherm.c @@ -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, diff --git a/drivers/thermal/tegra/tegra210-soctherm.c b/drivers/thermal/tegra/tegra210-soctherm.c index 0a0c3cec7134..d31b50050faa 100644 --- a/drivers/thermal/tegra/tegra210-soctherm.c +++ b/drivers/thermal/tegra/tegra210-soctherm.c @@ -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, -- cgit v1.2.3