brintos

brintos / linux-shallow public Read only

0
0
Text · 63.9 KiB · a023c94 Raw
2284 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2014 - 2018, NVIDIA CORPORATION.  All rights reserved.4 *5 * Author:6 *	Mikko Perttunen <mperttunen@nvidia.com>7 *8 * This software is licensed under the terms of the GNU General Public9 * License version 2, as published by the Free Software Foundation, and10 * may be copied, distributed, and modified under those terms.11 *12 * This program is distributed in the hope that it will be useful,13 * but WITHOUT ANY WARRANTY; without even the implied warranty of14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the15 * GNU General Public License for more details.16 *17 */18 19#include <linux/debugfs.h>20#include <linux/bitops.h>21#include <linux/clk.h>22#include <linux/delay.h>23#include <linux/err.h>24#include <linux/interrupt.h>25#include <linux/io.h>26#include <linux/irq.h>27#include <linux/irqdomain.h>28#include <linux/module.h>29#include <linux/of.h>30#include <linux/platform_device.h>31#include <linux/reset.h>32#include <linux/thermal.h>33 34#include <dt-bindings/thermal/tegra124-soctherm.h>35 36#include "../thermal_core.h"37#include "soctherm.h"38 39#define SENSOR_CONFIG0				040#define SENSOR_CONFIG0_STOP			BIT(0)41#define SENSOR_CONFIG0_CPTR_OVER		BIT(2)42#define SENSOR_CONFIG0_OVER			BIT(3)43#define SENSOR_CONFIG0_TCALC_OVER		BIT(4)44#define SENSOR_CONFIG0_TALL_MASK		(0xfffff << 8)45#define SENSOR_CONFIG0_TALL_SHIFT		846 47#define SENSOR_CONFIG1				448#define SENSOR_CONFIG1_TSAMPLE_MASK		0x3ff49#define SENSOR_CONFIG1_TSAMPLE_SHIFT		050#define SENSOR_CONFIG1_TIDDQ_EN_MASK		(0x3f << 15)51#define SENSOR_CONFIG1_TIDDQ_EN_SHIFT		1552#define SENSOR_CONFIG1_TEN_COUNT_MASK		(0x3f << 24)53#define SENSOR_CONFIG1_TEN_COUNT_SHIFT		2454#define SENSOR_CONFIG1_TEMP_ENABLE		BIT(31)55 56/*57 * SENSOR_CONFIG2 is defined in soctherm.h58 * because, it will be used by tegra_soctherm_fuse.c59 */60 61#define SENSOR_STATUS0				0xc62#define SENSOR_STATUS0_VALID_MASK		BIT(31)63#define SENSOR_STATUS0_CAPTURE_MASK		0xffff64 65#define SENSOR_STATUS1				0x1066#define SENSOR_STATUS1_TEMP_VALID_MASK		BIT(31)67#define SENSOR_STATUS1_TEMP_MASK		0xffff68 69#define READBACK_VALUE_MASK			0xff0070#define READBACK_VALUE_SHIFT			871#define READBACK_ADD_HALF			BIT(7)72#define READBACK_NEGATE				BIT(0)73 74/*75 * THERMCTL_LEVEL0_GROUP_CPU is defined in soctherm.h76 * because it will be used by tegraxxx_soctherm.c77 */78#define THERMCTL_LVL0_CPU0_EN_MASK		BIT(8)79#define THERMCTL_LVL0_CPU0_CPU_THROT_MASK	(0x3 << 5)80#define THERMCTL_LVL0_CPU0_CPU_THROT_LIGHT	0x181#define THERMCTL_LVL0_CPU0_CPU_THROT_HEAVY	0x282#define THERMCTL_LVL0_CPU0_GPU_THROT_MASK	(0x3 << 3)83#define THERMCTL_LVL0_CPU0_GPU_THROT_LIGHT	0x184#define THERMCTL_LVL0_CPU0_GPU_THROT_HEAVY	0x285#define THERMCTL_LVL0_CPU0_MEM_THROT_MASK	BIT(2)86#define THERMCTL_LVL0_CPU0_STATUS_MASK		0x387 88#define THERMCTL_LVL0_UP_STATS			0x1089#define THERMCTL_LVL0_DN_STATS			0x1490 91#define THERMCTL_INTR_STATUS			0x8492 93#define TH_INTR_MD0_MASK			BIT(25)94#define TH_INTR_MU0_MASK			BIT(24)95#define TH_INTR_GD0_MASK			BIT(17)96#define TH_INTR_GU0_MASK			BIT(16)97#define TH_INTR_CD0_MASK			BIT(9)98#define TH_INTR_CU0_MASK			BIT(8)99#define TH_INTR_PD0_MASK			BIT(1)100#define TH_INTR_PU0_MASK			BIT(0)101#define TH_INTR_IGNORE_MASK			0xFCFCFCFC102 103#define THERMCTL_STATS_CTL			0x94104#define STATS_CTL_CLR_DN			0x8105#define STATS_CTL_EN_DN				0x4106#define STATS_CTL_CLR_UP			0x2107#define STATS_CTL_EN_UP				0x1108 109#define OC1_CFG					0x310110#define OC1_CFG_LONG_LATENCY_MASK		BIT(6)111#define OC1_CFG_HW_RESTORE_MASK			BIT(5)112#define OC1_CFG_PWR_GOOD_MASK_MASK		BIT(4)113#define OC1_CFG_THROTTLE_MODE_MASK		(0x3 << 2)114#define OC1_CFG_ALARM_POLARITY_MASK		BIT(1)115#define OC1_CFG_EN_THROTTLE_MASK		BIT(0)116 117#define OC1_CNT_THRESHOLD			0x314118#define OC1_THROTTLE_PERIOD			0x318119#define OC1_ALARM_COUNT				0x31c120#define OC1_FILTER				0x320121#define OC1_STATS				0x3a8122 123#define OC_INTR_STATUS				0x39c124#define OC_INTR_ENABLE				0x3a0125#define OC_INTR_DISABLE				0x3a4126#define OC_STATS_CTL				0x3c4127#define OC_STATS_CTL_CLR_ALL			0x2128#define OC_STATS_CTL_EN_ALL			0x1129 130#define OC_INTR_OC1_MASK			BIT(0)131#define OC_INTR_OC2_MASK			BIT(1)132#define OC_INTR_OC3_MASK			BIT(2)133#define OC_INTR_OC4_MASK			BIT(3)134#define OC_INTR_OC5_MASK			BIT(4)135 136#define THROT_GLOBAL_CFG			0x400137#define THROT_GLOBAL_ENB_MASK			BIT(0)138 139#define CPU_PSKIP_STATUS			0x418140#define XPU_PSKIP_STATUS_M_MASK			(0xff << 12)141#define XPU_PSKIP_STATUS_N_MASK			(0xff << 4)142#define XPU_PSKIP_STATUS_SW_OVERRIDE_MASK	BIT(1)143#define XPU_PSKIP_STATUS_ENABLED_MASK		BIT(0)144 145#define THROT_PRIORITY_LOCK			0x424146#define THROT_PRIORITY_LOCK_PRIORITY_MASK	0xff147 148#define THROT_STATUS				0x428149#define THROT_STATUS_BREACH_MASK		BIT(12)150#define THROT_STATUS_STATE_MASK			(0xff << 4)151#define THROT_STATUS_ENABLED_MASK		BIT(0)152 153#define THROT_PSKIP_CTRL_LITE_CPU		0x430154#define THROT_PSKIP_CTRL_ENABLE_MASK            BIT(31)155#define THROT_PSKIP_CTRL_DIVIDEND_MASK          (0xff << 8)156#define THROT_PSKIP_CTRL_DIVISOR_MASK           0xff157#define THROT_PSKIP_CTRL_VECT_GPU_MASK          (0x7 << 16)158#define THROT_PSKIP_CTRL_VECT_CPU_MASK          (0x7 << 8)159#define THROT_PSKIP_CTRL_VECT2_CPU_MASK         0x7160 161#define THROT_VECT_NONE				0x0 /* 3'b000 */162#define THROT_VECT_LOW				0x1 /* 3'b001 */163#define THROT_VECT_MED				0x3 /* 3'b011 */164#define THROT_VECT_HIGH				0x7 /* 3'b111 */165 166#define THROT_PSKIP_RAMP_LITE_CPU		0x434167#define THROT_PSKIP_RAMP_SEQ_BYPASS_MODE_MASK	BIT(31)168#define THROT_PSKIP_RAMP_DURATION_MASK		(0xffff << 8)169#define THROT_PSKIP_RAMP_STEP_MASK		0xff170 171#define THROT_PRIORITY_LITE			0x444172#define THROT_PRIORITY_LITE_PRIO_MASK		0xff173 174#define THROT_DELAY_LITE			0x448175#define THROT_DELAY_LITE_DELAY_MASK		0xff176 177/* car register offsets needed for enabling HW throttling */178#define CAR_SUPER_CCLKG_DIVIDER			0x36c179#define CDIVG_USE_THERM_CONTROLS_MASK		BIT(30)180 181/* ccroc register offsets needed for enabling HW throttling for Tegra132 */182#define CCROC_SUPER_CCLKG_DIVIDER		0x024183 184#define CCROC_GLOBAL_CFG			0x148185 186#define CCROC_THROT_PSKIP_RAMP_CPU		0x150187#define CCROC_THROT_PSKIP_RAMP_SEQ_BYPASS_MODE_MASK	BIT(31)188#define CCROC_THROT_PSKIP_RAMP_DURATION_MASK	(0xffff << 8)189#define CCROC_THROT_PSKIP_RAMP_STEP_MASK	0xff190 191#define CCROC_THROT_PSKIP_CTRL_CPU		0x154192#define CCROC_THROT_PSKIP_CTRL_ENB_MASK		BIT(31)193#define CCROC_THROT_PSKIP_CTRL_DIVIDEND_MASK	(0xff << 8)194#define CCROC_THROT_PSKIP_CTRL_DIVISOR_MASK	0xff195 196/* get val from register(r) mask bits(m) */197#define REG_GET_MASK(r, m)	(((r) & (m)) >> (ffs(m) - 1))198/* set val(v) to mask bits(m) of register(r) */199#define REG_SET_MASK(r, m, v)	(((r) & ~(m)) | \200				 (((v) & (m >> (ffs(m) - 1))) << (ffs(m) - 1)))201 202/* get dividend from the depth */203#define THROT_DEPTH_DIVIDEND(depth)	((256 * (100 - (depth)) / 100) - 1)204 205/* gk20a nv_therm interface N:3 Mapping. Levels defined in tegra124-soctherm.h206 * level	vector207 * NONE		3'b000208 * LOW		3'b001209 * MED		3'b011210 * HIGH		3'b111211 */212#define THROT_LEVEL_TO_DEPTH(level)	((0x1 << (level)) - 1)213 214/* get THROT_PSKIP_xxx offset per LIGHT/HEAVY throt and CPU/GPU dev */215#define THROT_OFFSET			0x30216#define THROT_PSKIP_CTRL(throt, dev)	(THROT_PSKIP_CTRL_LITE_CPU + \217					(THROT_OFFSET * throt) + (8 * dev))218#define THROT_PSKIP_RAMP(throt, dev)	(THROT_PSKIP_RAMP_LITE_CPU + \219					(THROT_OFFSET * throt) + (8 * dev))220 221/* get THROT_xxx_CTRL offset per LIGHT/HEAVY throt */222#define THROT_PRIORITY_CTRL(throt)	(THROT_PRIORITY_LITE + \223					(THROT_OFFSET * throt))224#define THROT_DELAY_CTRL(throt)		(THROT_DELAY_LITE + \225					(THROT_OFFSET * throt))226 227#define ALARM_OFFSET			0x14228#define ALARM_CFG(throt)		(OC1_CFG + \229					(ALARM_OFFSET * (throt - THROTTLE_OC1)))230 231#define ALARM_CNT_THRESHOLD(throt)	(OC1_CNT_THRESHOLD + \232					(ALARM_OFFSET * (throt - THROTTLE_OC1)))233 234#define ALARM_THROTTLE_PERIOD(throt)	(OC1_THROTTLE_PERIOD + \235					(ALARM_OFFSET * (throt - THROTTLE_OC1)))236 237#define ALARM_ALARM_COUNT(throt)	(OC1_ALARM_COUNT + \238					(ALARM_OFFSET * (throt - THROTTLE_OC1)))239 240#define ALARM_FILTER(throt)		(OC1_FILTER + \241					(ALARM_OFFSET * (throt - THROTTLE_OC1)))242 243#define ALARM_STATS(throt)		(OC1_STATS + \244					(4 * (throt - THROTTLE_OC1)))245 246/* get CCROC_THROT_PSKIP_xxx offset per HIGH/MED/LOW vect*/247#define CCROC_THROT_OFFSET			0x0c248#define CCROC_THROT_PSKIP_CTRL_CPU_REG(vect)    (CCROC_THROT_PSKIP_CTRL_CPU + \249						(CCROC_THROT_OFFSET * vect))250#define CCROC_THROT_PSKIP_RAMP_CPU_REG(vect)    (CCROC_THROT_PSKIP_RAMP_CPU + \251						(CCROC_THROT_OFFSET * vect))252 253/* get THERMCTL_LEVELx offset per CPU/GPU/MEM/TSENSE rg and LEVEL0~3 lv */254#define THERMCTL_LVL_REGS_SIZE		0x20255#define THERMCTL_LVL_REG(rg, lv)	((rg) + ((lv) * THERMCTL_LVL_REGS_SIZE))256 257#define OC_THROTTLE_MODE_DISABLED	0258#define OC_THROTTLE_MODE_BRIEF		2259 260static const int min_low_temp = -127000;261static const int max_high_temp = 127000;262 263enum soctherm_throttle_id {264	THROTTLE_LIGHT = 0,265	THROTTLE_HEAVY,266	THROTTLE_OC1,267	THROTTLE_OC2,268	THROTTLE_OC3,269	THROTTLE_OC4,270	THROTTLE_OC5, /* OC5 is reserved */271	THROTTLE_SIZE,272};273 274enum soctherm_oc_irq_id {275	TEGRA_SOC_OC_IRQ_1,276	TEGRA_SOC_OC_IRQ_2,277	TEGRA_SOC_OC_IRQ_3,278	TEGRA_SOC_OC_IRQ_4,279	TEGRA_SOC_OC_IRQ_5,280	TEGRA_SOC_OC_IRQ_MAX,281};282 283enum soctherm_throttle_dev_id {284	THROTTLE_DEV_CPU = 0,285	THROTTLE_DEV_GPU,286	THROTTLE_DEV_SIZE,287};288 289static const char *const throt_names[] = {290	[THROTTLE_LIGHT] = "light",291	[THROTTLE_HEAVY] = "heavy",292	[THROTTLE_OC1]   = "oc1",293	[THROTTLE_OC2]   = "oc2",294	[THROTTLE_OC3]   = "oc3",295	[THROTTLE_OC4]   = "oc4",296	[THROTTLE_OC5]   = "oc5",297};298 299struct tegra_soctherm;300struct tegra_thermctl_zone {301	void __iomem *reg;302	struct device *dev;303	struct tegra_soctherm *ts;304	struct thermal_zone_device *tz;305	const struct tegra_tsensor_group *sg;306};307 308struct soctherm_oc_cfg {309	u32 active_low;310	u32 throt_period;311	u32 alarm_cnt_thresh;312	u32 alarm_filter;313	u32 mode;314	bool intr_en;315};316 317struct soctherm_throt_cfg {318	const char *name;319	unsigned int id;320	u8 priority;321	u8 cpu_throt_level;322	u32 cpu_throt_depth;323	u32 gpu_throt_level;324	struct soctherm_oc_cfg oc_cfg;325	struct thermal_cooling_device *cdev;326	bool init;327};328 329struct tegra_soctherm {330	struct reset_control *reset;331	struct clk *clock_tsensor;332	struct clk *clock_soctherm;333	void __iomem *regs;334	void __iomem *clk_regs;335	void __iomem *ccroc_regs;336 337	int thermal_irq;338	int edp_irq;339 340	u32 *calib;341	struct thermal_zone_device **thermctl_tzs;342	struct tegra_soctherm_soc *soc;343 344	struct soctherm_throt_cfg throt_cfgs[THROTTLE_SIZE];345 346	struct dentry *debugfs_dir;347 348	struct mutex thermctl_lock;349};350 351struct soctherm_oc_irq_chip_data {352	struct mutex		irq_lock; /* serialize OC IRQs */353	struct irq_chip		irq_chip;354	struct irq_domain	*domain;355	int			irq_enable;356};357 358static struct soctherm_oc_irq_chip_data soc_irq_cdata;359 360/**361 * ccroc_writel() - writes a value to a CCROC register362 * @ts: pointer to a struct tegra_soctherm363 * @value: the value to write364 * @reg: the register offset365 *366 * Writes @v to @reg.  No return value.367 */368static inline void ccroc_writel(struct tegra_soctherm *ts, u32 value, u32 reg)369{370	writel(value, (ts->ccroc_regs + reg));371}372 373/**374 * ccroc_readl() - reads specified register from CCROC IP block375 * @ts: pointer to a struct tegra_soctherm376 * @reg: register address to be read377 *378 * Return: the value of the register379 */380static inline u32 ccroc_readl(struct tegra_soctherm *ts, u32 reg)381{382	return readl(ts->ccroc_regs + reg);383}384 385static void enable_tsensor(struct tegra_soctherm *tegra, unsigned int i)386{387	const struct tegra_tsensor *sensor = &tegra->soc->tsensors[i];388	void __iomem *base = tegra->regs + sensor->base;389	unsigned int val;390 391	val = sensor->config->tall << SENSOR_CONFIG0_TALL_SHIFT;392	writel(val, base + SENSOR_CONFIG0);393 394	val  = (sensor->config->tsample - 1) << SENSOR_CONFIG1_TSAMPLE_SHIFT;395	val |= sensor->config->tiddq_en << SENSOR_CONFIG1_TIDDQ_EN_SHIFT;396	val |= sensor->config->ten_count << SENSOR_CONFIG1_TEN_COUNT_SHIFT;397	val |= SENSOR_CONFIG1_TEMP_ENABLE;398	writel(val, base + SENSOR_CONFIG1);399 400	writel(tegra->calib[i], base + SENSOR_CONFIG2);401}402 403/*404 * Translate from soctherm readback format to millicelsius.405 * The soctherm readback format in bits is as follows:406 *   TTTTTTTT H______N407 * where T's contain the temperature in Celsius,408 * H denotes an addition of 0.5 Celsius and N denotes negation409 * of the final value.410 */411static int translate_temp(u16 val)412{413	int t;414 415	t = ((val & READBACK_VALUE_MASK) >> READBACK_VALUE_SHIFT) * 1000;416	if (val & READBACK_ADD_HALF)417		t += 500;418	if (val & READBACK_NEGATE)419		t *= -1;420 421	return t;422}423 424static int tegra_thermctl_get_temp(struct thermal_zone_device *tz, int *out_temp)425{426	struct tegra_thermctl_zone *zone = thermal_zone_device_priv(tz);427	u32 val;428 429	val = readl(zone->reg);430	val = REG_GET_MASK(val, zone->sg->sensor_temp_mask);431	*out_temp = translate_temp(val);432 433	return 0;434}435 436/**437 * enforce_temp_range() - check and enforce temperature range [min, max]438 * @dev: struct device * of the SOC_THERM instance439 * @trip_temp: the trip temperature to check440 *441 * Checks and enforces the permitted temperature range that SOC_THERM442 * HW can support This is443 * done while taking care of precision.444 *445 * Return: The precision adjusted capped temperature in millicelsius.446 */447static int enforce_temp_range(struct device *dev, int trip_temp)448{449	int temp;450 451	temp = clamp_val(trip_temp, min_low_temp, max_high_temp);452	if (temp != trip_temp)453		dev_dbg(dev, "soctherm: trip temperature %d forced to %d\n",454			trip_temp, temp);455	return temp;456}457 458/**459 * thermtrip_program() - Configures the hardware to shut down the460 * system if a given sensor group reaches a given temperature461 * @dev: ptr to the struct device for the SOC_THERM IP block462 * @sg: pointer to the sensor group to set the thermtrip temperature for463 * @trip_temp: the temperature in millicelsius to trigger the thermal trip at464 *465 * Sets the thermal trip threshold of the given sensor group to be the466 * @trip_temp.  If this threshold is crossed, the hardware will shut467 * down.468 *469 * Note that, although @trip_temp is specified in millicelsius, the470 * hardware is programmed in degrees Celsius.471 *472 * Return: 0 upon success, or %-EINVAL upon failure.473 */474static int thermtrip_program(struct device *dev,475			     const struct tegra_tsensor_group *sg,476			     int trip_temp)477{478	struct tegra_soctherm *ts = dev_get_drvdata(dev);479	int temp;480	u32 r;481 482	if (!sg || !sg->thermtrip_threshold_mask)483		return -EINVAL;484 485	temp = enforce_temp_range(dev, trip_temp) / ts->soc->thresh_grain;486 487	r = readl(ts->regs + THERMCTL_THERMTRIP_CTL);488	r = REG_SET_MASK(r, sg->thermtrip_threshold_mask, temp);489	r = REG_SET_MASK(r, sg->thermtrip_enable_mask, 1);490	r = REG_SET_MASK(r, sg->thermtrip_any_en_mask, 0);491	writel(r, ts->regs + THERMCTL_THERMTRIP_CTL);492 493	return 0;494}495 496/**497 * throttrip_program() - Configures the hardware to throttle the498 * pulse if a given sensor group reaches a given temperature499 * @dev: ptr to the struct device for the SOC_THERM IP block500 * @sg: pointer to the sensor group to set the thermtrip temperature for501 * @stc: pointer to the throttle need to be triggered502 * @trip_temp: the temperature in millicelsius to trigger the thermal trip at503 *504 * Sets the thermal trip threshold and throttle event of the given sensor505 * group. If this threshold is crossed, the hardware will trigger the506 * throttle.507 *508 * Note that, although @trip_temp is specified in millicelsius, the509 * hardware is programmed in degrees Celsius.510 *511 * Return: 0 upon success, or %-EINVAL upon failure.512 */513static int throttrip_program(struct device *dev,514			     const struct tegra_tsensor_group *sg,515			     struct soctherm_throt_cfg *stc,516			     int trip_temp)517{518	struct tegra_soctherm *ts = dev_get_drvdata(dev);519	int temp, cpu_throt, gpu_throt;520	unsigned int throt;521	u32 r, reg_off;522 523	if (!sg || !stc || !stc->init)524		return -EINVAL;525 526	temp = enforce_temp_range(dev, trip_temp) / ts->soc->thresh_grain;527 528	/* Hardcode LIGHT on LEVEL1 and HEAVY on LEVEL2 */529	throt = stc->id;530	reg_off = THERMCTL_LVL_REG(sg->thermctl_lvl0_offset, throt + 1);531 532	if (throt == THROTTLE_LIGHT) {533		cpu_throt = THERMCTL_LVL0_CPU0_CPU_THROT_LIGHT;534		gpu_throt = THERMCTL_LVL0_CPU0_GPU_THROT_LIGHT;535	} else {536		cpu_throt = THERMCTL_LVL0_CPU0_CPU_THROT_HEAVY;537		gpu_throt = THERMCTL_LVL0_CPU0_GPU_THROT_HEAVY;538		if (throt != THROTTLE_HEAVY)539			dev_warn(dev,540				 "invalid throt id %d - assuming HEAVY",541				 throt);542	}543 544	r = readl(ts->regs + reg_off);545	r = REG_SET_MASK(r, sg->thermctl_lvl0_up_thresh_mask, temp);546	r = REG_SET_MASK(r, sg->thermctl_lvl0_dn_thresh_mask, temp);547	r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_CPU_THROT_MASK, cpu_throt);548	r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_GPU_THROT_MASK, gpu_throt);549	r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 1);550	writel(r, ts->regs + reg_off);551 552	return 0;553}554 555static struct soctherm_throt_cfg *556find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name)557{558	unsigned int i;559 560	for (i = 0; ts->throt_cfgs[i].name; i++)561		if (!strcmp(ts->throt_cfgs[i].name, name))562			return &ts->throt_cfgs[i];563 564	return NULL;565}566 567static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id)568{569	int i, temp = min_low_temp;570	struct tsensor_group_thermtrips *tt = ts->soc->thermtrips;571 572	if (id >= TEGRA124_SOCTHERM_SENSOR_NUM)573		return temp;574 575	if (tt) {576		for (i = 0; i < ts->soc->num_ttgs; i++) {577			if (tt[i].id == id)578				return tt[i].temp;579		}580	}581 582	return temp;583}584 585static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz,586					const struct thermal_trip *trip, int temp)587{588	struct tegra_thermctl_zone *zone = thermal_zone_device_priv(tz);589	struct tegra_soctherm *ts = zone->ts;590	const struct tegra_tsensor_group *sg = zone->sg;591	struct device *dev = zone->dev;592 593	if (!tz)594		return -EINVAL;595 596	if (trip->type == THERMAL_TRIP_CRITICAL) {597		/*598		 * If thermtrips property is set in DT,599		 * doesn't need to program critical type trip to HW,600		 * if not, program critical trip to HW.601		 */602		if (min_low_temp == tsensor_group_thermtrip_get(ts, sg->id))603			return thermtrip_program(dev, sg, temp);604		else605			return 0;606 607	} else if (trip->type == THERMAL_TRIP_HOT) {608		int i;609 610		for (i = 0; i < THROTTLE_SIZE; i++) {611			struct thermal_cooling_device *cdev;612			struct soctherm_throt_cfg *stc;613 614			if (!ts->throt_cfgs[i].init)615				continue;616 617			cdev = ts->throt_cfgs[i].cdev;618			if (thermal_trip_is_bound_to_cdev(tz, trip, cdev))619				stc = find_throttle_cfg_by_name(ts, cdev->type);620			else621				continue;622 623			return throttrip_program(dev, sg, stc, temp);624		}625	}626 627	return 0;628}629 630static void thermal_irq_enable(struct tegra_thermctl_zone *zn)631{632	u32 r;633 634	/* multiple zones could be handling and setting trips at once */635	mutex_lock(&zn->ts->thermctl_lock);636	r = readl(zn->ts->regs + THERMCTL_INTR_ENABLE);637	r = REG_SET_MASK(r, zn->sg->thermctl_isr_mask, TH_INTR_UP_DN_EN);638	writel(r, zn->ts->regs + THERMCTL_INTR_ENABLE);639	mutex_unlock(&zn->ts->thermctl_lock);640}641 642static void thermal_irq_disable(struct tegra_thermctl_zone *zn)643{644	u32 r;645 646	/* multiple zones could be handling and setting trips at once */647	mutex_lock(&zn->ts->thermctl_lock);648	r = readl(zn->ts->regs + THERMCTL_INTR_DISABLE);649	r = REG_SET_MASK(r, zn->sg->thermctl_isr_mask, 0);650	writel(r, zn->ts->regs + THERMCTL_INTR_DISABLE);651	mutex_unlock(&zn->ts->thermctl_lock);652}653 654static int tegra_thermctl_set_trips(struct thermal_zone_device *tz, int lo, int hi)655{656	struct tegra_thermctl_zone *zone = thermal_zone_device_priv(tz);657	u32 r;658 659	thermal_irq_disable(zone);660 661	r = readl(zone->ts->regs + zone->sg->thermctl_lvl0_offset);662	r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 0);663	writel(r, zone->ts->regs + zone->sg->thermctl_lvl0_offset);664 665	lo = enforce_temp_range(zone->dev, lo) / zone->ts->soc->thresh_grain;666	hi = enforce_temp_range(zone->dev, hi) / zone->ts->soc->thresh_grain;667	dev_dbg(zone->dev, "%s hi:%d, lo:%d\n", __func__, hi, lo);668 669	r = REG_SET_MASK(r, zone->sg->thermctl_lvl0_up_thresh_mask, hi);670	r = REG_SET_MASK(r, zone->sg->thermctl_lvl0_dn_thresh_mask, lo);671	r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 1);672	writel(r, zone->ts->regs + zone->sg->thermctl_lvl0_offset);673 674	thermal_irq_enable(zone);675 676	return 0;677}678 679static const struct thermal_zone_device_ops tegra_of_thermal_ops = {680	.get_temp = tegra_thermctl_get_temp,681	.set_trip_temp = tegra_thermctl_set_trip_temp,682	.set_trips = tegra_thermctl_set_trips,683};684 685static int get_hot_trip_cb(struct thermal_trip *trip, void *arg)686{687	const struct thermal_trip **trip_ret = arg;688 689	if (trip->type != THERMAL_TRIP_HOT)690		return 0;691 692	*trip_ret = trip;693	/* Return nonzero to terminate the search. */694	return 1;695}696 697static const struct thermal_trip *get_hot_trip(struct thermal_zone_device *tz)698{699	const struct thermal_trip *trip = NULL;700 701	thermal_zone_for_each_trip(tz, get_hot_trip_cb, &trip);702 703	return trip;704}705 706/**707 * tegra_soctherm_set_hwtrips() - set HW trip point from DT data708 * @dev: struct device * of the SOC_THERM instance709 * @sg: pointer to the sensor group to set the thermtrip temperature for710 * @tz: struct thermal_zone_device *711 *712 * Configure the SOC_THERM HW trip points, setting "THERMTRIP"713 * "THROTTLE" trip points , using "thermtrips", "critical" or "hot"714 * type trip_temp715 * from thermal zone.716 * After they have been configured, THERMTRIP or THROTTLE will take717 * action when the configured SoC thermal sensor group reaches a718 * certain temperature.719 *720 * Return: 0 upon success, or a negative error code on failure.721 * "Success" does not mean that trips was enabled; it could also722 * mean that no node was found in DT.723 * THERMTRIP has been enabled successfully when a message similar to724 * this one appears on the serial console:725 * "thermtrip: will shut down when sensor group XXX reaches YYYYYY mC"726 * THROTTLE has been enabled successfully when a message similar to727 * this one appears on the serial console:728 * ""throttrip: will throttle when sensor group XXX reaches YYYYYY mC"729 */730static int tegra_soctherm_set_hwtrips(struct device *dev,731				      const struct tegra_tsensor_group *sg,732				      struct thermal_zone_device *tz)733{734	struct tegra_soctherm *ts = dev_get_drvdata(dev);735	const struct thermal_trip *hot_trip;736	struct soctherm_throt_cfg *stc;737	int i, temperature, ret;738 739	/* Get thermtrips. If missing, try to get critical trips. */740	temperature = tsensor_group_thermtrip_get(ts, sg->id);741	if (min_low_temp == temperature)742		if (thermal_zone_get_crit_temp(tz, &temperature))743			temperature = max_high_temp;744 745	ret = thermtrip_program(dev, sg, temperature);746	if (ret) {747		dev_err(dev, "thermtrip: %s: error during enable\n", sg->name);748		return ret;749	}750 751	dev_info(dev, "thermtrip: will shut down when %s reaches %d mC\n",752		 sg->name, temperature);753 754	hot_trip = get_hot_trip(tz);755	if (!hot_trip) {756		dev_info(dev, "throttrip: %s: missing hot temperature\n",757			 sg->name);758		return 0;759	}760 761	for (i = 0; i < THROTTLE_OC1; i++) {762		struct thermal_cooling_device *cdev;763 764		if (!ts->throt_cfgs[i].init)765			continue;766 767		cdev = ts->throt_cfgs[i].cdev;768		if (thermal_trip_is_bound_to_cdev(tz, hot_trip, cdev))769			stc = find_throttle_cfg_by_name(ts, cdev->type);770		else771			continue;772 773		ret = throttrip_program(dev, sg, stc, temperature);774		if (ret) {775			dev_err(dev, "throttrip: %s: error during enable\n",776				sg->name);777			return ret;778		}779 780		dev_info(dev,781			 "throttrip: will throttle when %s reaches %d mC\n",782			 sg->name, temperature);783		break;784	}785 786	if (i == THROTTLE_SIZE)787		dev_info(dev, "throttrip: %s: missing throttle cdev\n",788			 sg->name);789 790	return 0;791}792 793static irqreturn_t soctherm_thermal_isr(int irq, void *dev_id)794{795	struct tegra_soctherm *ts = dev_id;796	u32 r;797 798	/* Case for no lock:799	 * Although interrupts are enabled in set_trips, there is still no need800	 * to lock here because the interrupts are disabled before programming801	 * new trip points. Hence there cant be a interrupt on the same sensor.802	 * An interrupt can however occur on a sensor while trips are being803	 * programmed on a different one. This beign a LEVEL interrupt won't804	 * cause a new interrupt but this is taken care of by the re-reading of805	 * the STATUS register in the thread function.806	 */807	r = readl(ts->regs + THERMCTL_INTR_STATUS);808	writel(r, ts->regs + THERMCTL_INTR_DISABLE);809 810	return IRQ_WAKE_THREAD;811}812 813/**814 * soctherm_thermal_isr_thread() - Handles a thermal interrupt request815 * @irq:       The interrupt number being requested; not used816 * @dev_id:    Opaque pointer to tegra_soctherm;817 *818 * Clears the interrupt status register if there are expected819 * interrupt bits set.820 * The interrupt(s) are then handled by updating the corresponding821 * thermal zones.822 *823 * An error is logged if any unexpected interrupt bits are set.824 *825 * Disabled interrupts are re-enabled.826 *827 * Return: %IRQ_HANDLED. Interrupt was handled and no further processing828 * is needed.829 */830static irqreturn_t soctherm_thermal_isr_thread(int irq, void *dev_id)831{832	struct tegra_soctherm *ts = dev_id;833	struct thermal_zone_device *tz;834	u32 st, ex = 0, cp = 0, gp = 0, pl = 0, me = 0;835 836	st = readl(ts->regs + THERMCTL_INTR_STATUS);837 838	/* deliberately clear expected interrupts handled in SW */839	cp |= st & TH_INTR_CD0_MASK;840	cp |= st & TH_INTR_CU0_MASK;841 842	gp |= st & TH_INTR_GD0_MASK;843	gp |= st & TH_INTR_GU0_MASK;844 845	pl |= st & TH_INTR_PD0_MASK;846	pl |= st & TH_INTR_PU0_MASK;847 848	me |= st & TH_INTR_MD0_MASK;849	me |= st & TH_INTR_MU0_MASK;850 851	ex |= cp | gp | pl | me;852	if (ex) {853		writel(ex, ts->regs + THERMCTL_INTR_STATUS);854		st &= ~ex;855 856		if (cp) {857			tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_CPU];858			thermal_zone_device_update(tz,859						   THERMAL_EVENT_UNSPECIFIED);860		}861 862		if (gp) {863			tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_GPU];864			thermal_zone_device_update(tz,865						   THERMAL_EVENT_UNSPECIFIED);866		}867 868		if (pl) {869			tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_PLLX];870			thermal_zone_device_update(tz,871						   THERMAL_EVENT_UNSPECIFIED);872		}873 874		if (me) {875			tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_MEM];876			thermal_zone_device_update(tz,877						   THERMAL_EVENT_UNSPECIFIED);878		}879	}880 881	/* deliberately ignore expected interrupts NOT handled in SW */882	ex |= TH_INTR_IGNORE_MASK;883	st &= ~ex;884 885	if (st) {886		/* Whine about any other unexpected INTR bits still set */887		pr_err("soctherm: Ignored unexpected INTRs 0x%08x\n", st);888		writel(st, ts->regs + THERMCTL_INTR_STATUS);889	}890 891	return IRQ_HANDLED;892}893 894/**895 * soctherm_oc_intr_enable() - Enables the soctherm over-current interrupt896 * @ts:		pointer to a struct tegra_soctherm897 * @alarm:		The soctherm throttle id898 * @enable:		Flag indicating enable the soctherm over-current899 *			interrupt or disable it900 *901 * Enables a specific over-current pins @alarm to raise an interrupt if the flag902 * is set and the alarm corresponds to OC1, OC2, OC3, or OC4.903 */904static void soctherm_oc_intr_enable(struct tegra_soctherm *ts,905				    enum soctherm_throttle_id alarm,906				    bool enable)907{908	u32 r;909 910	if (!enable)911		return;912 913	r = readl(ts->regs + OC_INTR_ENABLE);914	switch (alarm) {915	case THROTTLE_OC1:916		r = REG_SET_MASK(r, OC_INTR_OC1_MASK, 1);917		break;918	case THROTTLE_OC2:919		r = REG_SET_MASK(r, OC_INTR_OC2_MASK, 1);920		break;921	case THROTTLE_OC3:922		r = REG_SET_MASK(r, OC_INTR_OC3_MASK, 1);923		break;924	case THROTTLE_OC4:925		r = REG_SET_MASK(r, OC_INTR_OC4_MASK, 1);926		break;927	default:928		r = 0;929		break;930	}931	writel(r, ts->regs + OC_INTR_ENABLE);932}933 934/**935 * soctherm_handle_alarm() - Handles soctherm alarms936 * @alarm:		The soctherm throttle id937 *938 * "Handles" over-current alarms (OC1, OC2, OC3, and OC4) by printing939 * a warning or informative message.940 *941 * Return: -EINVAL for @alarm = THROTTLE_OC3, otherwise 0 (success).942 */943static int soctherm_handle_alarm(enum soctherm_throttle_id alarm)944{945	int rv = -EINVAL;946 947	switch (alarm) {948	case THROTTLE_OC1:949		pr_debug("soctherm: Successfully handled OC1 alarm\n");950		rv = 0;951		break;952 953	case THROTTLE_OC2:954		pr_debug("soctherm: Successfully handled OC2 alarm\n");955		rv = 0;956		break;957 958	case THROTTLE_OC3:959		pr_debug("soctherm: Successfully handled OC3 alarm\n");960		rv = 0;961		break;962 963	case THROTTLE_OC4:964		pr_debug("soctherm: Successfully handled OC4 alarm\n");965		rv = 0;966		break;967 968	default:969		break;970	}971 972	if (rv)973		pr_err("soctherm: ERROR in handling %s alarm\n",974		       throt_names[alarm]);975 976	return rv;977}978 979/**980 * soctherm_edp_isr_thread() - log an over-current interrupt request981 * @irq:	OC irq number. Currently not being used. See description982 * @arg:	a void pointer for callback, currently not being used983 *984 * Over-current events are handled in hardware. This function is called to log985 * and handle any OC events that happened. Additionally, it checks every986 * over-current interrupt registers for registers are set but987 * was not expected (i.e. any discrepancy in interrupt status) by the function,988 * the discrepancy will logged.989 *990 * Return: %IRQ_HANDLED991 */992static irqreturn_t soctherm_edp_isr_thread(int irq, void *arg)993{994	struct tegra_soctherm *ts = arg;995	u32 st, ex, oc1, oc2, oc3, oc4;996 997	st = readl(ts->regs + OC_INTR_STATUS);998 999	/* deliberately clear expected interrupts handled in SW */1000	oc1 = st & OC_INTR_OC1_MASK;1001	oc2 = st & OC_INTR_OC2_MASK;1002	oc3 = st & OC_INTR_OC3_MASK;1003	oc4 = st & OC_INTR_OC4_MASK;1004	ex = oc1 | oc2 | oc3 | oc4;1005 1006	pr_err("soctherm: OC ALARM 0x%08x\n", ex);1007	if (ex) {1008		writel(st, ts->regs + OC_INTR_STATUS);1009		st &= ~ex;1010 1011		if (oc1 && !soctherm_handle_alarm(THROTTLE_OC1))1012			soctherm_oc_intr_enable(ts, THROTTLE_OC1, true);1013 1014		if (oc2 && !soctherm_handle_alarm(THROTTLE_OC2))1015			soctherm_oc_intr_enable(ts, THROTTLE_OC2, true);1016 1017		if (oc3 && !soctherm_handle_alarm(THROTTLE_OC3))1018			soctherm_oc_intr_enable(ts, THROTTLE_OC3, true);1019 1020		if (oc4 && !soctherm_handle_alarm(THROTTLE_OC4))1021			soctherm_oc_intr_enable(ts, THROTTLE_OC4, true);1022 1023		if (oc1 && soc_irq_cdata.irq_enable & BIT(0))1024			handle_nested_irq(1025				irq_find_mapping(soc_irq_cdata.domain, 0));1026 1027		if (oc2 && soc_irq_cdata.irq_enable & BIT(1))1028			handle_nested_irq(1029				irq_find_mapping(soc_irq_cdata.domain, 1));1030 1031		if (oc3 && soc_irq_cdata.irq_enable & BIT(2))1032			handle_nested_irq(1033				irq_find_mapping(soc_irq_cdata.domain, 2));1034 1035		if (oc4 && soc_irq_cdata.irq_enable & BIT(3))1036			handle_nested_irq(1037				irq_find_mapping(soc_irq_cdata.domain, 3));1038	}1039 1040	if (st) {1041		pr_err("soctherm: Ignored unexpected OC ALARM 0x%08x\n", st);1042		writel(st, ts->regs + OC_INTR_STATUS);1043	}1044 1045	return IRQ_HANDLED;1046}1047 1048/**1049 * soctherm_edp_isr() - Disables any active interrupts1050 * @irq:	The interrupt request number1051 * @arg:	Opaque pointer to an argument1052 *1053 * Writes to the OC_INTR_DISABLE register the over current interrupt status,1054 * masking any asserted interrupts. Doing this prevents the same interrupts1055 * from triggering this isr repeatedly. The thread woken by this isr will1056 * handle asserted interrupts and subsequently unmask/re-enable them.1057 *1058 * The OC_INTR_DISABLE register indicates which OC interrupts1059 * have been disabled.1060 *1061 * Return: %IRQ_WAKE_THREAD, handler requests to wake the handler thread1062 */1063static irqreturn_t soctherm_edp_isr(int irq, void *arg)1064{1065	struct tegra_soctherm *ts = arg;1066	u32 r;1067 1068	if (!ts)1069		return IRQ_NONE;1070 1071	r = readl(ts->regs + OC_INTR_STATUS);1072	writel(r, ts->regs + OC_INTR_DISABLE);1073 1074	return IRQ_WAKE_THREAD;1075}1076 1077/**1078 * soctherm_oc_irq_lock() - locks the over-current interrupt request1079 * @data:	Interrupt request data1080 *1081 * Looks up the chip data from @data and locks the mutex associated with1082 * a particular over-current interrupt request.1083 */1084static void soctherm_oc_irq_lock(struct irq_data *data)1085{1086	struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);1087 1088	mutex_lock(&d->irq_lock);1089}1090 1091/**1092 * soctherm_oc_irq_sync_unlock() - Unlocks the OC interrupt request1093 * @data:		Interrupt request data1094 *1095 * Looks up the interrupt request data @data and unlocks the mutex associated1096 * with a particular over-current interrupt request.1097 */1098static void soctherm_oc_irq_sync_unlock(struct irq_data *data)1099{1100	struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);1101 1102	mutex_unlock(&d->irq_lock);1103}1104 1105/**1106 * soctherm_oc_irq_enable() - Enables the SOC_THERM over-current interrupt queue1107 * @data:       irq_data structure of the chip1108 *1109 * Sets the irq_enable bit of SOC_THERM allowing SOC_THERM1110 * to respond to over-current interrupts.1111 *1112 */1113static void soctherm_oc_irq_enable(struct irq_data *data)1114{1115	struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);1116 1117	d->irq_enable |= BIT(data->hwirq);1118}1119 1120/**1121 * soctherm_oc_irq_disable() - Disables overcurrent interrupt requests1122 * @data:	The interrupt request information1123 *1124 * Clears the interrupt request enable bit of the overcurrent1125 * interrupt request chip data.1126 *1127 * Return: Nothing is returned (void)1128 */1129static void soctherm_oc_irq_disable(struct irq_data *data)1130{1131	struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);1132 1133	d->irq_enable &= ~BIT(data->hwirq);1134}1135 1136static int soctherm_oc_irq_set_type(struct irq_data *data, unsigned int type)1137{1138	return 0;1139}1140 1141/**1142 * soctherm_oc_irq_map() - SOC_THERM interrupt request domain mapper1143 * @h:		Interrupt request domain1144 * @virq:	Virtual interrupt request number1145 * @hw:		Hardware interrupt request number1146 *1147 * Mapping callback function for SOC_THERM's irq_domain. When a SOC_THERM1148 * interrupt request is called, the irq_domain takes the request's virtual1149 * request number (much like a virtual memory address) and maps it to a1150 * physical hardware request number.1151 *1152 * When a mapping doesn't already exist for a virtual request number, the1153 * irq_domain calls this function to associate the virtual request number with1154 * a hardware request number.1155 *1156 * Return: 01157 */1158static int soctherm_oc_irq_map(struct irq_domain *h, unsigned int virq,1159		irq_hw_number_t hw)1160{1161	struct soctherm_oc_irq_chip_data *data = h->host_data;1162 1163	irq_set_chip_data(virq, data);1164	irq_set_chip(virq, &data->irq_chip);1165	irq_set_nested_thread(virq, 1);1166	return 0;1167}1168 1169/**1170 * soctherm_irq_domain_xlate_twocell() - xlate for soctherm interrupts1171 * @d:      Interrupt request domain1172 * @ctrlr:      Controller device tree node1173 * @intspec:    Array of u32s from DTs "interrupt" property1174 * @intsize:    Number of values inside the intspec array1175 * @out_hwirq:  HW IRQ value associated with this interrupt1176 * @out_type:   The IRQ SENSE type for this interrupt.1177 *1178 * This Device Tree IRQ specifier translation function will translate a1179 * specific "interrupt" as defined by 2 DT values where the cell values map1180 * the hwirq number + 1 and linux irq flags. Since the output is the hwirq1181 * number, this function will subtract 1 from the value listed in DT.1182 *1183 * Return: 01184 */1185static int soctherm_irq_domain_xlate_twocell(struct irq_domain *d,1186	struct device_node *ctrlr, const u32 *intspec, unsigned int intsize,1187	irq_hw_number_t *out_hwirq, unsigned int *out_type)1188{1189	if (WARN_ON(intsize < 2))1190		return -EINVAL;1191 1192	/*1193	 * The HW value is 1 index less than the DT IRQ values.1194	 * i.e. OC4 goes to HW index 3.1195	 */1196	*out_hwirq = intspec[0] - 1;1197	*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;1198	return 0;1199}1200 1201static const struct irq_domain_ops soctherm_oc_domain_ops = {1202	.map	= soctherm_oc_irq_map,1203	.xlate	= soctherm_irq_domain_xlate_twocell,1204};1205 1206/**1207 * soctherm_oc_int_init() - Initial enabling of the over1208 * current interrupts1209 * @np:	The devicetree node for soctherm1210 * @num_irqs:	The number of new interrupt requests1211 *1212 * Sets the over current interrupt request chip data1213 *1214 * Return: 0 on success or if overcurrent interrupts are not enabled,1215 * -ENOMEM (out of memory), or irq_base if the function failed to1216 * allocate the irqs1217 */1218static int soctherm_oc_int_init(struct device_node *np, int num_irqs)1219{1220	if (!num_irqs) {1221		pr_info("%s(): OC interrupts are not enabled\n", __func__);1222		return 0;1223	}1224 1225	mutex_init(&soc_irq_cdata.irq_lock);1226	soc_irq_cdata.irq_enable = 0;1227 1228	soc_irq_cdata.irq_chip.name = "soc_therm_oc";1229	soc_irq_cdata.irq_chip.irq_bus_lock = soctherm_oc_irq_lock;1230	soc_irq_cdata.irq_chip.irq_bus_sync_unlock =1231		soctherm_oc_irq_sync_unlock;1232	soc_irq_cdata.irq_chip.irq_disable = soctherm_oc_irq_disable;1233	soc_irq_cdata.irq_chip.irq_enable = soctherm_oc_irq_enable;1234	soc_irq_cdata.irq_chip.irq_set_type = soctherm_oc_irq_set_type;1235	soc_irq_cdata.irq_chip.irq_set_wake = NULL;1236 1237	soc_irq_cdata.domain = irq_domain_add_linear(np, num_irqs,1238						     &soctherm_oc_domain_ops,1239						     &soc_irq_cdata);1240 1241	if (!soc_irq_cdata.domain) {1242		pr_err("%s: Failed to create IRQ domain\n", __func__);1243		return -ENOMEM;1244	}1245 1246	pr_debug("%s(): OC interrupts enabled successful\n", __func__);1247	return 0;1248}1249 1250#ifdef CONFIG_DEBUG_FS1251static int regs_show(struct seq_file *s, void *data)1252{1253	struct platform_device *pdev = s->private;1254	struct tegra_soctherm *ts = platform_get_drvdata(pdev);1255	const struct tegra_tsensor *tsensors = ts->soc->tsensors;1256	const struct tegra_tsensor_group **ttgs = ts->soc->ttgs;1257	u32 r, state;1258	int i, level;1259 1260	seq_puts(s, "-----TSENSE (convert HW)-----\n");1261 1262	for (i = 0; i < ts->soc->num_tsensors; i++) {1263		r = readl(ts->regs + tsensors[i].base + SENSOR_CONFIG1);1264		state = REG_GET_MASK(r, SENSOR_CONFIG1_TEMP_ENABLE);1265 1266		seq_printf(s, "%s: ", tsensors[i].name);1267		seq_printf(s, "En(%d) ", state);1268 1269		if (!state) {1270			seq_puts(s, "\n");1271			continue;1272		}1273 1274		state = REG_GET_MASK(r, SENSOR_CONFIG1_TIDDQ_EN_MASK);1275		seq_printf(s, "tiddq(%d) ", state);1276		state = REG_GET_MASK(r, SENSOR_CONFIG1_TEN_COUNT_MASK);1277		seq_printf(s, "ten_count(%d) ", state);1278		state = REG_GET_MASK(r, SENSOR_CONFIG1_TSAMPLE_MASK);1279		seq_printf(s, "tsample(%d) ", state + 1);1280 1281		r = readl(ts->regs + tsensors[i].base + SENSOR_STATUS1);1282		state = REG_GET_MASK(r, SENSOR_STATUS1_TEMP_VALID_MASK);1283		seq_printf(s, "Temp(%d/", state);1284		state = REG_GET_MASK(r, SENSOR_STATUS1_TEMP_MASK);1285		seq_printf(s, "%d) ", translate_temp(state));1286 1287		r = readl(ts->regs + tsensors[i].base + SENSOR_STATUS0);1288		state = REG_GET_MASK(r, SENSOR_STATUS0_VALID_MASK);1289		seq_printf(s, "Capture(%d/", state);1290		state = REG_GET_MASK(r, SENSOR_STATUS0_CAPTURE_MASK);1291		seq_printf(s, "%d) ", state);1292 1293		r = readl(ts->regs + tsensors[i].base + SENSOR_CONFIG0);1294		state = REG_GET_MASK(r, SENSOR_CONFIG0_STOP);1295		seq_printf(s, "Stop(%d) ", state);1296		state = REG_GET_MASK(r, SENSOR_CONFIG0_TALL_MASK);1297		seq_printf(s, "Tall(%d) ", state);1298		state = REG_GET_MASK(r, SENSOR_CONFIG0_TCALC_OVER);1299		seq_printf(s, "Over(%d/", state);1300		state = REG_GET_MASK(r, SENSOR_CONFIG0_OVER);1301		seq_printf(s, "%d/", state);1302		state = REG_GET_MASK(r, SENSOR_CONFIG0_CPTR_OVER);1303		seq_printf(s, "%d) ", state);1304 1305		r = readl(ts->regs + tsensors[i].base + SENSOR_CONFIG2);1306		state = REG_GET_MASK(r, SENSOR_CONFIG2_THERMA_MASK);1307		seq_printf(s, "Therm_A/B(%d/", state);1308		state = REG_GET_MASK(r, SENSOR_CONFIG2_THERMB_MASK);1309		seq_printf(s, "%d)\n", (s16)state);1310	}1311 1312	r = readl(ts->regs + SENSOR_PDIV);1313	seq_printf(s, "PDIV: 0x%x\n", r);1314 1315	r = readl(ts->regs + SENSOR_HOTSPOT_OFF);1316	seq_printf(s, "HOTSPOT: 0x%x\n", r);1317 1318	seq_puts(s, "\n");1319	seq_puts(s, "-----SOC_THERM-----\n");1320 1321	r = readl(ts->regs + SENSOR_TEMP1);1322	state = REG_GET_MASK(r, SENSOR_TEMP1_CPU_TEMP_MASK);1323	seq_printf(s, "Temperatures: CPU(%d) ", translate_temp(state));1324	state = REG_GET_MASK(r, SENSOR_TEMP1_GPU_TEMP_MASK);1325	seq_printf(s, " GPU(%d) ", translate_temp(state));1326	r = readl(ts->regs + SENSOR_TEMP2);1327	state = REG_GET_MASK(r, SENSOR_TEMP2_PLLX_TEMP_MASK);1328	seq_printf(s, " PLLX(%d) ", translate_temp(state));1329	state = REG_GET_MASK(r, SENSOR_TEMP2_MEM_TEMP_MASK);1330	seq_printf(s, " MEM(%d)\n", translate_temp(state));1331 1332	for (i = 0; i < ts->soc->num_ttgs; i++) {1333		seq_printf(s, "%s:\n", ttgs[i]->name);1334		for (level = 0; level < 4; level++) {1335			s32 v;1336			u32 mask;1337			u16 off = ttgs[i]->thermctl_lvl0_offset;1338 1339			r = readl(ts->regs + THERMCTL_LVL_REG(off, level));1340 1341			mask = ttgs[i]->thermctl_lvl0_up_thresh_mask;1342			state = REG_GET_MASK(r, mask);1343			v = sign_extend32(state, ts->soc->bptt - 1);1344			v *= ts->soc->thresh_grain;1345			seq_printf(s, "   %d: Up/Dn(%d /", level, v);1346 1347			mask = ttgs[i]->thermctl_lvl0_dn_thresh_mask;1348			state = REG_GET_MASK(r, mask);1349			v = sign_extend32(state, ts->soc->bptt - 1);1350			v *= ts->soc->thresh_grain;1351			seq_printf(s, "%d ) ", v);1352 1353			mask = THERMCTL_LVL0_CPU0_EN_MASK;1354			state = REG_GET_MASK(r, mask);1355			seq_printf(s, "En(%d) ", state);1356 1357			mask = THERMCTL_LVL0_CPU0_CPU_THROT_MASK;1358			state = REG_GET_MASK(r, mask);1359			seq_puts(s, "CPU Throt");1360			if (!state)1361				seq_printf(s, "(%s) ", "none");1362			else if (state == THERMCTL_LVL0_CPU0_CPU_THROT_LIGHT)1363				seq_printf(s, "(%s) ", "L");1364			else if (state == THERMCTL_LVL0_CPU0_CPU_THROT_HEAVY)1365				seq_printf(s, "(%s) ", "H");1366			else1367				seq_printf(s, "(%s) ", "H+L");1368 1369			mask = THERMCTL_LVL0_CPU0_GPU_THROT_MASK;1370			state = REG_GET_MASK(r, mask);1371			seq_puts(s, "GPU Throt");1372			if (!state)1373				seq_printf(s, "(%s) ", "none");1374			else if (state == THERMCTL_LVL0_CPU0_GPU_THROT_LIGHT)1375				seq_printf(s, "(%s) ", "L");1376			else if (state == THERMCTL_LVL0_CPU0_GPU_THROT_HEAVY)1377				seq_printf(s, "(%s) ", "H");1378			else1379				seq_printf(s, "(%s) ", "H+L");1380 1381			mask = THERMCTL_LVL0_CPU0_STATUS_MASK;1382			state = REG_GET_MASK(r, mask);1383			seq_printf(s, "Status(%s)\n",1384				   state == 0 ? "LO" :1385				   state == 1 ? "In" :1386				   state == 2 ? "Res" : "HI");1387		}1388	}1389 1390	r = readl(ts->regs + THERMCTL_STATS_CTL);1391	seq_printf(s, "STATS: Up(%s) Dn(%s)\n",1392		   r & STATS_CTL_EN_UP ? "En" : "--",1393		   r & STATS_CTL_EN_DN ? "En" : "--");1394 1395	for (level = 0; level < 4; level++) {1396		u16 off;1397 1398		off = THERMCTL_LVL0_UP_STATS;1399		r = readl(ts->regs + THERMCTL_LVL_REG(off, level));1400		seq_printf(s, "  Level_%d Up(%d) ", level, r);1401 1402		off = THERMCTL_LVL0_DN_STATS;1403		r = readl(ts->regs + THERMCTL_LVL_REG(off, level));1404		seq_printf(s, "Dn(%d)\n", r);1405	}1406 1407	r = readl(ts->regs + THERMCTL_THERMTRIP_CTL);1408	state = REG_GET_MASK(r, ttgs[0]->thermtrip_any_en_mask);1409	seq_printf(s, "Thermtrip Any En(%d)\n", state);1410	for (i = 0; i < ts->soc->num_ttgs; i++) {1411		state = REG_GET_MASK(r, ttgs[i]->thermtrip_enable_mask);1412		seq_printf(s, "     %s En(%d) ", ttgs[i]->name, state);1413		state = REG_GET_MASK(r, ttgs[i]->thermtrip_threshold_mask);1414		state *= ts->soc->thresh_grain;1415		seq_printf(s, "Thresh(%d)\n", state);1416	}1417 1418	r = readl(ts->regs + THROT_GLOBAL_CFG);1419	seq_puts(s, "\n");1420	seq_printf(s, "GLOBAL THROTTLE CONFIG: 0x%08x\n", r);1421 1422	seq_puts(s, "---------------------------------------------------\n");1423	r = readl(ts->regs + THROT_STATUS);1424	state = REG_GET_MASK(r, THROT_STATUS_BREACH_MASK);1425	seq_printf(s, "THROT STATUS: breach(%d) ", state);1426	state = REG_GET_MASK(r, THROT_STATUS_STATE_MASK);1427	seq_printf(s, "state(%d) ", state);1428	state = REG_GET_MASK(r, THROT_STATUS_ENABLED_MASK);1429	seq_printf(s, "enabled(%d)\n", state);1430 1431	r = readl(ts->regs + CPU_PSKIP_STATUS);1432	if (ts->soc->use_ccroc) {1433		state = REG_GET_MASK(r, XPU_PSKIP_STATUS_ENABLED_MASK);1434		seq_printf(s, "CPU PSKIP STATUS: enabled(%d)\n", state);1435	} else {1436		state = REG_GET_MASK(r, XPU_PSKIP_STATUS_M_MASK);1437		seq_printf(s, "CPU PSKIP STATUS: M(%d) ", state);1438		state = REG_GET_MASK(r, XPU_PSKIP_STATUS_N_MASK);1439		seq_printf(s, "N(%d) ", state);1440		state = REG_GET_MASK(r, XPU_PSKIP_STATUS_ENABLED_MASK);1441		seq_printf(s, "enabled(%d)\n", state);1442	}1443 1444	return 0;1445}1446 1447DEFINE_SHOW_ATTRIBUTE(regs);1448 1449static void soctherm_debug_init(struct platform_device *pdev)1450{1451	struct tegra_soctherm *tegra = platform_get_drvdata(pdev);1452	struct dentry *root;1453 1454	root = debugfs_create_dir("soctherm", NULL);1455 1456	tegra->debugfs_dir = root;1457 1458	debugfs_create_file("reg_contents", 0644, root, pdev, &regs_fops);1459}1460#else1461static inline void soctherm_debug_init(struct platform_device *pdev) {}1462#endif1463 1464static int soctherm_clk_enable(struct platform_device *pdev, bool enable)1465{1466	struct tegra_soctherm *tegra = platform_get_drvdata(pdev);1467	int err;1468 1469	if (!tegra->clock_soctherm || !tegra->clock_tsensor)1470		return -EINVAL;1471 1472	reset_control_assert(tegra->reset);1473 1474	if (enable) {1475		err = clk_prepare_enable(tegra->clock_soctherm);1476		if (err) {1477			reset_control_deassert(tegra->reset);1478			return err;1479		}1480 1481		err = clk_prepare_enable(tegra->clock_tsensor);1482		if (err) {1483			clk_disable_unprepare(tegra->clock_soctherm);1484			reset_control_deassert(tegra->reset);1485			return err;1486		}1487	} else {1488		clk_disable_unprepare(tegra->clock_tsensor);1489		clk_disable_unprepare(tegra->clock_soctherm);1490	}1491 1492	reset_control_deassert(tegra->reset);1493 1494	return 0;1495}1496 1497static int throt_get_cdev_max_state(struct thermal_cooling_device *cdev,1498				    unsigned long *max_state)1499{1500	*max_state = 1;1501	return 0;1502}1503 1504static int throt_get_cdev_cur_state(struct thermal_cooling_device *cdev,1505				    unsigned long *cur_state)1506{1507	struct tegra_soctherm *ts = cdev->devdata;1508	u32 r;1509 1510	r = readl(ts->regs + THROT_STATUS);1511	if (REG_GET_MASK(r, THROT_STATUS_STATE_MASK))1512		*cur_state = 1;1513	else1514		*cur_state = 0;1515 1516	return 0;1517}1518 1519static int throt_set_cdev_state(struct thermal_cooling_device *cdev,1520				unsigned long cur_state)1521{1522	return 0;1523}1524 1525static const struct thermal_cooling_device_ops throt_cooling_ops = {1526	.get_max_state = throt_get_cdev_max_state,1527	.get_cur_state = throt_get_cdev_cur_state,1528	.set_cur_state = throt_set_cdev_state,1529};1530 1531static int soctherm_thermtrips_parse(struct platform_device *pdev)1532{1533	struct device *dev = &pdev->dev;1534	struct tegra_soctherm *ts = dev_get_drvdata(dev);1535	struct tsensor_group_thermtrips *tt = ts->soc->thermtrips;1536	const int max_num_prop = ts->soc->num_ttgs * 2;1537	u32 *tlb;1538	int i, j, n, ret;1539 1540	if (!tt)1541		return -ENOMEM;1542 1543	n = of_property_count_u32_elems(dev->of_node, "nvidia,thermtrips");1544	if (n <= 0) {1545		dev_info(dev,1546			 "missing thermtrips, will use critical trips as shut down temp\n");1547		return n;1548	}1549 1550	n = min(max_num_prop, n);1551 1552	tlb = devm_kcalloc(&pdev->dev, max_num_prop, sizeof(u32), GFP_KERNEL);1553	if (!tlb)1554		return -ENOMEM;1555	ret = of_property_read_u32_array(dev->of_node, "nvidia,thermtrips",1556					 tlb, n);1557	if (ret) {1558		dev_err(dev, "invalid num ele: thermtrips:%d\n", ret);1559		return ret;1560	}1561 1562	i = 0;1563	for (j = 0; j < n; j = j + 2) {1564		if (tlb[j] >= TEGRA124_SOCTHERM_SENSOR_NUM)1565			continue;1566 1567		tt[i].id = tlb[j];1568		tt[i].temp = tlb[j + 1];1569		i++;1570	}1571 1572	return 0;1573}1574 1575static void soctherm_oc_cfg_parse(struct device *dev,1576				struct device_node *np_oc,1577				struct soctherm_throt_cfg *stc)1578{1579	u32 val;1580 1581	if (of_property_read_bool(np_oc, "nvidia,polarity-active-low"))1582		stc->oc_cfg.active_low = 1;1583	else1584		stc->oc_cfg.active_low = 0;1585 1586	if (!of_property_read_u32(np_oc, "nvidia,count-threshold", &val)) {1587		stc->oc_cfg.intr_en = 1;1588		stc->oc_cfg.alarm_cnt_thresh = val;1589	}1590 1591	if (!of_property_read_u32(np_oc, "nvidia,throttle-period-us", &val))1592		stc->oc_cfg.throt_period = val;1593 1594	if (!of_property_read_u32(np_oc, "nvidia,alarm-filter", &val))1595		stc->oc_cfg.alarm_filter = val;1596 1597	/* BRIEF throttling by default, do not support STICKY */1598	stc->oc_cfg.mode = OC_THROTTLE_MODE_BRIEF;1599}1600 1601static int soctherm_throt_cfg_parse(struct device *dev,1602				    struct device_node *np,1603				    struct soctherm_throt_cfg *stc)1604{1605	struct tegra_soctherm *ts = dev_get_drvdata(dev);1606	int ret;1607	u32 val;1608 1609	ret = of_property_read_u32(np, "nvidia,priority", &val);1610	if (ret) {1611		dev_err(dev, "throttle-cfg: %s: invalid priority\n", stc->name);1612		return -EINVAL;1613	}1614	stc->priority = val;1615 1616	ret = of_property_read_u32(np, ts->soc->use_ccroc ?1617				   "nvidia,cpu-throt-level" :1618				   "nvidia,cpu-throt-percent", &val);1619	if (!ret) {1620		if (ts->soc->use_ccroc &&1621		    val <= TEGRA_SOCTHERM_THROT_LEVEL_HIGH)1622			stc->cpu_throt_level = val;1623		else if (!ts->soc->use_ccroc && val <= 100)1624			stc->cpu_throt_depth = val;1625		else1626			goto err;1627	} else {1628		goto err;1629	}1630 1631	ret = of_property_read_u32(np, "nvidia,gpu-throt-level", &val);1632	if (!ret && val <= TEGRA_SOCTHERM_THROT_LEVEL_HIGH)1633		stc->gpu_throt_level = val;1634	else1635		goto err;1636 1637	return 0;1638 1639err:1640	dev_err(dev, "throttle-cfg: %s: no throt prop or invalid prop\n",1641		stc->name);1642	return -EINVAL;1643}1644 1645/**1646 * soctherm_init_hw_throt_cdev() - Parse the HW throttle configurations1647 * and register them as cooling devices.1648 * @pdev: Pointer to platform_device struct1649 */1650static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)1651{1652	struct device *dev = &pdev->dev;1653	struct tegra_soctherm *ts = dev_get_drvdata(dev);1654	struct device_node *np_stc, *np_stcc;1655	const char *name;1656	int i;1657 1658	for (i = 0; i < THROTTLE_SIZE; i++) {1659		ts->throt_cfgs[i].name = throt_names[i];1660		ts->throt_cfgs[i].id = i;1661		ts->throt_cfgs[i].init = false;1662	}1663 1664	np_stc = of_get_child_by_name(dev->of_node, "throttle-cfgs");1665	if (!np_stc) {1666		dev_info(dev,1667			 "throttle-cfg: no throttle-cfgs - not enabling\n");1668		return;1669	}1670 1671	for_each_child_of_node(np_stc, np_stcc) {1672		struct soctherm_throt_cfg *stc;1673		struct thermal_cooling_device *tcd;1674		int err;1675 1676		name = np_stcc->name;1677		stc = find_throttle_cfg_by_name(ts, name);1678		if (!stc) {1679			dev_err(dev,1680				"throttle-cfg: could not find %s\n", name);1681			continue;1682		}1683 1684		if (stc->init) {1685			dev_err(dev, "throttle-cfg: %s: redefined!\n", name);1686			of_node_put(np_stcc);1687			break;1688		}1689 1690		err = soctherm_throt_cfg_parse(dev, np_stcc, stc);1691		if (err)1692			continue;1693 1694		if (stc->id >= THROTTLE_OC1) {1695			soctherm_oc_cfg_parse(dev, np_stcc, stc);1696			stc->init = true;1697		} else {1698 1699			tcd = thermal_of_cooling_device_register(np_stcc,1700							 (char *)name, ts,1701							 &throt_cooling_ops);1702			if (IS_ERR_OR_NULL(tcd)) {1703				dev_err(dev,1704					"throttle-cfg: %s: failed to register cooling device\n",1705					name);1706				continue;1707			}1708			stc->cdev = tcd;1709			stc->init = true;1710		}1711 1712	}1713 1714	of_node_put(np_stc);1715}1716 1717/**1718 * throttlectl_cpu_level_cfg() - programs CCROC NV_THERM level config1719 * @ts: pointer to a struct tegra_soctherm1720 * @level: describing the level LOW/MED/HIGH of throttling1721 *1722 * It's necessary to set up the CPU-local CCROC NV_THERM instance with1723 * the M/N values desired for each level. This function does this.1724 *1725 * This function pre-programs the CCROC NV_THERM levels in terms of1726 * pre-configured "Low", "Medium" or "Heavy" throttle levels which are1727 * mapped to THROT_LEVEL_LOW, THROT_LEVEL_MED and THROT_LEVEL_HVY.1728 */1729static void throttlectl_cpu_level_cfg(struct tegra_soctherm *ts, int level)1730{1731	u8 depth, dividend;1732	u32 r;1733 1734	switch (level) {1735	case TEGRA_SOCTHERM_THROT_LEVEL_LOW:1736		depth = 50;1737		break;1738	case TEGRA_SOCTHERM_THROT_LEVEL_MED:1739		depth = 75;1740		break;1741	case TEGRA_SOCTHERM_THROT_LEVEL_HIGH:1742		depth = 80;1743		break;1744	case TEGRA_SOCTHERM_THROT_LEVEL_NONE:1745		return;1746	default:1747		return;1748	}1749 1750	dividend = THROT_DEPTH_DIVIDEND(depth);1751 1752	/* setup PSKIP in ccroc nv_therm registers */1753	r = ccroc_readl(ts, CCROC_THROT_PSKIP_RAMP_CPU_REG(level));1754	r = REG_SET_MASK(r, CCROC_THROT_PSKIP_RAMP_DURATION_MASK, 0xff);1755	r = REG_SET_MASK(r, CCROC_THROT_PSKIP_RAMP_STEP_MASK, 0xf);1756	ccroc_writel(ts, r, CCROC_THROT_PSKIP_RAMP_CPU_REG(level));1757 1758	r = ccroc_readl(ts, CCROC_THROT_PSKIP_CTRL_CPU_REG(level));1759	r = REG_SET_MASK(r, CCROC_THROT_PSKIP_CTRL_ENB_MASK, 1);1760	r = REG_SET_MASK(r, CCROC_THROT_PSKIP_CTRL_DIVIDEND_MASK, dividend);1761	r = REG_SET_MASK(r, CCROC_THROT_PSKIP_CTRL_DIVISOR_MASK, 0xff);1762	ccroc_writel(ts, r, CCROC_THROT_PSKIP_CTRL_CPU_REG(level));1763}1764 1765/**1766 * throttlectl_cpu_level_select() - program CPU pulse skipper config1767 * @ts: pointer to a struct tegra_soctherm1768 * @throt: the LIGHT/HEAVY of throttle event id1769 *1770 * Pulse skippers are used to throttle clock frequencies.  This1771 * function programs the pulse skippers based on @throt and platform1772 * data.  This function is used on SoCs which have CPU-local pulse1773 * skipper control, such as T13x. It programs soctherm's interface to1774 * Denver:CCROC NV_THERM in terms of Low, Medium and HIGH throttling1775 * vectors. PSKIP_BYPASS mode is set as required per HW spec.1776 */1777static void throttlectl_cpu_level_select(struct tegra_soctherm *ts,1778					 enum soctherm_throttle_id throt)1779{1780	u32 r, throt_vect;1781 1782	/* Denver:CCROC NV_THERM interface N:3 Mapping */1783	switch (ts->throt_cfgs[throt].cpu_throt_level) {1784	case TEGRA_SOCTHERM_THROT_LEVEL_LOW:1785		throt_vect = THROT_VECT_LOW;1786		break;1787	case TEGRA_SOCTHERM_THROT_LEVEL_MED:1788		throt_vect = THROT_VECT_MED;1789		break;1790	case TEGRA_SOCTHERM_THROT_LEVEL_HIGH:1791		throt_vect = THROT_VECT_HIGH;1792		break;1793	default:1794		throt_vect = THROT_VECT_NONE;1795		break;1796	}1797 1798	r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));1799	r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1);1800	r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT_CPU_MASK, throt_vect);1801	r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT2_CPU_MASK, throt_vect);1802	writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));1803 1804	/* bypass sequencer in soc_therm as it is programmed in ccroc */1805	r = REG_SET_MASK(0, THROT_PSKIP_RAMP_SEQ_BYPASS_MODE_MASK, 1);1806	writel(r, ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));1807}1808 1809/**1810 * throttlectl_cpu_mn() - program CPU pulse skipper configuration1811 * @ts: pointer to a struct tegra_soctherm1812 * @throt: the LIGHT/HEAVY of throttle event id1813 *1814 * Pulse skippers are used to throttle clock frequencies.  This1815 * function programs the pulse skippers based on @throt and platform1816 * data.  This function is used for CPUs that have "remote" pulse1817 * skipper control, e.g., the CPU pulse skipper is controlled by the1818 * SOC_THERM IP block.  (SOC_THERM is located outside the CPU1819 * complex.)1820 */1821static void throttlectl_cpu_mn(struct tegra_soctherm *ts,1822			       enum soctherm_throttle_id throt)1823{1824	u32 r;1825	int depth;1826	u8 dividend;1827 1828	depth = ts->throt_cfgs[throt].cpu_throt_depth;1829	dividend = THROT_DEPTH_DIVIDEND(depth);1830 1831	r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));1832	r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1);1833	r = REG_SET_MASK(r, THROT_PSKIP_CTRL_DIVIDEND_MASK, dividend);1834	r = REG_SET_MASK(r, THROT_PSKIP_CTRL_DIVISOR_MASK, 0xff);1835	writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_CPU));1836 1837	r = readl(ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));1838	r = REG_SET_MASK(r, THROT_PSKIP_RAMP_DURATION_MASK, 0xff);1839	r = REG_SET_MASK(r, THROT_PSKIP_RAMP_STEP_MASK, 0xf);1840	writel(r, ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));1841}1842 1843/**1844 * throttlectl_gpu_level_select() - selects throttling level for GPU1845 * @ts: pointer to a struct tegra_soctherm1846 * @throt: the LIGHT/HEAVY of throttle event id1847 *1848 * This function programs soctherm's interface to GK20a NV_THERM to select1849 * pre-configured "Low", "Medium" or "Heavy" throttle levels.1850 *1851 * Return: boolean true if HW was programmed1852 */1853static void throttlectl_gpu_level_select(struct tegra_soctherm *ts,1854					 enum soctherm_throttle_id throt)1855{1856	u32 r, level, throt_vect;1857 1858	level = ts->throt_cfgs[throt].gpu_throt_level;1859	throt_vect = THROT_LEVEL_TO_DEPTH(level);1860	r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_GPU));1861	r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1);1862	r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT_GPU_MASK, throt_vect);1863	writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_GPU));1864}1865 1866static int soctherm_oc_cfg_program(struct tegra_soctherm *ts,1867				      enum soctherm_throttle_id throt)1868{1869	u32 r;1870	struct soctherm_oc_cfg *oc = &ts->throt_cfgs[throt].oc_cfg;1871 1872	if (oc->mode == OC_THROTTLE_MODE_DISABLED)1873		return -EINVAL;1874 1875	r = REG_SET_MASK(0, OC1_CFG_HW_RESTORE_MASK, 1);1876	r = REG_SET_MASK(r, OC1_CFG_THROTTLE_MODE_MASK, oc->mode);1877	r = REG_SET_MASK(r, OC1_CFG_ALARM_POLARITY_MASK, oc->active_low);1878	r = REG_SET_MASK(r, OC1_CFG_EN_THROTTLE_MASK, 1);1879	writel(r, ts->regs + ALARM_CFG(throt));1880	writel(oc->throt_period, ts->regs + ALARM_THROTTLE_PERIOD(throt));1881	writel(oc->alarm_cnt_thresh, ts->regs + ALARM_CNT_THRESHOLD(throt));1882	writel(oc->alarm_filter, ts->regs + ALARM_FILTER(throt));1883	soctherm_oc_intr_enable(ts, throt, oc->intr_en);1884 1885	return 0;1886}1887 1888/**1889 * soctherm_throttle_program() - programs pulse skippers' configuration1890 * @ts: pointer to a struct tegra_soctherm1891 * @throt: the LIGHT/HEAVY of the throttle event id.1892 *1893 * Pulse skippers are used to throttle clock frequencies.1894 * This function programs the pulse skippers.1895 */1896static void soctherm_throttle_program(struct tegra_soctherm *ts,1897				      enum soctherm_throttle_id throt)1898{1899	u32 r;1900	struct soctherm_throt_cfg stc = ts->throt_cfgs[throt];1901 1902	if (!stc.init)1903		return;1904 1905	if ((throt >= THROTTLE_OC1) && (soctherm_oc_cfg_program(ts, throt)))1906		return;1907 1908	/* Setup PSKIP parameters */1909	if (ts->soc->use_ccroc)1910		throttlectl_cpu_level_select(ts, throt);1911	else1912		throttlectl_cpu_mn(ts, throt);1913 1914	throttlectl_gpu_level_select(ts, throt);1915 1916	r = REG_SET_MASK(0, THROT_PRIORITY_LITE_PRIO_MASK, stc.priority);1917	writel(r, ts->regs + THROT_PRIORITY_CTRL(throt));1918 1919	r = REG_SET_MASK(0, THROT_DELAY_LITE_DELAY_MASK, 0);1920	writel(r, ts->regs + THROT_DELAY_CTRL(throt));1921 1922	r = readl(ts->regs + THROT_PRIORITY_LOCK);1923	r = REG_GET_MASK(r, THROT_PRIORITY_LOCK_PRIORITY_MASK);1924	if (r >= stc.priority)1925		return;1926	r = REG_SET_MASK(0, THROT_PRIORITY_LOCK_PRIORITY_MASK,1927			 stc.priority);1928	writel(r, ts->regs + THROT_PRIORITY_LOCK);1929}1930 1931static void tegra_soctherm_throttle(struct device *dev)1932{1933	struct tegra_soctherm *ts = dev_get_drvdata(dev);1934	u32 v;1935	int i;1936 1937	/* configure LOW, MED and HIGH levels for CCROC NV_THERM */1938	if (ts->soc->use_ccroc) {1939		throttlectl_cpu_level_cfg(ts, TEGRA_SOCTHERM_THROT_LEVEL_LOW);1940		throttlectl_cpu_level_cfg(ts, TEGRA_SOCTHERM_THROT_LEVEL_MED);1941		throttlectl_cpu_level_cfg(ts, TEGRA_SOCTHERM_THROT_LEVEL_HIGH);1942	}1943 1944	/* Thermal HW throttle programming */1945	for (i = 0; i < THROTTLE_SIZE; i++)1946		soctherm_throttle_program(ts, i);1947 1948	v = REG_SET_MASK(0, THROT_GLOBAL_ENB_MASK, 1);1949	if (ts->soc->use_ccroc) {1950		ccroc_writel(ts, v, CCROC_GLOBAL_CFG);1951 1952		v = ccroc_readl(ts, CCROC_SUPER_CCLKG_DIVIDER);1953		v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1);1954		ccroc_writel(ts, v, CCROC_SUPER_CCLKG_DIVIDER);1955	} else {1956		writel(v, ts->regs + THROT_GLOBAL_CFG);1957 1958		v = readl(ts->clk_regs + CAR_SUPER_CCLKG_DIVIDER);1959		v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1);1960		writel(v, ts->clk_regs + CAR_SUPER_CCLKG_DIVIDER);1961	}1962 1963	/* initialize stats collection */1964	v = STATS_CTL_CLR_DN | STATS_CTL_EN_DN |1965	    STATS_CTL_CLR_UP | STATS_CTL_EN_UP;1966	writel(v, ts->regs + THERMCTL_STATS_CTL);1967}1968 1969static int soctherm_interrupts_init(struct platform_device *pdev,1970				    struct tegra_soctherm *tegra)1971{1972	struct device_node *np = pdev->dev.of_node;1973	int ret;1974 1975	ret = soctherm_oc_int_init(np, TEGRA_SOC_OC_IRQ_MAX);1976	if (ret < 0) {1977		dev_err(&pdev->dev, "soctherm_oc_int_init failed\n");1978		return ret;1979	}1980 1981	tegra->thermal_irq = platform_get_irq(pdev, 0);1982	if (tegra->thermal_irq < 0) {1983		dev_dbg(&pdev->dev, "get 'thermal_irq' failed.\n");1984		return 0;1985	}1986 1987	tegra->edp_irq = platform_get_irq(pdev, 1);1988	if (tegra->edp_irq < 0) {1989		dev_dbg(&pdev->dev, "get 'edp_irq' failed.\n");1990		return 0;1991	}1992 1993	ret = devm_request_threaded_irq(&pdev->dev,1994					tegra->thermal_irq,1995					soctherm_thermal_isr,1996					soctherm_thermal_isr_thread,1997					IRQF_ONESHOT,1998					dev_name(&pdev->dev),1999					tegra);2000	if (ret < 0) {2001		dev_err(&pdev->dev, "request_irq 'thermal_irq' failed.\n");2002		return ret;2003	}2004 2005	ret = devm_request_threaded_irq(&pdev->dev,2006					tegra->edp_irq,2007					soctherm_edp_isr,2008					soctherm_edp_isr_thread,2009					IRQF_ONESHOT,2010					"soctherm_edp",2011					tegra);2012	if (ret < 0) {2013		dev_err(&pdev->dev, "request_irq 'edp_irq' failed.\n");2014		return ret;2015	}2016 2017	return 0;2018}2019 2020static void soctherm_init(struct platform_device *pdev)2021{2022	struct tegra_soctherm *tegra = platform_get_drvdata(pdev);2023	const struct tegra_tsensor_group **ttgs = tegra->soc->ttgs;2024	int i;2025	u32 pdiv, hotspot;2026 2027	/* Initialize raw sensors */2028	for (i = 0; i < tegra->soc->num_tsensors; ++i)2029		enable_tsensor(tegra, i);2030 2031	/* program pdiv and hotspot offsets per THERM */2032	pdiv = readl(tegra->regs + SENSOR_PDIV);2033	hotspot = readl(tegra->regs + SENSOR_HOTSPOT_OFF);2034	for (i = 0; i < tegra->soc->num_ttgs; ++i) {2035		pdiv = REG_SET_MASK(pdiv, ttgs[i]->pdiv_mask,2036				    ttgs[i]->pdiv);2037		/* hotspot offset from PLLX, doesn't need to configure PLLX */2038		if (ttgs[i]->id == TEGRA124_SOCTHERM_SENSOR_PLLX)2039			continue;2040		hotspot =  REG_SET_MASK(hotspot,2041					ttgs[i]->pllx_hotspot_mask,2042					ttgs[i]->pllx_hotspot_diff);2043	}2044	writel(pdiv, tegra->regs + SENSOR_PDIV);2045	writel(hotspot, tegra->regs + SENSOR_HOTSPOT_OFF);2046 2047	/* Configure hw throttle */2048	tegra_soctherm_throttle(&pdev->dev);2049}2050 2051static const struct of_device_id tegra_soctherm_of_match[] = {2052#ifdef CONFIG_ARCH_TEGRA_124_SOC2053	{2054		.compatible = "nvidia,tegra124-soctherm",2055		.data = &tegra124_soctherm,2056	},2057#endif2058#ifdef CONFIG_ARCH_TEGRA_132_SOC2059	{2060		.compatible = "nvidia,tegra132-soctherm",2061		.data = &tegra132_soctherm,2062	},2063#endif2064#ifdef CONFIG_ARCH_TEGRA_210_SOC2065	{2066		.compatible = "nvidia,tegra210-soctherm",2067		.data = &tegra210_soctherm,2068	},2069#endif2070	{ },2071};2072MODULE_DEVICE_TABLE(of, tegra_soctherm_of_match);2073 2074static int tegra_soctherm_probe(struct platform_device *pdev)2075{2076	const struct of_device_id *match;2077	struct tegra_soctherm *tegra;2078	struct thermal_zone_device *z;2079	struct tsensor_shared_calib shared_calib;2080	struct tegra_soctherm_soc *soc;2081	unsigned int i;2082	int err;2083 2084	match = of_match_node(tegra_soctherm_of_match, pdev->dev.of_node);2085	if (!match)2086		return -ENODEV;2087 2088	soc = (struct tegra_soctherm_soc *)match->data;2089	if (soc->num_ttgs > TEGRA124_SOCTHERM_SENSOR_NUM)2090		return -EINVAL;2091 2092	tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);2093	if (!tegra)2094		return -ENOMEM;2095 2096	mutex_init(&tegra->thermctl_lock);2097	dev_set_drvdata(&pdev->dev, tegra);2098 2099	tegra->soc = soc;2100 2101	tegra->regs = devm_platform_ioremap_resource_byname(pdev, "soctherm-reg");2102	if (IS_ERR(tegra->regs)) {2103		dev_err(&pdev->dev, "can't get soctherm registers");2104		return PTR_ERR(tegra->regs);2105	}2106 2107	if (!tegra->soc->use_ccroc) {2108		tegra->clk_regs = devm_platform_ioremap_resource_byname(pdev, "car-reg");2109		if (IS_ERR(tegra->clk_regs)) {2110			dev_err(&pdev->dev, "can't get car clk registers");2111			return PTR_ERR(tegra->clk_regs);2112		}2113	} else {2114		tegra->ccroc_regs = devm_platform_ioremap_resource_byname(pdev, "ccroc-reg");2115		if (IS_ERR(tegra->ccroc_regs)) {2116			dev_err(&pdev->dev, "can't get ccroc registers");2117			return PTR_ERR(tegra->ccroc_regs);2118		}2119	}2120 2121	tegra->reset = devm_reset_control_get(&pdev->dev, "soctherm");2122	if (IS_ERR(tegra->reset)) {2123		dev_err(&pdev->dev, "can't get soctherm reset\n");2124		return PTR_ERR(tegra->reset);2125	}2126 2127	tegra->clock_tsensor = devm_clk_get(&pdev->dev, "tsensor");2128	if (IS_ERR(tegra->clock_tsensor)) {2129		dev_err(&pdev->dev, "can't get tsensor clock\n");2130		return PTR_ERR(tegra->clock_tsensor);2131	}2132 2133	tegra->clock_soctherm = devm_clk_get(&pdev->dev, "soctherm");2134	if (IS_ERR(tegra->clock_soctherm)) {2135		dev_err(&pdev->dev, "can't get soctherm clock\n");2136		return PTR_ERR(tegra->clock_soctherm);2137	}2138 2139	tegra->calib = devm_kcalloc(&pdev->dev,2140				    soc->num_tsensors, sizeof(u32),2141				    GFP_KERNEL);2142	if (!tegra->calib)2143		return -ENOMEM;2144 2145	/* calculate shared calibration data */2146	err = tegra_calc_shared_calib(soc->tfuse, &shared_calib);2147	if (err)2148		return err;2149 2150	/* calculate tsensor calibration data */2151	for (i = 0; i < soc->num_tsensors; ++i) {2152		err = tegra_calc_tsensor_calib(&soc->tsensors[i],2153					       &shared_calib,2154					       &tegra->calib[i]);2155		if (err)2156			return err;2157	}2158 2159	tegra->thermctl_tzs = devm_kcalloc(&pdev->dev,2160					   soc->num_ttgs, sizeof(z),2161					   GFP_KERNEL);2162	if (!tegra->thermctl_tzs)2163		return -ENOMEM;2164 2165	err = soctherm_clk_enable(pdev, true);2166	if (err)2167		return err;2168 2169	soctherm_thermtrips_parse(pdev);2170 2171	soctherm_init_hw_throt_cdev(pdev);2172 2173	soctherm_init(pdev);2174 2175	for (i = 0; i < soc->num_ttgs; ++i) {2176		struct tegra_thermctl_zone *zone =2177			devm_kzalloc(&pdev->dev, sizeof(*zone), GFP_KERNEL);2178		if (!zone) {2179			err = -ENOMEM;2180			goto disable_clocks;2181		}2182 2183		zone->reg = tegra->regs + soc->ttgs[i]->sensor_temp_offset;2184		zone->dev = &pdev->dev;2185		zone->sg = soc->ttgs[i];2186		zone->ts = tegra;2187 2188		z = devm_thermal_of_zone_register(&pdev->dev,2189						  soc->ttgs[i]->id, zone,2190						  &tegra_of_thermal_ops);2191		if (IS_ERR(z)) {2192			err = PTR_ERR(z);2193			dev_err(&pdev->dev, "failed to register sensor: %d\n",2194				err);2195			goto disable_clocks;2196		}2197 2198		zone->tz = z;2199		tegra->thermctl_tzs[soc->ttgs[i]->id] = z;2200 2201		/* Configure hw trip points */2202		err = tegra_soctherm_set_hwtrips(&pdev->dev, soc->ttgs[i], z);2203		if (err)2204			goto disable_clocks;2205	}2206 2207	err = soctherm_interrupts_init(pdev, tegra);2208 2209	soctherm_debug_init(pdev);2210 2211	return 0;2212 2213disable_clocks:2214	soctherm_clk_enable(pdev, false);2215 2216	return err;2217}2218 2219static void tegra_soctherm_remove(struct platform_device *pdev)2220{2221	struct tegra_soctherm *tegra = platform_get_drvdata(pdev);2222 2223	debugfs_remove_recursive(tegra->debugfs_dir);2224 2225	soctherm_clk_enable(pdev, false);2226}2227 2228static int __maybe_unused soctherm_suspend(struct device *dev)2229{2230	struct platform_device *pdev = to_platform_device(dev);2231 2232	soctherm_clk_enable(pdev, false);2233 2234	return 0;2235}2236 2237static int __maybe_unused soctherm_resume(struct device *dev)2238{2239	struct platform_device *pdev = to_platform_device(dev);2240	struct tegra_soctherm *tegra = platform_get_drvdata(pdev);2241	struct tegra_soctherm_soc *soc = tegra->soc;2242	int err, i;2243 2244	err = soctherm_clk_enable(pdev, true);2245	if (err) {2246		dev_err(&pdev->dev,2247			"Resume failed: enable clocks failed\n");2248		return err;2249	}2250 2251	soctherm_init(pdev);2252 2253	for (i = 0; i < soc->num_ttgs; ++i) {2254		struct thermal_zone_device *tz;2255 2256		tz = tegra->thermctl_tzs[soc->ttgs[i]->id];2257		err = tegra_soctherm_set_hwtrips(dev, soc->ttgs[i], tz);2258		if (err) {2259			dev_err(&pdev->dev,2260				"Resume failed: set hwtrips failed\n");2261			return err;2262		}2263	}2264 2265	return 0;2266}2267 2268static SIMPLE_DEV_PM_OPS(tegra_soctherm_pm, soctherm_suspend, soctherm_resume);2269 2270static struct platform_driver tegra_soctherm_driver = {2271	.probe = tegra_soctherm_probe,2272	.remove_new = tegra_soctherm_remove,2273	.driver = {2274		.name = "tegra_soctherm",2275		.pm = &tegra_soctherm_pm,2276		.of_match_table = tegra_soctherm_of_match,2277	},2278};2279module_platform_driver(tegra_soctherm_driver);2280 2281MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");2282MODULE_DESCRIPTION("NVIDIA Tegra SOCTHERM thermal management driver");2283MODULE_LICENSE("GPL v2");2284