Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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