xref: /openbmc/linux/drivers/soc/mediatek/mtk-svs.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1681a02e9SRoger Lu // SPDX-License-Identifier: GPL-2.0-only
2681a02e9SRoger Lu /*
3681a02e9SRoger Lu  * Copyright (C) 2022 MediaTek Inc.
4681a02e9SRoger Lu  */
5681a02e9SRoger Lu 
69d0d887aSNícolas F. R. A. Prado #include <linux/bitfield.h>
7681a02e9SRoger Lu #include <linux/bits.h>
8681a02e9SRoger Lu #include <linux/clk.h>
9681a02e9SRoger Lu #include <linux/completion.h>
10*26c68267SRob Herring #include <linux/cpu.h>
11681a02e9SRoger Lu #include <linux/cpuidle.h>
1213f1bbcfSRoger Lu #include <linux/debugfs.h>
13681a02e9SRoger Lu #include <linux/device.h>
14681a02e9SRoger Lu #include <linux/init.h>
15681a02e9SRoger Lu #include <linux/interrupt.h>
16681a02e9SRoger Lu #include <linux/kernel.h>
17681a02e9SRoger Lu #include <linux/kthread.h>
18681a02e9SRoger Lu #include <linux/module.h>
19681a02e9SRoger Lu #include <linux/mutex.h>
20681a02e9SRoger Lu #include <linux/nvmem-consumer.h>
21681a02e9SRoger Lu #include <linux/of_address.h>
22681a02e9SRoger Lu #include <linux/of_irq.h>
23681a02e9SRoger Lu #include <linux/of_platform.h>
24681a02e9SRoger Lu #include <linux/platform_device.h>
25681a02e9SRoger Lu #include <linux/pm_domain.h>
26681a02e9SRoger Lu #include <linux/pm_opp.h>
27681a02e9SRoger Lu #include <linux/pm_runtime.h>
28681a02e9SRoger Lu #include <linux/regulator/consumer.h>
290bbb09b2SRoger Lu #include <linux/reset.h>
3013f1bbcfSRoger Lu #include <linux/seq_file.h>
31681a02e9SRoger Lu #include <linux/slab.h>
32681a02e9SRoger Lu #include <linux/spinlock.h>
336c692719SRoger Lu #include <linux/thermal.h>
34681a02e9SRoger Lu 
35681a02e9SRoger Lu /* svs bank 1-line software id */
36681a02e9SRoger Lu #define SVSB_CPU_LITTLE			BIT(0)
37681a02e9SRoger Lu #define SVSB_CPU_BIG			BIT(1)
38681a02e9SRoger Lu #define SVSB_CCI			BIT(2)
39681a02e9SRoger Lu #define SVSB_GPU			BIT(3)
40681a02e9SRoger Lu 
410bbb09b2SRoger Lu /* svs bank 2-line type */
420bbb09b2SRoger Lu #define SVSB_LOW			BIT(8)
430bbb09b2SRoger Lu #define SVSB_HIGH			BIT(9)
440bbb09b2SRoger Lu 
45681a02e9SRoger Lu /* svs bank mode support */
46681a02e9SRoger Lu #define SVSB_MODE_ALL_DISABLE		0
47681a02e9SRoger Lu #define SVSB_MODE_INIT01		BIT(1)
48681a02e9SRoger Lu #define SVSB_MODE_INIT02		BIT(2)
496c692719SRoger Lu #define SVSB_MODE_MON			BIT(3)
50681a02e9SRoger Lu 
51681a02e9SRoger Lu /* svs bank volt flags */
52681a02e9SRoger Lu #define SVSB_INIT01_PD_REQ		BIT(0)
53681a02e9SRoger Lu #define SVSB_INIT01_VOLT_IGNORE		BIT(1)
54681a02e9SRoger Lu #define SVSB_INIT01_VOLT_INC_ONLY	BIT(2)
550bbb09b2SRoger Lu #define SVSB_MON_VOLT_IGNORE		BIT(16)
560bbb09b2SRoger Lu #define SVSB_REMOVE_DVTFIXED_VOLT	BIT(24)
57681a02e9SRoger Lu 
58a92438c5SAngeloGioacchino Del Regno /* svs bank register fields and common configuration */
59a92438c5SAngeloGioacchino Del Regno #define SVSB_PTPCONFIG_DETMAX		GENMASK(15, 0)
60a92438c5SAngeloGioacchino Del Regno #define SVSB_DET_MAX			FIELD_PREP(SVSB_PTPCONFIG_DETMAX, 0xffff)
61681a02e9SRoger Lu #define SVSB_DET_WINDOW			0xa28
62a92438c5SAngeloGioacchino Del Regno 
63a92438c5SAngeloGioacchino Del Regno /* DESCHAR */
64a92438c5SAngeloGioacchino Del Regno #define SVSB_DESCHAR_FLD_MDES		GENMASK(7, 0)
65a92438c5SAngeloGioacchino Del Regno #define SVSB_DESCHAR_FLD_BDES		GENMASK(15, 8)
66a92438c5SAngeloGioacchino Del Regno 
67a92438c5SAngeloGioacchino Del Regno /* TEMPCHAR */
68a92438c5SAngeloGioacchino Del Regno #define SVSB_TEMPCHAR_FLD_DVT_FIXED	GENMASK(7, 0)
69a92438c5SAngeloGioacchino Del Regno #define SVSB_TEMPCHAR_FLD_MTDES		GENMASK(15, 8)
70a92438c5SAngeloGioacchino Del Regno #define SVSB_TEMPCHAR_FLD_VCO		GENMASK(23, 16)
71a92438c5SAngeloGioacchino Del Regno 
72a92438c5SAngeloGioacchino Del Regno /* DETCHAR */
73a92438c5SAngeloGioacchino Del Regno #define SVSB_DETCHAR_FLD_DCMDET		GENMASK(7, 0)
74a92438c5SAngeloGioacchino Del Regno #define SVSB_DETCHAR_FLD_DCBDET		GENMASK(15, 8)
75a92438c5SAngeloGioacchino Del Regno 
76a92438c5SAngeloGioacchino Del Regno /* SVSEN (PTPEN) */
77a92438c5SAngeloGioacchino Del Regno #define SVSB_PTPEN_INIT01		BIT(0)
78a92438c5SAngeloGioacchino Del Regno #define SVSB_PTPEN_MON			BIT(1)
79a92438c5SAngeloGioacchino Del Regno #define SVSB_PTPEN_INIT02		(SVSB_PTPEN_INIT01 | BIT(2))
80a92438c5SAngeloGioacchino Del Regno #define SVSB_PTPEN_OFF			0x0
81a92438c5SAngeloGioacchino Del Regno 
82a92438c5SAngeloGioacchino Del Regno /* FREQPCTS */
83a92438c5SAngeloGioacchino Del Regno #define SVSB_FREQPCTS_FLD_PCT0_4	GENMASK(7, 0)
84a92438c5SAngeloGioacchino Del Regno #define SVSB_FREQPCTS_FLD_PCT1_5	GENMASK(15, 8)
85a92438c5SAngeloGioacchino Del Regno #define SVSB_FREQPCTS_FLD_PCT2_6	GENMASK(23, 16)
86a92438c5SAngeloGioacchino Del Regno #define SVSB_FREQPCTS_FLD_PCT3_7	GENMASK(31, 24)
87a92438c5SAngeloGioacchino Del Regno 
88a92438c5SAngeloGioacchino Del Regno /* INTSTS */
89a92438c5SAngeloGioacchino Del Regno #define SVSB_INTSTS_VAL_CLEAN		0x00ffffff
90a92438c5SAngeloGioacchino Del Regno #define SVSB_INTSTS_F0_COMPLETE		BIT(0)
91a92438c5SAngeloGioacchino Del Regno #define SVSB_INTSTS_FLD_MONVOP		GENMASK(23, 16)
92681a02e9SRoger Lu #define SVSB_RUNCONFIG_DEFAULT		0x80000000
93681a02e9SRoger Lu 
94a92438c5SAngeloGioacchino Del Regno /* LIMITVALS */
95a92438c5SAngeloGioacchino Del Regno #define SVSB_LIMITVALS_FLD_DTLO		GENMASK(7, 0)
96a92438c5SAngeloGioacchino Del Regno #define SVSB_LIMITVALS_FLD_DTHI		GENMASK(15, 8)
97a92438c5SAngeloGioacchino Del Regno #define SVSB_LIMITVALS_FLD_VMIN		GENMASK(23, 16)
98a92438c5SAngeloGioacchino Del Regno #define SVSB_LIMITVALS_FLD_VMAX		GENMASK(31, 24)
99a92438c5SAngeloGioacchino Del Regno #define SVSB_VAL_DTHI			0x1
100a92438c5SAngeloGioacchino Del Regno #define SVSB_VAL_DTLO			0xfe
101a92438c5SAngeloGioacchino Del Regno 
102a92438c5SAngeloGioacchino Del Regno /* INTEN */
103a92438c5SAngeloGioacchino Del Regno #define SVSB_INTEN_F0EN			BIT(0)
104a92438c5SAngeloGioacchino Del Regno #define SVSB_INTEN_DACK0UPEN		BIT(8)
105a92438c5SAngeloGioacchino Del Regno #define SVSB_INTEN_DC0EN		BIT(9)
106a92438c5SAngeloGioacchino Del Regno #define SVSB_INTEN_DC1EN		BIT(10)
107a92438c5SAngeloGioacchino Del Regno #define SVSB_INTEN_DACK0LOEN		BIT(11)
108a92438c5SAngeloGioacchino Del Regno #define SVSB_INTEN_INITPROD_OVF_EN	BIT(12)
109a92438c5SAngeloGioacchino Del Regno #define SVSB_INTEN_INITSUM_OVF_EN	BIT(14)
110a92438c5SAngeloGioacchino Del Regno #define SVSB_INTEN_MONVOPEN		GENMASK(23, 16)
111a92438c5SAngeloGioacchino Del Regno #define SVSB_INTEN_INIT0x		(SVSB_INTEN_F0EN | SVSB_INTEN_DACK0UPEN |	\
112a92438c5SAngeloGioacchino Del Regno 					 SVSB_INTEN_DC0EN | SVSB_INTEN_DC1EN |		\
113a92438c5SAngeloGioacchino Del Regno 					 SVSB_INTEN_DACK0LOEN |				\
114a92438c5SAngeloGioacchino Del Regno 					 SVSB_INTEN_INITPROD_OVF_EN |			\
115a92438c5SAngeloGioacchino Del Regno 					 SVSB_INTEN_INITSUM_OVF_EN)
116a92438c5SAngeloGioacchino Del Regno 
117a92438c5SAngeloGioacchino Del Regno /* TSCALCS */
118a92438c5SAngeloGioacchino Del Regno #define SVSB_TSCALCS_FLD_MTS		GENMASK(11, 0)
119a92438c5SAngeloGioacchino Del Regno #define SVSB_TSCALCS_FLD_BTS		GENMASK(23, 12)
120a92438c5SAngeloGioacchino Del Regno 
121a92438c5SAngeloGioacchino Del Regno /* INIT2VALS */
122a92438c5SAngeloGioacchino Del Regno #define SVSB_INIT2VALS_FLD_DCVOFFSETIN	GENMASK(15, 0)
123a92438c5SAngeloGioacchino Del Regno #define SVSB_INIT2VALS_FLD_AGEVOFFSETIN	GENMASK(31, 16)
124a92438c5SAngeloGioacchino Del Regno 
125a92438c5SAngeloGioacchino Del Regno /* VOPS */
126a92438c5SAngeloGioacchino Del Regno #define SVSB_VOPS_FLD_VOP0_4		GENMASK(7, 0)
127a92438c5SAngeloGioacchino Del Regno #define SVSB_VOPS_FLD_VOP1_5		GENMASK(15, 8)
128a92438c5SAngeloGioacchino Del Regno #define SVSB_VOPS_FLD_VOP2_6		GENMASK(23, 16)
129a92438c5SAngeloGioacchino Del Regno #define SVSB_VOPS_FLD_VOP3_7		GENMASK(31, 24)
130a92438c5SAngeloGioacchino Del Regno 
131681a02e9SRoger Lu /* svs bank related setting */
1320bbb09b2SRoger Lu #define BITS8				8
133681a02e9SRoger Lu #define MAX_OPP_ENTRIES			16
1340bbb09b2SRoger Lu #define REG_BYTES			4
135681a02e9SRoger Lu #define SVSB_DC_SIGNED_BIT		BIT(15)
136681a02e9SRoger Lu #define SVSB_DET_CLK_EN			BIT(31)
1376c692719SRoger Lu #define SVSB_TEMP_LOWER_BOUND		0xb2
1386c692719SRoger Lu #define SVSB_TEMP_UPPER_BOUND		0x64
139681a02e9SRoger Lu 
140681a02e9SRoger Lu static DEFINE_SPINLOCK(svs_lock);
141681a02e9SRoger Lu 
1428bf30508SRoger Lu #ifdef CONFIG_DEBUG_FS
14313f1bbcfSRoger Lu #define debug_fops_ro(name)						\
14413f1bbcfSRoger Lu 	static int svs_##name##_debug_open(struct inode *inode,		\
14513f1bbcfSRoger Lu 					   struct file *filp)		\
14613f1bbcfSRoger Lu 	{								\
14713f1bbcfSRoger Lu 		return single_open(filp, svs_##name##_debug_show,	\
14813f1bbcfSRoger Lu 				   inode->i_private);			\
14913f1bbcfSRoger Lu 	}								\
15013f1bbcfSRoger Lu 	static const struct file_operations svs_##name##_debug_fops = {	\
15113f1bbcfSRoger Lu 		.owner = THIS_MODULE,					\
15213f1bbcfSRoger Lu 		.open = svs_##name##_debug_open,			\
15313f1bbcfSRoger Lu 		.read = seq_read,					\
15413f1bbcfSRoger Lu 		.llseek = seq_lseek,					\
15513f1bbcfSRoger Lu 		.release = single_release,				\
15613f1bbcfSRoger Lu 	}
15713f1bbcfSRoger Lu 
15813f1bbcfSRoger Lu #define debug_fops_rw(name)						\
15913f1bbcfSRoger Lu 	static int svs_##name##_debug_open(struct inode *inode,		\
16013f1bbcfSRoger Lu 					   struct file *filp)		\
16113f1bbcfSRoger Lu 	{								\
16213f1bbcfSRoger Lu 		return single_open(filp, svs_##name##_debug_show,	\
16313f1bbcfSRoger Lu 				   inode->i_private);			\
16413f1bbcfSRoger Lu 	}								\
16513f1bbcfSRoger Lu 	static const struct file_operations svs_##name##_debug_fops = {	\
16613f1bbcfSRoger Lu 		.owner = THIS_MODULE,					\
16713f1bbcfSRoger Lu 		.open = svs_##name##_debug_open,			\
16813f1bbcfSRoger Lu 		.read = seq_read,					\
16913f1bbcfSRoger Lu 		.write = svs_##name##_debug_write,			\
17013f1bbcfSRoger Lu 		.llseek = seq_lseek,					\
17113f1bbcfSRoger Lu 		.release = single_release,				\
17213f1bbcfSRoger Lu 	}
17313f1bbcfSRoger Lu 
17413f1bbcfSRoger Lu #define svs_dentry_data(name)	{__stringify(name), &svs_##name##_debug_fops}
1758bf30508SRoger Lu #endif
17613f1bbcfSRoger Lu 
177681a02e9SRoger Lu /**
178681a02e9SRoger Lu  * enum svsb_phase - svs bank phase enumeration
179681a02e9SRoger Lu  * @SVSB_PHASE_ERROR: svs bank encounters unexpected condition
180681a02e9SRoger Lu  * @SVSB_PHASE_INIT01: svs bank basic init for data calibration
181681a02e9SRoger Lu  * @SVSB_PHASE_INIT02: svs bank can provide voltages to opp table
1826c692719SRoger Lu  * @SVSB_PHASE_MON: svs bank can provide voltages with thermal effect
183681a02e9SRoger Lu  * @SVSB_PHASE_MAX: total number of svs bank phase (debug purpose)
184681a02e9SRoger Lu  *
185681a02e9SRoger Lu  * Each svs bank has its own independent phase and we enable each svs bank by
186681a02e9SRoger Lu  * running their phase orderly. However, when svs bank encounters unexpected
187681a02e9SRoger Lu  * condition, it will fire an irq (PHASE_ERROR) to inform svs software.
188681a02e9SRoger Lu  *
189681a02e9SRoger Lu  * svs bank general phase-enabled order:
1906c692719SRoger Lu  * SVSB_PHASE_INIT01 -> SVSB_PHASE_INIT02 -> SVSB_PHASE_MON
191681a02e9SRoger Lu  */
192681a02e9SRoger Lu enum svsb_phase {
193681a02e9SRoger Lu 	SVSB_PHASE_ERROR = 0,
194681a02e9SRoger Lu 	SVSB_PHASE_INIT01,
195681a02e9SRoger Lu 	SVSB_PHASE_INIT02,
1966c692719SRoger Lu 	SVSB_PHASE_MON,
197681a02e9SRoger Lu 	SVSB_PHASE_MAX,
198681a02e9SRoger Lu };
199681a02e9SRoger Lu 
200681a02e9SRoger Lu enum svs_reg_index {
201681a02e9SRoger Lu 	DESCHAR = 0,
202681a02e9SRoger Lu 	TEMPCHAR,
203681a02e9SRoger Lu 	DETCHAR,
204681a02e9SRoger Lu 	AGECHAR,
205681a02e9SRoger Lu 	DCCONFIG,
206681a02e9SRoger Lu 	AGECONFIG,
207681a02e9SRoger Lu 	FREQPCT30,
208681a02e9SRoger Lu 	FREQPCT74,
209681a02e9SRoger Lu 	LIMITVALS,
210681a02e9SRoger Lu 	VBOOT,
211681a02e9SRoger Lu 	DETWINDOW,
212681a02e9SRoger Lu 	CONFIG,
213681a02e9SRoger Lu 	TSCALCS,
214681a02e9SRoger Lu 	RUNCONFIG,
215681a02e9SRoger Lu 	SVSEN,
216681a02e9SRoger Lu 	INIT2VALS,
217681a02e9SRoger Lu 	DCVALUES,
218681a02e9SRoger Lu 	AGEVALUES,
219681a02e9SRoger Lu 	VOP30,
220681a02e9SRoger Lu 	VOP74,
221681a02e9SRoger Lu 	TEMP,
222681a02e9SRoger Lu 	INTSTS,
223681a02e9SRoger Lu 	INTSTSRAW,
224681a02e9SRoger Lu 	INTEN,
225681a02e9SRoger Lu 	CHKINT,
226681a02e9SRoger Lu 	CHKSHIFT,
227681a02e9SRoger Lu 	STATUS,
228681a02e9SRoger Lu 	VDESIGN30,
229681a02e9SRoger Lu 	VDESIGN74,
230681a02e9SRoger Lu 	DVT30,
231681a02e9SRoger Lu 	DVT74,
232681a02e9SRoger Lu 	AGECOUNT,
233681a02e9SRoger Lu 	SMSTATE0,
234681a02e9SRoger Lu 	SMSTATE1,
235681a02e9SRoger Lu 	CTL0,
236681a02e9SRoger Lu 	DESDETSEC,
237681a02e9SRoger Lu 	TEMPAGESEC,
238681a02e9SRoger Lu 	CTRLSPARE0,
239681a02e9SRoger Lu 	CTRLSPARE1,
240681a02e9SRoger Lu 	CTRLSPARE2,
241681a02e9SRoger Lu 	CTRLSPARE3,
242681a02e9SRoger Lu 	CORESEL,
243681a02e9SRoger Lu 	THERMINTST,
244681a02e9SRoger Lu 	INTST,
245681a02e9SRoger Lu 	THSTAGE0ST,
246681a02e9SRoger Lu 	THSTAGE1ST,
247681a02e9SRoger Lu 	THSTAGE2ST,
248681a02e9SRoger Lu 	THAHBST0,
249681a02e9SRoger Lu 	THAHBST1,
250681a02e9SRoger Lu 	SPARE0,
251681a02e9SRoger Lu 	SPARE1,
252681a02e9SRoger Lu 	SPARE2,
253681a02e9SRoger Lu 	SPARE3,
254681a02e9SRoger Lu 	THSLPEVEB,
255681a02e9SRoger Lu 	SVS_REG_MAX,
256681a02e9SRoger Lu };
257681a02e9SRoger Lu 
258681a02e9SRoger Lu static const u32 svs_regs_v2[] = {
259681a02e9SRoger Lu 	[DESCHAR]		= 0xc00,
260681a02e9SRoger Lu 	[TEMPCHAR]		= 0xc04,
261681a02e9SRoger Lu 	[DETCHAR]		= 0xc08,
262681a02e9SRoger Lu 	[AGECHAR]		= 0xc0c,
263681a02e9SRoger Lu 	[DCCONFIG]		= 0xc10,
264681a02e9SRoger Lu 	[AGECONFIG]		= 0xc14,
265681a02e9SRoger Lu 	[FREQPCT30]		= 0xc18,
266681a02e9SRoger Lu 	[FREQPCT74]		= 0xc1c,
267681a02e9SRoger Lu 	[LIMITVALS]		= 0xc20,
268681a02e9SRoger Lu 	[VBOOT]			= 0xc24,
269681a02e9SRoger Lu 	[DETWINDOW]		= 0xc28,
270681a02e9SRoger Lu 	[CONFIG]		= 0xc2c,
271681a02e9SRoger Lu 	[TSCALCS]		= 0xc30,
272681a02e9SRoger Lu 	[RUNCONFIG]		= 0xc34,
273681a02e9SRoger Lu 	[SVSEN]			= 0xc38,
274681a02e9SRoger Lu 	[INIT2VALS]		= 0xc3c,
275681a02e9SRoger Lu 	[DCVALUES]		= 0xc40,
276681a02e9SRoger Lu 	[AGEVALUES]		= 0xc44,
277681a02e9SRoger Lu 	[VOP30]			= 0xc48,
278681a02e9SRoger Lu 	[VOP74]			= 0xc4c,
279681a02e9SRoger Lu 	[TEMP]			= 0xc50,
280681a02e9SRoger Lu 	[INTSTS]		= 0xc54,
281681a02e9SRoger Lu 	[INTSTSRAW]		= 0xc58,
282681a02e9SRoger Lu 	[INTEN]			= 0xc5c,
283681a02e9SRoger Lu 	[CHKINT]		= 0xc60,
284681a02e9SRoger Lu 	[CHKSHIFT]		= 0xc64,
285681a02e9SRoger Lu 	[STATUS]		= 0xc68,
286681a02e9SRoger Lu 	[VDESIGN30]		= 0xc6c,
287681a02e9SRoger Lu 	[VDESIGN74]		= 0xc70,
288681a02e9SRoger Lu 	[DVT30]			= 0xc74,
289681a02e9SRoger Lu 	[DVT74]			= 0xc78,
290681a02e9SRoger Lu 	[AGECOUNT]		= 0xc7c,
291681a02e9SRoger Lu 	[SMSTATE0]		= 0xc80,
292681a02e9SRoger Lu 	[SMSTATE1]		= 0xc84,
293681a02e9SRoger Lu 	[CTL0]			= 0xc88,
294681a02e9SRoger Lu 	[DESDETSEC]		= 0xce0,
295681a02e9SRoger Lu 	[TEMPAGESEC]		= 0xce4,
296681a02e9SRoger Lu 	[CTRLSPARE0]		= 0xcf0,
297681a02e9SRoger Lu 	[CTRLSPARE1]		= 0xcf4,
298681a02e9SRoger Lu 	[CTRLSPARE2]		= 0xcf8,
299681a02e9SRoger Lu 	[CTRLSPARE3]		= 0xcfc,
300681a02e9SRoger Lu 	[CORESEL]		= 0xf00,
301681a02e9SRoger Lu 	[THERMINTST]		= 0xf04,
302681a02e9SRoger Lu 	[INTST]			= 0xf08,
303681a02e9SRoger Lu 	[THSTAGE0ST]		= 0xf0c,
304681a02e9SRoger Lu 	[THSTAGE1ST]		= 0xf10,
305681a02e9SRoger Lu 	[THSTAGE2ST]		= 0xf14,
306681a02e9SRoger Lu 	[THAHBST0]		= 0xf18,
307681a02e9SRoger Lu 	[THAHBST1]		= 0xf1c,
308681a02e9SRoger Lu 	[SPARE0]		= 0xf20,
309681a02e9SRoger Lu 	[SPARE1]		= 0xf24,
310681a02e9SRoger Lu 	[SPARE2]		= 0xf28,
311681a02e9SRoger Lu 	[SPARE3]		= 0xf2c,
312681a02e9SRoger Lu 	[THSLPEVEB]		= 0xf30,
313681a02e9SRoger Lu };
314681a02e9SRoger Lu 
315681a02e9SRoger Lu /**
316681a02e9SRoger Lu  * struct svs_platform - svs platform control
317681a02e9SRoger Lu  * @base: svs platform register base
318681a02e9SRoger Lu  * @dev: svs platform device
319681a02e9SRoger Lu  * @main_clk: main clock for svs bank
320681a02e9SRoger Lu  * @pbank: svs bank pointer needing to be protected by spin_lock section
321681a02e9SRoger Lu  * @banks: svs banks that svs platform supports
3220bbb09b2SRoger Lu  * @rst: svs platform reset control
323681a02e9SRoger Lu  * @efuse_max: total number of svs efuse
3246c692719SRoger Lu  * @tefuse_max: total number of thermal efuse
325681a02e9SRoger Lu  * @regs: svs platform registers map
326681a02e9SRoger Lu  * @bank_max: total number of svs banks
327681a02e9SRoger Lu  * @efuse: svs efuse data received from NVMEM framework
3286c692719SRoger Lu  * @tefuse: thermal efuse data received from NVMEM framework
329681a02e9SRoger Lu  */
330681a02e9SRoger Lu struct svs_platform {
331681a02e9SRoger Lu 	void __iomem *base;
332681a02e9SRoger Lu 	struct device *dev;
333681a02e9SRoger Lu 	struct clk *main_clk;
334681a02e9SRoger Lu 	struct svs_bank *pbank;
335681a02e9SRoger Lu 	struct svs_bank *banks;
3360bbb09b2SRoger Lu 	struct reset_control *rst;
337681a02e9SRoger Lu 	size_t efuse_max;
3386c692719SRoger Lu 	size_t tefuse_max;
339681a02e9SRoger Lu 	const u32 *regs;
340681a02e9SRoger Lu 	u32 bank_max;
341681a02e9SRoger Lu 	u32 *efuse;
3426c692719SRoger Lu 	u32 *tefuse;
343681a02e9SRoger Lu };
344681a02e9SRoger Lu 
345681a02e9SRoger Lu struct svs_platform_data {
346681a02e9SRoger Lu 	char *name;
347681a02e9SRoger Lu 	struct svs_bank *banks;
348681a02e9SRoger Lu 	bool (*efuse_parsing)(struct svs_platform *svsp);
349681a02e9SRoger Lu 	int (*probe)(struct svs_platform *svsp);
350681a02e9SRoger Lu 	const u32 *regs;
351681a02e9SRoger Lu 	u32 bank_max;
352681a02e9SRoger Lu };
353681a02e9SRoger Lu 
354681a02e9SRoger Lu /**
355681a02e9SRoger Lu  * struct svs_bank - svs bank representation
356681a02e9SRoger Lu  * @dev: bank device
357681a02e9SRoger Lu  * @opp_dev: device for opp table/buck control
358681a02e9SRoger Lu  * @init_completion: the timeout completion for bank init
359681a02e9SRoger Lu  * @buck: regulator used by opp_dev
3606c692719SRoger Lu  * @tzd: thermal zone device for getting temperature
361681a02e9SRoger Lu  * @lock: mutex lock to protect voltage update process
362681a02e9SRoger Lu  * @set_freq_pct: function pointer to set bank frequency percent table
363681a02e9SRoger Lu  * @get_volts: function pointer to get bank voltages
364681a02e9SRoger Lu  * @name: bank name
365681a02e9SRoger Lu  * @buck_name: regulator name
3666c692719SRoger Lu  * @tzone_name: thermal zone name
367681a02e9SRoger Lu  * @phase: bank current phase
368681a02e9SRoger Lu  * @volt_od: bank voltage overdrive
36913f1bbcfSRoger Lu  * @reg_data: bank register data in different phase for debug purpose
370681a02e9SRoger Lu  * @pm_runtime_enabled_count: bank pm runtime enabled count
371681a02e9SRoger Lu  * @mode_support: bank mode support.
372681a02e9SRoger Lu  * @freq_base: reference frequency for bank init
3730bbb09b2SRoger Lu  * @turn_freq_base: refenrece frequency for 2-line turn point
374681a02e9SRoger Lu  * @vboot: voltage request for bank init01 only
375681a02e9SRoger Lu  * @opp_dfreq: default opp frequency table
376681a02e9SRoger Lu  * @opp_dvolt: default opp voltage table
377681a02e9SRoger Lu  * @freq_pct: frequency percent table for bank init
378681a02e9SRoger Lu  * @volt: bank voltage table
379681a02e9SRoger Lu  * @volt_step: bank voltage step
380681a02e9SRoger Lu  * @volt_base: bank voltage base
381681a02e9SRoger Lu  * @volt_flags: bank voltage flags
382681a02e9SRoger Lu  * @vmax: bank voltage maximum
383681a02e9SRoger Lu  * @vmin: bank voltage minimum
384681a02e9SRoger Lu  * @age_config: bank age configuration
385681a02e9SRoger Lu  * @age_voffset_in: bank age voltage offset
386681a02e9SRoger Lu  * @dc_config: bank dc configuration
387681a02e9SRoger Lu  * @dc_voffset_in: bank dc voltage offset
388681a02e9SRoger Lu  * @dvt_fixed: bank dvt fixed value
389681a02e9SRoger Lu  * @vco: bank VCO value
390681a02e9SRoger Lu  * @chk_shift: bank chicken shift
391681a02e9SRoger Lu  * @core_sel: bank selection
392681a02e9SRoger Lu  * @opp_count: bank opp count
393681a02e9SRoger Lu  * @int_st: bank interrupt identification
394681a02e9SRoger Lu  * @sw_id: bank software identification
395681a02e9SRoger Lu  * @cpu_id: cpu core id for SVS CPU bank use only
396681a02e9SRoger Lu  * @ctl0: TS-x selection
3976c692719SRoger Lu  * @temp: bank temperature
3986c692719SRoger Lu  * @tzone_htemp: thermal zone high temperature threshold
3996c692719SRoger Lu  * @tzone_htemp_voffset: thermal zone high temperature voltage offset
4006c692719SRoger Lu  * @tzone_ltemp: thermal zone low temperature threshold
4016c692719SRoger Lu  * @tzone_ltemp_voffset: thermal zone low temperature voltage offset
4026c692719SRoger Lu  * @bts: svs efuse data
4036c692719SRoger Lu  * @mts: svs efuse data
404681a02e9SRoger Lu  * @bdes: svs efuse data
405681a02e9SRoger Lu  * @mdes: svs efuse data
406681a02e9SRoger Lu  * @mtdes: svs efuse data
407681a02e9SRoger Lu  * @dcbdet: svs efuse data
408681a02e9SRoger Lu  * @dcmdet: svs efuse data
4090bbb09b2SRoger Lu  * @turn_pt: 2-line turn point tells which opp_volt calculated by high/low bank
4100bbb09b2SRoger Lu  * @type: bank type to represent it is 2-line (high/low) bank or 1-line bank
411681a02e9SRoger Lu  *
412681a02e9SRoger Lu  * Svs bank will generate suitalbe voltages by below general math equation
413681a02e9SRoger Lu  * and provide these voltages to opp voltage table.
414681a02e9SRoger Lu  *
415681a02e9SRoger Lu  * opp_volt[i] = (volt[i] * volt_step) + volt_base;
416681a02e9SRoger Lu  */
417681a02e9SRoger Lu struct svs_bank {
418681a02e9SRoger Lu 	struct device *dev;
419681a02e9SRoger Lu 	struct device *opp_dev;
420681a02e9SRoger Lu 	struct completion init_completion;
421681a02e9SRoger Lu 	struct regulator *buck;
4226c692719SRoger Lu 	struct thermal_zone_device *tzd;
423681a02e9SRoger Lu 	struct mutex lock;	/* lock to protect voltage update process */
424681a02e9SRoger Lu 	void (*set_freq_pct)(struct svs_platform *svsp);
425681a02e9SRoger Lu 	void (*get_volts)(struct svs_platform *svsp);
426681a02e9SRoger Lu 	char *name;
427681a02e9SRoger Lu 	char *buck_name;
4286c692719SRoger Lu 	char *tzone_name;
429681a02e9SRoger Lu 	enum svsb_phase phase;
430681a02e9SRoger Lu 	s32 volt_od;
43113f1bbcfSRoger Lu 	u32 reg_data[SVSB_PHASE_MAX][SVS_REG_MAX];
432681a02e9SRoger Lu 	u32 pm_runtime_enabled_count;
433681a02e9SRoger Lu 	u32 mode_support;
434681a02e9SRoger Lu 	u32 freq_base;
4350bbb09b2SRoger Lu 	u32 turn_freq_base;
436681a02e9SRoger Lu 	u32 vboot;
437681a02e9SRoger Lu 	u32 opp_dfreq[MAX_OPP_ENTRIES];
438681a02e9SRoger Lu 	u32 opp_dvolt[MAX_OPP_ENTRIES];
439681a02e9SRoger Lu 	u32 freq_pct[MAX_OPP_ENTRIES];
440681a02e9SRoger Lu 	u32 volt[MAX_OPP_ENTRIES];
441681a02e9SRoger Lu 	u32 volt_step;
442681a02e9SRoger Lu 	u32 volt_base;
443681a02e9SRoger Lu 	u32 volt_flags;
444681a02e9SRoger Lu 	u32 vmax;
445681a02e9SRoger Lu 	u32 vmin;
446681a02e9SRoger Lu 	u32 age_config;
447681a02e9SRoger Lu 	u32 age_voffset_in;
448681a02e9SRoger Lu 	u32 dc_config;
449681a02e9SRoger Lu 	u32 dc_voffset_in;
450681a02e9SRoger Lu 	u32 dvt_fixed;
451681a02e9SRoger Lu 	u32 vco;
452681a02e9SRoger Lu 	u32 chk_shift;
453681a02e9SRoger Lu 	u32 core_sel;
454681a02e9SRoger Lu 	u32 opp_count;
455681a02e9SRoger Lu 	u32 int_st;
456681a02e9SRoger Lu 	u32 sw_id;
457681a02e9SRoger Lu 	u32 cpu_id;
458681a02e9SRoger Lu 	u32 ctl0;
4596c692719SRoger Lu 	u32 temp;
4606c692719SRoger Lu 	u32 tzone_htemp;
4616c692719SRoger Lu 	u32 tzone_htemp_voffset;
4626c692719SRoger Lu 	u32 tzone_ltemp;
4636c692719SRoger Lu 	u32 tzone_ltemp_voffset;
4646c692719SRoger Lu 	u32 bts;
4656c692719SRoger Lu 	u32 mts;
466681a02e9SRoger Lu 	u32 bdes;
467681a02e9SRoger Lu 	u32 mdes;
468681a02e9SRoger Lu 	u32 mtdes;
469681a02e9SRoger Lu 	u32 dcbdet;
470681a02e9SRoger Lu 	u32 dcmdet;
4710bbb09b2SRoger Lu 	u32 turn_pt;
4720bbb09b2SRoger Lu 	u32 type;
473681a02e9SRoger Lu };
474681a02e9SRoger Lu 
percent(u32 numerator,u32 denominator)475681a02e9SRoger Lu static u32 percent(u32 numerator, u32 denominator)
476681a02e9SRoger Lu {
477681a02e9SRoger Lu 	/* If not divide 1000, "numerator * 100" will have data overflow. */
478681a02e9SRoger Lu 	numerator /= 1000;
479681a02e9SRoger Lu 	denominator /= 1000;
480681a02e9SRoger Lu 
481681a02e9SRoger Lu 	return DIV_ROUND_UP(numerator * 100, denominator);
482681a02e9SRoger Lu }
483681a02e9SRoger Lu 
svs_readl_relaxed(struct svs_platform * svsp,enum svs_reg_index rg_i)484681a02e9SRoger Lu static u32 svs_readl_relaxed(struct svs_platform *svsp, enum svs_reg_index rg_i)
485681a02e9SRoger Lu {
486681a02e9SRoger Lu 	return readl_relaxed(svsp->base + svsp->regs[rg_i]);
487681a02e9SRoger Lu }
488681a02e9SRoger Lu 
svs_writel_relaxed(struct svs_platform * svsp,u32 val,enum svs_reg_index rg_i)489681a02e9SRoger Lu static void svs_writel_relaxed(struct svs_platform *svsp, u32 val,
490681a02e9SRoger Lu 			       enum svs_reg_index rg_i)
491681a02e9SRoger Lu {
492681a02e9SRoger Lu 	writel_relaxed(val, svsp->base + svsp->regs[rg_i]);
493681a02e9SRoger Lu }
494681a02e9SRoger Lu 
svs_switch_bank(struct svs_platform * svsp)495681a02e9SRoger Lu static void svs_switch_bank(struct svs_platform *svsp)
496681a02e9SRoger Lu {
497681a02e9SRoger Lu 	struct svs_bank *svsb = svsp->pbank;
498681a02e9SRoger Lu 
499681a02e9SRoger Lu 	svs_writel_relaxed(svsp, svsb->core_sel, CORESEL);
500681a02e9SRoger Lu }
501681a02e9SRoger Lu 
svs_bank_volt_to_opp_volt(u32 svsb_volt,u32 svsb_volt_step,u32 svsb_volt_base)502681a02e9SRoger Lu static u32 svs_bank_volt_to_opp_volt(u32 svsb_volt, u32 svsb_volt_step,
503681a02e9SRoger Lu 				     u32 svsb_volt_base)
504681a02e9SRoger Lu {
505681a02e9SRoger Lu 	return (svsb_volt * svsb_volt_step) + svsb_volt_base;
506681a02e9SRoger Lu }
507681a02e9SRoger Lu 
svs_opp_volt_to_bank_volt(u32 opp_u_volt,u32 svsb_volt_step,u32 svsb_volt_base)5080bbb09b2SRoger Lu static u32 svs_opp_volt_to_bank_volt(u32 opp_u_volt, u32 svsb_volt_step,
5090bbb09b2SRoger Lu 				     u32 svsb_volt_base)
5100bbb09b2SRoger Lu {
5110bbb09b2SRoger Lu 	return (opp_u_volt - svsb_volt_base) / svsb_volt_step;
5120bbb09b2SRoger Lu }
5130bbb09b2SRoger Lu 
svs_sync_bank_volts_from_opp(struct svs_bank * svsb)5140bbb09b2SRoger Lu static int svs_sync_bank_volts_from_opp(struct svs_bank *svsb)
5150bbb09b2SRoger Lu {
5160bbb09b2SRoger Lu 	struct dev_pm_opp *opp;
5170bbb09b2SRoger Lu 	u32 i, opp_u_volt;
5180bbb09b2SRoger Lu 
5190bbb09b2SRoger Lu 	for (i = 0; i < svsb->opp_count; i++) {
5200bbb09b2SRoger Lu 		opp = dev_pm_opp_find_freq_exact(svsb->opp_dev,
5210bbb09b2SRoger Lu 						 svsb->opp_dfreq[i],
5220bbb09b2SRoger Lu 						 true);
5230bbb09b2SRoger Lu 		if (IS_ERR(opp)) {
5240bbb09b2SRoger Lu 			dev_err(svsb->dev, "cannot find freq = %u (%ld)\n",
5250bbb09b2SRoger Lu 				svsb->opp_dfreq[i], PTR_ERR(opp));
5260bbb09b2SRoger Lu 			return PTR_ERR(opp);
5270bbb09b2SRoger Lu 		}
5280bbb09b2SRoger Lu 
5290bbb09b2SRoger Lu 		opp_u_volt = dev_pm_opp_get_voltage(opp);
5300bbb09b2SRoger Lu 		svsb->volt[i] = svs_opp_volt_to_bank_volt(opp_u_volt,
5310bbb09b2SRoger Lu 							  svsb->volt_step,
5320bbb09b2SRoger Lu 							  svsb->volt_base);
5330bbb09b2SRoger Lu 		dev_pm_opp_put(opp);
5340bbb09b2SRoger Lu 	}
5350bbb09b2SRoger Lu 
5360bbb09b2SRoger Lu 	return 0;
5370bbb09b2SRoger Lu }
5380bbb09b2SRoger Lu 
svs_adjust_pm_opp_volts(struct svs_bank * svsb)539681a02e9SRoger Lu static int svs_adjust_pm_opp_volts(struct svs_bank *svsb)
540681a02e9SRoger Lu {
5416c692719SRoger Lu 	int ret = -EPERM, tzone_temp = 0;
5420bbb09b2SRoger Lu 	u32 i, svsb_volt, opp_volt, temp_voffset = 0, opp_start, opp_stop;
543681a02e9SRoger Lu 
544681a02e9SRoger Lu 	mutex_lock(&svsb->lock);
545681a02e9SRoger Lu 
5460bbb09b2SRoger Lu 	/*
5470bbb09b2SRoger Lu 	 * 2-line bank updates its corresponding opp volts.
5480bbb09b2SRoger Lu 	 * 1-line bank updates all opp volts.
5490bbb09b2SRoger Lu 	 */
5500bbb09b2SRoger Lu 	if (svsb->type == SVSB_HIGH) {
5510bbb09b2SRoger Lu 		opp_start = 0;
5520bbb09b2SRoger Lu 		opp_stop = svsb->turn_pt;
5530bbb09b2SRoger Lu 	} else if (svsb->type == SVSB_LOW) {
5540bbb09b2SRoger Lu 		opp_start = svsb->turn_pt;
5550bbb09b2SRoger Lu 		opp_stop = svsb->opp_count;
5560bbb09b2SRoger Lu 	} else {
5570bbb09b2SRoger Lu 		opp_start = 0;
5580bbb09b2SRoger Lu 		opp_stop = svsb->opp_count;
5590bbb09b2SRoger Lu 	}
5600bbb09b2SRoger Lu 
5616c692719SRoger Lu 	/* Get thermal effect */
562bd0a62a6SRoger Lu 	if (!IS_ERR_OR_NULL(svsb->tzd)) {
5636c692719SRoger Lu 		ret = thermal_zone_get_temp(svsb->tzd, &tzone_temp);
5646c692719SRoger Lu 		if (ret || (svsb->temp > SVSB_TEMP_UPPER_BOUND &&
5656c692719SRoger Lu 			    svsb->temp < SVSB_TEMP_LOWER_BOUND)) {
5666c692719SRoger Lu 			dev_err(svsb->dev, "%s: %d (0x%x), run default volts\n",
5676c692719SRoger Lu 				svsb->tzone_name, ret, svsb->temp);
5686c692719SRoger Lu 			svsb->phase = SVSB_PHASE_ERROR;
5696c692719SRoger Lu 		}
5706c692719SRoger Lu 
5716c692719SRoger Lu 		if (tzone_temp >= svsb->tzone_htemp)
5726c692719SRoger Lu 			temp_voffset += svsb->tzone_htemp_voffset;
5736c692719SRoger Lu 		else if (tzone_temp <= svsb->tzone_ltemp)
5746c692719SRoger Lu 			temp_voffset += svsb->tzone_ltemp_voffset;
5750bbb09b2SRoger Lu 
5760bbb09b2SRoger Lu 		/* 2-line bank update all opp volts when running mon mode */
577bd0a62a6SRoger Lu 		if (svsb->phase == SVSB_PHASE_MON && (svsb->type == SVSB_HIGH ||
578bd0a62a6SRoger Lu 						      svsb->type == SVSB_LOW)) {
5790bbb09b2SRoger Lu 			opp_start = 0;
5800bbb09b2SRoger Lu 			opp_stop = svsb->opp_count;
5810bbb09b2SRoger Lu 		}
5826c692719SRoger Lu 	}
5836c692719SRoger Lu 
584681a02e9SRoger Lu 	/* vmin <= svsb_volt (opp_volt) <= default opp voltage */
5850bbb09b2SRoger Lu 	for (i = opp_start; i < opp_stop; i++) {
586681a02e9SRoger Lu 		switch (svsb->phase) {
587681a02e9SRoger Lu 		case SVSB_PHASE_ERROR:
588681a02e9SRoger Lu 			opp_volt = svsb->opp_dvolt[i];
589681a02e9SRoger Lu 			break;
590681a02e9SRoger Lu 		case SVSB_PHASE_INIT01:
591681a02e9SRoger Lu 			/* do nothing */
592681a02e9SRoger Lu 			goto unlock_mutex;
593681a02e9SRoger Lu 		case SVSB_PHASE_INIT02:
5946c692719SRoger Lu 		case SVSB_PHASE_MON:
5956c692719SRoger Lu 			svsb_volt = max(svsb->volt[i] + temp_voffset, svsb->vmin);
5966c692719SRoger Lu 			opp_volt = svs_bank_volt_to_opp_volt(svsb_volt,
5976c692719SRoger Lu 							     svsb->volt_step,
5986c692719SRoger Lu 							     svsb->volt_base);
5996c692719SRoger Lu 			break;
600681a02e9SRoger Lu 		default:
601681a02e9SRoger Lu 			dev_err(svsb->dev, "unknown phase: %u\n", svsb->phase);
602681a02e9SRoger Lu 			ret = -EINVAL;
603681a02e9SRoger Lu 			goto unlock_mutex;
604681a02e9SRoger Lu 		}
605681a02e9SRoger Lu 
606681a02e9SRoger Lu 		opp_volt = min(opp_volt, svsb->opp_dvolt[i]);
607681a02e9SRoger Lu 		ret = dev_pm_opp_adjust_voltage(svsb->opp_dev,
608681a02e9SRoger Lu 						svsb->opp_dfreq[i],
609681a02e9SRoger Lu 						opp_volt, opp_volt,
610681a02e9SRoger Lu 						svsb->opp_dvolt[i]);
611681a02e9SRoger Lu 		if (ret) {
612681a02e9SRoger Lu 			dev_err(svsb->dev, "set %uuV fail: %d\n",
613681a02e9SRoger Lu 				opp_volt, ret);
614681a02e9SRoger Lu 			goto unlock_mutex;
615681a02e9SRoger Lu 		}
616681a02e9SRoger Lu 	}
617681a02e9SRoger Lu 
618681a02e9SRoger Lu unlock_mutex:
619681a02e9SRoger Lu 	mutex_unlock(&svsb->lock);
620681a02e9SRoger Lu 
621681a02e9SRoger Lu 	return ret;
622681a02e9SRoger Lu }
623681a02e9SRoger Lu 
svs_bank_disable_and_restore_default_volts(struct svs_platform * svsp,struct svs_bank * svsb)6245061c47eSRoger Lu static void svs_bank_disable_and_restore_default_volts(struct svs_platform *svsp,
6255061c47eSRoger Lu 						       struct svs_bank *svsb)
6265061c47eSRoger Lu {
6275061c47eSRoger Lu 	unsigned long flags;
6285061c47eSRoger Lu 
6295061c47eSRoger Lu 	if (svsb->mode_support == SVSB_MODE_ALL_DISABLE)
6305061c47eSRoger Lu 		return;
6315061c47eSRoger Lu 
6325061c47eSRoger Lu 	spin_lock_irqsave(&svs_lock, flags);
6335061c47eSRoger Lu 	svsp->pbank = svsb;
6345061c47eSRoger Lu 	svs_switch_bank(svsp);
6355061c47eSRoger Lu 	svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
6365061c47eSRoger Lu 	svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
6375061c47eSRoger Lu 	spin_unlock_irqrestore(&svs_lock, flags);
6385061c47eSRoger Lu 
6395061c47eSRoger Lu 	svsb->phase = SVSB_PHASE_ERROR;
6405061c47eSRoger Lu 	svs_adjust_pm_opp_volts(svsb);
6415061c47eSRoger Lu }
6425061c47eSRoger Lu 
6438bf30508SRoger Lu #ifdef CONFIG_DEBUG_FS
svs_dump_debug_show(struct seq_file * m,void * p)64413f1bbcfSRoger Lu static int svs_dump_debug_show(struct seq_file *m, void *p)
64513f1bbcfSRoger Lu {
64613f1bbcfSRoger Lu 	struct svs_platform *svsp = (struct svs_platform *)m->private;
64713f1bbcfSRoger Lu 	struct svs_bank *svsb;
64813f1bbcfSRoger Lu 	unsigned long svs_reg_addr;
64913f1bbcfSRoger Lu 	u32 idx, i, j, bank_id;
65013f1bbcfSRoger Lu 
65113f1bbcfSRoger Lu 	for (i = 0; i < svsp->efuse_max; i++)
65213f1bbcfSRoger Lu 		if (svsp->efuse && svsp->efuse[i])
65313f1bbcfSRoger Lu 			seq_printf(m, "M_HW_RES%d = 0x%08x\n",
65413f1bbcfSRoger Lu 				   i, svsp->efuse[i]);
65513f1bbcfSRoger Lu 
65613f1bbcfSRoger Lu 	for (i = 0; i < svsp->tefuse_max; i++)
65713f1bbcfSRoger Lu 		if (svsp->tefuse)
65813f1bbcfSRoger Lu 			seq_printf(m, "THERMAL_EFUSE%d = 0x%08x\n",
65913f1bbcfSRoger Lu 				   i, svsp->tefuse[i]);
66013f1bbcfSRoger Lu 
66113f1bbcfSRoger Lu 	for (bank_id = 0, idx = 0; idx < svsp->bank_max; idx++, bank_id++) {
66213f1bbcfSRoger Lu 		svsb = &svsp->banks[idx];
66313f1bbcfSRoger Lu 
66413f1bbcfSRoger Lu 		for (i = SVSB_PHASE_INIT01; i <= SVSB_PHASE_MON; i++) {
66513f1bbcfSRoger Lu 			seq_printf(m, "Bank_number = %u\n", bank_id);
66613f1bbcfSRoger Lu 
66713f1bbcfSRoger Lu 			if (i == SVSB_PHASE_INIT01 || i == SVSB_PHASE_INIT02)
66813f1bbcfSRoger Lu 				seq_printf(m, "mode = init%d\n", i);
66913f1bbcfSRoger Lu 			else if (i == SVSB_PHASE_MON)
67013f1bbcfSRoger Lu 				seq_puts(m, "mode = mon\n");
67113f1bbcfSRoger Lu 			else
67213f1bbcfSRoger Lu 				seq_puts(m, "mode = error\n");
67313f1bbcfSRoger Lu 
67413f1bbcfSRoger Lu 			for (j = DESCHAR; j < SVS_REG_MAX; j++) {
67513f1bbcfSRoger Lu 				svs_reg_addr = (unsigned long)(svsp->base +
67613f1bbcfSRoger Lu 							       svsp->regs[j]);
67713f1bbcfSRoger Lu 				seq_printf(m, "0x%08lx = 0x%08x\n",
67813f1bbcfSRoger Lu 					   svs_reg_addr, svsb->reg_data[i][j]);
67913f1bbcfSRoger Lu 			}
68013f1bbcfSRoger Lu 		}
68113f1bbcfSRoger Lu 	}
68213f1bbcfSRoger Lu 
68313f1bbcfSRoger Lu 	return 0;
68413f1bbcfSRoger Lu }
68513f1bbcfSRoger Lu 
68613f1bbcfSRoger Lu debug_fops_ro(dump);
68713f1bbcfSRoger Lu 
svs_enable_debug_show(struct seq_file * m,void * v)68813f1bbcfSRoger Lu static int svs_enable_debug_show(struct seq_file *m, void *v)
68913f1bbcfSRoger Lu {
69013f1bbcfSRoger Lu 	struct svs_bank *svsb = (struct svs_bank *)m->private;
69113f1bbcfSRoger Lu 
69213f1bbcfSRoger Lu 	switch (svsb->phase) {
69313f1bbcfSRoger Lu 	case SVSB_PHASE_ERROR:
69413f1bbcfSRoger Lu 		seq_puts(m, "disabled\n");
69513f1bbcfSRoger Lu 		break;
69613f1bbcfSRoger Lu 	case SVSB_PHASE_INIT01:
69713f1bbcfSRoger Lu 		seq_puts(m, "init1\n");
69813f1bbcfSRoger Lu 		break;
69913f1bbcfSRoger Lu 	case SVSB_PHASE_INIT02:
70013f1bbcfSRoger Lu 		seq_puts(m, "init2\n");
70113f1bbcfSRoger Lu 		break;
70213f1bbcfSRoger Lu 	case SVSB_PHASE_MON:
70313f1bbcfSRoger Lu 		seq_puts(m, "mon mode\n");
70413f1bbcfSRoger Lu 		break;
70513f1bbcfSRoger Lu 	default:
70613f1bbcfSRoger Lu 		seq_puts(m, "unknown\n");
70713f1bbcfSRoger Lu 		break;
70813f1bbcfSRoger Lu 	}
70913f1bbcfSRoger Lu 
71013f1bbcfSRoger Lu 	return 0;
71113f1bbcfSRoger Lu }
71213f1bbcfSRoger Lu 
svs_enable_debug_write(struct file * filp,const char __user * buffer,size_t count,loff_t * pos)71313f1bbcfSRoger Lu static ssize_t svs_enable_debug_write(struct file *filp,
71413f1bbcfSRoger Lu 				      const char __user *buffer,
71513f1bbcfSRoger Lu 				      size_t count, loff_t *pos)
71613f1bbcfSRoger Lu {
71713f1bbcfSRoger Lu 	struct svs_bank *svsb = file_inode(filp)->i_private;
71813f1bbcfSRoger Lu 	struct svs_platform *svsp = dev_get_drvdata(svsb->dev);
71913f1bbcfSRoger Lu 	int enabled, ret;
72013f1bbcfSRoger Lu 	char *buf = NULL;
72113f1bbcfSRoger Lu 
72213f1bbcfSRoger Lu 	if (count >= PAGE_SIZE)
72313f1bbcfSRoger Lu 		return -EINVAL;
72413f1bbcfSRoger Lu 
72513f1bbcfSRoger Lu 	buf = (char *)memdup_user_nul(buffer, count);
72613f1bbcfSRoger Lu 	if (IS_ERR(buf))
72713f1bbcfSRoger Lu 		return PTR_ERR(buf);
72813f1bbcfSRoger Lu 
72913f1bbcfSRoger Lu 	ret = kstrtoint(buf, 10, &enabled);
73013f1bbcfSRoger Lu 	if (ret)
73113f1bbcfSRoger Lu 		return ret;
73213f1bbcfSRoger Lu 
73313f1bbcfSRoger Lu 	if (!enabled) {
7345061c47eSRoger Lu 		svs_bank_disable_and_restore_default_volts(svsp, svsb);
73513f1bbcfSRoger Lu 		svsb->mode_support = SVSB_MODE_ALL_DISABLE;
73613f1bbcfSRoger Lu 	}
73713f1bbcfSRoger Lu 
73813f1bbcfSRoger Lu 	kfree(buf);
73913f1bbcfSRoger Lu 
74013f1bbcfSRoger Lu 	return count;
74113f1bbcfSRoger Lu }
74213f1bbcfSRoger Lu 
74313f1bbcfSRoger Lu debug_fops_rw(enable);
74413f1bbcfSRoger Lu 
svs_status_debug_show(struct seq_file * m,void * v)74513f1bbcfSRoger Lu static int svs_status_debug_show(struct seq_file *m, void *v)
74613f1bbcfSRoger Lu {
74713f1bbcfSRoger Lu 	struct svs_bank *svsb = (struct svs_bank *)m->private;
74813f1bbcfSRoger Lu 	struct dev_pm_opp *opp;
74913f1bbcfSRoger Lu 	int tzone_temp = 0, ret;
75013f1bbcfSRoger Lu 	u32 i;
75113f1bbcfSRoger Lu 
75213f1bbcfSRoger Lu 	ret = thermal_zone_get_temp(svsb->tzd, &tzone_temp);
75313f1bbcfSRoger Lu 	if (ret)
7540bbb09b2SRoger Lu 		seq_printf(m, "%s: temperature ignore, turn_pt = %u\n",
7550bbb09b2SRoger Lu 			   svsb->name, svsb->turn_pt);
75613f1bbcfSRoger Lu 	else
7570bbb09b2SRoger Lu 		seq_printf(m, "%s: temperature = %d, turn_pt = %u\n",
7580bbb09b2SRoger Lu 			   svsb->name, tzone_temp, svsb->turn_pt);
75913f1bbcfSRoger Lu 
76013f1bbcfSRoger Lu 	for (i = 0; i < svsb->opp_count; i++) {
76113f1bbcfSRoger Lu 		opp = dev_pm_opp_find_freq_exact(svsb->opp_dev,
76213f1bbcfSRoger Lu 						 svsb->opp_dfreq[i], true);
76313f1bbcfSRoger Lu 		if (IS_ERR(opp)) {
76413f1bbcfSRoger Lu 			seq_printf(m, "%s: cannot find freq = %u (%ld)\n",
76513f1bbcfSRoger Lu 				   svsb->name, svsb->opp_dfreq[i],
76613f1bbcfSRoger Lu 				   PTR_ERR(opp));
76713f1bbcfSRoger Lu 			return PTR_ERR(opp);
76813f1bbcfSRoger Lu 		}
76913f1bbcfSRoger Lu 
77013f1bbcfSRoger Lu 		seq_printf(m, "opp_freq[%02u]: %u, opp_volt[%02u]: %lu, ",
77113f1bbcfSRoger Lu 			   i, svsb->opp_dfreq[i], i,
77213f1bbcfSRoger Lu 			   dev_pm_opp_get_voltage(opp));
77313f1bbcfSRoger Lu 		seq_printf(m, "svsb_volt[%02u]: 0x%x, freq_pct[%02u]: %u\n",
77413f1bbcfSRoger Lu 			   i, svsb->volt[i], i, svsb->freq_pct[i]);
77513f1bbcfSRoger Lu 		dev_pm_opp_put(opp);
77613f1bbcfSRoger Lu 	}
77713f1bbcfSRoger Lu 
77813f1bbcfSRoger Lu 	return 0;
77913f1bbcfSRoger Lu }
78013f1bbcfSRoger Lu 
78113f1bbcfSRoger Lu debug_fops_ro(status);
78213f1bbcfSRoger Lu 
svs_create_debug_cmds(struct svs_platform * svsp)78313f1bbcfSRoger Lu static int svs_create_debug_cmds(struct svs_platform *svsp)
78413f1bbcfSRoger Lu {
78513f1bbcfSRoger Lu 	struct svs_bank *svsb;
78613f1bbcfSRoger Lu 	struct dentry *svs_dir, *svsb_dir, *file_entry;
78713f1bbcfSRoger Lu 	const char *d = "/sys/kernel/debug/svs";
78813f1bbcfSRoger Lu 	u32 i, idx;
78913f1bbcfSRoger Lu 
79013f1bbcfSRoger Lu 	struct svs_dentry {
79113f1bbcfSRoger Lu 		const char *name;
79213f1bbcfSRoger Lu 		const struct file_operations *fops;
79313f1bbcfSRoger Lu 	};
79413f1bbcfSRoger Lu 
79513f1bbcfSRoger Lu 	struct svs_dentry svs_entries[] = {
79613f1bbcfSRoger Lu 		svs_dentry_data(dump),
79713f1bbcfSRoger Lu 	};
79813f1bbcfSRoger Lu 
79913f1bbcfSRoger Lu 	struct svs_dentry svsb_entries[] = {
80013f1bbcfSRoger Lu 		svs_dentry_data(enable),
80113f1bbcfSRoger Lu 		svs_dentry_data(status),
80213f1bbcfSRoger Lu 	};
80313f1bbcfSRoger Lu 
80413f1bbcfSRoger Lu 	svs_dir = debugfs_create_dir("svs", NULL);
80513f1bbcfSRoger Lu 	if (IS_ERR(svs_dir)) {
80613f1bbcfSRoger Lu 		dev_err(svsp->dev, "cannot create %s: %ld\n",
80713f1bbcfSRoger Lu 			d, PTR_ERR(svs_dir));
80813f1bbcfSRoger Lu 		return PTR_ERR(svs_dir);
80913f1bbcfSRoger Lu 	}
81013f1bbcfSRoger Lu 
81113f1bbcfSRoger Lu 	for (i = 0; i < ARRAY_SIZE(svs_entries); i++) {
81213f1bbcfSRoger Lu 		file_entry = debugfs_create_file(svs_entries[i].name, 0664,
81313f1bbcfSRoger Lu 						 svs_dir, svsp,
81413f1bbcfSRoger Lu 						 svs_entries[i].fops);
81513f1bbcfSRoger Lu 		if (IS_ERR(file_entry)) {
81613f1bbcfSRoger Lu 			dev_err(svsp->dev, "cannot create %s/%s: %ld\n",
81713f1bbcfSRoger Lu 				d, svs_entries[i].name, PTR_ERR(file_entry));
81813f1bbcfSRoger Lu 			return PTR_ERR(file_entry);
81913f1bbcfSRoger Lu 		}
82013f1bbcfSRoger Lu 	}
82113f1bbcfSRoger Lu 
82213f1bbcfSRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
82313f1bbcfSRoger Lu 		svsb = &svsp->banks[idx];
82413f1bbcfSRoger Lu 
82513f1bbcfSRoger Lu 		if (svsb->mode_support == SVSB_MODE_ALL_DISABLE)
82613f1bbcfSRoger Lu 			continue;
82713f1bbcfSRoger Lu 
82813f1bbcfSRoger Lu 		svsb_dir = debugfs_create_dir(svsb->name, svs_dir);
82913f1bbcfSRoger Lu 		if (IS_ERR(svsb_dir)) {
83013f1bbcfSRoger Lu 			dev_err(svsp->dev, "cannot create %s/%s: %ld\n",
83113f1bbcfSRoger Lu 				d, svsb->name, PTR_ERR(svsb_dir));
83213f1bbcfSRoger Lu 			return PTR_ERR(svsb_dir);
83313f1bbcfSRoger Lu 		}
83413f1bbcfSRoger Lu 
83513f1bbcfSRoger Lu 		for (i = 0; i < ARRAY_SIZE(svsb_entries); i++) {
83613f1bbcfSRoger Lu 			file_entry = debugfs_create_file(svsb_entries[i].name,
83713f1bbcfSRoger Lu 							 0664, svsb_dir, svsb,
83813f1bbcfSRoger Lu 							 svsb_entries[i].fops);
83913f1bbcfSRoger Lu 			if (IS_ERR(file_entry)) {
84013f1bbcfSRoger Lu 				dev_err(svsp->dev, "no %s/%s/%s?: %ld\n",
84113f1bbcfSRoger Lu 					d, svsb->name, svsb_entries[i].name,
84213f1bbcfSRoger Lu 					PTR_ERR(file_entry));
84313f1bbcfSRoger Lu 				return PTR_ERR(file_entry);
84413f1bbcfSRoger Lu 			}
84513f1bbcfSRoger Lu 		}
84613f1bbcfSRoger Lu 	}
84713f1bbcfSRoger Lu 
84813f1bbcfSRoger Lu 	return 0;
84913f1bbcfSRoger Lu }
8508bf30508SRoger Lu #endif /* CONFIG_DEBUG_FS */
85113f1bbcfSRoger Lu 
interpolate(u32 f0,u32 f1,u32 v0,u32 v1,u32 fx)852681a02e9SRoger Lu static u32 interpolate(u32 f0, u32 f1, u32 v0, u32 v1, u32 fx)
853681a02e9SRoger Lu {
854681a02e9SRoger Lu 	u32 vx;
855681a02e9SRoger Lu 
856681a02e9SRoger Lu 	if (v0 == v1 || f0 == f1)
857681a02e9SRoger Lu 		return v0;
858681a02e9SRoger Lu 
859681a02e9SRoger Lu 	/* *100 to have decimal fraction factor */
860681a02e9SRoger Lu 	vx = (v0 * 100) - ((((v0 - v1) * 100) / (f0 - f1)) * (f0 - fx));
861681a02e9SRoger Lu 
862681a02e9SRoger Lu 	return DIV_ROUND_UP(vx, 100);
863681a02e9SRoger Lu }
864681a02e9SRoger Lu 
svs_get_bank_volts_v3(struct svs_platform * svsp)8650bbb09b2SRoger Lu static void svs_get_bank_volts_v3(struct svs_platform *svsp)
8660bbb09b2SRoger Lu {
8670bbb09b2SRoger Lu 	struct svs_bank *svsb = svsp->pbank;
8680bbb09b2SRoger Lu 	u32 i, j, *vop, vop74, vop30, turn_pt = svsb->turn_pt;
8690bbb09b2SRoger Lu 	u32 b_sft, shift_byte = 0, opp_start = 0, opp_stop = 0;
8700bbb09b2SRoger Lu 	u32 middle_index = (svsb->opp_count / 2);
8710bbb09b2SRoger Lu 
8720bbb09b2SRoger Lu 	if (svsb->phase == SVSB_PHASE_MON &&
8730bbb09b2SRoger Lu 	    svsb->volt_flags & SVSB_MON_VOLT_IGNORE)
8740bbb09b2SRoger Lu 		return;
8750bbb09b2SRoger Lu 
8760bbb09b2SRoger Lu 	vop74 = svs_readl_relaxed(svsp, VOP74);
8770bbb09b2SRoger Lu 	vop30 = svs_readl_relaxed(svsp, VOP30);
8780bbb09b2SRoger Lu 
8790bbb09b2SRoger Lu 	/* Target is to set svsb->volt[] by algorithm */
8800bbb09b2SRoger Lu 	if (turn_pt < middle_index) {
8810bbb09b2SRoger Lu 		if (svsb->type == SVSB_HIGH) {
8820bbb09b2SRoger Lu 			/* volt[0] ~ volt[turn_pt - 1] */
8830bbb09b2SRoger Lu 			for (i = 0; i < turn_pt; i++) {
8840bbb09b2SRoger Lu 				b_sft = BITS8 * (shift_byte % REG_BYTES);
8850bbb09b2SRoger Lu 				vop = (shift_byte < REG_BYTES) ? &vop30 :
8860bbb09b2SRoger Lu 								 &vop74;
8870bbb09b2SRoger Lu 				svsb->volt[i] = (*vop >> b_sft) & GENMASK(7, 0);
8880bbb09b2SRoger Lu 				shift_byte++;
8890bbb09b2SRoger Lu 			}
8900bbb09b2SRoger Lu 		} else if (svsb->type == SVSB_LOW) {
8910bbb09b2SRoger Lu 			/* volt[turn_pt] + volt[j] ~ volt[opp_count - 1] */
8920bbb09b2SRoger Lu 			j = svsb->opp_count - 7;
893a92438c5SAngeloGioacchino Del Regno 			svsb->volt[turn_pt] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, vop30);
8940bbb09b2SRoger Lu 			shift_byte++;
8950bbb09b2SRoger Lu 			for (i = j; i < svsb->opp_count; i++) {
8960bbb09b2SRoger Lu 				b_sft = BITS8 * (shift_byte % REG_BYTES);
8970bbb09b2SRoger Lu 				vop = (shift_byte < REG_BYTES) ? &vop30 :
8980bbb09b2SRoger Lu 								 &vop74;
8990bbb09b2SRoger Lu 				svsb->volt[i] = (*vop >> b_sft) & GENMASK(7, 0);
9000bbb09b2SRoger Lu 				shift_byte++;
9010bbb09b2SRoger Lu 			}
9020bbb09b2SRoger Lu 
9030bbb09b2SRoger Lu 			/* volt[turn_pt + 1] ~ volt[j - 1] by interpolate */
9040bbb09b2SRoger Lu 			for (i = turn_pt + 1; i < j; i++)
9050bbb09b2SRoger Lu 				svsb->volt[i] = interpolate(svsb->freq_pct[turn_pt],
9060bbb09b2SRoger Lu 							    svsb->freq_pct[j],
9070bbb09b2SRoger Lu 							    svsb->volt[turn_pt],
9080bbb09b2SRoger Lu 							    svsb->volt[j],
9090bbb09b2SRoger Lu 							    svsb->freq_pct[i]);
9100bbb09b2SRoger Lu 		}
9110bbb09b2SRoger Lu 	} else {
9120bbb09b2SRoger Lu 		if (svsb->type == SVSB_HIGH) {
9130bbb09b2SRoger Lu 			/* volt[0] + volt[j] ~ volt[turn_pt - 1] */
9140bbb09b2SRoger Lu 			j = turn_pt - 7;
915a92438c5SAngeloGioacchino Del Regno 			svsb->volt[0] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, vop30);
9160bbb09b2SRoger Lu 			shift_byte++;
9170bbb09b2SRoger Lu 			for (i = j; i < turn_pt; i++) {
9180bbb09b2SRoger Lu 				b_sft = BITS8 * (shift_byte % REG_BYTES);
9190bbb09b2SRoger Lu 				vop = (shift_byte < REG_BYTES) ? &vop30 :
9200bbb09b2SRoger Lu 								 &vop74;
9210bbb09b2SRoger Lu 				svsb->volt[i] = (*vop >> b_sft) & GENMASK(7, 0);
9220bbb09b2SRoger Lu 				shift_byte++;
9230bbb09b2SRoger Lu 			}
9240bbb09b2SRoger Lu 
9250bbb09b2SRoger Lu 			/* volt[1] ~ volt[j - 1] by interpolate */
9260bbb09b2SRoger Lu 			for (i = 1; i < j; i++)
9270bbb09b2SRoger Lu 				svsb->volt[i] = interpolate(svsb->freq_pct[0],
9280bbb09b2SRoger Lu 							    svsb->freq_pct[j],
9290bbb09b2SRoger Lu 							    svsb->volt[0],
9300bbb09b2SRoger Lu 							    svsb->volt[j],
9310bbb09b2SRoger Lu 							    svsb->freq_pct[i]);
9320bbb09b2SRoger Lu 		} else if (svsb->type == SVSB_LOW) {
9330bbb09b2SRoger Lu 			/* volt[turn_pt] ~ volt[opp_count - 1] */
9340bbb09b2SRoger Lu 			for (i = turn_pt; i < svsb->opp_count; i++) {
9350bbb09b2SRoger Lu 				b_sft = BITS8 * (shift_byte % REG_BYTES);
9360bbb09b2SRoger Lu 				vop = (shift_byte < REG_BYTES) ? &vop30 :
9370bbb09b2SRoger Lu 								 &vop74;
9380bbb09b2SRoger Lu 				svsb->volt[i] = (*vop >> b_sft) & GENMASK(7, 0);
9390bbb09b2SRoger Lu 				shift_byte++;
9400bbb09b2SRoger Lu 			}
9410bbb09b2SRoger Lu 		}
9420bbb09b2SRoger Lu 	}
9430bbb09b2SRoger Lu 
9440bbb09b2SRoger Lu 	if (svsb->type == SVSB_HIGH) {
9450bbb09b2SRoger Lu 		opp_start = 0;
9460bbb09b2SRoger Lu 		opp_stop = svsb->turn_pt;
9470bbb09b2SRoger Lu 	} else if (svsb->type == SVSB_LOW) {
9480bbb09b2SRoger Lu 		opp_start = svsb->turn_pt;
9490bbb09b2SRoger Lu 		opp_stop = svsb->opp_count;
9500bbb09b2SRoger Lu 	}
9510bbb09b2SRoger Lu 
9520bbb09b2SRoger Lu 	for (i = opp_start; i < opp_stop; i++)
9530bbb09b2SRoger Lu 		if (svsb->volt_flags & SVSB_REMOVE_DVTFIXED_VOLT)
9540bbb09b2SRoger Lu 			svsb->volt[i] -= svsb->dvt_fixed;
9550bbb09b2SRoger Lu }
9560bbb09b2SRoger Lu 
svs_set_bank_freq_pct_v3(struct svs_platform * svsp)9570bbb09b2SRoger Lu static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp)
9580bbb09b2SRoger Lu {
9590bbb09b2SRoger Lu 	struct svs_bank *svsb = svsp->pbank;
9600bbb09b2SRoger Lu 	u32 i, j, *freq_pct, freq_pct74 = 0, freq_pct30 = 0;
9610bbb09b2SRoger Lu 	u32 b_sft, shift_byte = 0, turn_pt;
9620bbb09b2SRoger Lu 	u32 middle_index = (svsb->opp_count / 2);
9630bbb09b2SRoger Lu 
9640bbb09b2SRoger Lu 	for (i = 0; i < svsb->opp_count; i++) {
9650bbb09b2SRoger Lu 		if (svsb->opp_dfreq[i] <= svsb->turn_freq_base) {
9660bbb09b2SRoger Lu 			svsb->turn_pt = i;
9670bbb09b2SRoger Lu 			break;
9680bbb09b2SRoger Lu 		}
9690bbb09b2SRoger Lu 	}
9700bbb09b2SRoger Lu 
9710bbb09b2SRoger Lu 	turn_pt = svsb->turn_pt;
9720bbb09b2SRoger Lu 
9730bbb09b2SRoger Lu 	/* Target is to fill out freq_pct74 / freq_pct30 by algorithm */
9740bbb09b2SRoger Lu 	if (turn_pt < middle_index) {
9750bbb09b2SRoger Lu 		if (svsb->type == SVSB_HIGH) {
9760bbb09b2SRoger Lu 			/*
9770bbb09b2SRoger Lu 			 * If we don't handle this situation,
9780bbb09b2SRoger Lu 			 * SVSB_HIGH's FREQPCT74 / FREQPCT30 would keep "0"
9790bbb09b2SRoger Lu 			 * and this leads SVSB_LOW to work abnormally.
9800bbb09b2SRoger Lu 			 */
9810bbb09b2SRoger Lu 			if (turn_pt == 0)
9820bbb09b2SRoger Lu 				freq_pct30 = svsb->freq_pct[0];
9830bbb09b2SRoger Lu 
9840bbb09b2SRoger Lu 			/* freq_pct[0] ~ freq_pct[turn_pt - 1] */
9850bbb09b2SRoger Lu 			for (i = 0; i < turn_pt; i++) {
9860bbb09b2SRoger Lu 				b_sft = BITS8 * (shift_byte % REG_BYTES);
9870bbb09b2SRoger Lu 				freq_pct = (shift_byte < REG_BYTES) ?
9880bbb09b2SRoger Lu 					   &freq_pct30 : &freq_pct74;
9890bbb09b2SRoger Lu 				*freq_pct |= (svsb->freq_pct[i] << b_sft);
9900bbb09b2SRoger Lu 				shift_byte++;
9910bbb09b2SRoger Lu 			}
9920bbb09b2SRoger Lu 		} else if (svsb->type == SVSB_LOW) {
9930bbb09b2SRoger Lu 			/*
9940bbb09b2SRoger Lu 			 * freq_pct[turn_pt] +
9950bbb09b2SRoger Lu 			 * freq_pct[opp_count - 7] ~ freq_pct[opp_count -1]
9960bbb09b2SRoger Lu 			 */
9970bbb09b2SRoger Lu 			freq_pct30 = svsb->freq_pct[turn_pt];
9980bbb09b2SRoger Lu 			shift_byte++;
9990bbb09b2SRoger Lu 			j = svsb->opp_count - 7;
10000bbb09b2SRoger Lu 			for (i = j; i < svsb->opp_count; i++) {
10010bbb09b2SRoger Lu 				b_sft = BITS8 * (shift_byte % REG_BYTES);
10020bbb09b2SRoger Lu 				freq_pct = (shift_byte < REG_BYTES) ?
10030bbb09b2SRoger Lu 					   &freq_pct30 : &freq_pct74;
10040bbb09b2SRoger Lu 				*freq_pct |= (svsb->freq_pct[i] << b_sft);
10050bbb09b2SRoger Lu 				shift_byte++;
10060bbb09b2SRoger Lu 			}
10070bbb09b2SRoger Lu 		}
10080bbb09b2SRoger Lu 	} else {
10090bbb09b2SRoger Lu 		if (svsb->type == SVSB_HIGH) {
10100bbb09b2SRoger Lu 			/*
10110bbb09b2SRoger Lu 			 * freq_pct[0] +
10120bbb09b2SRoger Lu 			 * freq_pct[turn_pt - 7] ~ freq_pct[turn_pt - 1]
10130bbb09b2SRoger Lu 			 */
10140bbb09b2SRoger Lu 			freq_pct30 = svsb->freq_pct[0];
10150bbb09b2SRoger Lu 			shift_byte++;
10160bbb09b2SRoger Lu 			j = turn_pt - 7;
10170bbb09b2SRoger Lu 			for (i = j; i < turn_pt; i++) {
10180bbb09b2SRoger Lu 				b_sft = BITS8 * (shift_byte % REG_BYTES);
10190bbb09b2SRoger Lu 				freq_pct = (shift_byte < REG_BYTES) ?
10200bbb09b2SRoger Lu 					   &freq_pct30 : &freq_pct74;
10210bbb09b2SRoger Lu 				*freq_pct |= (svsb->freq_pct[i] << b_sft);
10220bbb09b2SRoger Lu 				shift_byte++;
10230bbb09b2SRoger Lu 			}
10240bbb09b2SRoger Lu 		} else if (svsb->type == SVSB_LOW) {
10250bbb09b2SRoger Lu 			/* freq_pct[turn_pt] ~ freq_pct[opp_count - 1] */
10260bbb09b2SRoger Lu 			for (i = turn_pt; i < svsb->opp_count; i++) {
10270bbb09b2SRoger Lu 				b_sft = BITS8 * (shift_byte % REG_BYTES);
10280bbb09b2SRoger Lu 				freq_pct = (shift_byte < REG_BYTES) ?
10290bbb09b2SRoger Lu 					   &freq_pct30 : &freq_pct74;
10300bbb09b2SRoger Lu 				*freq_pct |= (svsb->freq_pct[i] << b_sft);
10310bbb09b2SRoger Lu 				shift_byte++;
10320bbb09b2SRoger Lu 			}
10330bbb09b2SRoger Lu 		}
10340bbb09b2SRoger Lu 	}
10350bbb09b2SRoger Lu 
10360bbb09b2SRoger Lu 	svs_writel_relaxed(svsp, freq_pct74, FREQPCT74);
10370bbb09b2SRoger Lu 	svs_writel_relaxed(svsp, freq_pct30, FREQPCT30);
10380bbb09b2SRoger Lu }
10390bbb09b2SRoger Lu 
svs_get_bank_volts_v2(struct svs_platform * svsp)1040681a02e9SRoger Lu static void svs_get_bank_volts_v2(struct svs_platform *svsp)
1041681a02e9SRoger Lu {
1042681a02e9SRoger Lu 	struct svs_bank *svsb = svsp->pbank;
1043681a02e9SRoger Lu 	u32 temp, i;
1044681a02e9SRoger Lu 
1045681a02e9SRoger Lu 	temp = svs_readl_relaxed(svsp, VOP74);
1046a92438c5SAngeloGioacchino Del Regno 	svsb->volt[14] = FIELD_GET(SVSB_VOPS_FLD_VOP3_7, temp);
1047a92438c5SAngeloGioacchino Del Regno 	svsb->volt[12] = FIELD_GET(SVSB_VOPS_FLD_VOP2_6, temp);
1048a92438c5SAngeloGioacchino Del Regno 	svsb->volt[10] = FIELD_GET(SVSB_VOPS_FLD_VOP1_5, temp);
1049a92438c5SAngeloGioacchino Del Regno 	svsb->volt[8] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, temp);
1050681a02e9SRoger Lu 
1051681a02e9SRoger Lu 	temp = svs_readl_relaxed(svsp, VOP30);
1052a92438c5SAngeloGioacchino Del Regno 	svsb->volt[6] = FIELD_GET(SVSB_VOPS_FLD_VOP3_7, temp);
1053a92438c5SAngeloGioacchino Del Regno 	svsb->volt[4] = FIELD_GET(SVSB_VOPS_FLD_VOP2_6, temp);
1054a92438c5SAngeloGioacchino Del Regno 	svsb->volt[2] = FIELD_GET(SVSB_VOPS_FLD_VOP1_5, temp);
1055a92438c5SAngeloGioacchino Del Regno 	svsb->volt[0] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, temp);
1056681a02e9SRoger Lu 
1057681a02e9SRoger Lu 	for (i = 0; i <= 12; i += 2)
1058681a02e9SRoger Lu 		svsb->volt[i + 1] = interpolate(svsb->freq_pct[i],
1059681a02e9SRoger Lu 						svsb->freq_pct[i + 2],
1060681a02e9SRoger Lu 						svsb->volt[i],
1061681a02e9SRoger Lu 						svsb->volt[i + 2],
1062681a02e9SRoger Lu 						svsb->freq_pct[i + 1]);
1063681a02e9SRoger Lu 
1064681a02e9SRoger Lu 	svsb->volt[15] = interpolate(svsb->freq_pct[12],
1065681a02e9SRoger Lu 				     svsb->freq_pct[14],
1066681a02e9SRoger Lu 				     svsb->volt[12],
1067681a02e9SRoger Lu 				     svsb->volt[14],
1068681a02e9SRoger Lu 				     svsb->freq_pct[15]);
1069681a02e9SRoger Lu 
1070681a02e9SRoger Lu 	for (i = 0; i < svsb->opp_count; i++)
1071681a02e9SRoger Lu 		svsb->volt[i] += svsb->volt_od;
1072681a02e9SRoger Lu }
1073681a02e9SRoger Lu 
svs_set_bank_freq_pct_v2(struct svs_platform * svsp)1074681a02e9SRoger Lu static void svs_set_bank_freq_pct_v2(struct svs_platform *svsp)
1075681a02e9SRoger Lu {
1076681a02e9SRoger Lu 	struct svs_bank *svsb = svsp->pbank;
1077a92438c5SAngeloGioacchino Del Regno 	u32 freqpct74_val, freqpct30_val;
1078681a02e9SRoger Lu 
1079a92438c5SAngeloGioacchino Del Regno 	freqpct74_val = FIELD_PREP(SVSB_FREQPCTS_FLD_PCT0_4, svsb->freq_pct[8]) |
1080a92438c5SAngeloGioacchino Del Regno 			FIELD_PREP(SVSB_FREQPCTS_FLD_PCT1_5, svsb->freq_pct[10]) |
1081a92438c5SAngeloGioacchino Del Regno 			FIELD_PREP(SVSB_FREQPCTS_FLD_PCT2_6, svsb->freq_pct[12]) |
1082a92438c5SAngeloGioacchino Del Regno 			FIELD_PREP(SVSB_FREQPCTS_FLD_PCT3_7, svsb->freq_pct[14]);
1083681a02e9SRoger Lu 
1084a92438c5SAngeloGioacchino Del Regno 	freqpct30_val = FIELD_PREP(SVSB_FREQPCTS_FLD_PCT0_4, svsb->freq_pct[0]) |
1085a92438c5SAngeloGioacchino Del Regno 			FIELD_PREP(SVSB_FREQPCTS_FLD_PCT1_5, svsb->freq_pct[2]) |
1086a92438c5SAngeloGioacchino Del Regno 			FIELD_PREP(SVSB_FREQPCTS_FLD_PCT2_6, svsb->freq_pct[4]) |
1087a92438c5SAngeloGioacchino Del Regno 			FIELD_PREP(SVSB_FREQPCTS_FLD_PCT3_7, svsb->freq_pct[6]);
1088a92438c5SAngeloGioacchino Del Regno 
1089a92438c5SAngeloGioacchino Del Regno 	svs_writel_relaxed(svsp, freqpct74_val, FREQPCT74);
1090a92438c5SAngeloGioacchino Del Regno 	svs_writel_relaxed(svsp, freqpct30_val, FREQPCT30);
1091681a02e9SRoger Lu }
1092681a02e9SRoger Lu 
svs_set_bank_phase(struct svs_platform * svsp,enum svsb_phase target_phase)1093681a02e9SRoger Lu static void svs_set_bank_phase(struct svs_platform *svsp,
1094681a02e9SRoger Lu 			       enum svsb_phase target_phase)
1095681a02e9SRoger Lu {
1096681a02e9SRoger Lu 	struct svs_bank *svsb = svsp->pbank;
10976c692719SRoger Lu 	u32 des_char, temp_char, det_char, limit_vals, init2vals, ts_calcs;
1098681a02e9SRoger Lu 
1099681a02e9SRoger Lu 	svs_switch_bank(svsp);
1100681a02e9SRoger Lu 
1101a92438c5SAngeloGioacchino Del Regno 	des_char = FIELD_PREP(SVSB_DESCHAR_FLD_BDES, svsb->bdes) |
1102a92438c5SAngeloGioacchino Del Regno 		   FIELD_PREP(SVSB_DESCHAR_FLD_MDES, svsb->mdes);
1103681a02e9SRoger Lu 	svs_writel_relaxed(svsp, des_char, DESCHAR);
1104681a02e9SRoger Lu 
1105a92438c5SAngeloGioacchino Del Regno 	temp_char = FIELD_PREP(SVSB_TEMPCHAR_FLD_VCO, svsb->vco) |
1106a92438c5SAngeloGioacchino Del Regno 		    FIELD_PREP(SVSB_TEMPCHAR_FLD_MTDES, svsb->mtdes) |
1107a92438c5SAngeloGioacchino Del Regno 		    FIELD_PREP(SVSB_TEMPCHAR_FLD_DVT_FIXED, svsb->dvt_fixed);
1108681a02e9SRoger Lu 	svs_writel_relaxed(svsp, temp_char, TEMPCHAR);
1109681a02e9SRoger Lu 
1110a92438c5SAngeloGioacchino Del Regno 	det_char = FIELD_PREP(SVSB_DETCHAR_FLD_DCBDET, svsb->dcbdet) |
1111a92438c5SAngeloGioacchino Del Regno 		   FIELD_PREP(SVSB_DETCHAR_FLD_DCMDET, svsb->dcmdet);
1112681a02e9SRoger Lu 	svs_writel_relaxed(svsp, det_char, DETCHAR);
1113681a02e9SRoger Lu 
1114681a02e9SRoger Lu 	svs_writel_relaxed(svsp, svsb->dc_config, DCCONFIG);
1115681a02e9SRoger Lu 	svs_writel_relaxed(svsp, svsb->age_config, AGECONFIG);
1116681a02e9SRoger Lu 	svs_writel_relaxed(svsp, SVSB_RUNCONFIG_DEFAULT, RUNCONFIG);
1117681a02e9SRoger Lu 
1118681a02e9SRoger Lu 	svsb->set_freq_pct(svsp);
1119681a02e9SRoger Lu 
1120a92438c5SAngeloGioacchino Del Regno 	limit_vals = FIELD_PREP(SVSB_LIMITVALS_FLD_DTLO, SVSB_VAL_DTLO) |
1121a92438c5SAngeloGioacchino Del Regno 		     FIELD_PREP(SVSB_LIMITVALS_FLD_DTHI, SVSB_VAL_DTHI) |
1122a92438c5SAngeloGioacchino Del Regno 		     FIELD_PREP(SVSB_LIMITVALS_FLD_VMIN, svsb->vmin) |
1123a92438c5SAngeloGioacchino Del Regno 		     FIELD_PREP(SVSB_LIMITVALS_FLD_VMAX, svsb->vmax);
1124681a02e9SRoger Lu 	svs_writel_relaxed(svsp, limit_vals, LIMITVALS);
1125681a02e9SRoger Lu 
1126681a02e9SRoger Lu 	svs_writel_relaxed(svsp, SVSB_DET_WINDOW, DETWINDOW);
1127681a02e9SRoger Lu 	svs_writel_relaxed(svsp, SVSB_DET_MAX, CONFIG);
1128681a02e9SRoger Lu 	svs_writel_relaxed(svsp, svsb->chk_shift, CHKSHIFT);
1129681a02e9SRoger Lu 	svs_writel_relaxed(svsp, svsb->ctl0, CTL0);
1130a92438c5SAngeloGioacchino Del Regno 	svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
1131681a02e9SRoger Lu 
1132681a02e9SRoger Lu 	switch (target_phase) {
1133681a02e9SRoger Lu 	case SVSB_PHASE_INIT01:
1134681a02e9SRoger Lu 		svs_writel_relaxed(svsp, svsb->vboot, VBOOT);
1135681a02e9SRoger Lu 		svs_writel_relaxed(svsp, SVSB_INTEN_INIT0x, INTEN);
1136a92438c5SAngeloGioacchino Del Regno 		svs_writel_relaxed(svsp, SVSB_PTPEN_INIT01, SVSEN);
1137681a02e9SRoger Lu 		break;
1138681a02e9SRoger Lu 	case SVSB_PHASE_INIT02:
1139a92438c5SAngeloGioacchino Del Regno 		init2vals = FIELD_PREP(SVSB_INIT2VALS_FLD_AGEVOFFSETIN, svsb->age_voffset_in) |
1140a92438c5SAngeloGioacchino Del Regno 			    FIELD_PREP(SVSB_INIT2VALS_FLD_DCVOFFSETIN, svsb->dc_voffset_in);
1141681a02e9SRoger Lu 		svs_writel_relaxed(svsp, SVSB_INTEN_INIT0x, INTEN);
1142681a02e9SRoger Lu 		svs_writel_relaxed(svsp, init2vals, INIT2VALS);
1143a92438c5SAngeloGioacchino Del Regno 		svs_writel_relaxed(svsp, SVSB_PTPEN_INIT02, SVSEN);
1144681a02e9SRoger Lu 		break;
11456c692719SRoger Lu 	case SVSB_PHASE_MON:
1146a92438c5SAngeloGioacchino Del Regno 		ts_calcs = FIELD_PREP(SVSB_TSCALCS_FLD_BTS, svsb->bts) |
1147a92438c5SAngeloGioacchino Del Regno 			   FIELD_PREP(SVSB_TSCALCS_FLD_MTS, svsb->mts);
11486c692719SRoger Lu 		svs_writel_relaxed(svsp, ts_calcs, TSCALCS);
11496c692719SRoger Lu 		svs_writel_relaxed(svsp, SVSB_INTEN_MONVOPEN, INTEN);
1150a92438c5SAngeloGioacchino Del Regno 		svs_writel_relaxed(svsp, SVSB_PTPEN_MON, SVSEN);
11516c692719SRoger Lu 		break;
1152681a02e9SRoger Lu 	default:
1153681a02e9SRoger Lu 		dev_err(svsb->dev, "requested unknown target phase: %u\n",
1154681a02e9SRoger Lu 			target_phase);
1155681a02e9SRoger Lu 		break;
1156681a02e9SRoger Lu 	}
1157681a02e9SRoger Lu }
1158681a02e9SRoger Lu 
svs_save_bank_register_data(struct svs_platform * svsp,enum svsb_phase phase)115913f1bbcfSRoger Lu static inline void svs_save_bank_register_data(struct svs_platform *svsp,
116013f1bbcfSRoger Lu 					       enum svsb_phase phase)
116113f1bbcfSRoger Lu {
116213f1bbcfSRoger Lu 	struct svs_bank *svsb = svsp->pbank;
116313f1bbcfSRoger Lu 	enum svs_reg_index rg_i;
116413f1bbcfSRoger Lu 
116513f1bbcfSRoger Lu 	for (rg_i = DESCHAR; rg_i < SVS_REG_MAX; rg_i++)
116613f1bbcfSRoger Lu 		svsb->reg_data[phase][rg_i] = svs_readl_relaxed(svsp, rg_i);
116713f1bbcfSRoger Lu }
116813f1bbcfSRoger Lu 
svs_error_isr_handler(struct svs_platform * svsp)1169681a02e9SRoger Lu static inline void svs_error_isr_handler(struct svs_platform *svsp)
1170681a02e9SRoger Lu {
1171681a02e9SRoger Lu 	struct svs_bank *svsb = svsp->pbank;
1172681a02e9SRoger Lu 
1173681a02e9SRoger Lu 	dev_err(svsb->dev, "%s: CORESEL = 0x%08x\n",
1174681a02e9SRoger Lu 		__func__, svs_readl_relaxed(svsp, CORESEL));
1175681a02e9SRoger Lu 	dev_err(svsb->dev, "SVSEN = 0x%08x, INTSTS = 0x%08x\n",
1176681a02e9SRoger Lu 		svs_readl_relaxed(svsp, SVSEN),
1177681a02e9SRoger Lu 		svs_readl_relaxed(svsp, INTSTS));
1178681a02e9SRoger Lu 	dev_err(svsb->dev, "SMSTATE0 = 0x%08x, SMSTATE1 = 0x%08x\n",
1179681a02e9SRoger Lu 		svs_readl_relaxed(svsp, SMSTATE0),
1180681a02e9SRoger Lu 		svs_readl_relaxed(svsp, SMSTATE1));
11816c692719SRoger Lu 	dev_err(svsb->dev, "TEMP = 0x%08x\n", svs_readl_relaxed(svsp, TEMP));
1182681a02e9SRoger Lu 
118313f1bbcfSRoger Lu 	svs_save_bank_register_data(svsp, SVSB_PHASE_ERROR);
118413f1bbcfSRoger Lu 
1185681a02e9SRoger Lu 	svsb->phase = SVSB_PHASE_ERROR;
1186a92438c5SAngeloGioacchino Del Regno 	svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
1187a92438c5SAngeloGioacchino Del Regno 	svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
1188681a02e9SRoger Lu }
1189681a02e9SRoger Lu 
svs_init01_isr_handler(struct svs_platform * svsp)1190681a02e9SRoger Lu static inline void svs_init01_isr_handler(struct svs_platform *svsp)
1191681a02e9SRoger Lu {
1192681a02e9SRoger Lu 	struct svs_bank *svsb = svsp->pbank;
1193681a02e9SRoger Lu 
1194681a02e9SRoger Lu 	dev_info(svsb->dev, "%s: VDN74~30:0x%08x~0x%08x, DC:0x%08x\n",
1195681a02e9SRoger Lu 		 __func__, svs_readl_relaxed(svsp, VDESIGN74),
1196681a02e9SRoger Lu 		 svs_readl_relaxed(svsp, VDESIGN30),
1197681a02e9SRoger Lu 		 svs_readl_relaxed(svsp, DCVALUES));
1198681a02e9SRoger Lu 
119913f1bbcfSRoger Lu 	svs_save_bank_register_data(svsp, SVSB_PHASE_INIT01);
120013f1bbcfSRoger Lu 
1201681a02e9SRoger Lu 	svsb->phase = SVSB_PHASE_INIT01;
1202681a02e9SRoger Lu 	svsb->dc_voffset_in = ~(svs_readl_relaxed(svsp, DCVALUES) &
1203681a02e9SRoger Lu 				GENMASK(15, 0)) + 1;
1204681a02e9SRoger Lu 	if (svsb->volt_flags & SVSB_INIT01_VOLT_IGNORE ||
1205681a02e9SRoger Lu 	    (svsb->dc_voffset_in & SVSB_DC_SIGNED_BIT &&
1206681a02e9SRoger Lu 	     svsb->volt_flags & SVSB_INIT01_VOLT_INC_ONLY))
1207681a02e9SRoger Lu 		svsb->dc_voffset_in = 0;
1208681a02e9SRoger Lu 
1209681a02e9SRoger Lu 	svsb->age_voffset_in = svs_readl_relaxed(svsp, AGEVALUES) &
1210681a02e9SRoger Lu 			       GENMASK(15, 0);
1211681a02e9SRoger Lu 
1212a92438c5SAngeloGioacchino Del Regno 	svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
1213a92438c5SAngeloGioacchino Del Regno 	svs_writel_relaxed(svsp, SVSB_INTSTS_F0_COMPLETE, INTSTS);
1214681a02e9SRoger Lu 	svsb->core_sel &= ~SVSB_DET_CLK_EN;
1215681a02e9SRoger Lu }
1216681a02e9SRoger Lu 
svs_init02_isr_handler(struct svs_platform * svsp)1217681a02e9SRoger Lu static inline void svs_init02_isr_handler(struct svs_platform *svsp)
1218681a02e9SRoger Lu {
1219681a02e9SRoger Lu 	struct svs_bank *svsb = svsp->pbank;
1220681a02e9SRoger Lu 
1221681a02e9SRoger Lu 	dev_info(svsb->dev, "%s: VOP74~30:0x%08x~0x%08x, DC:0x%08x\n",
1222681a02e9SRoger Lu 		 __func__, svs_readl_relaxed(svsp, VOP74),
1223681a02e9SRoger Lu 		 svs_readl_relaxed(svsp, VOP30),
1224681a02e9SRoger Lu 		 svs_readl_relaxed(svsp, DCVALUES));
1225681a02e9SRoger Lu 
122613f1bbcfSRoger Lu 	svs_save_bank_register_data(svsp, SVSB_PHASE_INIT02);
122713f1bbcfSRoger Lu 
1228681a02e9SRoger Lu 	svsb->phase = SVSB_PHASE_INIT02;
1229681a02e9SRoger Lu 	svsb->get_volts(svsp);
1230681a02e9SRoger Lu 
1231a92438c5SAngeloGioacchino Del Regno 	svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
1232a92438c5SAngeloGioacchino Del Regno 	svs_writel_relaxed(svsp, SVSB_INTSTS_F0_COMPLETE, INTSTS);
1233681a02e9SRoger Lu }
1234681a02e9SRoger Lu 
svs_mon_mode_isr_handler(struct svs_platform * svsp)12356c692719SRoger Lu static inline void svs_mon_mode_isr_handler(struct svs_platform *svsp)
12366c692719SRoger Lu {
12376c692719SRoger Lu 	struct svs_bank *svsb = svsp->pbank;
12386c692719SRoger Lu 
123913f1bbcfSRoger Lu 	svs_save_bank_register_data(svsp, SVSB_PHASE_MON);
124013f1bbcfSRoger Lu 
12416c692719SRoger Lu 	svsb->phase = SVSB_PHASE_MON;
12426c692719SRoger Lu 	svsb->get_volts(svsp);
12436c692719SRoger Lu 
12446c692719SRoger Lu 	svsb->temp = svs_readl_relaxed(svsp, TEMP) & GENMASK(7, 0);
1245a92438c5SAngeloGioacchino Del Regno 	svs_writel_relaxed(svsp, SVSB_INTSTS_FLD_MONVOP, INTSTS);
12466c692719SRoger Lu }
12476c692719SRoger Lu 
svs_isr(int irq,void * data)1248681a02e9SRoger Lu static irqreturn_t svs_isr(int irq, void *data)
1249681a02e9SRoger Lu {
1250681a02e9SRoger Lu 	struct svs_platform *svsp = data;
1251681a02e9SRoger Lu 	struct svs_bank *svsb = NULL;
1252681a02e9SRoger Lu 	unsigned long flags;
1253681a02e9SRoger Lu 	u32 idx, int_sts, svs_en;
1254681a02e9SRoger Lu 
1255681a02e9SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
1256681a02e9SRoger Lu 		svsb = &svsp->banks[idx];
1257681a02e9SRoger Lu 		WARN(!svsb, "%s: svsb(%s) is null", __func__, svsb->name);
1258681a02e9SRoger Lu 
1259681a02e9SRoger Lu 		spin_lock_irqsave(&svs_lock, flags);
1260681a02e9SRoger Lu 		svsp->pbank = svsb;
1261681a02e9SRoger Lu 
1262681a02e9SRoger Lu 		/* Find out which svs bank fires interrupt */
1263681a02e9SRoger Lu 		if (svsb->int_st & svs_readl_relaxed(svsp, INTST)) {
1264681a02e9SRoger Lu 			spin_unlock_irqrestore(&svs_lock, flags);
1265681a02e9SRoger Lu 			continue;
1266681a02e9SRoger Lu 		}
1267681a02e9SRoger Lu 
1268681a02e9SRoger Lu 		svs_switch_bank(svsp);
1269681a02e9SRoger Lu 		int_sts = svs_readl_relaxed(svsp, INTSTS);
1270681a02e9SRoger Lu 		svs_en = svs_readl_relaxed(svsp, SVSEN);
1271681a02e9SRoger Lu 
1272a92438c5SAngeloGioacchino Del Regno 		if (int_sts == SVSB_INTSTS_F0_COMPLETE &&
1273a92438c5SAngeloGioacchino Del Regno 		    svs_en == SVSB_PTPEN_INIT01)
1274681a02e9SRoger Lu 			svs_init01_isr_handler(svsp);
1275a92438c5SAngeloGioacchino Del Regno 		else if (int_sts == SVSB_INTSTS_F0_COMPLETE &&
1276a92438c5SAngeloGioacchino Del Regno 			 svs_en == SVSB_PTPEN_INIT02)
1277681a02e9SRoger Lu 			svs_init02_isr_handler(svsp);
1278a92438c5SAngeloGioacchino Del Regno 		else if (int_sts & SVSB_INTSTS_FLD_MONVOP)
12796c692719SRoger Lu 			svs_mon_mode_isr_handler(svsp);
1280681a02e9SRoger Lu 		else
1281681a02e9SRoger Lu 			svs_error_isr_handler(svsp);
1282681a02e9SRoger Lu 
1283681a02e9SRoger Lu 		spin_unlock_irqrestore(&svs_lock, flags);
1284681a02e9SRoger Lu 		break;
1285681a02e9SRoger Lu 	}
1286681a02e9SRoger Lu 
1287681a02e9SRoger Lu 	svs_adjust_pm_opp_volts(svsb);
1288681a02e9SRoger Lu 
1289681a02e9SRoger Lu 	if (svsb->phase == SVSB_PHASE_INIT01 ||
1290681a02e9SRoger Lu 	    svsb->phase == SVSB_PHASE_INIT02)
1291681a02e9SRoger Lu 		complete(&svsb->init_completion);
1292681a02e9SRoger Lu 
1293681a02e9SRoger Lu 	return IRQ_HANDLED;
1294681a02e9SRoger Lu }
1295681a02e9SRoger Lu 
svs_init01(struct svs_platform * svsp)1296681a02e9SRoger Lu static int svs_init01(struct svs_platform *svsp)
1297681a02e9SRoger Lu {
1298681a02e9SRoger Lu 	struct svs_bank *svsb;
1299681a02e9SRoger Lu 	unsigned long flags, time_left;
1300681a02e9SRoger Lu 	bool search_done;
1301681a02e9SRoger Lu 	int ret = 0, r;
1302681a02e9SRoger Lu 	u32 opp_freq, opp_vboot, buck_volt, idx, i;
1303681a02e9SRoger Lu 
1304681a02e9SRoger Lu 	/* Keep CPUs' core power on for svs_init01 initialization */
1305681a02e9SRoger Lu 	cpuidle_pause_and_lock();
1306681a02e9SRoger Lu 
1307681a02e9SRoger Lu 	 /* Svs bank init01 preparation - power enable */
1308681a02e9SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
1309681a02e9SRoger Lu 		svsb = &svsp->banks[idx];
1310681a02e9SRoger Lu 
1311681a02e9SRoger Lu 		if (!(svsb->mode_support & SVSB_MODE_INIT01))
1312681a02e9SRoger Lu 			continue;
1313681a02e9SRoger Lu 
1314681a02e9SRoger Lu 		ret = regulator_enable(svsb->buck);
1315681a02e9SRoger Lu 		if (ret) {
1316681a02e9SRoger Lu 			dev_err(svsb->dev, "%s enable fail: %d\n",
1317681a02e9SRoger Lu 				svsb->buck_name, ret);
1318681a02e9SRoger Lu 			goto svs_init01_resume_cpuidle;
1319681a02e9SRoger Lu 		}
1320681a02e9SRoger Lu 
1321681a02e9SRoger Lu 		/* Some buck doesn't support mode change. Show fail msg only */
1322681a02e9SRoger Lu 		ret = regulator_set_mode(svsb->buck, REGULATOR_MODE_FAST);
1323681a02e9SRoger Lu 		if (ret)
1324681a02e9SRoger Lu 			dev_notice(svsb->dev, "set fast mode fail: %d\n", ret);
1325681a02e9SRoger Lu 
1326681a02e9SRoger Lu 		if (svsb->volt_flags & SVSB_INIT01_PD_REQ) {
1327681a02e9SRoger Lu 			if (!pm_runtime_enabled(svsb->opp_dev)) {
1328681a02e9SRoger Lu 				pm_runtime_enable(svsb->opp_dev);
1329681a02e9SRoger Lu 				svsb->pm_runtime_enabled_count++;
1330681a02e9SRoger Lu 			}
1331681a02e9SRoger Lu 
133237fa2affSShang XiaoJing 			ret = pm_runtime_resume_and_get(svsb->opp_dev);
1333681a02e9SRoger Lu 			if (ret < 0) {
1334681a02e9SRoger Lu 				dev_err(svsb->dev, "mtcmos on fail: %d\n", ret);
1335681a02e9SRoger Lu 				goto svs_init01_resume_cpuidle;
1336681a02e9SRoger Lu 			}
1337681a02e9SRoger Lu 		}
1338681a02e9SRoger Lu 	}
1339681a02e9SRoger Lu 
1340681a02e9SRoger Lu 	/*
1341681a02e9SRoger Lu 	 * Svs bank init01 preparation - vboot voltage adjustment
1342681a02e9SRoger Lu 	 * Sometimes two svs banks use the same buck. Therefore,
1343681a02e9SRoger Lu 	 * we have to set each svs bank to target voltage(vboot) first.
1344681a02e9SRoger Lu 	 */
1345681a02e9SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
1346681a02e9SRoger Lu 		svsb = &svsp->banks[idx];
1347681a02e9SRoger Lu 
1348681a02e9SRoger Lu 		if (!(svsb->mode_support & SVSB_MODE_INIT01))
1349681a02e9SRoger Lu 			continue;
1350681a02e9SRoger Lu 
1351681a02e9SRoger Lu 		/*
1352681a02e9SRoger Lu 		 * Find the fastest freq that can be run at vboot and
1353681a02e9SRoger Lu 		 * fix to that freq until svs_init01 is done.
1354681a02e9SRoger Lu 		 */
1355681a02e9SRoger Lu 		search_done = false;
1356681a02e9SRoger Lu 		opp_vboot = svs_bank_volt_to_opp_volt(svsb->vboot,
1357681a02e9SRoger Lu 						      svsb->volt_step,
1358681a02e9SRoger Lu 						      svsb->volt_base);
1359681a02e9SRoger Lu 
1360681a02e9SRoger Lu 		for (i = 0; i < svsb->opp_count; i++) {
1361681a02e9SRoger Lu 			opp_freq = svsb->opp_dfreq[i];
1362681a02e9SRoger Lu 			if (!search_done && svsb->opp_dvolt[i] <= opp_vboot) {
1363681a02e9SRoger Lu 				ret = dev_pm_opp_adjust_voltage(svsb->opp_dev,
1364681a02e9SRoger Lu 								opp_freq,
1365681a02e9SRoger Lu 								opp_vboot,
1366681a02e9SRoger Lu 								opp_vboot,
1367681a02e9SRoger Lu 								opp_vboot);
1368681a02e9SRoger Lu 				if (ret) {
1369681a02e9SRoger Lu 					dev_err(svsb->dev,
1370681a02e9SRoger Lu 						"set opp %uuV vboot fail: %d\n",
1371681a02e9SRoger Lu 						opp_vboot, ret);
1372681a02e9SRoger Lu 					goto svs_init01_finish;
1373681a02e9SRoger Lu 				}
1374681a02e9SRoger Lu 
1375681a02e9SRoger Lu 				search_done = true;
1376681a02e9SRoger Lu 			} else {
1377681a02e9SRoger Lu 				ret = dev_pm_opp_disable(svsb->opp_dev,
1378681a02e9SRoger Lu 							 svsb->opp_dfreq[i]);
1379681a02e9SRoger Lu 				if (ret) {
1380681a02e9SRoger Lu 					dev_err(svsb->dev,
1381681a02e9SRoger Lu 						"opp %uHz disable fail: %d\n",
1382681a02e9SRoger Lu 						svsb->opp_dfreq[i], ret);
1383681a02e9SRoger Lu 					goto svs_init01_finish;
1384681a02e9SRoger Lu 				}
1385681a02e9SRoger Lu 			}
1386681a02e9SRoger Lu 		}
1387681a02e9SRoger Lu 	}
1388681a02e9SRoger Lu 
1389681a02e9SRoger Lu 	/* Svs bank init01 begins */
1390681a02e9SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
1391681a02e9SRoger Lu 		svsb = &svsp->banks[idx];
1392681a02e9SRoger Lu 
1393681a02e9SRoger Lu 		if (!(svsb->mode_support & SVSB_MODE_INIT01))
1394681a02e9SRoger Lu 			continue;
1395681a02e9SRoger Lu 
1396681a02e9SRoger Lu 		opp_vboot = svs_bank_volt_to_opp_volt(svsb->vboot,
1397681a02e9SRoger Lu 						      svsb->volt_step,
1398681a02e9SRoger Lu 						      svsb->volt_base);
1399681a02e9SRoger Lu 
1400681a02e9SRoger Lu 		buck_volt = regulator_get_voltage(svsb->buck);
1401681a02e9SRoger Lu 		if (buck_volt != opp_vboot) {
1402681a02e9SRoger Lu 			dev_err(svsb->dev,
1403681a02e9SRoger Lu 				"buck voltage: %uuV, expected vboot: %uuV\n",
1404681a02e9SRoger Lu 				buck_volt, opp_vboot);
1405681a02e9SRoger Lu 			ret = -EPERM;
1406681a02e9SRoger Lu 			goto svs_init01_finish;
1407681a02e9SRoger Lu 		}
1408681a02e9SRoger Lu 
1409681a02e9SRoger Lu 		spin_lock_irqsave(&svs_lock, flags);
1410681a02e9SRoger Lu 		svsp->pbank = svsb;
1411681a02e9SRoger Lu 		svs_set_bank_phase(svsp, SVSB_PHASE_INIT01);
1412681a02e9SRoger Lu 		spin_unlock_irqrestore(&svs_lock, flags);
1413681a02e9SRoger Lu 
1414681a02e9SRoger Lu 		time_left = wait_for_completion_timeout(&svsb->init_completion,
1415681a02e9SRoger Lu 							msecs_to_jiffies(5000));
1416681a02e9SRoger Lu 		if (!time_left) {
1417681a02e9SRoger Lu 			dev_err(svsb->dev, "init01 completion timeout\n");
1418681a02e9SRoger Lu 			ret = -EBUSY;
1419681a02e9SRoger Lu 			goto svs_init01_finish;
1420681a02e9SRoger Lu 		}
1421681a02e9SRoger Lu 	}
1422681a02e9SRoger Lu 
1423681a02e9SRoger Lu svs_init01_finish:
1424681a02e9SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
1425681a02e9SRoger Lu 		svsb = &svsp->banks[idx];
1426681a02e9SRoger Lu 
1427681a02e9SRoger Lu 		if (!(svsb->mode_support & SVSB_MODE_INIT01))
1428681a02e9SRoger Lu 			continue;
1429681a02e9SRoger Lu 
1430681a02e9SRoger Lu 		for (i = 0; i < svsb->opp_count; i++) {
1431681a02e9SRoger Lu 			r = dev_pm_opp_enable(svsb->opp_dev,
1432681a02e9SRoger Lu 					      svsb->opp_dfreq[i]);
1433681a02e9SRoger Lu 			if (r)
1434681a02e9SRoger Lu 				dev_err(svsb->dev, "opp %uHz enable fail: %d\n",
1435681a02e9SRoger Lu 					svsb->opp_dfreq[i], r);
1436681a02e9SRoger Lu 		}
1437681a02e9SRoger Lu 
1438681a02e9SRoger Lu 		if (svsb->volt_flags & SVSB_INIT01_PD_REQ) {
1439681a02e9SRoger Lu 			r = pm_runtime_put_sync(svsb->opp_dev);
1440681a02e9SRoger Lu 			if (r)
1441681a02e9SRoger Lu 				dev_err(svsb->dev, "mtcmos off fail: %d\n", r);
1442681a02e9SRoger Lu 
1443681a02e9SRoger Lu 			if (svsb->pm_runtime_enabled_count > 0) {
1444681a02e9SRoger Lu 				pm_runtime_disable(svsb->opp_dev);
1445681a02e9SRoger Lu 				svsb->pm_runtime_enabled_count--;
1446681a02e9SRoger Lu 			}
1447681a02e9SRoger Lu 		}
1448681a02e9SRoger Lu 
1449681a02e9SRoger Lu 		r = regulator_set_mode(svsb->buck, REGULATOR_MODE_NORMAL);
1450681a02e9SRoger Lu 		if (r)
1451681a02e9SRoger Lu 			dev_notice(svsb->dev, "set normal mode fail: %d\n", r);
1452681a02e9SRoger Lu 
1453681a02e9SRoger Lu 		r = regulator_disable(svsb->buck);
1454681a02e9SRoger Lu 		if (r)
1455681a02e9SRoger Lu 			dev_err(svsb->dev, "%s disable fail: %d\n",
1456681a02e9SRoger Lu 				svsb->buck_name, r);
1457681a02e9SRoger Lu 	}
1458681a02e9SRoger Lu 
1459681a02e9SRoger Lu svs_init01_resume_cpuidle:
1460681a02e9SRoger Lu 	cpuidle_resume_and_unlock();
1461681a02e9SRoger Lu 
1462681a02e9SRoger Lu 	return ret;
1463681a02e9SRoger Lu }
1464681a02e9SRoger Lu 
svs_init02(struct svs_platform * svsp)1465681a02e9SRoger Lu static int svs_init02(struct svs_platform *svsp)
1466681a02e9SRoger Lu {
1467681a02e9SRoger Lu 	struct svs_bank *svsb;
1468681a02e9SRoger Lu 	unsigned long flags, time_left;
1469a0674cd2SRoger Lu 	int ret;
1470681a02e9SRoger Lu 	u32 idx;
1471681a02e9SRoger Lu 
1472681a02e9SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
1473681a02e9SRoger Lu 		svsb = &svsp->banks[idx];
1474681a02e9SRoger Lu 
1475681a02e9SRoger Lu 		if (!(svsb->mode_support & SVSB_MODE_INIT02))
1476681a02e9SRoger Lu 			continue;
1477681a02e9SRoger Lu 
1478681a02e9SRoger Lu 		reinit_completion(&svsb->init_completion);
1479681a02e9SRoger Lu 		spin_lock_irqsave(&svs_lock, flags);
1480681a02e9SRoger Lu 		svsp->pbank = svsb;
1481681a02e9SRoger Lu 		svs_set_bank_phase(svsp, SVSB_PHASE_INIT02);
1482681a02e9SRoger Lu 		spin_unlock_irqrestore(&svs_lock, flags);
1483681a02e9SRoger Lu 
1484681a02e9SRoger Lu 		time_left = wait_for_completion_timeout(&svsb->init_completion,
1485681a02e9SRoger Lu 							msecs_to_jiffies(5000));
1486681a02e9SRoger Lu 		if (!time_left) {
1487681a02e9SRoger Lu 			dev_err(svsb->dev, "init02 completion timeout\n");
1488a0674cd2SRoger Lu 			ret = -EBUSY;
1489a0674cd2SRoger Lu 			goto out_of_init02;
1490681a02e9SRoger Lu 		}
1491681a02e9SRoger Lu 	}
1492681a02e9SRoger Lu 
14930bbb09b2SRoger Lu 	/*
14940bbb09b2SRoger Lu 	 * 2-line high/low bank update its corresponding opp voltages only.
14950bbb09b2SRoger Lu 	 * Therefore, we sync voltages from opp for high/low bank voltages
14960bbb09b2SRoger Lu 	 * consistency.
14970bbb09b2SRoger Lu 	 */
14980bbb09b2SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
14990bbb09b2SRoger Lu 		svsb = &svsp->banks[idx];
15000bbb09b2SRoger Lu 
15010bbb09b2SRoger Lu 		if (!(svsb->mode_support & SVSB_MODE_INIT02))
15020bbb09b2SRoger Lu 			continue;
15030bbb09b2SRoger Lu 
15040bbb09b2SRoger Lu 		if (svsb->type == SVSB_HIGH || svsb->type == SVSB_LOW) {
15050bbb09b2SRoger Lu 			if (svs_sync_bank_volts_from_opp(svsb)) {
15060bbb09b2SRoger Lu 				dev_err(svsb->dev, "sync volt fail\n");
1507a0674cd2SRoger Lu 				ret = -EPERM;
1508a0674cd2SRoger Lu 				goto out_of_init02;
15090bbb09b2SRoger Lu 			}
15100bbb09b2SRoger Lu 		}
15110bbb09b2SRoger Lu 	}
15120bbb09b2SRoger Lu 
1513681a02e9SRoger Lu 	return 0;
1514a0674cd2SRoger Lu 
1515a0674cd2SRoger Lu out_of_init02:
1516a0674cd2SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
1517a0674cd2SRoger Lu 		svsb = &svsp->banks[idx];
15185061c47eSRoger Lu 		svs_bank_disable_and_restore_default_volts(svsp, svsb);
1519a0674cd2SRoger Lu 	}
1520a0674cd2SRoger Lu 
1521a0674cd2SRoger Lu 	return ret;
1522681a02e9SRoger Lu }
1523681a02e9SRoger Lu 
svs_mon_mode(struct svs_platform * svsp)15246c692719SRoger Lu static void svs_mon_mode(struct svs_platform *svsp)
15256c692719SRoger Lu {
15266c692719SRoger Lu 	struct svs_bank *svsb;
15276c692719SRoger Lu 	unsigned long flags;
15286c692719SRoger Lu 	u32 idx;
15296c692719SRoger Lu 
15306c692719SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
15316c692719SRoger Lu 		svsb = &svsp->banks[idx];
15326c692719SRoger Lu 
15336c692719SRoger Lu 		if (!(svsb->mode_support & SVSB_MODE_MON))
15346c692719SRoger Lu 			continue;
15356c692719SRoger Lu 
15366c692719SRoger Lu 		spin_lock_irqsave(&svs_lock, flags);
15376c692719SRoger Lu 		svsp->pbank = svsb;
15386c692719SRoger Lu 		svs_set_bank_phase(svsp, SVSB_PHASE_MON);
15396c692719SRoger Lu 		spin_unlock_irqrestore(&svs_lock, flags);
15406c692719SRoger Lu 	}
15416c692719SRoger Lu }
15426c692719SRoger Lu 
svs_start(struct svs_platform * svsp)1543681a02e9SRoger Lu static int svs_start(struct svs_platform *svsp)
1544681a02e9SRoger Lu {
1545681a02e9SRoger Lu 	int ret;
1546681a02e9SRoger Lu 
1547681a02e9SRoger Lu 	ret = svs_init01(svsp);
1548681a02e9SRoger Lu 	if (ret)
1549681a02e9SRoger Lu 		return ret;
1550681a02e9SRoger Lu 
1551681a02e9SRoger Lu 	ret = svs_init02(svsp);
1552681a02e9SRoger Lu 	if (ret)
1553681a02e9SRoger Lu 		return ret;
1554681a02e9SRoger Lu 
15556c692719SRoger Lu 	svs_mon_mode(svsp);
15566c692719SRoger Lu 
1557681a02e9SRoger Lu 	return 0;
1558681a02e9SRoger Lu }
1559681a02e9SRoger Lu 
svs_suspend(struct device * dev)1560681a02e9SRoger Lu static int svs_suspend(struct device *dev)
1561681a02e9SRoger Lu {
1562681a02e9SRoger Lu 	struct svs_platform *svsp = dev_get_drvdata(dev);
1563681a02e9SRoger Lu 	struct svs_bank *svsb;
15640bbb09b2SRoger Lu 	int ret;
1565681a02e9SRoger Lu 	u32 idx;
1566681a02e9SRoger Lu 
1567681a02e9SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
1568681a02e9SRoger Lu 		svsb = &svsp->banks[idx];
15695061c47eSRoger Lu 		svs_bank_disable_and_restore_default_volts(svsp, svsb);
1570681a02e9SRoger Lu 	}
1571681a02e9SRoger Lu 
15720bbb09b2SRoger Lu 	ret = reset_control_assert(svsp->rst);
15730bbb09b2SRoger Lu 	if (ret) {
15740bbb09b2SRoger Lu 		dev_err(svsp->dev, "cannot assert reset %d\n", ret);
15750bbb09b2SRoger Lu 		return ret;
15760bbb09b2SRoger Lu 	}
15770bbb09b2SRoger Lu 
1578681a02e9SRoger Lu 	clk_disable_unprepare(svsp->main_clk);
1579681a02e9SRoger Lu 
1580681a02e9SRoger Lu 	return 0;
1581681a02e9SRoger Lu }
1582681a02e9SRoger Lu 
svs_resume(struct device * dev)1583681a02e9SRoger Lu static int svs_resume(struct device *dev)
1584681a02e9SRoger Lu {
1585681a02e9SRoger Lu 	struct svs_platform *svsp = dev_get_drvdata(dev);
1586681a02e9SRoger Lu 	int ret;
1587681a02e9SRoger Lu 
1588681a02e9SRoger Lu 	ret = clk_prepare_enable(svsp->main_clk);
1589681a02e9SRoger Lu 	if (ret) {
1590681a02e9SRoger Lu 		dev_err(svsp->dev, "cannot enable main_clk, disable svs\n");
1591681a02e9SRoger Lu 		return ret;
1592681a02e9SRoger Lu 	}
1593681a02e9SRoger Lu 
15940bbb09b2SRoger Lu 	ret = reset_control_deassert(svsp->rst);
15950bbb09b2SRoger Lu 	if (ret) {
15960bbb09b2SRoger Lu 		dev_err(svsp->dev, "cannot deassert reset %d\n", ret);
1597a825d72fSPeng Wu 		goto out_of_resume;
15980bbb09b2SRoger Lu 	}
15990bbb09b2SRoger Lu 
1600681a02e9SRoger Lu 	ret = svs_init02(svsp);
1601681a02e9SRoger Lu 	if (ret)
1602f4f8ad20SRoger Lu 		goto svs_resume_reset_assert;
1603681a02e9SRoger Lu 
16046c692719SRoger Lu 	svs_mon_mode(svsp);
16056c692719SRoger Lu 
1606681a02e9SRoger Lu 	return 0;
1607a825d72fSPeng Wu 
1608f4f8ad20SRoger Lu svs_resume_reset_assert:
1609f4f8ad20SRoger Lu 	dev_err(svsp->dev, "assert reset: %d\n",
1610f4f8ad20SRoger Lu 		reset_control_assert(svsp->rst));
1611f4f8ad20SRoger Lu 
1612a825d72fSPeng Wu out_of_resume:
1613a825d72fSPeng Wu 	clk_disable_unprepare(svsp->main_clk);
1614a825d72fSPeng Wu 	return ret;
1615681a02e9SRoger Lu }
1616681a02e9SRoger Lu 
svs_bank_resource_setup(struct svs_platform * svsp)1617681a02e9SRoger Lu static int svs_bank_resource_setup(struct svs_platform *svsp)
1618681a02e9SRoger Lu {
1619681a02e9SRoger Lu 	struct svs_bank *svsb;
1620681a02e9SRoger Lu 	struct dev_pm_opp *opp;
1621681a02e9SRoger Lu 	unsigned long freq;
1622681a02e9SRoger Lu 	int count, ret;
1623681a02e9SRoger Lu 	u32 idx, i;
1624681a02e9SRoger Lu 
1625681a02e9SRoger Lu 	dev_set_drvdata(svsp->dev, svsp);
1626681a02e9SRoger Lu 
1627681a02e9SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
1628681a02e9SRoger Lu 		svsb = &svsp->banks[idx];
1629681a02e9SRoger Lu 
1630681a02e9SRoger Lu 		switch (svsb->sw_id) {
1631681a02e9SRoger Lu 		case SVSB_CPU_LITTLE:
1632681a02e9SRoger Lu 			svsb->name = "SVSB_CPU_LITTLE";
1633681a02e9SRoger Lu 			break;
1634681a02e9SRoger Lu 		case SVSB_CPU_BIG:
1635681a02e9SRoger Lu 			svsb->name = "SVSB_CPU_BIG";
1636681a02e9SRoger Lu 			break;
1637681a02e9SRoger Lu 		case SVSB_CCI:
1638681a02e9SRoger Lu 			svsb->name = "SVSB_CCI";
1639681a02e9SRoger Lu 			break;
1640681a02e9SRoger Lu 		case SVSB_GPU:
16410bbb09b2SRoger Lu 			if (svsb->type == SVSB_HIGH)
16420bbb09b2SRoger Lu 				svsb->name = "SVSB_GPU_HIGH";
16430bbb09b2SRoger Lu 			else if (svsb->type == SVSB_LOW)
16440bbb09b2SRoger Lu 				svsb->name = "SVSB_GPU_LOW";
16450bbb09b2SRoger Lu 			else
1646681a02e9SRoger Lu 				svsb->name = "SVSB_GPU";
1647681a02e9SRoger Lu 			break;
1648681a02e9SRoger Lu 		default:
1649681a02e9SRoger Lu 			dev_err(svsb->dev, "unknown sw_id: %u\n", svsb->sw_id);
1650681a02e9SRoger Lu 			return -EINVAL;
1651681a02e9SRoger Lu 		}
1652681a02e9SRoger Lu 
1653681a02e9SRoger Lu 		svsb->dev = devm_kzalloc(svsp->dev, sizeof(*svsb->dev),
1654681a02e9SRoger Lu 					 GFP_KERNEL);
1655681a02e9SRoger Lu 		if (!svsb->dev)
1656681a02e9SRoger Lu 			return -ENOMEM;
1657681a02e9SRoger Lu 
1658681a02e9SRoger Lu 		ret = dev_set_name(svsb->dev, "%s", svsb->name);
1659681a02e9SRoger Lu 		if (ret)
1660681a02e9SRoger Lu 			return ret;
1661681a02e9SRoger Lu 
1662681a02e9SRoger Lu 		dev_set_drvdata(svsb->dev, svsp);
1663681a02e9SRoger Lu 
166402aace9bSAngeloGioacchino Del Regno 		ret = devm_pm_opp_of_add_table(svsb->opp_dev);
1665681a02e9SRoger Lu 		if (ret) {
1666681a02e9SRoger Lu 			dev_err(svsb->dev, "add opp table fail: %d\n", ret);
1667681a02e9SRoger Lu 			return ret;
1668681a02e9SRoger Lu 		}
1669681a02e9SRoger Lu 
1670681a02e9SRoger Lu 		mutex_init(&svsb->lock);
1671681a02e9SRoger Lu 		init_completion(&svsb->init_completion);
1672681a02e9SRoger Lu 
1673681a02e9SRoger Lu 		if (svsb->mode_support & SVSB_MODE_INIT01) {
1674681a02e9SRoger Lu 			svsb->buck = devm_regulator_get_optional(svsb->opp_dev,
1675681a02e9SRoger Lu 								 svsb->buck_name);
1676681a02e9SRoger Lu 			if (IS_ERR(svsb->buck)) {
1677681a02e9SRoger Lu 				dev_err(svsb->dev, "cannot get \"%s-supply\"\n",
1678681a02e9SRoger Lu 					svsb->buck_name);
1679681a02e9SRoger Lu 				return PTR_ERR(svsb->buck);
1680681a02e9SRoger Lu 			}
1681681a02e9SRoger Lu 		}
1682681a02e9SRoger Lu 
1683bd0a62a6SRoger Lu 		if (!IS_ERR_OR_NULL(svsb->tzone_name)) {
16846c692719SRoger Lu 			svsb->tzd = thermal_zone_get_zone_by_name(svsb->tzone_name);
16856c692719SRoger Lu 			if (IS_ERR(svsb->tzd)) {
16866c692719SRoger Lu 				dev_err(svsb->dev, "cannot get \"%s\" thermal zone\n",
16876c692719SRoger Lu 					svsb->tzone_name);
16886c692719SRoger Lu 				return PTR_ERR(svsb->tzd);
16896c692719SRoger Lu 			}
16906c692719SRoger Lu 		}
16916c692719SRoger Lu 
1692681a02e9SRoger Lu 		count = dev_pm_opp_get_opp_count(svsb->opp_dev);
1693681a02e9SRoger Lu 		if (svsb->opp_count != count) {
1694681a02e9SRoger Lu 			dev_err(svsb->dev,
1695681a02e9SRoger Lu 				"opp_count not \"%u\" but get \"%d\"?\n",
1696681a02e9SRoger Lu 				svsb->opp_count, count);
1697681a02e9SRoger Lu 			return count;
1698681a02e9SRoger Lu 		}
1699681a02e9SRoger Lu 
1700681a02e9SRoger Lu 		for (i = 0, freq = U32_MAX; i < svsb->opp_count; i++, freq--) {
1701681a02e9SRoger Lu 			opp = dev_pm_opp_find_freq_floor(svsb->opp_dev, &freq);
1702681a02e9SRoger Lu 			if (IS_ERR(opp)) {
1703681a02e9SRoger Lu 				dev_err(svsb->dev, "cannot find freq = %ld\n",
1704681a02e9SRoger Lu 					PTR_ERR(opp));
1705681a02e9SRoger Lu 				return PTR_ERR(opp);
1706681a02e9SRoger Lu 			}
1707681a02e9SRoger Lu 
1708681a02e9SRoger Lu 			svsb->opp_dfreq[i] = freq;
1709681a02e9SRoger Lu 			svsb->opp_dvolt[i] = dev_pm_opp_get_voltage(opp);
1710681a02e9SRoger Lu 			svsb->freq_pct[i] = percent(svsb->opp_dfreq[i],
1711681a02e9SRoger Lu 						    svsb->freq_base);
1712681a02e9SRoger Lu 			dev_pm_opp_put(opp);
1713681a02e9SRoger Lu 		}
1714681a02e9SRoger Lu 	}
1715681a02e9SRoger Lu 
1716681a02e9SRoger Lu 	return 0;
1717681a02e9SRoger Lu }
1718681a02e9SRoger Lu 
svs_get_efuse_data(struct svs_platform * svsp,const char * nvmem_cell_name,u32 ** svsp_efuse,size_t * svsp_efuse_max)17199f195f3aSRoger Lu static int svs_get_efuse_data(struct svs_platform *svsp,
17209f195f3aSRoger Lu 			      const char *nvmem_cell_name,
17219f195f3aSRoger Lu 			      u32 **svsp_efuse, size_t *svsp_efuse_max)
172243819e38SAngeloGioacchino Del Regno {
172343819e38SAngeloGioacchino Del Regno 	struct nvmem_cell *cell;
172443819e38SAngeloGioacchino Del Regno 
17259f195f3aSRoger Lu 	cell = nvmem_cell_get(svsp->dev, nvmem_cell_name);
1726edecdcccSRoger Lu 	if (IS_ERR(cell)) {
17279f195f3aSRoger Lu 		dev_err(svsp->dev, "no \"%s\"? %ld\n",
17289f195f3aSRoger Lu 			nvmem_cell_name, PTR_ERR(cell));
172943819e38SAngeloGioacchino Del Regno 		return PTR_ERR(cell);
173043819e38SAngeloGioacchino Del Regno 	}
173143819e38SAngeloGioacchino Del Regno 
17329f195f3aSRoger Lu 	*svsp_efuse = nvmem_cell_read(cell, svsp_efuse_max);
17339f195f3aSRoger Lu 	if (IS_ERR(*svsp_efuse)) {
17349f195f3aSRoger Lu 		dev_err(svsp->dev, "cannot read \"%s\" efuse: %ld\n",
17359f195f3aSRoger Lu 			nvmem_cell_name, PTR_ERR(*svsp_efuse));
173643819e38SAngeloGioacchino Del Regno 		nvmem_cell_put(cell);
17379f195f3aSRoger Lu 		return PTR_ERR(*svsp_efuse);
173843819e38SAngeloGioacchino Del Regno 	}
173943819e38SAngeloGioacchino Del Regno 
17409f195f3aSRoger Lu 	*svsp_efuse_max /= sizeof(u32);
174143819e38SAngeloGioacchino Del Regno 	nvmem_cell_put(cell);
174243819e38SAngeloGioacchino Del Regno 
174343819e38SAngeloGioacchino Del Regno 	return 0;
174443819e38SAngeloGioacchino Del Regno }
174543819e38SAngeloGioacchino Del Regno 
svs_mt8192_efuse_parsing(struct svs_platform * svsp)17460bbb09b2SRoger Lu static bool svs_mt8192_efuse_parsing(struct svs_platform *svsp)
17470bbb09b2SRoger Lu {
17480bbb09b2SRoger Lu 	struct svs_bank *svsb;
17490bbb09b2SRoger Lu 	u32 idx, i, vmin, golden_temp;
175043819e38SAngeloGioacchino Del Regno 	int ret;
17510bbb09b2SRoger Lu 
17520bbb09b2SRoger Lu 	for (i = 0; i < svsp->efuse_max; i++)
17530bbb09b2SRoger Lu 		if (svsp->efuse[i])
17540bbb09b2SRoger Lu 			dev_info(svsp->dev, "M_HW_RES%d: 0x%08x\n",
17550bbb09b2SRoger Lu 				 i, svsp->efuse[i]);
17560bbb09b2SRoger Lu 
17570bbb09b2SRoger Lu 	if (!svsp->efuse[9]) {
17580bbb09b2SRoger Lu 		dev_notice(svsp->dev, "svs_efuse[9] = 0x0?\n");
17590bbb09b2SRoger Lu 		return false;
17600bbb09b2SRoger Lu 	}
17610bbb09b2SRoger Lu 
17620bbb09b2SRoger Lu 	/* Svs efuse parsing */
17630bbb09b2SRoger Lu 	vmin = (svsp->efuse[19] >> 4) & GENMASK(1, 0);
17640bbb09b2SRoger Lu 
17650bbb09b2SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
17660bbb09b2SRoger Lu 		svsb = &svsp->banks[idx];
17670bbb09b2SRoger Lu 
17680bbb09b2SRoger Lu 		if (vmin == 0x1)
17690bbb09b2SRoger Lu 			svsb->vmin = 0x1e;
17700bbb09b2SRoger Lu 
17710bbb09b2SRoger Lu 		if (svsb->type == SVSB_LOW) {
17720bbb09b2SRoger Lu 			svsb->mtdes = svsp->efuse[10] & GENMASK(7, 0);
17730bbb09b2SRoger Lu 			svsb->bdes = (svsp->efuse[10] >> 16) & GENMASK(7, 0);
17740bbb09b2SRoger Lu 			svsb->mdes = (svsp->efuse[10] >> 24) & GENMASK(7, 0);
17750bbb09b2SRoger Lu 			svsb->dcbdet = (svsp->efuse[17]) & GENMASK(7, 0);
17760bbb09b2SRoger Lu 			svsb->dcmdet = (svsp->efuse[17] >> 8) & GENMASK(7, 0);
17770bbb09b2SRoger Lu 		} else if (svsb->type == SVSB_HIGH) {
17780bbb09b2SRoger Lu 			svsb->mtdes = svsp->efuse[9] & GENMASK(7, 0);
17790bbb09b2SRoger Lu 			svsb->bdes = (svsp->efuse[9] >> 16) & GENMASK(7, 0);
17800bbb09b2SRoger Lu 			svsb->mdes = (svsp->efuse[9] >> 24) & GENMASK(7, 0);
17810bbb09b2SRoger Lu 			svsb->dcbdet = (svsp->efuse[17] >> 16) & GENMASK(7, 0);
17820bbb09b2SRoger Lu 			svsb->dcmdet = (svsp->efuse[17] >> 24) & GENMASK(7, 0);
17830bbb09b2SRoger Lu 		}
17840bbb09b2SRoger Lu 
17850bbb09b2SRoger Lu 		svsb->vmax += svsb->dvt_fixed;
17860bbb09b2SRoger Lu 	}
17870bbb09b2SRoger Lu 
17889f195f3aSRoger Lu 	ret = svs_get_efuse_data(svsp, "t-calibration-data",
17899f195f3aSRoger Lu 				 &svsp->tefuse, &svsp->tefuse_max);
179043819e38SAngeloGioacchino Del Regno 	if (ret)
17910bbb09b2SRoger Lu 		return false;
17920bbb09b2SRoger Lu 
17930bbb09b2SRoger Lu 	for (i = 0; i < svsp->tefuse_max; i++)
17940bbb09b2SRoger Lu 		if (svsp->tefuse[i] != 0)
17950bbb09b2SRoger Lu 			break;
17960bbb09b2SRoger Lu 
17970bbb09b2SRoger Lu 	if (i == svsp->tefuse_max)
17980bbb09b2SRoger Lu 		golden_temp = 50; /* All thermal efuse data are 0 */
17990bbb09b2SRoger Lu 	else
18000bbb09b2SRoger Lu 		golden_temp = (svsp->tefuse[0] >> 24) & GENMASK(7, 0);
18010bbb09b2SRoger Lu 
18020bbb09b2SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
18030bbb09b2SRoger Lu 		svsb = &svsp->banks[idx];
18040bbb09b2SRoger Lu 		svsb->mts = 500;
18050bbb09b2SRoger Lu 		svsb->bts = (((500 * golden_temp + 250460) / 1000) - 25) * 4;
18060bbb09b2SRoger Lu 	}
18070bbb09b2SRoger Lu 
18080bbb09b2SRoger Lu 	return true;
18090bbb09b2SRoger Lu }
18100bbb09b2SRoger Lu 
svs_mt8183_efuse_parsing(struct svs_platform * svsp)1811681a02e9SRoger Lu static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp)
1812681a02e9SRoger Lu {
1813681a02e9SRoger Lu 	struct svs_bank *svsb;
18146c692719SRoger Lu 	int format[6], x_roomt[6], o_vtsmcu[5], o_vtsabb, tb_roomt = 0;
18156c692719SRoger Lu 	int adc_ge_t, adc_oe_t, ge, oe, gain, degc_cali, adc_cali_en_t;
18166c692719SRoger Lu 	int o_slope, o_slope_sign, ts_id;
18176c692719SRoger Lu 	u32 idx, i, ft_pgm, mts, temp0, temp1, temp2;
181843819e38SAngeloGioacchino Del Regno 	int ret;
1819681a02e9SRoger Lu 
1820681a02e9SRoger Lu 	for (i = 0; i < svsp->efuse_max; i++)
1821681a02e9SRoger Lu 		if (svsp->efuse[i])
1822681a02e9SRoger Lu 			dev_info(svsp->dev, "M_HW_RES%d: 0x%08x\n",
1823681a02e9SRoger Lu 				 i, svsp->efuse[i]);
1824681a02e9SRoger Lu 
1825681a02e9SRoger Lu 	if (!svsp->efuse[2]) {
1826681a02e9SRoger Lu 		dev_notice(svsp->dev, "svs_efuse[2] = 0x0?\n");
1827681a02e9SRoger Lu 		return false;
1828681a02e9SRoger Lu 	}
1829681a02e9SRoger Lu 
1830681a02e9SRoger Lu 	/* Svs efuse parsing */
1831681a02e9SRoger Lu 	ft_pgm = (svsp->efuse[0] >> 4) & GENMASK(3, 0);
1832681a02e9SRoger Lu 
1833681a02e9SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
1834681a02e9SRoger Lu 		svsb = &svsp->banks[idx];
1835681a02e9SRoger Lu 
1836681a02e9SRoger Lu 		if (ft_pgm <= 1)
1837681a02e9SRoger Lu 			svsb->volt_flags |= SVSB_INIT01_VOLT_IGNORE;
1838681a02e9SRoger Lu 
1839681a02e9SRoger Lu 		switch (svsb->sw_id) {
1840681a02e9SRoger Lu 		case SVSB_CPU_LITTLE:
1841681a02e9SRoger Lu 			svsb->bdes = svsp->efuse[16] & GENMASK(7, 0);
1842681a02e9SRoger Lu 			svsb->mdes = (svsp->efuse[16] >> 8) & GENMASK(7, 0);
1843681a02e9SRoger Lu 			svsb->dcbdet = (svsp->efuse[16] >> 16) & GENMASK(7, 0);
1844681a02e9SRoger Lu 			svsb->dcmdet = (svsp->efuse[16] >> 24) & GENMASK(7, 0);
1845681a02e9SRoger Lu 			svsb->mtdes  = (svsp->efuse[17] >> 16) & GENMASK(7, 0);
1846681a02e9SRoger Lu 
1847681a02e9SRoger Lu 			if (ft_pgm <= 3)
1848681a02e9SRoger Lu 				svsb->volt_od += 10;
1849681a02e9SRoger Lu 			else
1850681a02e9SRoger Lu 				svsb->volt_od += 2;
1851681a02e9SRoger Lu 			break;
1852681a02e9SRoger Lu 		case SVSB_CPU_BIG:
1853681a02e9SRoger Lu 			svsb->bdes = svsp->efuse[18] & GENMASK(7, 0);
1854681a02e9SRoger Lu 			svsb->mdes = (svsp->efuse[18] >> 8) & GENMASK(7, 0);
1855681a02e9SRoger Lu 			svsb->dcbdet = (svsp->efuse[18] >> 16) & GENMASK(7, 0);
1856681a02e9SRoger Lu 			svsb->dcmdet = (svsp->efuse[18] >> 24) & GENMASK(7, 0);
1857681a02e9SRoger Lu 			svsb->mtdes  = svsp->efuse[17] & GENMASK(7, 0);
1858681a02e9SRoger Lu 
1859681a02e9SRoger Lu 			if (ft_pgm <= 3)
1860681a02e9SRoger Lu 				svsb->volt_od += 15;
1861681a02e9SRoger Lu 			else
1862681a02e9SRoger Lu 				svsb->volt_od += 12;
1863681a02e9SRoger Lu 			break;
1864681a02e9SRoger Lu 		case SVSB_CCI:
1865681a02e9SRoger Lu 			svsb->bdes = svsp->efuse[4] & GENMASK(7, 0);
1866681a02e9SRoger Lu 			svsb->mdes = (svsp->efuse[4] >> 8) & GENMASK(7, 0);
1867681a02e9SRoger Lu 			svsb->dcbdet = (svsp->efuse[4] >> 16) & GENMASK(7, 0);
1868681a02e9SRoger Lu 			svsb->dcmdet = (svsp->efuse[4] >> 24) & GENMASK(7, 0);
1869681a02e9SRoger Lu 			svsb->mtdes  = (svsp->efuse[5] >> 16) & GENMASK(7, 0);
1870681a02e9SRoger Lu 
1871681a02e9SRoger Lu 			if (ft_pgm <= 3)
1872681a02e9SRoger Lu 				svsb->volt_od += 10;
1873681a02e9SRoger Lu 			else
1874681a02e9SRoger Lu 				svsb->volt_od += 2;
1875681a02e9SRoger Lu 			break;
1876681a02e9SRoger Lu 		case SVSB_GPU:
1877681a02e9SRoger Lu 			svsb->bdes = svsp->efuse[6] & GENMASK(7, 0);
1878681a02e9SRoger Lu 			svsb->mdes = (svsp->efuse[6] >> 8) & GENMASK(7, 0);
1879681a02e9SRoger Lu 			svsb->dcbdet = (svsp->efuse[6] >> 16) & GENMASK(7, 0);
1880681a02e9SRoger Lu 			svsb->dcmdet = (svsp->efuse[6] >> 24) & GENMASK(7, 0);
1881681a02e9SRoger Lu 			svsb->mtdes  = svsp->efuse[5] & GENMASK(7, 0);
1882681a02e9SRoger Lu 
1883681a02e9SRoger Lu 			if (ft_pgm >= 2) {
1884681a02e9SRoger Lu 				svsb->freq_base = 800000000; /* 800MHz */
1885681a02e9SRoger Lu 				svsb->dvt_fixed = 2;
1886681a02e9SRoger Lu 			}
1887681a02e9SRoger Lu 			break;
1888681a02e9SRoger Lu 		default:
1889681a02e9SRoger Lu 			dev_err(svsb->dev, "unknown sw_id: %u\n", svsb->sw_id);
1890681a02e9SRoger Lu 			return false;
1891681a02e9SRoger Lu 		}
1892681a02e9SRoger Lu 	}
1893681a02e9SRoger Lu 
18949f195f3aSRoger Lu 	ret = svs_get_efuse_data(svsp, "t-calibration-data",
18959f195f3aSRoger Lu 				 &svsp->tefuse, &svsp->tefuse_max);
189643819e38SAngeloGioacchino Del Regno 	if (ret)
189743819e38SAngeloGioacchino Del Regno 		return false;
18986c692719SRoger Lu 
18996c692719SRoger Lu 	/* Thermal efuse parsing */
19006c692719SRoger Lu 	adc_ge_t = (svsp->tefuse[1] >> 22) & GENMASK(9, 0);
19016c692719SRoger Lu 	adc_oe_t = (svsp->tefuse[1] >> 12) & GENMASK(9, 0);
19026c692719SRoger Lu 
19036c692719SRoger Lu 	o_vtsmcu[0] = (svsp->tefuse[0] >> 17) & GENMASK(8, 0);
19046c692719SRoger Lu 	o_vtsmcu[1] = (svsp->tefuse[0] >> 8) & GENMASK(8, 0);
19056c692719SRoger Lu 	o_vtsmcu[2] = svsp->tefuse[1] & GENMASK(8, 0);
19066c692719SRoger Lu 	o_vtsmcu[3] = (svsp->tefuse[2] >> 23) & GENMASK(8, 0);
19076c692719SRoger Lu 	o_vtsmcu[4] = (svsp->tefuse[2] >> 5) & GENMASK(8, 0);
19086c692719SRoger Lu 	o_vtsabb = (svsp->tefuse[2] >> 14) & GENMASK(8, 0);
19096c692719SRoger Lu 
19106c692719SRoger Lu 	degc_cali = (svsp->tefuse[0] >> 1) & GENMASK(5, 0);
19116c692719SRoger Lu 	adc_cali_en_t = svsp->tefuse[0] & BIT(0);
19126c692719SRoger Lu 	o_slope_sign = (svsp->tefuse[0] >> 7) & BIT(0);
19136c692719SRoger Lu 
19146c692719SRoger Lu 	ts_id = (svsp->tefuse[1] >> 9) & BIT(0);
1915d5a7d809SRoger Lu 	if (!ts_id) {
1916d5a7d809SRoger Lu 		o_slope = 1534;
1917d5a7d809SRoger Lu 	} else {
19186c692719SRoger Lu 		o_slope = (svsp->tefuse[0] >> 26) & GENMASK(5, 0);
1919d5a7d809SRoger Lu 		if (!o_slope_sign)
1920d5a7d809SRoger Lu 			o_slope = 1534 + o_slope * 10;
1921d5a7d809SRoger Lu 		else
1922d5a7d809SRoger Lu 			o_slope = 1534 - o_slope * 10;
1923d5a7d809SRoger Lu 	}
19246c692719SRoger Lu 
1925d5a7d809SRoger Lu 	if (adc_cali_en_t == 0 ||
1926d5a7d809SRoger Lu 	    adc_ge_t < 265 || adc_ge_t > 758 ||
19276c692719SRoger Lu 	    adc_oe_t < 265 || adc_oe_t > 758 ||
19286c692719SRoger Lu 	    o_vtsmcu[0] < -8 || o_vtsmcu[0] > 484 ||
19296c692719SRoger Lu 	    o_vtsmcu[1] < -8 || o_vtsmcu[1] > 484 ||
19306c692719SRoger Lu 	    o_vtsmcu[2] < -8 || o_vtsmcu[2] > 484 ||
19316c692719SRoger Lu 	    o_vtsmcu[3] < -8 || o_vtsmcu[3] > 484 ||
19326c692719SRoger Lu 	    o_vtsmcu[4] < -8 || o_vtsmcu[4] > 484 ||
19336c692719SRoger Lu 	    o_vtsabb < -8 || o_vtsabb > 484 ||
19346c692719SRoger Lu 	    degc_cali < 1 || degc_cali > 63) {
19356c692719SRoger Lu 		dev_err(svsp->dev, "bad thermal efuse, no mon mode\n");
19366c692719SRoger Lu 		goto remove_mt8183_svsb_mon_mode;
19376c692719SRoger Lu 	}
19386c692719SRoger Lu 
19396c692719SRoger Lu 	ge = ((adc_ge_t - 512) * 10000) / 4096;
19406c692719SRoger Lu 	oe = (adc_oe_t - 512);
19416c692719SRoger Lu 	gain = (10000 + ge);
19426c692719SRoger Lu 
19436c692719SRoger Lu 	format[0] = (o_vtsmcu[0] + 3350 - oe);
19446c692719SRoger Lu 	format[1] = (o_vtsmcu[1] + 3350 - oe);
19456c692719SRoger Lu 	format[2] = (o_vtsmcu[2] + 3350 - oe);
19466c692719SRoger Lu 	format[3] = (o_vtsmcu[3] + 3350 - oe);
19476c692719SRoger Lu 	format[4] = (o_vtsmcu[4] + 3350 - oe);
19486c692719SRoger Lu 	format[5] = (o_vtsabb + 3350 - oe);
19496c692719SRoger Lu 
19506c692719SRoger Lu 	for (i = 0; i < 6; i++)
19516c692719SRoger Lu 		x_roomt[i] = (((format[i] * 10000) / 4096) * 10000) / gain;
19526c692719SRoger Lu 
19536c692719SRoger Lu 	temp0 = (10000 * 100000 / gain) * 15 / 18;
1954d5a7d809SRoger Lu 	mts = (temp0 * 10) / o_slope;
19556c692719SRoger Lu 
19566c692719SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
19576c692719SRoger Lu 		svsb = &svsp->banks[idx];
19586c692719SRoger Lu 		svsb->mts = mts;
19596c692719SRoger Lu 
19606c692719SRoger Lu 		switch (svsb->sw_id) {
19616c692719SRoger Lu 		case SVSB_CPU_LITTLE:
19626c692719SRoger Lu 			tb_roomt = x_roomt[3];
19636c692719SRoger Lu 			break;
19646c692719SRoger Lu 		case SVSB_CPU_BIG:
19656c692719SRoger Lu 			tb_roomt = x_roomt[4];
19666c692719SRoger Lu 			break;
19676c692719SRoger Lu 		case SVSB_CCI:
19686c692719SRoger Lu 			tb_roomt = x_roomt[3];
19696c692719SRoger Lu 			break;
19706c692719SRoger Lu 		case SVSB_GPU:
19716c692719SRoger Lu 			tb_roomt = x_roomt[1];
19726c692719SRoger Lu 			break;
19736c692719SRoger Lu 		default:
19746c692719SRoger Lu 			dev_err(svsb->dev, "unknown sw_id: %u\n", svsb->sw_id);
19756c692719SRoger Lu 			goto remove_mt8183_svsb_mon_mode;
19766c692719SRoger Lu 		}
19776c692719SRoger Lu 
19786c692719SRoger Lu 		temp0 = (degc_cali * 10 / 2);
19796c692719SRoger Lu 		temp1 = ((10000 * 100000 / 4096 / gain) *
19806c692719SRoger Lu 			 oe + tb_roomt * 10) * 15 / 18;
1981d5a7d809SRoger Lu 		temp2 = temp1 * 100 / o_slope;
19826c692719SRoger Lu 
19836c692719SRoger Lu 		svsb->bts = (temp0 + temp2 - 250) * 4 / 10;
19846c692719SRoger Lu 	}
19856c692719SRoger Lu 
19866c692719SRoger Lu 	return true;
19876c692719SRoger Lu 
19886c692719SRoger Lu remove_mt8183_svsb_mon_mode:
19896c692719SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
19906c692719SRoger Lu 		svsb = &svsp->banks[idx];
19916c692719SRoger Lu 		svsb->mode_support &= ~SVSB_MODE_MON;
19926c692719SRoger Lu 	}
19936c692719SRoger Lu 
1994681a02e9SRoger Lu 	return true;
1995681a02e9SRoger Lu }
1996681a02e9SRoger Lu 
svs_get_subsys_device(struct svs_platform * svsp,const char * node_name)1997681a02e9SRoger Lu static struct device *svs_get_subsys_device(struct svs_platform *svsp,
1998681a02e9SRoger Lu 					    const char *node_name)
1999681a02e9SRoger Lu {
2000681a02e9SRoger Lu 	struct platform_device *pdev;
2001681a02e9SRoger Lu 	struct device_node *np;
2002681a02e9SRoger Lu 
2003681a02e9SRoger Lu 	np = of_find_node_by_name(NULL, node_name);
2004681a02e9SRoger Lu 	if (!np) {
2005681a02e9SRoger Lu 		dev_err(svsp->dev, "cannot find %s node\n", node_name);
2006681a02e9SRoger Lu 		return ERR_PTR(-ENODEV);
2007681a02e9SRoger Lu 	}
2008681a02e9SRoger Lu 
2009681a02e9SRoger Lu 	pdev = of_find_device_by_node(np);
2010681a02e9SRoger Lu 	if (!pdev) {
2011681a02e9SRoger Lu 		of_node_put(np);
2012681a02e9SRoger Lu 		dev_err(svsp->dev, "cannot find pdev by %s\n", node_name);
2013681a02e9SRoger Lu 		return ERR_PTR(-ENXIO);
2014681a02e9SRoger Lu 	}
2015681a02e9SRoger Lu 
2016681a02e9SRoger Lu 	of_node_put(np);
2017681a02e9SRoger Lu 
2018681a02e9SRoger Lu 	return &pdev->dev;
2019681a02e9SRoger Lu }
2020681a02e9SRoger Lu 
svs_add_device_link(struct svs_platform * svsp,const char * node_name)2021681a02e9SRoger Lu static struct device *svs_add_device_link(struct svs_platform *svsp,
2022681a02e9SRoger Lu 					  const char *node_name)
2023681a02e9SRoger Lu {
2024681a02e9SRoger Lu 	struct device *dev;
2025681a02e9SRoger Lu 	struct device_link *sup_link;
2026681a02e9SRoger Lu 
2027681a02e9SRoger Lu 	dev = svs_get_subsys_device(svsp, node_name);
2028681a02e9SRoger Lu 	if (IS_ERR(dev))
2029681a02e9SRoger Lu 		return dev;
2030681a02e9SRoger Lu 
2031681a02e9SRoger Lu 	sup_link = device_link_add(svsp->dev, dev,
2032681a02e9SRoger Lu 				   DL_FLAG_AUTOREMOVE_CONSUMER);
2033681a02e9SRoger Lu 	if (!sup_link) {
2034681a02e9SRoger Lu 		dev_err(svsp->dev, "sup_link is NULL\n");
2035681a02e9SRoger Lu 		return ERR_PTR(-EINVAL);
2036681a02e9SRoger Lu 	}
2037681a02e9SRoger Lu 
2038681a02e9SRoger Lu 	if (sup_link->supplier->links.status != DL_DEV_DRIVER_BOUND)
2039681a02e9SRoger Lu 		return ERR_PTR(-EPROBE_DEFER);
2040681a02e9SRoger Lu 
2041681a02e9SRoger Lu 	return dev;
2042681a02e9SRoger Lu }
2043681a02e9SRoger Lu 
svs_mt8192_platform_probe(struct svs_platform * svsp)20440bbb09b2SRoger Lu static int svs_mt8192_platform_probe(struct svs_platform *svsp)
20450bbb09b2SRoger Lu {
20460bbb09b2SRoger Lu 	struct device *dev;
20470bbb09b2SRoger Lu 	struct svs_bank *svsb;
20480bbb09b2SRoger Lu 	u32 idx;
20490bbb09b2SRoger Lu 
20500bbb09b2SRoger Lu 	svsp->rst = devm_reset_control_get_optional(svsp->dev, "svs_rst");
20510bbb09b2SRoger Lu 	if (IS_ERR(svsp->rst))
20520bbb09b2SRoger Lu 		return dev_err_probe(svsp->dev, PTR_ERR(svsp->rst),
20530bbb09b2SRoger Lu 				     "cannot get svs reset control\n");
20540bbb09b2SRoger Lu 
20550bbb09b2SRoger Lu 	dev = svs_add_device_link(svsp, "lvts");
20560bbb09b2SRoger Lu 	if (IS_ERR(dev))
20570bbb09b2SRoger Lu 		return dev_err_probe(svsp->dev, PTR_ERR(dev),
20580bbb09b2SRoger Lu 				     "failed to get lvts device\n");
20590bbb09b2SRoger Lu 
20600bbb09b2SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
20610bbb09b2SRoger Lu 		svsb = &svsp->banks[idx];
20620bbb09b2SRoger Lu 
20630bbb09b2SRoger Lu 		if (svsb->type == SVSB_HIGH)
20640bbb09b2SRoger Lu 			svsb->opp_dev = svs_add_device_link(svsp, "gpu");
20650bbb09b2SRoger Lu 		else if (svsb->type == SVSB_LOW)
20660bbb09b2SRoger Lu 			svsb->opp_dev = svs_get_subsys_device(svsp, "gpu");
20670bbb09b2SRoger Lu 
20680bbb09b2SRoger Lu 		if (IS_ERR(svsb->opp_dev))
20690bbb09b2SRoger Lu 			return dev_err_probe(svsp->dev, PTR_ERR(svsb->opp_dev),
20700bbb09b2SRoger Lu 					     "failed to get OPP device for bank %d\n",
20710bbb09b2SRoger Lu 					     idx);
20720bbb09b2SRoger Lu 	}
20730bbb09b2SRoger Lu 
20740bbb09b2SRoger Lu 	return 0;
20750bbb09b2SRoger Lu }
20760bbb09b2SRoger Lu 
svs_mt8183_platform_probe(struct svs_platform * svsp)2077681a02e9SRoger Lu static int svs_mt8183_platform_probe(struct svs_platform *svsp)
2078681a02e9SRoger Lu {
20796c692719SRoger Lu 	struct device *dev;
2080681a02e9SRoger Lu 	struct svs_bank *svsb;
2081681a02e9SRoger Lu 	u32 idx;
2082681a02e9SRoger Lu 
20836c692719SRoger Lu 	dev = svs_add_device_link(svsp, "thermal");
20846c692719SRoger Lu 	if (IS_ERR(dev))
20856c692719SRoger Lu 		return dev_err_probe(svsp->dev, PTR_ERR(dev),
20866c692719SRoger Lu 				     "failed to get thermal device\n");
20876c692719SRoger Lu 
2088681a02e9SRoger Lu 	for (idx = 0; idx < svsp->bank_max; idx++) {
2089681a02e9SRoger Lu 		svsb = &svsp->banks[idx];
2090681a02e9SRoger Lu 
2091681a02e9SRoger Lu 		switch (svsb->sw_id) {
2092681a02e9SRoger Lu 		case SVSB_CPU_LITTLE:
2093681a02e9SRoger Lu 		case SVSB_CPU_BIG:
2094681a02e9SRoger Lu 			svsb->opp_dev = get_cpu_device(svsb->cpu_id);
2095681a02e9SRoger Lu 			break;
2096681a02e9SRoger Lu 		case SVSB_CCI:
2097681a02e9SRoger Lu 			svsb->opp_dev = svs_add_device_link(svsp, "cci");
2098681a02e9SRoger Lu 			break;
2099681a02e9SRoger Lu 		case SVSB_GPU:
2100681a02e9SRoger Lu 			svsb->opp_dev = svs_add_device_link(svsp, "gpu");
2101681a02e9SRoger Lu 			break;
2102681a02e9SRoger Lu 		default:
2103681a02e9SRoger Lu 			dev_err(svsb->dev, "unknown sw_id: %u\n", svsb->sw_id);
2104681a02e9SRoger Lu 			return -EINVAL;
2105681a02e9SRoger Lu 		}
2106681a02e9SRoger Lu 
2107681a02e9SRoger Lu 		if (IS_ERR(svsb->opp_dev))
2108681a02e9SRoger Lu 			return dev_err_probe(svsp->dev, PTR_ERR(svsb->opp_dev),
2109681a02e9SRoger Lu 					     "failed to get OPP device for bank %d\n",
2110681a02e9SRoger Lu 					     idx);
2111681a02e9SRoger Lu 	}
2112681a02e9SRoger Lu 
2113681a02e9SRoger Lu 	return 0;
2114681a02e9SRoger Lu }
2115681a02e9SRoger Lu 
21160bbb09b2SRoger Lu static struct svs_bank svs_mt8192_banks[] = {
21170bbb09b2SRoger Lu 	{
21180bbb09b2SRoger Lu 		.sw_id			= SVSB_GPU,
21190bbb09b2SRoger Lu 		.type			= SVSB_LOW,
21200bbb09b2SRoger Lu 		.set_freq_pct		= svs_set_bank_freq_pct_v3,
21210bbb09b2SRoger Lu 		.get_volts		= svs_get_bank_volts_v3,
2122bd0a62a6SRoger Lu 		.tzone_name		= "gpu1",
21230bbb09b2SRoger Lu 		.volt_flags		= SVSB_REMOVE_DVTFIXED_VOLT,
21240bbb09b2SRoger Lu 		.mode_support		= SVSB_MODE_INIT02,
21250bbb09b2SRoger Lu 		.opp_count		= MAX_OPP_ENTRIES,
21260bbb09b2SRoger Lu 		.freq_base		= 688000000,
21270bbb09b2SRoger Lu 		.turn_freq_base		= 688000000,
21280bbb09b2SRoger Lu 		.volt_step		= 6250,
21290bbb09b2SRoger Lu 		.volt_base		= 400000,
21300bbb09b2SRoger Lu 		.vmax			= 0x60,
21310bbb09b2SRoger Lu 		.vmin			= 0x1a,
21320bbb09b2SRoger Lu 		.age_config		= 0x555555,
21330bbb09b2SRoger Lu 		.dc_config		= 0x1,
21340bbb09b2SRoger Lu 		.dvt_fixed		= 0x1,
21350bbb09b2SRoger Lu 		.vco			= 0x18,
21360bbb09b2SRoger Lu 		.chk_shift		= 0x87,
21370bbb09b2SRoger Lu 		.core_sel		= 0x0fff0100,
21380bbb09b2SRoger Lu 		.int_st			= BIT(0),
21390bbb09b2SRoger Lu 		.ctl0			= 0x00540003,
2140bd0a62a6SRoger Lu 		.tzone_htemp		= 85000,
2141bd0a62a6SRoger Lu 		.tzone_htemp_voffset	= 0,
2142bd0a62a6SRoger Lu 		.tzone_ltemp		= 25000,
2143bd0a62a6SRoger Lu 		.tzone_ltemp_voffset	= 7,
21440bbb09b2SRoger Lu 	},
21450bbb09b2SRoger Lu 	{
21460bbb09b2SRoger Lu 		.sw_id			= SVSB_GPU,
21470bbb09b2SRoger Lu 		.type			= SVSB_HIGH,
21480bbb09b2SRoger Lu 		.set_freq_pct		= svs_set_bank_freq_pct_v3,
21490bbb09b2SRoger Lu 		.get_volts		= svs_get_bank_volts_v3,
21500bbb09b2SRoger Lu 		.tzone_name		= "gpu1",
21510bbb09b2SRoger Lu 		.volt_flags		= SVSB_REMOVE_DVTFIXED_VOLT |
21520bbb09b2SRoger Lu 					  SVSB_MON_VOLT_IGNORE,
21530bbb09b2SRoger Lu 		.mode_support		= SVSB_MODE_INIT02 | SVSB_MODE_MON,
21540bbb09b2SRoger Lu 		.opp_count		= MAX_OPP_ENTRIES,
21550bbb09b2SRoger Lu 		.freq_base		= 902000000,
21560bbb09b2SRoger Lu 		.turn_freq_base		= 688000000,
21570bbb09b2SRoger Lu 		.volt_step		= 6250,
21580bbb09b2SRoger Lu 		.volt_base		= 400000,
21590bbb09b2SRoger Lu 		.vmax			= 0x60,
21600bbb09b2SRoger Lu 		.vmin			= 0x1a,
21610bbb09b2SRoger Lu 		.age_config		= 0x555555,
21620bbb09b2SRoger Lu 		.dc_config		= 0x1,
21630bbb09b2SRoger Lu 		.dvt_fixed		= 0x6,
21640bbb09b2SRoger Lu 		.vco			= 0x18,
21650bbb09b2SRoger Lu 		.chk_shift		= 0x87,
21660bbb09b2SRoger Lu 		.core_sel		= 0x0fff0101,
21670bbb09b2SRoger Lu 		.int_st			= BIT(1),
21680bbb09b2SRoger Lu 		.ctl0			= 0x00540003,
21690bbb09b2SRoger Lu 		.tzone_htemp		= 85000,
21700bbb09b2SRoger Lu 		.tzone_htemp_voffset	= 0,
21710bbb09b2SRoger Lu 		.tzone_ltemp		= 25000,
21720bbb09b2SRoger Lu 		.tzone_ltemp_voffset	= 7,
21730bbb09b2SRoger Lu 	},
21740bbb09b2SRoger Lu };
21750bbb09b2SRoger Lu 
2176681a02e9SRoger Lu static struct svs_bank svs_mt8183_banks[] = {
2177681a02e9SRoger Lu 	{
2178681a02e9SRoger Lu 		.sw_id			= SVSB_CPU_LITTLE,
2179681a02e9SRoger Lu 		.set_freq_pct		= svs_set_bank_freq_pct_v2,
2180681a02e9SRoger Lu 		.get_volts		= svs_get_bank_volts_v2,
2181681a02e9SRoger Lu 		.cpu_id			= 0,
2182681a02e9SRoger Lu 		.buck_name		= "proc",
2183681a02e9SRoger Lu 		.volt_flags		= SVSB_INIT01_VOLT_INC_ONLY,
2184681a02e9SRoger Lu 		.mode_support		= SVSB_MODE_INIT01 | SVSB_MODE_INIT02,
2185681a02e9SRoger Lu 		.opp_count		= MAX_OPP_ENTRIES,
2186681a02e9SRoger Lu 		.freq_base		= 1989000000,
2187681a02e9SRoger Lu 		.vboot			= 0x30,
2188681a02e9SRoger Lu 		.volt_step		= 6250,
2189681a02e9SRoger Lu 		.volt_base		= 500000,
2190681a02e9SRoger Lu 		.vmax			= 0x64,
2191681a02e9SRoger Lu 		.vmin			= 0x18,
2192681a02e9SRoger Lu 		.age_config		= 0x555555,
2193681a02e9SRoger Lu 		.dc_config		= 0x555555,
2194681a02e9SRoger Lu 		.dvt_fixed		= 0x7,
2195681a02e9SRoger Lu 		.vco			= 0x10,
2196681a02e9SRoger Lu 		.chk_shift		= 0x77,
2197681a02e9SRoger Lu 		.core_sel		= 0x8fff0000,
2198681a02e9SRoger Lu 		.int_st			= BIT(0),
2199681a02e9SRoger Lu 		.ctl0			= 0x00010001,
2200681a02e9SRoger Lu 	},
2201681a02e9SRoger Lu 	{
2202681a02e9SRoger Lu 		.sw_id			= SVSB_CPU_BIG,
2203681a02e9SRoger Lu 		.set_freq_pct		= svs_set_bank_freq_pct_v2,
2204681a02e9SRoger Lu 		.get_volts		= svs_get_bank_volts_v2,
2205681a02e9SRoger Lu 		.cpu_id			= 4,
2206681a02e9SRoger Lu 		.buck_name		= "proc",
2207681a02e9SRoger Lu 		.volt_flags		= SVSB_INIT01_VOLT_INC_ONLY,
2208681a02e9SRoger Lu 		.mode_support		= SVSB_MODE_INIT01 | SVSB_MODE_INIT02,
2209681a02e9SRoger Lu 		.opp_count		= MAX_OPP_ENTRIES,
2210681a02e9SRoger Lu 		.freq_base		= 1989000000,
2211681a02e9SRoger Lu 		.vboot			= 0x30,
2212681a02e9SRoger Lu 		.volt_step		= 6250,
2213681a02e9SRoger Lu 		.volt_base		= 500000,
2214681a02e9SRoger Lu 		.vmax			= 0x58,
2215681a02e9SRoger Lu 		.vmin			= 0x10,
2216681a02e9SRoger Lu 		.age_config		= 0x555555,
2217681a02e9SRoger Lu 		.dc_config		= 0x555555,
2218681a02e9SRoger Lu 		.dvt_fixed		= 0x7,
2219681a02e9SRoger Lu 		.vco			= 0x10,
2220681a02e9SRoger Lu 		.chk_shift		= 0x77,
2221681a02e9SRoger Lu 		.core_sel		= 0x8fff0001,
2222681a02e9SRoger Lu 		.int_st			= BIT(1),
2223681a02e9SRoger Lu 		.ctl0			= 0x00000001,
2224681a02e9SRoger Lu 	},
2225681a02e9SRoger Lu 	{
2226681a02e9SRoger Lu 		.sw_id			= SVSB_CCI,
2227681a02e9SRoger Lu 		.set_freq_pct		= svs_set_bank_freq_pct_v2,
2228681a02e9SRoger Lu 		.get_volts		= svs_get_bank_volts_v2,
2229681a02e9SRoger Lu 		.buck_name		= "proc",
2230681a02e9SRoger Lu 		.volt_flags		= SVSB_INIT01_VOLT_INC_ONLY,
2231681a02e9SRoger Lu 		.mode_support		= SVSB_MODE_INIT01 | SVSB_MODE_INIT02,
2232681a02e9SRoger Lu 		.opp_count		= MAX_OPP_ENTRIES,
2233681a02e9SRoger Lu 		.freq_base		= 1196000000,
2234681a02e9SRoger Lu 		.vboot			= 0x30,
2235681a02e9SRoger Lu 		.volt_step		= 6250,
2236681a02e9SRoger Lu 		.volt_base		= 500000,
2237681a02e9SRoger Lu 		.vmax			= 0x64,
2238681a02e9SRoger Lu 		.vmin			= 0x18,
2239681a02e9SRoger Lu 		.age_config		= 0x555555,
2240681a02e9SRoger Lu 		.dc_config		= 0x555555,
2241681a02e9SRoger Lu 		.dvt_fixed		= 0x7,
2242681a02e9SRoger Lu 		.vco			= 0x10,
2243681a02e9SRoger Lu 		.chk_shift		= 0x77,
2244681a02e9SRoger Lu 		.core_sel		= 0x8fff0002,
2245681a02e9SRoger Lu 		.int_st			= BIT(2),
2246681a02e9SRoger Lu 		.ctl0			= 0x00100003,
2247681a02e9SRoger Lu 	},
2248681a02e9SRoger Lu 	{
2249681a02e9SRoger Lu 		.sw_id			= SVSB_GPU,
2250681a02e9SRoger Lu 		.set_freq_pct		= svs_set_bank_freq_pct_v2,
2251681a02e9SRoger Lu 		.get_volts		= svs_get_bank_volts_v2,
2252681a02e9SRoger Lu 		.buck_name		= "mali",
22536c692719SRoger Lu 		.tzone_name		= "tzts2",
2254681a02e9SRoger Lu 		.volt_flags		= SVSB_INIT01_PD_REQ |
2255681a02e9SRoger Lu 					  SVSB_INIT01_VOLT_INC_ONLY,
22566c692719SRoger Lu 		.mode_support		= SVSB_MODE_INIT01 | SVSB_MODE_INIT02 |
22576c692719SRoger Lu 					  SVSB_MODE_MON,
2258681a02e9SRoger Lu 		.opp_count		= MAX_OPP_ENTRIES,
2259681a02e9SRoger Lu 		.freq_base		= 900000000,
2260681a02e9SRoger Lu 		.vboot			= 0x30,
2261681a02e9SRoger Lu 		.volt_step		= 6250,
2262681a02e9SRoger Lu 		.volt_base		= 500000,
2263681a02e9SRoger Lu 		.vmax			= 0x40,
2264681a02e9SRoger Lu 		.vmin			= 0x14,
2265681a02e9SRoger Lu 		.age_config		= 0x555555,
2266681a02e9SRoger Lu 		.dc_config		= 0x555555,
2267681a02e9SRoger Lu 		.dvt_fixed		= 0x3,
2268681a02e9SRoger Lu 		.vco			= 0x10,
2269681a02e9SRoger Lu 		.chk_shift		= 0x77,
2270681a02e9SRoger Lu 		.core_sel		= 0x8fff0003,
2271681a02e9SRoger Lu 		.int_st			= BIT(3),
2272681a02e9SRoger Lu 		.ctl0			= 0x00050001,
22736c692719SRoger Lu 		.tzone_htemp		= 85000,
22746c692719SRoger Lu 		.tzone_htemp_voffset	= 0,
22756c692719SRoger Lu 		.tzone_ltemp		= 25000,
22766c692719SRoger Lu 		.tzone_ltemp_voffset	= 3,
2277681a02e9SRoger Lu 	},
2278681a02e9SRoger Lu };
2279681a02e9SRoger Lu 
22800bbb09b2SRoger Lu static const struct svs_platform_data svs_mt8192_platform_data = {
22810bbb09b2SRoger Lu 	.name = "mt8192-svs",
22820bbb09b2SRoger Lu 	.banks = svs_mt8192_banks,
22830bbb09b2SRoger Lu 	.efuse_parsing = svs_mt8192_efuse_parsing,
22840bbb09b2SRoger Lu 	.probe = svs_mt8192_platform_probe,
22850bbb09b2SRoger Lu 	.regs = svs_regs_v2,
22860bbb09b2SRoger Lu 	.bank_max = ARRAY_SIZE(svs_mt8192_banks),
22870bbb09b2SRoger Lu };
22880bbb09b2SRoger Lu 
2289681a02e9SRoger Lu static const struct svs_platform_data svs_mt8183_platform_data = {
2290681a02e9SRoger Lu 	.name = "mt8183-svs",
2291681a02e9SRoger Lu 	.banks = svs_mt8183_banks,
2292681a02e9SRoger Lu 	.efuse_parsing = svs_mt8183_efuse_parsing,
2293681a02e9SRoger Lu 	.probe = svs_mt8183_platform_probe,
2294681a02e9SRoger Lu 	.regs = svs_regs_v2,
2295681a02e9SRoger Lu 	.bank_max = ARRAY_SIZE(svs_mt8183_banks),
2296681a02e9SRoger Lu };
2297681a02e9SRoger Lu 
2298681a02e9SRoger Lu static const struct of_device_id svs_of_match[] = {
2299681a02e9SRoger Lu 	{
23000bbb09b2SRoger Lu 		.compatible = "mediatek,mt8192-svs",
23010bbb09b2SRoger Lu 		.data = &svs_mt8192_platform_data,
23020bbb09b2SRoger Lu 	}, {
2303681a02e9SRoger Lu 		.compatible = "mediatek,mt8183-svs",
2304681a02e9SRoger Lu 		.data = &svs_mt8183_platform_data,
2305681a02e9SRoger Lu 	}, {
2306681a02e9SRoger Lu 		/* Sentinel */
2307681a02e9SRoger Lu 	},
2308681a02e9SRoger Lu };
23096f42f5e7SZeng Heng MODULE_DEVICE_TABLE(of, svs_of_match);
2310681a02e9SRoger Lu 
svs_probe(struct platform_device * pdev)23115343e9ffSMatthias Brugger static int svs_probe(struct platform_device *pdev)
2312681a02e9SRoger Lu {
2313681a02e9SRoger Lu 	struct svs_platform *svsp;
2314681a02e9SRoger Lu 	const struct svs_platform_data *svsp_data;
23155343e9ffSMatthias Brugger 	int ret, svsp_irq;
2316681a02e9SRoger Lu 
2317681a02e9SRoger Lu 	svsp_data = of_device_get_match_data(&pdev->dev);
2318681a02e9SRoger Lu 
2319681a02e9SRoger Lu 	svsp = devm_kzalloc(&pdev->dev, sizeof(*svsp), GFP_KERNEL);
2320681a02e9SRoger Lu 	if (!svsp)
23215343e9ffSMatthias Brugger 		return -ENOMEM;
2322681a02e9SRoger Lu 
2323681a02e9SRoger Lu 	svsp->dev = &pdev->dev;
2324681a02e9SRoger Lu 	svsp->banks = svsp_data->banks;
2325681a02e9SRoger Lu 	svsp->regs = svsp_data->regs;
2326681a02e9SRoger Lu 	svsp->bank_max = svsp_data->bank_max;
2327681a02e9SRoger Lu 
23283bab727bSMatthias Brugger 	ret = svsp_data->probe(svsp);
2329681a02e9SRoger Lu 	if (ret)
23305343e9ffSMatthias Brugger 		return ret;
2331681a02e9SRoger Lu 
23329f195f3aSRoger Lu 	ret = svs_get_efuse_data(svsp, "svs-calibration-data",
23339f195f3aSRoger Lu 				 &svsp->efuse, &svsp->efuse_max);
23349f195f3aSRoger Lu 	if (ret) {
2335681a02e9SRoger Lu 		ret = -EPERM;
233601c9a8bdSMatthias Brugger 		goto svs_probe_free_efuse;
233701c9a8bdSMatthias Brugger 	}
233801c9a8bdSMatthias Brugger 
233901c9a8bdSMatthias Brugger 	if (!svsp_data->efuse_parsing(svsp)) {
234001c9a8bdSMatthias Brugger 		dev_err(svsp->dev, "efuse data parsing failed\n");
234101c9a8bdSMatthias Brugger 		ret = -EPERM;
23429f195f3aSRoger Lu 		goto svs_probe_free_tefuse;
2343681a02e9SRoger Lu 	}
2344681a02e9SRoger Lu 
2345681a02e9SRoger Lu 	ret = svs_bank_resource_setup(svsp);
2346681a02e9SRoger Lu 	if (ret) {
2347681a02e9SRoger Lu 		dev_err(svsp->dev, "svs bank resource setup fail: %d\n", ret);
23489f195f3aSRoger Lu 		goto svs_probe_free_tefuse;
2349681a02e9SRoger Lu 	}
2350681a02e9SRoger Lu 
23512efddd28SAngeloGioacchino Del Regno 	svsp_irq = platform_get_irq(pdev, 0);
23522efddd28SAngeloGioacchino Del Regno 	if (svsp_irq < 0) {
23532efddd28SAngeloGioacchino Del Regno 		ret = svsp_irq;
23549f195f3aSRoger Lu 		goto svs_probe_free_tefuse;
23552efddd28SAngeloGioacchino Del Regno 	}
23562efddd28SAngeloGioacchino Del Regno 
2357681a02e9SRoger Lu 	svsp->main_clk = devm_clk_get(svsp->dev, "main");
2358681a02e9SRoger Lu 	if (IS_ERR(svsp->main_clk)) {
2359681a02e9SRoger Lu 		dev_err(svsp->dev, "failed to get clock: %ld\n",
2360681a02e9SRoger Lu 			PTR_ERR(svsp->main_clk));
2361681a02e9SRoger Lu 		ret = PTR_ERR(svsp->main_clk);
23629f195f3aSRoger Lu 		goto svs_probe_free_tefuse;
2363681a02e9SRoger Lu 	}
2364681a02e9SRoger Lu 
2365681a02e9SRoger Lu 	ret = clk_prepare_enable(svsp->main_clk);
2366681a02e9SRoger Lu 	if (ret) {
2367681a02e9SRoger Lu 		dev_err(svsp->dev, "cannot enable main clk: %d\n", ret);
23689f195f3aSRoger Lu 		goto svs_probe_free_tefuse;
2369681a02e9SRoger Lu 	}
2370681a02e9SRoger Lu 
2371681a02e9SRoger Lu 	svsp->base = of_iomap(svsp->dev->of_node, 0);
2372681a02e9SRoger Lu 	if (IS_ERR_OR_NULL(svsp->base)) {
2373681a02e9SRoger Lu 		dev_err(svsp->dev, "cannot find svs register base\n");
2374681a02e9SRoger Lu 		ret = -EINVAL;
2375681a02e9SRoger Lu 		goto svs_probe_clk_disable;
2376681a02e9SRoger Lu 	}
2377681a02e9SRoger Lu 
2378b74952abSRicardo Ribalda 	ret = devm_request_threaded_irq(svsp->dev, svsp_irq, NULL, svs_isr,
237901c9a8bdSMatthias Brugger 					IRQF_ONESHOT, svsp_data->name, svsp);
2380b74952abSRicardo Ribalda 	if (ret) {
2381b74952abSRicardo Ribalda 		dev_err(svsp->dev, "register irq(%d) failed: %d\n",
2382b74952abSRicardo Ribalda 			svsp_irq, ret);
2383b74952abSRicardo Ribalda 		goto svs_probe_iounmap;
2384b74952abSRicardo Ribalda 	}
2385b74952abSRicardo Ribalda 
2386681a02e9SRoger Lu 	ret = svs_start(svsp);
2387681a02e9SRoger Lu 	if (ret) {
2388681a02e9SRoger Lu 		dev_err(svsp->dev, "svs start fail: %d\n", ret);
2389681a02e9SRoger Lu 		goto svs_probe_iounmap;
2390681a02e9SRoger Lu 	}
2391681a02e9SRoger Lu 
23928bf30508SRoger Lu #ifdef CONFIG_DEBUG_FS
239313f1bbcfSRoger Lu 	ret = svs_create_debug_cmds(svsp);
239413f1bbcfSRoger Lu 	if (ret) {
239513f1bbcfSRoger Lu 		dev_err(svsp->dev, "svs create debug cmds fail: %d\n", ret);
239613f1bbcfSRoger Lu 		goto svs_probe_iounmap;
239713f1bbcfSRoger Lu 	}
23988bf30508SRoger Lu #endif
239913f1bbcfSRoger Lu 
2400681a02e9SRoger Lu 	return 0;
2401681a02e9SRoger Lu 
2402681a02e9SRoger Lu svs_probe_iounmap:
2403681a02e9SRoger Lu 	iounmap(svsp->base);
2404681a02e9SRoger Lu 
2405681a02e9SRoger Lu svs_probe_clk_disable:
2406681a02e9SRoger Lu 	clk_disable_unprepare(svsp->main_clk);
2407681a02e9SRoger Lu 
24089f195f3aSRoger Lu svs_probe_free_tefuse:
24096c692719SRoger Lu 	if (!IS_ERR_OR_NULL(svsp->tefuse))
24106c692719SRoger Lu 		kfree(svsp->tefuse);
2411681a02e9SRoger Lu 
241201c9a8bdSMatthias Brugger svs_probe_free_efuse:
241301c9a8bdSMatthias Brugger 	if (!IS_ERR_OR_NULL(svsp->efuse))
241401c9a8bdSMatthias Brugger 		kfree(svsp->efuse);
241501c9a8bdSMatthias Brugger 
2416681a02e9SRoger Lu 	return ret;
2417681a02e9SRoger Lu }
2418681a02e9SRoger Lu 
2419c749d676SNathan Chancellor static DEFINE_SIMPLE_DEV_PM_OPS(svs_pm_ops, svs_suspend, svs_resume);
2420681a02e9SRoger Lu 
2421681a02e9SRoger Lu static struct platform_driver svs_driver = {
2422681a02e9SRoger Lu 	.probe	= svs_probe,
2423681a02e9SRoger Lu 	.driver	= {
2424681a02e9SRoger Lu 		.name		= "mtk-svs",
2425681a02e9SRoger Lu 		.pm		= &svs_pm_ops,
24261cd80c06SAngeloGioacchino Del Regno 		.of_match_table	= svs_of_match,
2427681a02e9SRoger Lu 	},
2428681a02e9SRoger Lu };
2429681a02e9SRoger Lu 
2430681a02e9SRoger Lu module_platform_driver(svs_driver);
2431681a02e9SRoger Lu 
2432681a02e9SRoger Lu MODULE_AUTHOR("Roger Lu <roger.lu@mediatek.com>");
2433681a02e9SRoger Lu MODULE_DESCRIPTION("MediaTek SVS driver");
2434681a02e9SRoger Lu MODULE_LICENSE("GPL");
2435