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