blob: 5d8687b6f43837cca9256066ebd1b9eeb89d5ab1 [file] [log] [blame]
Peng Fanbbcd2c42022-07-26 16:40:39 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2022 NXP
4 *
5 * Peng Fan <peng.fan@nxp.com>
6 */
7
8#include <common.h>
9#include <cpu_func.h>
10#include <init.h>
11#include <log.h>
12#include <asm/arch/imx-regs.h>
13#include <asm/global_data.h>
14#include <asm/io.h>
15#include <asm/arch/clock.h>
Peng Fan6d929962022-07-26 16:41:03 +080016#include <asm/arch/ccm_regs.h>
Peng Fanbbcd2c42022-07-26 16:40:39 +080017#include <asm/arch/sys_proto.h>
Ye Li62185922022-07-26 16:40:54 +080018#include <asm/arch/trdc.h>
Peng Fanbbcd2c42022-07-26 16:40:39 +080019#include <asm/mach-imx/boot_mode.h>
20#include <asm/mach-imx/syscounter.h>
21#include <asm/armv8/mmu.h>
Peng Fanb1815c42023-04-28 12:08:27 +080022#include <dm/device.h>
23#include <dm/device_compat.h>
Peng Fanbbcd2c42022-07-26 16:40:39 +080024#include <dm/uclass.h>
25#include <env.h>
26#include <env_internal.h>
27#include <errno.h>
28#include <fdt_support.h>
Peng Fan0c2f3682023-04-28 12:08:28 +080029#include <imx_thermal.h>
Peng Fanbbcd2c42022-07-26 16:40:39 +080030#include <linux/bitops.h>
Peng Fan0c2f3682023-04-28 12:08:28 +080031#include <linux/bitfield.h>
32#include <linux/delay.h>
33#include <thermal.h>
Peng Fanbbcd2c42022-07-26 16:40:39 +080034#include <asm/setup.h>
35#include <asm/bootm.h>
36#include <asm/arch-imx/cpu.h>
Peng Fand5c31832023-06-15 18:09:05 +080037#include <asm/mach-imx/ele_api.h>
Ye Li66baefb2023-04-28 12:08:21 +080038#include <fuse.h>
Ye Libb1187b2023-04-28 12:08:45 +080039#include <asm/arch/ddr.h>
Peng Fanbbcd2c42022-07-26 16:40:39 +080040
41DECLARE_GLOBAL_DATA_PTR;
42
Peng Fan5de0fc02022-07-26 16:40:48 +080043struct rom_api *g_rom_api = (struct rom_api *)0x1980;
44
45#ifdef CONFIG_ENV_IS_IN_MMC
46__weak int board_mmc_get_env_dev(int devno)
47{
Peng Fan77b36c62023-04-28 12:08:33 +080048 return devno;
49}
Peng Fan5de0fc02022-07-26 16:40:48 +080050
51int mmc_get_env_dev(void)
52{
Peng Fan5de0fc02022-07-26 16:40:48 +080053 int ret;
54 u32 boot;
55 u16 boot_type;
56 u8 boot_instance;
57
Peng Fanc459b582023-04-28 12:08:34 +080058 ret = rom_api_query_boot_infor(QUERY_BT_DEV, &boot);
Peng Fan5de0fc02022-07-26 16:40:48 +080059
60 if (ret != ROM_API_OKAY) {
61 puts("ROMAPI: failure at query_boot_info\n");
62 return CONFIG_SYS_MMC_ENV_DEV;
63 }
64
65 boot_type = boot >> 16;
66 boot_instance = (boot >> 8) & 0xff;
67
68 debug("boot_type %d, instance %d\n", boot_type, boot_instance);
69
70 /* If not boot from sd/mmc, use default value */
71 if (boot_type != BOOT_TYPE_SD && boot_type != BOOT_TYPE_MMC)
72 return env_get_ulong("mmcdev", 10, CONFIG_SYS_MMC_ENV_DEV);
73
74 return board_mmc_get_env_dev(boot_instance);
75}
76#endif
77
Peng Fan0c2f3682023-04-28 12:08:28 +080078/*
79 * SPEED_GRADE[5:4] SPEED_GRADE[3:0] MHz
80 * xx 0000 2300
81 * xx 0001 2200
82 * xx 0010 2100
83 * xx 0011 2000
84 * xx 0100 1900
85 * xx 0101 1800
86 * xx 0110 1700
87 * xx 0111 1600
88 * xx 1000 1500
89 * xx 1001 1400
90 * xx 1010 1300
91 * xx 1011 1200
92 * xx 1100 1100
93 * xx 1101 1000
94 * xx 1110 900
95 * xx 1111 800
96 */
97u32 get_cpu_speed_grade_hz(void)
98{
99 u32 speed, max_speed;
100 u32 val;
101
102 fuse_read(2, 3, &val);
103 val = FIELD_GET(SPEED_GRADING_MASK, val) & 0xF;
104
105 speed = MHZ(2300) - val * MHZ(100);
106
107 if (is_imx93())
108 max_speed = MHZ(1700);
109
110 /* In case the fuse of speed grade not programmed */
111 if (speed > max_speed)
112 speed = max_speed;
113
114 return speed;
115}
116
117/*
118 * `00` - Consumer 0C to 95C
119 * `01` - Ext. Consumer -20C to 105C
120 * `10` - Industrial -40C to 105C
121 * `11` - Automotive -40C to 125C
122 */
123u32 get_cpu_temp_grade(int *minc, int *maxc)
124{
125 u32 val;
126
127 fuse_read(2, 3, &val);
128 val = FIELD_GET(MARKETING_GRADING_MASK, val);
129
130 if (minc && maxc) {
131 if (val == TEMP_AUTOMOTIVE) {
132 *minc = -40;
133 *maxc = 125;
134 } else if (val == TEMP_INDUSTRIAL) {
135 *minc = -40;
136 *maxc = 105;
137 } else if (val == TEMP_EXTCOMMERCIAL) {
138 if (is_imx93()) {
139 /* imx93 only has extended industrial*/
140 *minc = -40;
141 *maxc = 125;
142 } else {
143 *minc = -20;
144 *maxc = 105;
145 }
146 } else {
147 *minc = 0;
148 *maxc = 95;
149 }
150 }
151 return val;
152}
153
Peng Fand5c31832023-06-15 18:09:05 +0800154static void set_cpu_info(struct ele_get_info_data *info)
Peng Fan3700c472022-07-26 16:40:56 +0800155{
156 gd->arch.soc_rev = info->soc;
157 gd->arch.lifecycle = info->lc;
158 memcpy((void *)&gd->arch.uid, &info->uid, 4 * sizeof(u32));
159}
160
Peng Fanc3db3ad2023-04-28 12:08:32 +0800161static u32 get_cpu_variant_type(u32 type)
162{
163 /* word 19 */
164 u32 val = readl((ulong)FSB_BASE_ADDR + 0x8000 + (19 << 2));
165 u32 val2 = readl((ulong)FSB_BASE_ADDR + 0x8000 + (20 << 2));
166 bool npu_disable = !!(val & BIT(13));
167 bool core1_disable = !!(val & BIT(15));
168 u32 pack_9x9_fused = BIT(4) | BIT(17) | BIT(19) | BIT(24);
169
170 if ((val2 & pack_9x9_fused) == pack_9x9_fused)
171 type = MXC_CPU_IMX9322;
172
173 if (npu_disable && core1_disable)
174 return type + 3;
175 else if (npu_disable)
176 return type + 2;
177 else if (core1_disable)
178 return type + 1;
179
180 return type;
181}
182
Peng Fanbbcd2c42022-07-26 16:40:39 +0800183u32 get_cpu_rev(void)
184{
Peng Fan3700c472022-07-26 16:40:56 +0800185 u32 rev = (gd->arch.soc_rev >> 24) - 0xa0;
186
Peng Fanc3db3ad2023-04-28 12:08:32 +0800187 return (get_cpu_variant_type(MXC_CPU_IMX93) << 12) |
188 (CHIP_REV_1_0 + rev);
Peng Fanbbcd2c42022-07-26 16:40:39 +0800189}
190
Ye Li9e19ff92022-07-26 16:40:47 +0800191#define UNLOCK_WORD 0xD928C520 /* unlock word */
192#define REFRESH_WORD 0xB480A602 /* refresh word */
193
194static void disable_wdog(void __iomem *wdog_base)
195{
196 u32 val_cs = readl(wdog_base + 0x00);
197
198 if (!(val_cs & 0x80))
199 return;
200
201 /* default is 32bits cmd */
202 writel(REFRESH_WORD, (wdog_base + 0x04)); /* Refresh the CNT */
203
204 if (!(val_cs & 0x800)) {
205 writel(UNLOCK_WORD, (wdog_base + 0x04));
206 while (!(readl(wdog_base + 0x00) & 0x800))
207 ;
208 }
209 writel(0x0, (wdog_base + 0x0C)); /* Set WIN to 0 */
210 writel(0x400, (wdog_base + 0x08)); /* Set timeout to default 0x400 */
211 writel(0x2120, (wdog_base + 0x00)); /* Disable it and set update */
212
213 while (!(readl(wdog_base + 0x00) & 0x400))
214 ;
215}
216
217void init_wdog(void)
218{
219 u32 src_val;
220
221 disable_wdog((void __iomem *)WDG3_BASE_ADDR);
222 disable_wdog((void __iomem *)WDG4_BASE_ADDR);
223 disable_wdog((void __iomem *)WDG5_BASE_ADDR);
224
225 src_val = readl(0x54460018); /* reset mask */
226 src_val &= ~0x1c;
227 writel(src_val, 0x54460018);
228}
229
Peng Fanbbcd2c42022-07-26 16:40:39 +0800230static struct mm_region imx93_mem_map[] = {
231 {
232 /* ROM */
233 .virt = 0x0UL,
234 .phys = 0x0UL,
235 .size = 0x100000UL,
236 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
237 PTE_BLOCK_OUTER_SHARE
238 }, {
Peng Fan313af252022-07-26 16:41:04 +0800239 /* TCM */
240 .virt = 0x201c0000UL,
241 .phys = 0x201c0000UL,
242 .size = 0x80000UL,
243 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
244 PTE_BLOCK_NON_SHARE |
245 PTE_BLOCK_PXN | PTE_BLOCK_UXN
246 }, {
Peng Fanbbcd2c42022-07-26 16:40:39 +0800247 /* OCRAM */
248 .virt = 0x20480000UL,
249 .phys = 0x20480000UL,
250 .size = 0xA0000UL,
251 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
252 PTE_BLOCK_OUTER_SHARE
253 }, {
254 /* AIPS */
255 .virt = 0x40000000UL,
256 .phys = 0x40000000UL,
257 .size = 0x40000000UL,
258 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
259 PTE_BLOCK_NON_SHARE |
260 PTE_BLOCK_PXN | PTE_BLOCK_UXN
261 }, {
262 /* Flexible Serial Peripheral Interface */
263 .virt = 0x28000000UL,
264 .phys = 0x28000000UL,
265 .size = 0x30000000UL,
266 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
267 PTE_BLOCK_NON_SHARE |
268 PTE_BLOCK_PXN | PTE_BLOCK_UXN
269 }, {
270 /* DRAM1 */
271 .virt = 0x80000000UL,
272 .phys = 0x80000000UL,
273 .size = PHYS_SDRAM_SIZE,
274 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
275 PTE_BLOCK_OUTER_SHARE
276 }, {
277 /* empty entrie to split table entry 5 if needed when TEEs are used */
278 0,
279 }, {
280 /* List terminator */
281 0,
282 }
283};
284
285struct mm_region *mem_map = imx93_mem_map;
286
Peng Fan1ed3c0a2023-04-28 12:08:20 +0800287static unsigned int imx9_find_dram_entry_in_mem_map(void)
288{
289 int i;
290
291 for (i = 0; i < ARRAY_SIZE(imx93_mem_map); i++)
292 if (imx93_mem_map[i].phys == CFG_SYS_SDRAM_BASE)
293 return i;
294
295 hang(); /* Entry not found, this must never happen. */
296}
297
298void enable_caches(void)
299{
300 /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch
301 * If OPTEE does not run, still update the MMU table according to dram banks structure
302 * to set correct dram size from board_phys_sdram_size
303 */
304 int i = 0;
305 /*
306 * please make sure that entry initial value matches
307 * imx93_mem_map for DRAM1
308 */
309 int entry = imx9_find_dram_entry_in_mem_map();
310 u64 attrs = imx93_mem_map[entry].attrs;
311
312 while (i < CONFIG_NR_DRAM_BANKS &&
313 entry < ARRAY_SIZE(imx93_mem_map)) {
314 if (gd->bd->bi_dram[i].start == 0)
315 break;
316 imx93_mem_map[entry].phys = gd->bd->bi_dram[i].start;
317 imx93_mem_map[entry].virt = gd->bd->bi_dram[i].start;
318 imx93_mem_map[entry].size = gd->bd->bi_dram[i].size;
319 imx93_mem_map[entry].attrs = attrs;
320 debug("Added memory mapping (%d): %llx %llx\n", entry,
321 imx93_mem_map[entry].phys, imx93_mem_map[entry].size);
322 i++; entry++;
323 }
324
325 icache_enable();
326 dcache_enable();
327}
328
329__weak int board_phys_sdram_size(phys_size_t *size)
330{
Ye Libb1187b2023-04-28 12:08:45 +0800331 phys_size_t start, end;
332 phys_size_t val;
333
Peng Fan1ed3c0a2023-04-28 12:08:20 +0800334 if (!size)
335 return -EINVAL;
336
Ye Libb1187b2023-04-28 12:08:45 +0800337 val = readl(REG_DDR_CS0_BNDS);
338 start = (val >> 16) << 24;
339 end = (val & 0xFFFF);
340 end = end ? end + 1 : 0;
341 end = end << 24;
342 *size = end - start;
Peng Fan1ed3c0a2023-04-28 12:08:20 +0800343
Ye Libb1187b2023-04-28 12:08:45 +0800344 val = readl(REG_DDR_CS1_BNDS);
345 start = (val >> 16) << 24;
346 end = (val & 0xFFFF);
347 end = end ? end + 1 : 0;
348 end = end << 24;
349 *size += end - start;
350
Peng Fan1ed3c0a2023-04-28 12:08:20 +0800351 return 0;
352}
353
Peng Fanbbcd2c42022-07-26 16:40:39 +0800354int dram_init(void)
355{
Peng Fan1ed3c0a2023-04-28 12:08:20 +0800356 phys_size_t sdram_size;
357 int ret;
358
359 ret = board_phys_sdram_size(&sdram_size);
360 if (ret)
361 return ret;
362
363 /* rom_pointer[1] contains the size of TEE occupies */
364 if (rom_pointer[1])
365 gd->ram_size = sdram_size - rom_pointer[1];
366 else
367 gd->ram_size = sdram_size;
368
369 return 0;
370}
371
372int dram_init_banksize(void)
373{
374 int bank = 0;
375 int ret;
376 phys_size_t sdram_size;
377 phys_size_t sdram_b1_size, sdram_b2_size;
378
379 ret = board_phys_sdram_size(&sdram_size);
380 if (ret)
381 return ret;
382
383 /* Bank 1 can't cross over 4GB space */
384 if (sdram_size > 0x80000000) {
385 sdram_b1_size = 0x80000000;
386 sdram_b2_size = sdram_size - 0x80000000;
387 } else {
388 sdram_b1_size = sdram_size;
389 sdram_b2_size = 0;
390 }
391
392 gd->bd->bi_dram[bank].start = PHYS_SDRAM;
393 if (rom_pointer[1]) {
394 phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
395 phys_size_t optee_size = (size_t)rom_pointer[1];
396
397 gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
398 if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) {
399 if (++bank >= CONFIG_NR_DRAM_BANKS) {
400 puts("CONFIG_NR_DRAM_BANKS is not enough\n");
401 return -1;
402 }
403
404 gd->bd->bi_dram[bank].start = optee_start + optee_size;
405 gd->bd->bi_dram[bank].size = PHYS_SDRAM +
406 sdram_b1_size - gd->bd->bi_dram[bank].start;
407 }
408 } else {
409 gd->bd->bi_dram[bank].size = sdram_b1_size;
410 }
411
412 if (sdram_b2_size) {
413 if (++bank >= CONFIG_NR_DRAM_BANKS) {
414 puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
415 return -1;
416 }
417 gd->bd->bi_dram[bank].start = 0x100000000UL;
418 gd->bd->bi_dram[bank].size = sdram_b2_size;
419 }
Peng Fanbbcd2c42022-07-26 16:40:39 +0800420
421 return 0;
422}
423
Peng Fan1ed3c0a2023-04-28 12:08:20 +0800424phys_size_t get_effective_memsize(void)
425{
426 int ret;
427 phys_size_t sdram_size;
428 phys_size_t sdram_b1_size;
429
430 ret = board_phys_sdram_size(&sdram_size);
431 if (!ret) {
432 /* Bank 1 can't cross over 4GB space */
433 if (sdram_size > 0x80000000)
434 sdram_b1_size = 0x80000000;
435 else
436 sdram_b1_size = sdram_size;
437
438 if (rom_pointer[1]) {
439 /* We will relocate u-boot to top of dram1. TEE position has two cases:
440 * 1. At the top of dram1, Then return the size removed optee size.
441 * 2. In the middle of dram1, return the size of dram1.
442 */
443 if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size))
444 return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
445 }
446
447 return sdram_b1_size;
448 } else {
449 return PHYS_SDRAM_SIZE;
450 }
451}
452
Peng Fanbbcd2c42022-07-26 16:40:39 +0800453void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
454{
Ye Li66baefb2023-04-28 12:08:21 +0800455 u32 val[2] = {};
456 int ret;
457
458 if (dev_id == 0) {
459 ret = fuse_read(39, 3, &val[0]);
460 if (ret)
461 goto err;
462
463 ret = fuse_read(39, 4, &val[1]);
464 if (ret)
465 goto err;
466
467 mac[0] = val[1] >> 8;
468 mac[1] = val[1];
469 mac[2] = val[0] >> 24;
470 mac[3] = val[0] >> 16;
471 mac[4] = val[0] >> 8;
472 mac[5] = val[0];
473
474 } else {
475 ret = fuse_read(39, 5, &val[0]);
476 if (ret)
477 goto err;
478
479 ret = fuse_read(39, 4, &val[1]);
480 if (ret)
481 goto err;
482
483 mac[0] = val[1] >> 24;
484 mac[1] = val[1] >> 16;
485 mac[2] = val[0] >> 24;
486 mac[3] = val[0] >> 16;
487 mac[4] = val[0] >> 8;
488 mac[5] = val[0];
489 }
490
491 debug("%s: MAC%d: %02x.%02x.%02x.%02x.%02x.%02x\n",
492 __func__, dev_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
493 return;
494err:
495 memset(mac, 0, 6);
496 printf("%s: fuse read err: %d\n", __func__, ret);
Peng Fanbbcd2c42022-07-26 16:40:39 +0800497}
498
499int print_cpuinfo(void)
500{
501 u32 cpurev;
502
503 cpurev = get_cpu_rev();
504
505 printf("CPU: i.MX93 rev%d.%d\n", (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0);
506
507 return 0;
508}
509
Peng Fanbbcd2c42022-07-26 16:40:39 +0800510int ft_system_setup(void *blob, struct bd_info *bd)
511{
512 return 0;
513}
Peng Fan3700c472022-07-26 16:40:56 +0800514
515#if defined(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)
516void get_board_serial(struct tag_serialnr *serialnr)
517{
518 printf("UID: 0x%x 0x%x 0x%x 0x%x\n",
519 gd->arch.uid[0], gd->arch.uid[1], gd->arch.uid[2], gd->arch.uid[3]);
520
521 serialnr->low = gd->arch.uid[0];
522 serialnr->high = gd->arch.uid[3];
523}
524#endif
Peng Fanbbcd2c42022-07-26 16:40:39 +0800525
Peng Fanb1815c42023-04-28 12:08:27 +0800526static void save_reset_cause(void)
527{
528 struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE;
529 u32 srsr = readl(&src->srsr);
530
531 /* clear srsr in sec mode */
532 writel(srsr, &src->srsr);
533
534 /* Save value to GPR1 to pass to nonsecure */
535 writel(srsr, &src->gpr[0]);
536}
537
Peng Fanbbcd2c42022-07-26 16:40:39 +0800538int arch_cpu_init(void)
539{
Ye Li9e19ff92022-07-26 16:40:47 +0800540 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
541 /* Disable wdog */
542 init_wdog();
543
Peng Fan28b5cb52022-07-26 16:40:43 +0800544 clock_init();
Ye Li62185922022-07-26 16:40:54 +0800545
546 trdc_early_init();
Peng Fanb1815c42023-04-28 12:08:27 +0800547
548 /* Save SRC SRSR to GPR1 and clear it */
549 save_reset_cause();
Ye Li9e19ff92022-07-26 16:40:47 +0800550 }
Peng Fan28b5cb52022-07-26 16:40:43 +0800551
Peng Fanbbcd2c42022-07-26 16:40:39 +0800552 return 0;
553}
Peng Fan3700c472022-07-26 16:40:56 +0800554
Simon Glassb8357c12023-08-21 21:16:56 -0600555int imx9_probe_mu(void)
Peng Fan3700c472022-07-26 16:40:56 +0800556{
557 struct udevice *devp;
558 int node, ret;
559 u32 res;
Peng Fand5c31832023-06-15 18:09:05 +0800560 struct ele_get_info_data info;
Peng Fan3700c472022-07-26 16:40:56 +0800561
562 node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx93-mu-s4");
563
564 ret = uclass_get_device_by_of_offset(UCLASS_MISC, node, &devp);
565 if (ret)
566 return ret;
567
568 if (gd->flags & GD_FLG_RELOC)
569 return 0;
570
Peng Fand5c31832023-06-15 18:09:05 +0800571 ret = ele_get_info(&info, &res);
Peng Fan3700c472022-07-26 16:40:56 +0800572 if (ret)
573 return ret;
574
575 set_cpu_info(&info);
576
577 return 0;
578}
Simon Glassb8357c12023-08-21 21:16:56 -0600579EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, imx9_probe_mu);
Jian Liacf41a32022-07-26 16:40:46 +0800580
581int timer_init(void)
582{
583#ifdef CONFIG_SPL_BUILD
584 struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR;
585 unsigned long freq = readl(&sctr->cntfid0);
586
587 /* Update with accurate clock frequency */
588 asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory");
589
590 clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1,
591 SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG);
592#endif
593
594 gd->arch.tbl = 0;
595 gd->arch.tbu = 0;
596
597 return 0;
598}
Peng Fan65563792022-07-26 16:41:02 +0800599
Ye Li8e8687c2022-07-26 16:41:05 +0800600enum env_location env_get_location(enum env_operation op, int prio)
601{
602 enum boot_device dev = get_boot_device();
Ye Li8e8687c2022-07-26 16:41:05 +0800603
604 if (prio)
Oleksandr Suvoroveff7c8d2023-04-11 20:27:41 +0300605 return ENVL_UNKNOWN;
Ye Li8e8687c2022-07-26 16:41:05 +0800606
607 switch (dev) {
Ye Li8e8687c2022-07-26 16:41:05 +0800608 case QSPI_BOOT:
Oleksandr Suvoroveff7c8d2023-04-11 20:27:41 +0300609 if (CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH))
610 return ENVL_SPI_FLASH;
611 return ENVL_NOWHERE;
Ye Li8e8687c2022-07-26 16:41:05 +0800612 case SD1_BOOT:
613 case SD2_BOOT:
614 case SD3_BOOT:
615 case MMC1_BOOT:
616 case MMC2_BOOT:
617 case MMC3_BOOT:
Oleksandr Suvoroveff7c8d2023-04-11 20:27:41 +0300618 if (CONFIG_IS_ENABLED(ENV_IS_IN_MMC))
619 return ENVL_MMC;
620 else if (CONFIG_IS_ENABLED(ENV_IS_IN_EXT4))
621 return ENVL_EXT4;
622 else if (CONFIG_IS_ENABLED(ENV_IS_IN_FAT))
623 return ENVL_FAT;
624 return ENVL_NOWHERE;
Ye Li8e8687c2022-07-26 16:41:05 +0800625 default:
Oleksandr Suvoroveff7c8d2023-04-11 20:27:41 +0300626 return ENVL_NOWHERE;
Ye Li8e8687c2022-07-26 16:41:05 +0800627 }
Ye Li8e8687c2022-07-26 16:41:05 +0800628}
629
Peng Fan65563792022-07-26 16:41:02 +0800630static int mix_power_init(enum mix_power_domain pd)
631{
632 enum src_mix_slice_id mix_id;
633 enum src_mem_slice_id mem_id;
634 struct src_mix_slice_regs *mix_regs;
635 struct src_mem_slice_regs *mem_regs;
636 struct src_general_regs *global_regs;
637 u32 scr, val;
638
639 switch (pd) {
640 case MIX_PD_MEDIAMIX:
641 mix_id = SRC_MIX_MEDIA;
642 mem_id = SRC_MEM_MEDIA;
643 scr = BIT(5);
644
Peng Fand5c31832023-06-15 18:09:05 +0800645 /* Enable ELE handshake */
Peng Fan65563792022-07-26 16:41:02 +0800646 struct blk_ctrl_s_aonmix_regs *s_regs =
647 (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR;
648
649 setbits_le32(&s_regs->lp_handshake[0], BIT(13));
650 break;
651 case MIX_PD_MLMIX:
652 mix_id = SRC_MIX_ML;
653 mem_id = SRC_MEM_ML;
654 scr = BIT(4);
655 break;
656 case MIX_PD_DDRMIX:
657 mix_id = SRC_MIX_DDRMIX;
658 mem_id = SRC_MEM_DDRMIX;
659 scr = BIT(6);
660 break;
661 default:
662 return -EINVAL;
663 }
664
665 mix_regs = (struct src_mix_slice_regs *)(ulong)(SRC_IPS_BASE_ADDR + 0x400 * (mix_id + 1));
666 mem_regs =
667 (struct src_mem_slice_regs *)(ulong)(SRC_IPS_BASE_ADDR + 0x3800 + 0x400 * mem_id);
668 global_regs = (struct src_general_regs *)(ulong)SRC_GLOBAL_RBASE;
669
670 /* Allow NS to set it */
671 setbits_le32(&mix_regs->authen_ctrl, BIT(9));
672
673 clrsetbits_le32(&mix_regs->psw_ack_ctrl[0], BIT(28), BIT(29));
674
675 /* mix reset will be held until boot core write this bit to 1 */
676 setbits_le32(&global_regs->scr, scr);
677
678 /* Enable mem in Low power auto sequence */
679 setbits_le32(&mem_regs->mem_ctrl, BIT(2));
680
681 /* Set the power down state */
682 val = readl(&mix_regs->func_stat);
683 if (val & SRC_MIX_SLICE_FUNC_STAT_PSW_STAT) {
684 /* The mix is default power off, power down it to make PDN_SFT bit
685 * aligned with FUNC STAT
686 */
687 setbits_le32(&mix_regs->slice_sw_ctrl, BIT(31));
688 val = readl(&mix_regs->func_stat);
689
690 /* Since PSW_STAT is 1, can't be used for power off status (SW_CTRL BIT31 set)) */
691 /* Check the MEM STAT change to ensure SSAR is completed */
692 while (!(val & SRC_MIX_SLICE_FUNC_STAT_MEM_STAT))
693 val = readl(&mix_regs->func_stat);
694
695 /* wait few ipg clock cycles to ensure FSM done and power off status is correct */
696 /* About 5 cycles at 24Mhz, 1us is enough */
697 udelay(1);
698 } else {
699 /* The mix is default power on, Do mix power cycle */
700 setbits_le32(&mix_regs->slice_sw_ctrl, BIT(31));
701 val = readl(&mix_regs->func_stat);
702 while (!(val & SRC_MIX_SLICE_FUNC_STAT_PSW_STAT))
703 val = readl(&mix_regs->func_stat);
704 }
705
706 /* power on */
707 clrbits_le32(&mix_regs->slice_sw_ctrl, BIT(31));
708 val = readl(&mix_regs->func_stat);
709 while (val & SRC_MIX_SLICE_FUNC_STAT_ISO_STAT)
710 val = readl(&mix_regs->func_stat);
711
712 return 0;
713}
714
715void disable_isolation(void)
716{
717 struct src_general_regs *global_regs = (struct src_general_regs *)(ulong)SRC_GLOBAL_RBASE;
718 /* clear isolation for usbphy, dsi, csi*/
719 writel(0x0, &global_regs->sp_iso_ctrl);
720}
721
722void soc_power_init(void)
723{
724 mix_power_init(MIX_PD_MEDIAMIX);
725 mix_power_init(MIX_PD_MLMIX);
726
727 disable_isolation();
728}
Peng Fan6d929962022-07-26 16:41:03 +0800729
Peng Fan313af252022-07-26 16:41:04 +0800730bool m33_is_rom_kicked(void)
Peng Fan6d929962022-07-26 16:41:03 +0800731{
732 struct blk_ctrl_s_aonmix_regs *s_regs =
733 (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR;
734
735 if (!(readl(&s_regs->m33_cfg) & BIT(2)))
736 return true;
737
738 return false;
739}
740
741int m33_prepare(void)
742{
743 struct src_mix_slice_regs *mix_regs =
744 (struct src_mix_slice_regs *)(ulong)(SRC_IPS_BASE_ADDR + 0x400 * (SRC_MIX_CM33 + 1));
745 struct src_general_regs *global_regs =
746 (struct src_general_regs *)(ulong)SRC_GLOBAL_RBASE;
747 struct blk_ctrl_s_aonmix_regs *s_regs =
748 (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR;
749 u32 val;
750
751 if (m33_is_rom_kicked())
752 return -EPERM;
753
754 /* Release reset of M33 */
755 setbits_le32(&global_regs->scr, BIT(0));
756
757 /* Check the reset released in M33 MIX func stat */
758 val = readl(&mix_regs->func_stat);
759 while (!(val & SRC_MIX_SLICE_FUNC_STAT_RST_STAT))
760 val = readl(&mix_regs->func_stat);
761
Peng Fand5c31832023-06-15 18:09:05 +0800762 /* Release ELE TROUT */
763 ele_release_m33_trout();
Peng Fan6d929962022-07-26 16:41:03 +0800764
765 /* Mask WDOG1 IRQ from A55, we use it for M33 reset */
766 setbits_le32(&s_regs->ca55_irq_mask[1], BIT(6));
767
768 /* Turn on WDOG1 clock */
769 ccm_lpcg_on(CCGR_WDG1, 1);
770
Peng Fand5c31832023-06-15 18:09:05 +0800771 /* Set ELE LP handshake for M33 reset */
Peng Fan6d929962022-07-26 16:41:03 +0800772 setbits_le32(&s_regs->lp_handshake[0], BIT(6));
773
774 /* Clear M33 TCM for ECC */
775 memset((void *)(ulong)0x201e0000, 0, 0x40000);
776
777 return 0;
778}
Peng Fanb1815c42023-04-28 12:08:27 +0800779
780int psci_sysreset_get_status(struct udevice *dev, char *buf, int size)
781{
782 static const char *reset_cause[] = {
783 "POR ",
784 "JTAG ",
785 "IPP USER ",
786 "WDOG1 ",
787 "WDOG2 ",
788 "WDOG3 ",
789 "WDOG4 ",
790 "WDOG5 ",
791 "TEMPSENSE ",
792 "CSU ",
793 "JTAG_SW ",
794 "M33_REQ ",
795 "M33_LOCKUP ",
796 "UNK ",
797 "UNK ",
798 "UNK "
799 };
800
801 struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE;
802 u32 srsr;
803 u32 i;
804 int res;
805
806 srsr = readl(&src->gpr[0]);
807
808 for (i = ARRAY_SIZE(reset_cause); i > 0; i--) {
809 if (srsr & (BIT(i - 1)))
810 break;
811 }
812
813 res = snprintf(buf, size, "Reset Status: %s\n", i ? reset_cause[i - 1] : "unknown reset");
814 if (res < 0) {
815 dev_err(dev, "Could not write reset status message (err = %d)\n", res);
816 return -EIO;
817 }
818
819 return 0;
820}