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