blob: e476581e5ef9d67887819430b22f0517ea594c53 [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>
29#include <linux/bitops.h>
30#include <asm/setup.h>
31#include <asm/bootm.h>
32#include <asm/arch-imx/cpu.h>
Peng Fan3700c472022-07-26 16:40:56 +080033#include <asm/mach-imx/s400_api.h>
Peng Fan65563792022-07-26 16:41:02 +080034#include <linux/delay.h>
Ye Li66baefb2023-04-28 12:08:21 +080035#include <fuse.h>
Peng Fanbbcd2c42022-07-26 16:40:39 +080036
37DECLARE_GLOBAL_DATA_PTR;
38
Peng Fan5de0fc02022-07-26 16:40:48 +080039struct rom_api *g_rom_api = (struct rom_api *)0x1980;
40
41#ifdef CONFIG_ENV_IS_IN_MMC
42__weak int board_mmc_get_env_dev(int devno)
43{
44 return devno; }
45
46int mmc_get_env_dev(void)
47{
48 volatile gd_t *pgd = gd;
49 int ret;
50 u32 boot;
51 u16 boot_type;
52 u8 boot_instance;
53
54 ret = g_rom_api->query_boot_infor(QUERY_BT_DEV, &boot,
55 ((uintptr_t)&boot) ^ QUERY_BT_DEV);
56 set_gd(pgd);
57
58 if (ret != ROM_API_OKAY) {
59 puts("ROMAPI: failure at query_boot_info\n");
60 return CONFIG_SYS_MMC_ENV_DEV;
61 }
62
63 boot_type = boot >> 16;
64 boot_instance = (boot >> 8) & 0xff;
65
66 debug("boot_type %d, instance %d\n", boot_type, boot_instance);
67
68 /* If not boot from sd/mmc, use default value */
69 if (boot_type != BOOT_TYPE_SD && boot_type != BOOT_TYPE_MMC)
70 return env_get_ulong("mmcdev", 10, CONFIG_SYS_MMC_ENV_DEV);
71
72 return board_mmc_get_env_dev(boot_instance);
73}
74#endif
75
Peng Fan3700c472022-07-26 16:40:56 +080076static void set_cpu_info(struct sentinel_get_info_data *info)
77{
78 gd->arch.soc_rev = info->soc;
79 gd->arch.lifecycle = info->lc;
80 memcpy((void *)&gd->arch.uid, &info->uid, 4 * sizeof(u32));
81}
82
Peng Fanbbcd2c42022-07-26 16:40:39 +080083u32 get_cpu_rev(void)
84{
Peng Fan3700c472022-07-26 16:40:56 +080085 u32 rev = (gd->arch.soc_rev >> 24) - 0xa0;
86
87 return (MXC_CPU_IMX93 << 12) | (CHIP_REV_1_0 + rev);
Peng Fanbbcd2c42022-07-26 16:40:39 +080088}
89
Ye Li9e19ff92022-07-26 16:40:47 +080090#define UNLOCK_WORD 0xD928C520 /* unlock word */
91#define REFRESH_WORD 0xB480A602 /* refresh word */
92
93static void disable_wdog(void __iomem *wdog_base)
94{
95 u32 val_cs = readl(wdog_base + 0x00);
96
97 if (!(val_cs & 0x80))
98 return;
99
100 /* default is 32bits cmd */
101 writel(REFRESH_WORD, (wdog_base + 0x04)); /* Refresh the CNT */
102
103 if (!(val_cs & 0x800)) {
104 writel(UNLOCK_WORD, (wdog_base + 0x04));
105 while (!(readl(wdog_base + 0x00) & 0x800))
106 ;
107 }
108 writel(0x0, (wdog_base + 0x0C)); /* Set WIN to 0 */
109 writel(0x400, (wdog_base + 0x08)); /* Set timeout to default 0x400 */
110 writel(0x2120, (wdog_base + 0x00)); /* Disable it and set update */
111
112 while (!(readl(wdog_base + 0x00) & 0x400))
113 ;
114}
115
116void init_wdog(void)
117{
118 u32 src_val;
119
120 disable_wdog((void __iomem *)WDG3_BASE_ADDR);
121 disable_wdog((void __iomem *)WDG4_BASE_ADDR);
122 disable_wdog((void __iomem *)WDG5_BASE_ADDR);
123
124 src_val = readl(0x54460018); /* reset mask */
125 src_val &= ~0x1c;
126 writel(src_val, 0x54460018);
127}
128
Peng Fanbbcd2c42022-07-26 16:40:39 +0800129static struct mm_region imx93_mem_map[] = {
130 {
131 /* ROM */
132 .virt = 0x0UL,
133 .phys = 0x0UL,
134 .size = 0x100000UL,
135 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
136 PTE_BLOCK_OUTER_SHARE
137 }, {
Peng Fan313af252022-07-26 16:41:04 +0800138 /* TCM */
139 .virt = 0x201c0000UL,
140 .phys = 0x201c0000UL,
141 .size = 0x80000UL,
142 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
143 PTE_BLOCK_NON_SHARE |
144 PTE_BLOCK_PXN | PTE_BLOCK_UXN
145 }, {
Peng Fanbbcd2c42022-07-26 16:40:39 +0800146 /* OCRAM */
147 .virt = 0x20480000UL,
148 .phys = 0x20480000UL,
149 .size = 0xA0000UL,
150 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
151 PTE_BLOCK_OUTER_SHARE
152 }, {
153 /* AIPS */
154 .virt = 0x40000000UL,
155 .phys = 0x40000000UL,
156 .size = 0x40000000UL,
157 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
158 PTE_BLOCK_NON_SHARE |
159 PTE_BLOCK_PXN | PTE_BLOCK_UXN
160 }, {
161 /* Flexible Serial Peripheral Interface */
162 .virt = 0x28000000UL,
163 .phys = 0x28000000UL,
164 .size = 0x30000000UL,
165 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
166 PTE_BLOCK_NON_SHARE |
167 PTE_BLOCK_PXN | PTE_BLOCK_UXN
168 }, {
169 /* DRAM1 */
170 .virt = 0x80000000UL,
171 .phys = 0x80000000UL,
172 .size = PHYS_SDRAM_SIZE,
173 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
174 PTE_BLOCK_OUTER_SHARE
175 }, {
176 /* empty entrie to split table entry 5 if needed when TEEs are used */
177 0,
178 }, {
179 /* List terminator */
180 0,
181 }
182};
183
184struct mm_region *mem_map = imx93_mem_map;
185
Peng Fan1ed3c0a2023-04-28 12:08:20 +0800186static unsigned int imx9_find_dram_entry_in_mem_map(void)
187{
188 int i;
189
190 for (i = 0; i < ARRAY_SIZE(imx93_mem_map); i++)
191 if (imx93_mem_map[i].phys == CFG_SYS_SDRAM_BASE)
192 return i;
193
194 hang(); /* Entry not found, this must never happen. */
195}
196
197void enable_caches(void)
198{
199 /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch
200 * If OPTEE does not run, still update the MMU table according to dram banks structure
201 * to set correct dram size from board_phys_sdram_size
202 */
203 int i = 0;
204 /*
205 * please make sure that entry initial value matches
206 * imx93_mem_map for DRAM1
207 */
208 int entry = imx9_find_dram_entry_in_mem_map();
209 u64 attrs = imx93_mem_map[entry].attrs;
210
211 while (i < CONFIG_NR_DRAM_BANKS &&
212 entry < ARRAY_SIZE(imx93_mem_map)) {
213 if (gd->bd->bi_dram[i].start == 0)
214 break;
215 imx93_mem_map[entry].phys = gd->bd->bi_dram[i].start;
216 imx93_mem_map[entry].virt = gd->bd->bi_dram[i].start;
217 imx93_mem_map[entry].size = gd->bd->bi_dram[i].size;
218 imx93_mem_map[entry].attrs = attrs;
219 debug("Added memory mapping (%d): %llx %llx\n", entry,
220 imx93_mem_map[entry].phys, imx93_mem_map[entry].size);
221 i++; entry++;
222 }
223
224 icache_enable();
225 dcache_enable();
226}
227
228__weak int board_phys_sdram_size(phys_size_t *size)
229{
230 if (!size)
231 return -EINVAL;
232
233 *size = PHYS_SDRAM_SIZE;
234
235#ifdef PHYS_SDRAM_2_SIZE
236 *size += PHYS_SDRAM_2_SIZE;
237#endif
238 return 0;
239}
240
Peng Fanbbcd2c42022-07-26 16:40:39 +0800241int dram_init(void)
242{
Peng Fan1ed3c0a2023-04-28 12:08:20 +0800243 phys_size_t sdram_size;
244 int ret;
245
246 ret = board_phys_sdram_size(&sdram_size);
247 if (ret)
248 return ret;
249
250 /* rom_pointer[1] contains the size of TEE occupies */
251 if (rom_pointer[1])
252 gd->ram_size = sdram_size - rom_pointer[1];
253 else
254 gd->ram_size = sdram_size;
255
256 return 0;
257}
258
259int dram_init_banksize(void)
260{
261 int bank = 0;
262 int ret;
263 phys_size_t sdram_size;
264 phys_size_t sdram_b1_size, sdram_b2_size;
265
266 ret = board_phys_sdram_size(&sdram_size);
267 if (ret)
268 return ret;
269
270 /* Bank 1 can't cross over 4GB space */
271 if (sdram_size > 0x80000000) {
272 sdram_b1_size = 0x80000000;
273 sdram_b2_size = sdram_size - 0x80000000;
274 } else {
275 sdram_b1_size = sdram_size;
276 sdram_b2_size = 0;
277 }
278
279 gd->bd->bi_dram[bank].start = PHYS_SDRAM;
280 if (rom_pointer[1]) {
281 phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
282 phys_size_t optee_size = (size_t)rom_pointer[1];
283
284 gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
285 if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) {
286 if (++bank >= CONFIG_NR_DRAM_BANKS) {
287 puts("CONFIG_NR_DRAM_BANKS is not enough\n");
288 return -1;
289 }
290
291 gd->bd->bi_dram[bank].start = optee_start + optee_size;
292 gd->bd->bi_dram[bank].size = PHYS_SDRAM +
293 sdram_b1_size - gd->bd->bi_dram[bank].start;
294 }
295 } else {
296 gd->bd->bi_dram[bank].size = sdram_b1_size;
297 }
298
299 if (sdram_b2_size) {
300 if (++bank >= CONFIG_NR_DRAM_BANKS) {
301 puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
302 return -1;
303 }
304 gd->bd->bi_dram[bank].start = 0x100000000UL;
305 gd->bd->bi_dram[bank].size = sdram_b2_size;
306 }
Peng Fanbbcd2c42022-07-26 16:40:39 +0800307
308 return 0;
309}
310
Peng Fan1ed3c0a2023-04-28 12:08:20 +0800311phys_size_t get_effective_memsize(void)
312{
313 int ret;
314 phys_size_t sdram_size;
315 phys_size_t sdram_b1_size;
316
317 ret = board_phys_sdram_size(&sdram_size);
318 if (!ret) {
319 /* Bank 1 can't cross over 4GB space */
320 if (sdram_size > 0x80000000)
321 sdram_b1_size = 0x80000000;
322 else
323 sdram_b1_size = sdram_size;
324
325 if (rom_pointer[1]) {
326 /* We will relocate u-boot to top of dram1. TEE position has two cases:
327 * 1. At the top of dram1, Then return the size removed optee size.
328 * 2. In the middle of dram1, return the size of dram1.
329 */
330 if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size))
331 return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
332 }
333
334 return sdram_b1_size;
335 } else {
336 return PHYS_SDRAM_SIZE;
337 }
338}
339
Peng Fanbbcd2c42022-07-26 16:40:39 +0800340void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
341{
Ye Li66baefb2023-04-28 12:08:21 +0800342 u32 val[2] = {};
343 int ret;
344
345 if (dev_id == 0) {
346 ret = fuse_read(39, 3, &val[0]);
347 if (ret)
348 goto err;
349
350 ret = fuse_read(39, 4, &val[1]);
351 if (ret)
352 goto err;
353
354 mac[0] = val[1] >> 8;
355 mac[1] = val[1];
356 mac[2] = val[0] >> 24;
357 mac[3] = val[0] >> 16;
358 mac[4] = val[0] >> 8;
359 mac[5] = val[0];
360
361 } else {
362 ret = fuse_read(39, 5, &val[0]);
363 if (ret)
364 goto err;
365
366 ret = fuse_read(39, 4, &val[1]);
367 if (ret)
368 goto err;
369
370 mac[0] = val[1] >> 24;
371 mac[1] = val[1] >> 16;
372 mac[2] = val[0] >> 24;
373 mac[3] = val[0] >> 16;
374 mac[4] = val[0] >> 8;
375 mac[5] = val[0];
376 }
377
378 debug("%s: MAC%d: %02x.%02x.%02x.%02x.%02x.%02x\n",
379 __func__, dev_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
380 return;
381err:
382 memset(mac, 0, 6);
383 printf("%s: fuse read err: %d\n", __func__, ret);
Peng Fanbbcd2c42022-07-26 16:40:39 +0800384}
385
386int print_cpuinfo(void)
387{
388 u32 cpurev;
389
390 cpurev = get_cpu_rev();
391
392 printf("CPU: i.MX93 rev%d.%d\n", (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0);
393
394 return 0;
395}
396
Peng Fanbbcd2c42022-07-26 16:40:39 +0800397int ft_system_setup(void *blob, struct bd_info *bd)
398{
399 return 0;
400}
Peng Fan3700c472022-07-26 16:40:56 +0800401
402#if defined(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)
403void get_board_serial(struct tag_serialnr *serialnr)
404{
405 printf("UID: 0x%x 0x%x 0x%x 0x%x\n",
406 gd->arch.uid[0], gd->arch.uid[1], gd->arch.uid[2], gd->arch.uid[3]);
407
408 serialnr->low = gd->arch.uid[0];
409 serialnr->high = gd->arch.uid[3];
410}
411#endif
Peng Fanbbcd2c42022-07-26 16:40:39 +0800412
Peng Fanb1815c42023-04-28 12:08:27 +0800413static void save_reset_cause(void)
414{
415 struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE;
416 u32 srsr = readl(&src->srsr);
417
418 /* clear srsr in sec mode */
419 writel(srsr, &src->srsr);
420
421 /* Save value to GPR1 to pass to nonsecure */
422 writel(srsr, &src->gpr[0]);
423}
424
Peng Fanbbcd2c42022-07-26 16:40:39 +0800425int arch_cpu_init(void)
426{
Ye Li9e19ff92022-07-26 16:40:47 +0800427 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
428 /* Disable wdog */
429 init_wdog();
430
Peng Fan28b5cb52022-07-26 16:40:43 +0800431 clock_init();
Ye Li62185922022-07-26 16:40:54 +0800432
433 trdc_early_init();
Peng Fanb1815c42023-04-28 12:08:27 +0800434
435 /* Save SRC SRSR to GPR1 and clear it */
436 save_reset_cause();
Ye Li9e19ff92022-07-26 16:40:47 +0800437 }
Peng Fan28b5cb52022-07-26 16:40:43 +0800438
Peng Fanbbcd2c42022-07-26 16:40:39 +0800439 return 0;
440}
Peng Fan3700c472022-07-26 16:40:56 +0800441
442int imx9_probe_mu(void *ctx, struct event *event)
443{
444 struct udevice *devp;
445 int node, ret;
446 u32 res;
447 struct sentinel_get_info_data info;
448
449 node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx93-mu-s4");
450
451 ret = uclass_get_device_by_of_offset(UCLASS_MISC, node, &devp);
452 if (ret)
453 return ret;
454
455 if (gd->flags & GD_FLG_RELOC)
456 return 0;
457
458 ret = ahab_get_info(&info, &res);
459 if (ret)
460 return ret;
461
462 set_cpu_info(&info);
463
464 return 0;
465}
Simon Glass93074012023-05-04 16:50:45 -0600466EVENT_SPY(EVT_DM_POST_INIT_F, imx9_probe_mu);
Jian Liacf41a32022-07-26 16:40:46 +0800467
468int timer_init(void)
469{
470#ifdef CONFIG_SPL_BUILD
471 struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR;
472 unsigned long freq = readl(&sctr->cntfid0);
473
474 /* Update with accurate clock frequency */
475 asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory");
476
477 clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1,
478 SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG);
479#endif
480
481 gd->arch.tbl = 0;
482 gd->arch.tbu = 0;
483
484 return 0;
485}
Peng Fan65563792022-07-26 16:41:02 +0800486
Ye Li8e8687c2022-07-26 16:41:05 +0800487enum env_location env_get_location(enum env_operation op, int prio)
488{
489 enum boot_device dev = get_boot_device();
490 enum env_location env_loc = ENVL_UNKNOWN;
491
492 if (prio)
493 return env_loc;
494
495 switch (dev) {
496#if defined(CONFIG_ENV_IS_IN_SPI_FLASH)
497 case QSPI_BOOT:
498 env_loc = ENVL_SPI_FLASH;
499 break;
500#endif
501#if defined(CONFIG_ENV_IS_IN_MMC)
502 case SD1_BOOT:
503 case SD2_BOOT:
504 case SD3_BOOT:
505 case MMC1_BOOT:
506 case MMC2_BOOT:
507 case MMC3_BOOT:
508 env_loc = ENVL_MMC;
509 break;
510#endif
511 default:
512#if defined(CONFIG_ENV_IS_NOWHERE)
513 env_loc = ENVL_NOWHERE;
514#endif
515 break;
516 }
517
518 return env_loc;
519}
520
Peng Fan65563792022-07-26 16:41:02 +0800521static int mix_power_init(enum mix_power_domain pd)
522{
523 enum src_mix_slice_id mix_id;
524 enum src_mem_slice_id mem_id;
525 struct src_mix_slice_regs *mix_regs;
526 struct src_mem_slice_regs *mem_regs;
527 struct src_general_regs *global_regs;
528 u32 scr, val;
529
530 switch (pd) {
531 case MIX_PD_MEDIAMIX:
532 mix_id = SRC_MIX_MEDIA;
533 mem_id = SRC_MEM_MEDIA;
534 scr = BIT(5);
535
536 /* Enable S400 handshake */
537 struct blk_ctrl_s_aonmix_regs *s_regs =
538 (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR;
539
540 setbits_le32(&s_regs->lp_handshake[0], BIT(13));
541 break;
542 case MIX_PD_MLMIX:
543 mix_id = SRC_MIX_ML;
544 mem_id = SRC_MEM_ML;
545 scr = BIT(4);
546 break;
547 case MIX_PD_DDRMIX:
548 mix_id = SRC_MIX_DDRMIX;
549 mem_id = SRC_MEM_DDRMIX;
550 scr = BIT(6);
551 break;
552 default:
553 return -EINVAL;
554 }
555
556 mix_regs = (struct src_mix_slice_regs *)(ulong)(SRC_IPS_BASE_ADDR + 0x400 * (mix_id + 1));
557 mem_regs =
558 (struct src_mem_slice_regs *)(ulong)(SRC_IPS_BASE_ADDR + 0x3800 + 0x400 * mem_id);
559 global_regs = (struct src_general_regs *)(ulong)SRC_GLOBAL_RBASE;
560
561 /* Allow NS to set it */
562 setbits_le32(&mix_regs->authen_ctrl, BIT(9));
563
564 clrsetbits_le32(&mix_regs->psw_ack_ctrl[0], BIT(28), BIT(29));
565
566 /* mix reset will be held until boot core write this bit to 1 */
567 setbits_le32(&global_regs->scr, scr);
568
569 /* Enable mem in Low power auto sequence */
570 setbits_le32(&mem_regs->mem_ctrl, BIT(2));
571
572 /* Set the power down state */
573 val = readl(&mix_regs->func_stat);
574 if (val & SRC_MIX_SLICE_FUNC_STAT_PSW_STAT) {
575 /* The mix is default power off, power down it to make PDN_SFT bit
576 * aligned with FUNC STAT
577 */
578 setbits_le32(&mix_regs->slice_sw_ctrl, BIT(31));
579 val = readl(&mix_regs->func_stat);
580
581 /* Since PSW_STAT is 1, can't be used for power off status (SW_CTRL BIT31 set)) */
582 /* Check the MEM STAT change to ensure SSAR is completed */
583 while (!(val & SRC_MIX_SLICE_FUNC_STAT_MEM_STAT))
584 val = readl(&mix_regs->func_stat);
585
586 /* wait few ipg clock cycles to ensure FSM done and power off status is correct */
587 /* About 5 cycles at 24Mhz, 1us is enough */
588 udelay(1);
589 } else {
590 /* The mix is default power on, Do mix power cycle */
591 setbits_le32(&mix_regs->slice_sw_ctrl, BIT(31));
592 val = readl(&mix_regs->func_stat);
593 while (!(val & SRC_MIX_SLICE_FUNC_STAT_PSW_STAT))
594 val = readl(&mix_regs->func_stat);
595 }
596
597 /* power on */
598 clrbits_le32(&mix_regs->slice_sw_ctrl, BIT(31));
599 val = readl(&mix_regs->func_stat);
600 while (val & SRC_MIX_SLICE_FUNC_STAT_ISO_STAT)
601 val = readl(&mix_regs->func_stat);
602
603 return 0;
604}
605
606void disable_isolation(void)
607{
608 struct src_general_regs *global_regs = (struct src_general_regs *)(ulong)SRC_GLOBAL_RBASE;
609 /* clear isolation for usbphy, dsi, csi*/
610 writel(0x0, &global_regs->sp_iso_ctrl);
611}
612
613void soc_power_init(void)
614{
615 mix_power_init(MIX_PD_MEDIAMIX);
616 mix_power_init(MIX_PD_MLMIX);
617
618 disable_isolation();
619}
Peng Fan6d929962022-07-26 16:41:03 +0800620
Peng Fan313af252022-07-26 16:41:04 +0800621bool m33_is_rom_kicked(void)
Peng Fan6d929962022-07-26 16:41:03 +0800622{
623 struct blk_ctrl_s_aonmix_regs *s_regs =
624 (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR;
625
626 if (!(readl(&s_regs->m33_cfg) & BIT(2)))
627 return true;
628
629 return false;
630}
631
632int m33_prepare(void)
633{
634 struct src_mix_slice_regs *mix_regs =
635 (struct src_mix_slice_regs *)(ulong)(SRC_IPS_BASE_ADDR + 0x400 * (SRC_MIX_CM33 + 1));
636 struct src_general_regs *global_regs =
637 (struct src_general_regs *)(ulong)SRC_GLOBAL_RBASE;
638 struct blk_ctrl_s_aonmix_regs *s_regs =
639 (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR;
640 u32 val;
641
642 if (m33_is_rom_kicked())
643 return -EPERM;
644
645 /* Release reset of M33 */
646 setbits_le32(&global_regs->scr, BIT(0));
647
648 /* Check the reset released in M33 MIX func stat */
649 val = readl(&mix_regs->func_stat);
650 while (!(val & SRC_MIX_SLICE_FUNC_STAT_RST_STAT))
651 val = readl(&mix_regs->func_stat);
652
653 /* Release Sentinel TROUT */
654 ahab_release_m33_trout();
655
656 /* Mask WDOG1 IRQ from A55, we use it for M33 reset */
657 setbits_le32(&s_regs->ca55_irq_mask[1], BIT(6));
658
659 /* Turn on WDOG1 clock */
660 ccm_lpcg_on(CCGR_WDG1, 1);
661
662 /* Set sentinel LP handshake for M33 reset */
663 setbits_le32(&s_regs->lp_handshake[0], BIT(6));
664
665 /* Clear M33 TCM for ECC */
666 memset((void *)(ulong)0x201e0000, 0, 0x40000);
667
668 return 0;
669}
Peng Fanb1815c42023-04-28 12:08:27 +0800670
671int psci_sysreset_get_status(struct udevice *dev, char *buf, int size)
672{
673 static const char *reset_cause[] = {
674 "POR ",
675 "JTAG ",
676 "IPP USER ",
677 "WDOG1 ",
678 "WDOG2 ",
679 "WDOG3 ",
680 "WDOG4 ",
681 "WDOG5 ",
682 "TEMPSENSE ",
683 "CSU ",
684 "JTAG_SW ",
685 "M33_REQ ",
686 "M33_LOCKUP ",
687 "UNK ",
688 "UNK ",
689 "UNK "
690 };
691
692 struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE;
693 u32 srsr;
694 u32 i;
695 int res;
696
697 srsr = readl(&src->gpr[0]);
698
699 for (i = ARRAY_SIZE(reset_cause); i > 0; i--) {
700 if (srsr & (BIT(i - 1)))
701 break;
702 }
703
704 res = snprintf(buf, size, "Reset Status: %s\n", i ? reset_cause[i - 1] : "unknown reset");
705 if (res < 0) {
706 dev_err(dev, "Could not write reset status message (err = %d)\n", res);
707 return -EIO;
708 }
709
710 return 0;
711}