1 /*
2 * Copyright (c) 2024-2025, MediaTek Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <inttypes.h>
8
9 #include <include/drivers/spmi_api.h>
10
11 #include <common/debug.h>
12 #include <drivers/delay_timer.h>
13 #include <lib/mmio.h>
14 #include <lib/spinlock.h>
15 #include <lib/utils_def.h>
16 #include <lib/xlat_tables/xlat_tables_v2.h>
17
18 #include "apusys_power.h"
19
apu_w_are(int entry,uint32_t reg,uint32_t data)20 static void apu_w_are(int entry, uint32_t reg, uint32_t data)
21 {
22 uint32_t are_entry_addr;
23
24 are_entry_addr = APUSYS_BASE + APU_ARE + ARE_REG_SIZE * ARE_ENTRY(entry);
25 mmio_write_32(are_entry_addr, reg);
26 mmio_write_32((are_entry_addr + ARE_REG_SIZE), data);
27 }
28
get_pll_pcw(uint32_t clk_rate,uint32_t * r1,uint32_t * r2)29 static void get_pll_pcw(uint32_t clk_rate, uint32_t *r1, uint32_t *r2)
30 {
31 unsigned int fvco = clk_rate;
32 unsigned int pcw_val;
33 unsigned int postdiv_val = 1;
34 unsigned int postdiv_reg = 0;
35
36 while (fvco <= OUT_CLK_FREQ_MIN) {
37 postdiv_val = postdiv_val << 1;
38 postdiv_reg = postdiv_reg + 1;
39 fvco = fvco << 1;
40 }
41
42 pcw_val = (fvco * (1 << DDS_SHIFT)) / BASIC_CLK_FREQ;
43
44 if (postdiv_reg == 0) {
45 pcw_val = pcw_val * 2;
46 postdiv_val = postdiv_val << 1;
47 postdiv_reg = postdiv_reg + 1;
48 }
49
50 *r1 = postdiv_reg;
51 *r2 = pcw_val;
52 }
53
buck_off_by_pcu(uint32_t ofs,uint32_t shift,uint32_t slv_id)54 static void buck_off_by_pcu(uint32_t ofs, uint32_t shift, uint32_t slv_id)
55 {
56 uint32_t pmif_id = 0x0;
57 int retry = 10;
58
59 mmio_setbits_32(APUSYS_PCU + APU_PCUTOP_CTRL_SET, PMIC_IRQ_EN);
60 mmio_write_32(APUSYS_PCU + APU_PCU_PMIC_TAR_BUF1,
61 (ofs << PMIC_OFF_ADDR_OFF) | BIT(shift));
62 mmio_write_32(APUSYS_PCU + APU_PCU_PMIC_TAR_BUF2,
63 (slv_id << PMIC_SLVID_OFF) | (pmif_id << PMIC_PMIFID_OFF) | PCU_BUCK_OFF_CMD);
64 mmio_write_32(APUSYS_PCU + APU_PCU_PMIC_CMD, PMIC_CMD_EN);
65
66 while ((mmio_read_32(APUSYS_PCU + APU_PCU_PMIC_IRQ) & PMIC_CMD_IRQ) == 0) {
67 udelay(10);
68 if (--retry < 0)
69 ERROR("%s wait APU_PCU_PMIC_IRQ timeout !\n", __func__);
70 }
71
72 mmio_write_32(APUSYS_PCU + APU_PCU_PMIC_IRQ, PMIC_CMD_IRQ);
73 }
74
apu_buck_off_cfg(void)75 static void apu_buck_off_cfg(void)
76 {
77 mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(10));
78 mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(9));
79 mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(12));
80 mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(14));
81
82 mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(10));
83 mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(9));
84 mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(12));
85 mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(14));
86 udelay(1);
87
88 mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, BUCK_PROT_REQ_SET);
89 udelay(1);
90
91 mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, SRAM_AOC_LHENB_SET);
92 udelay(1);
93
94 mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, SRAM_AOC_ISO_SET);
95 udelay(1);
96
97 mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, PLL_AOC_ISO_EN_SET);
98 udelay(1);
99
100 mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, BUCK_ELS_EN_SET);
101 udelay(1);
102
103 mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, BUCK_AO_RST_B_CLR);
104 udelay(1);
105
106 buck_off_by_pcu(BUCK_VAPU_PMIC_REG_EN_CLR_ADDR, BUCK_VAPU_PMIC_REG_EN_SHIFT,
107 BUCK_VAPU_PMIC_ID);
108
109 mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(6));
110 udelay(1);
111 mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(7));
112 udelay(1);
113 mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(6));
114 udelay(1);
115 mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(7));
116 udelay(1);
117 }
118
apu_acc_init(void)119 static void apu_acc_init(void)
120 {
121 uint32_t top_acc_base_arr[] = {MNOC_ACC_BASE, UP_ACC_BASE};
122 uint32_t eng_acc_base_arr[] = {MVPU_ACC_BASE, MDLA_ACC_BASE};
123 int acc_idx;
124 int are_idx = ACC_ENTRY_BEGIN;
125 uint32_t base_reg;
126
127 for (acc_idx = 0 ; acc_idx < ARRAY_SIZE(top_acc_base_arr) ; acc_idx++) {
128 base_reg = APUSYS_ACC + top_acc_base_arr[acc_idx];
129 #if CFG_APU_ARDCM_ENABLE
130 apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL1, APU_ARDCM_CTRL1_VAL_0);
131 apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL0, APU_ARDCM_CTRL0_VAL_0);
132 apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL1, APU_ARDCM_CTRL1_VAL_1);
133 apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL0, APU_ARDCM_CTRL0_VAL_1);
134 #endif
135 apu_w_are(are_idx++, base_reg + APU_ACC_CONFG_CLR0, CGEN_SOC);
136 apu_w_are(are_idx++, base_reg + APU_ACC_CONFG_SET0, HW_CTRL_EN);
137 }
138
139 for (acc_idx = 0 ; acc_idx < ARRAY_SIZE(eng_acc_base_arr) ; acc_idx++) {
140 base_reg = APUSYS_ACC + eng_acc_base_arr[acc_idx];
141 #if CFG_APU_ARDCM_ENABLE
142 apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL1, APU_ARDCM_CTRL1_VAL_0);
143 apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL0, APU_ARDCM_CTRL0_VAL_0);
144 apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL1, APU_ARDCM_CTRL1_VAL_1);
145 apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL0, APU_ARDCM_CTRL0_VAL_1);
146 #endif
147 apu_w_are(are_idx++, base_reg + APU_ACC_CONFG_CLR0, CGEN_SOC);
148 apu_w_are(are_idx++, base_reg + APU_ACC_CONFG_SET0, HW_CTRL_EN);
149 apu_w_are(are_idx++, base_reg + APU_ACC_AUTO_CTRL_SET0, CLK_REQ_SW_EN);
150 }
151 }
152
apu_pll_init(void)153 static void apu_pll_init(void)
154 {
155 uint32_t pll_base_arr[] = {MNOC_PLL_BASE, UP_PLL_BASE, MVPU_PLL_BASE, MDLA_PLL_BASE};
156 int32_t pll_freq_out[] = {
157 APUPLL0_DEFAULT_FREQ,
158 APUPLL1_DEFAULT_FREQ,
159 APUPLL2_DEFAULT_FREQ,
160 APUPLL3_DEFAULT_FREQ
161 };
162 uint32_t pcw_val, posdiv_val;
163 int pll_idx, are_idx;
164 uint32_t base_reg;
165
166 mmio_setbits_32(APUSYS_BASE + APU_ARE, ARE_RCX_AO_EN);
167 mmio_setbits_32(APUSYS_BASE + APU_ARE_REG, ARE_RCX_AO_EN);
168
169 mmio_write_32(APUSYS_BASE + APU_ARE + ARE_RCX_AO_CONFIG, ARE_ENTRY(RCX_AO_BEGIN) |
170 (ARE_ENTRIES(RCX_AO_BEGIN, RCX_AO_END) << ARE_RCX_AO_CONFIG_HIGH_OFF));
171
172 are_idx = PLL_ENTRY_BEGIN;
173 for (pll_idx = 0 ; pll_idx < ARRAY_SIZE(pll_base_arr) ; pll_idx++) {
174 base_reg = APUSYS_PLL + pll_base_arr[pll_idx];
175
176 apu_w_are(are_idx++, base_reg + RG_PLLGP_LVR_REFSEL, RG_PLLGP_LVR_REFSEL_VAL);
177 apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL_HP_EN, FHCTL_CTRL);
178 apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL_RST_CON, FHCTL_NO_RESET);
179 apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL_CLK_CON, FHCTL_CLKEN);
180 apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL0_CFG,
181 FHCTL_HOPPING_EN | FHCTL_SFSTR0_EN);
182
183 posdiv_val = 0;
184 pcw_val = 0;
185 get_pll_pcw(pll_freq_out[pll_idx], &posdiv_val, &pcw_val);
186
187 apu_w_are(are_idx++, base_reg + PLL1C_PLL1_CON1,
188 ((0x1U << RG_PLL_SDM_PCW_CHG_OFF) |
189 (posdiv_val << RG_PLL_POSDIV_OFF) | pcw_val));
190
191 apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL0_DDS,
192 ((0x1U << FHCTL0_PLL_TGL_ORG) | pcw_val));
193 }
194 }
195
apu_are_init(void)196 static void apu_are_init(void)
197 {
198 int entry = 0;
199
200 mmio_clrbits_32(APUSYS_BASE + APU_ARE, 0xFFFU << ARE_VCORE_OFF);
201
202 mmio_setbits_32(APUSYS_BASE + APU_ARE, ARE_VCORE_EN);
203 mmio_setbits_32(APUSYS_BASE + APU_ARE_REG, ARE_VCORE_EN);
204
205 for (entry = ARE_CONF_START; entry < ARE_CONF_END; entry += 4)
206 mmio_write_32(APUSYS_BASE + APU_ARE + entry, 0);
207 }
208
apu_rpclite_init(void)209 static void apu_rpclite_init(void)
210 {
211 uint32_t sleep_type_offset[] = {
212 APU_RPC_SW_TYPE1_OFF,
213 APU_RPC_SW_TYPE2_OFF,
214 APU_RPC_SW_TYPE3_OFF,
215 APU_RPC_SW_TYPE4_OFF
216 };
217 uint32_t rpc_lite_base[] = {
218 APU_ACX0_RPC_LITE,
219 APU_ACX1_RPC_LITE,
220 APU_ACX2_RPC_LITE,
221 };
222 int ofs_idx, rpc_lite_idx;
223 uint32_t base;
224
225 for (rpc_lite_idx = 0; rpc_lite_idx < ARRAY_SIZE(rpc_lite_base); rpc_lite_idx++) {
226 base = APUSYS_BASE + rpc_lite_base[rpc_lite_idx];
227 for (ofs_idx = 0; ofs_idx < ARRAY_SIZE(sleep_type_offset); ofs_idx++)
228 mmio_clrbits_32(base + sleep_type_offset[ofs_idx],
229 SW_TYPE_MVPU_MDLA_RV);
230 mmio_setbits_32(base + APU_RPC_TOP_SEL, TOP_SEL_VAL);
231 }
232 }
233
apu_rpc_mdla_init(void)234 static void apu_rpc_mdla_init(void)
235 {
236 mmio_clrbits_32(APUSYS_BASE + APU_RPCTOP_MDLA + APU_RPC_SW_TYPE0_OFF, SW_TYPE_MVPU_MDLA_RV);
237 }
238
apu_rpc_init(void)239 static void apu_rpc_init(void)
240 {
241 mmio_write_32(APUSYS_RPC + APU_RPC_SW_TYPE0_OFF, RPC_TYPE_INIT_VAL);
242 mmio_setbits_32(APUSYS_RPC + APU_RPC_TOP_SEL, RPC_TOP_SEL_VAL);
243
244 #if !CFG_CTL_RPC_BY_CE
245 mmio_clrbits_32(APUSYS_RPC + APU_RPC_TOP_SEL, CE_ENABLE);
246 #endif
247
248 mmio_setbits_32(APUSYS_RPC + APU_RPC_TOP_SEL_1, BUCK_PROT_SEL);
249 }
250
apu_pcu_init(void)251 static int apu_pcu_init(void)
252 {
253 uint32_t pmif_id = 0x0;
254 uint32_t slave_id = BUCK_VAPU_PMIC_ID;
255 uint32_t en_set_offset = BUCK_VAPU_PMIC_REG_EN_SET_ADDR;
256 uint32_t en_clr_offset = BUCK_VAPU_PMIC_REG_EN_CLR_ADDR;
257 uint32_t en_shift = BUCK_VAPU_PMIC_REG_EN_SHIFT;
258 struct spmi_device *vsram_sdev;
259 unsigned char vsram = 0;
260
261 mmio_write_32(APUSYS_PCU + APU_PCUTOP_CTRL_SET, AUTO_BUCK_EN);
262
263 mmio_write_32((APUSYS_PCU + APU_PCU_BUCK_STEP_SEL), BUCK_STEP_SEL_VAL);
264
265 vsram_sdev = get_spmi_device(SPMI_MASTER_1, SPMI_SLAVE_4);
266 if (!vsram_sdev) {
267 ERROR("[APUPW] VSRAM BUCK4 get device fail\n");
268 return -1;
269 }
270
271 if (spmi_ext_register_readl(vsram_sdev, MT6363_RG_BUCK_VBUCK4_VOSEL_ADDR, &vsram, 1)) {
272 ERROR("[APUPW] VSRAM BUCK4 read fail\n");
273 return -1;
274 }
275
276 mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_DAT0_L,
277 (BUCK_VAPU_PMIC_REG_VOSEL_ADDR << PMIC_OFF_ADDR_OFF) | vsram);
278
279 mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_DAT0_H,
280 (slave_id << PMIC_SLVID_OFF) | (pmif_id << PMIC_PMIFID_OFF) | PCU_CMD_OP_W);
281
282 mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_DAT1_L,
283 (en_set_offset << PMIC_OFF_ADDR_OFF) | (0x1U << en_shift));
284 mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_DAT1_H,
285 (slave_id << PMIC_SLVID_OFF) | (pmif_id << PMIC_PMIFID_OFF) | PCU_CMD_OP_W);
286
287 mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_OFF_DAT0_L,
288 (en_clr_offset << PMIC_OFF_ADDR_OFF) | (0x1U << en_shift));
289 mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_OFF_DAT0_H,
290 (slave_id << PMIC_SLVID_OFF) | (pmif_id << PMIC_PMIFID_OFF) | PCU_CMD_OP_W);
291
292 mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_SLE0, 0);
293 mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_SLE1, VAPU_BUCK_ON_SETTLE_TIME);
294
295 return 0;
296 }
297
apu_aoc_init(void)298 static void apu_aoc_init(void)
299 {
300 uint32_t reg;
301
302 mmio_setbits_32(SPM_BASE + 0xF6C, BIT(4));
303 mmio_clrbits_32(SPM_BASE + 0x414, BIT(1));
304
305 mmio_write_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CONFIG, APUSYS_AO_SRAM_EN);
306 udelay(1);
307
308 reg = APUSYS_AO_CTL + APUSYS_AO_SRAM_SET;
309
310 #if !CFG_CTL_RPC_BY_CE
311 mmio_setbits_32(reg, BIT(8));
312 udelay(1);
313 mmio_setbits_32(reg, BIT(11));
314 udelay(1);
315 mmio_setbits_32(reg, BIT(13));
316 udelay(1);
317
318 mmio_clrbits_32(reg, BIT(8));
319 udelay(1);
320 mmio_clrbits_32(reg, BIT(11));
321 udelay(1);
322 mmio_clrbits_32(reg, BIT(13));
323 #else
324 mmio_setbits_32(reg, BIT(9));
325 mmio_setbits_32(reg, BIT(12));
326 mmio_setbits_32(reg, BIT(14));
327
328 mmio_clrbits_32(reg, BIT(9));
329 mmio_clrbits_32(reg, BIT(12));
330 mmio_clrbits_32(reg, BIT(14));
331 udelay(1);
332 #endif
333
334 reg = APUSYS_RPC + APU_RPC_HW_CON;
335
336 mmio_write_32(reg, BUCK_ELS_EN_CLR);
337 udelay(1);
338
339 mmio_write_32(reg, BUCK_AO_RST_B_SET);
340 udelay(1);
341
342 mmio_write_32(reg, BUCK_PROT_REQ_CLR);
343 udelay(1);
344
345 mmio_write_32(reg, SRAM_AOC_ISO_CLR);
346 udelay(1);
347
348 mmio_write_32(reg, PLL_AOC_ISO_EN_CLR);
349 udelay(1);
350 }
351
init_hw_setting(void)352 static int init_hw_setting(void)
353 {
354 int ret;
355
356 apu_aoc_init();
357 ret = apu_pcu_init();
358 apu_rpc_init();
359 apu_rpc_mdla_init();
360 apu_rpclite_init();
361 apu_are_init();
362 apu_pll_init();
363 apu_acc_init();
364 apu_buck_off_cfg();
365
366 return ret;
367 }
368
apusys_power_init(void)369 int apusys_power_init(void)
370 {
371 int ret;
372
373 ret = init_hw_setting();
374 if (ret != 0)
375 ERROR("%s init HW failed\n", __func__);
376 else
377 INFO("%s init HW done\n", __func__);
378
379 mmio_write_32(APU_ACE_HW_FLAG_DIS, APU_ACE_DIS_FLAG_VAL);
380
381 return ret;
382 }
383