blob: 6ae7e704895f636f04ae2f3dc007764e73761785 [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 Fan3700c472022-07-26 16:40:56 +080037#include <asm/mach-imx/s400_api.h>
Ye Li66baefb2023-04-28 12:08:21 +080038#include <fuse.h>
Peng Fanbbcd2c42022-07-26 16:40:39 +080039
40DECLARE_GLOBAL_DATA_PTR;
41
Peng Fan5de0fc02022-07-26 16:40:48 +080042struct rom_api *g_rom_api = (struct rom_api *)0x1980;
43
44#ifdef CONFIG_ENV_IS_IN_MMC
45__weak int board_mmc_get_env_dev(int devno)
46{
Peng Fan77b36c62023-04-28 12:08:33 +080047 return devno;
48}
Peng Fan5de0fc02022-07-26 16:40:48 +080049
50int mmc_get_env_dev(void)
51{
Peng Fan5de0fc02022-07-26 16:40:48 +080052 int ret;
53 u32 boot;
54 u16 boot_type;
55 u8 boot_instance;
56
Peng Fanc459b582023-04-28 12:08:34 +080057 ret = rom_api_query_boot_infor(QUERY_BT_DEV, &boot);
Peng Fan5de0fc02022-07-26 16:40:48 +080058
59 if (ret != ROM_API_OKAY) {
60 puts("ROMAPI: failure at query_boot_info\n");
61 return CONFIG_SYS_MMC_ENV_DEV;
62 }
63
64 boot_type = boot >> 16;
65 boot_instance = (boot >> 8) & 0xff;
66
67 debug("boot_type %d, instance %d\n", boot_type, boot_instance);
68
69 /* If not boot from sd/mmc, use default value */
70 if (boot_type != BOOT_TYPE_SD && boot_type != BOOT_TYPE_MMC)
71 return env_get_ulong("mmcdev", 10, CONFIG_SYS_MMC_ENV_DEV);
72
73 return board_mmc_get_env_dev(boot_instance);
74}
75#endif
76
Peng Fan0c2f3682023-04-28 12:08:28 +080077/*
78 * SPEED_GRADE[5:4] SPEED_GRADE[3:0] MHz
79 * xx 0000 2300
80 * xx 0001 2200
81 * xx 0010 2100
82 * xx 0011 2000
83 * xx 0100 1900
84 * xx 0101 1800
85 * xx 0110 1700
86 * xx 0111 1600
87 * xx 1000 1500
88 * xx 1001 1400
89 * xx 1010 1300
90 * xx 1011 1200
91 * xx 1100 1100
92 * xx 1101 1000
93 * xx 1110 900
94 * xx 1111 800
95 */
96u32 get_cpu_speed_grade_hz(void)
97{
98 u32 speed, max_speed;
99 u32 val;
100
101 fuse_read(2, 3, &val);
102 val = FIELD_GET(SPEED_GRADING_MASK, val) & 0xF;
103
104 speed = MHZ(2300) - val * MHZ(100);
105
106 if (is_imx93())
107 max_speed = MHZ(1700);
108
109 /* In case the fuse of speed grade not programmed */
110 if (speed > max_speed)
111 speed = max_speed;
112
113 return speed;
114}
115
116/*
117 * `00` - Consumer 0C to 95C
118 * `01` - Ext. Consumer -20C to 105C
119 * `10` - Industrial -40C to 105C
120 * `11` - Automotive -40C to 125C
121 */
122u32 get_cpu_temp_grade(int *minc, int *maxc)
123{
124 u32 val;
125
126 fuse_read(2, 3, &val);
127 val = FIELD_GET(MARKETING_GRADING_MASK, val);
128
129 if (minc && maxc) {
130 if (val == TEMP_AUTOMOTIVE) {
131 *minc = -40;
132 *maxc = 125;
133 } else if (val == TEMP_INDUSTRIAL) {
134 *minc = -40;
135 *maxc = 105;
136 } else if (val == TEMP_EXTCOMMERCIAL) {
137 if (is_imx93()) {
138 /* imx93 only has extended industrial*/
139 *minc = -40;
140 *maxc = 125;
141 } else {
142 *minc = -20;
143 *maxc = 105;
144 }
145 } else {
146 *minc = 0;
147 *maxc = 95;
148 }
149 }
150 return val;
151}
152
Peng Fan3700c472022-07-26 16:40:56 +0800153static void set_cpu_info(struct sentinel_get_info_data *info)
154{
155 gd->arch.soc_rev = info->soc;
156 gd->arch.lifecycle = info->lc;
157 memcpy((void *)&gd->arch.uid, &info->uid, 4 * sizeof(u32));
158}
159
Peng Fanc3db3ad2023-04-28 12:08:32 +0800160static u32 get_cpu_variant_type(u32 type)
161{
162 /* word 19 */
163 u32 val = readl((ulong)FSB_BASE_ADDR + 0x8000 + (19 << 2));
164 u32 val2 = readl((ulong)FSB_BASE_ADDR + 0x8000 + (20 << 2));
165 bool npu_disable = !!(val & BIT(13));
166 bool core1_disable = !!(val & BIT(15));
167 u32 pack_9x9_fused = BIT(4) | BIT(17) | BIT(19) | BIT(24);
168
169 if ((val2 & pack_9x9_fused) == pack_9x9_fused)
170 type = MXC_CPU_IMX9322;
171
172 if (npu_disable && core1_disable)
173 return type + 3;
174 else if (npu_disable)
175 return type + 2;
176 else if (core1_disable)
177 return type + 1;
178
179 return type;
180}
181
Peng Fanbbcd2c42022-07-26 16:40:39 +0800182u32 get_cpu_rev(void)
183{
Peng Fan3700c472022-07-26 16:40:56 +0800184 u32 rev = (gd->arch.soc_rev >> 24) - 0xa0;
185
Peng Fanc3db3ad2023-04-28 12:08:32 +0800186 return (get_cpu_variant_type(MXC_CPU_IMX93) << 12) |
187 (CHIP_REV_1_0 + rev);
Peng Fanbbcd2c42022-07-26 16:40:39 +0800188}
189
Ye Li9e19ff92022-07-26 16:40:47 +0800190#define UNLOCK_WORD 0xD928C520 /* unlock word */
191#define REFRESH_WORD 0xB480A602 /* refresh word */
192
193static void disable_wdog(void __iomem *wdog_base)
194{
195 u32 val_cs = readl(wdog_base + 0x00);
196
197 if (!(val_cs & 0x80))
198 return;
199
200 /* default is 32bits cmd */
201 writel(REFRESH_WORD, (wdog_base + 0x04)); /* Refresh the CNT */
202
203 if (!(val_cs & 0x800)) {
204 writel(UNLOCK_WORD, (wdog_base + 0x04));
205 while (!(readl(wdog_base + 0x00) & 0x800))
206 ;
207 }
208 writel(0x0, (wdog_base + 0x0C)); /* Set WIN to 0 */
209 writel(0x400, (wdog_base + 0x08)); /* Set timeout to default 0x400 */
210 writel(0x2120, (wdog_base + 0x00)); /* Disable it and set update */
211
212 while (!(readl(wdog_base + 0x00) & 0x400))
213 ;
214}
215
216void init_wdog(void)
217{
218 u32 src_val;
219
220 disable_wdog((void __iomem *)WDG3_BASE_ADDR);
221 disable_wdog((void __iomem *)WDG4_BASE_ADDR);
222 disable_wdog((void __iomem *)WDG5_BASE_ADDR);
223
224 src_val = readl(0x54460018); /* reset mask */
225 src_val &= ~0x1c;
226 writel(src_val, 0x54460018);
227}
228
Peng Fanbbcd2c42022-07-26 16:40:39 +0800229static struct mm_region imx93_mem_map[] = {
230 {
231 /* ROM */
232 .virt = 0x0UL,
233 .phys = 0x0UL,
234 .size = 0x100000UL,
235 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
236 PTE_BLOCK_OUTER_SHARE
237 }, {
Peng Fan313af252022-07-26 16:41:04 +0800238 /* TCM */
239 .virt = 0x201c0000UL,
240 .phys = 0x201c0000UL,
241 .size = 0x80000UL,
242 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
243 PTE_BLOCK_NON_SHARE |
244 PTE_BLOCK_PXN | PTE_BLOCK_UXN
245 }, {
Peng Fanbbcd2c42022-07-26 16:40:39 +0800246 /* OCRAM */
247 .virt = 0x20480000UL,
248 .phys = 0x20480000UL,
249 .size = 0xA0000UL,
250 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
251 PTE_BLOCK_OUTER_SHARE
252 }, {
253 /* AIPS */
254 .virt = 0x40000000UL,
255 .phys = 0x40000000UL,
256 .size = 0x40000000UL,
257 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
258 PTE_BLOCK_NON_SHARE |
259 PTE_BLOCK_PXN | PTE_BLOCK_UXN
260 }, {
261 /* Flexible Serial Peripheral Interface */
262 .virt = 0x28000000UL,
263 .phys = 0x28000000UL,
264 .size = 0x30000000UL,
265 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
266 PTE_BLOCK_NON_SHARE |
267 PTE_BLOCK_PXN | PTE_BLOCK_UXN
268 }, {
269 /* DRAM1 */
270 .virt = 0x80000000UL,
271 .phys = 0x80000000UL,
272 .size = PHYS_SDRAM_SIZE,
273 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
274 PTE_BLOCK_OUTER_SHARE
275 }, {
276 /* empty entrie to split table entry 5 if needed when TEEs are used */
277 0,
278 }, {
279 /* List terminator */
280 0,
281 }
282};
283
284struct mm_region *mem_map = imx93_mem_map;
285
Peng Fan1ed3c0a2023-04-28 12:08:20 +0800286static unsigned int imx9_find_dram_entry_in_mem_map(void)
287{
288 int i;
289
290 for (i = 0; i < ARRAY_SIZE(imx93_mem_map); i++)
291 if (imx93_mem_map[i].phys == CFG_SYS_SDRAM_BASE)
292 return i;
293
294 hang(); /* Entry not found, this must never happen. */
295}
296
297void enable_caches(void)
298{
299 /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch
300 * If OPTEE does not run, still update the MMU table according to dram banks structure
301 * to set correct dram size from board_phys_sdram_size
302 */
303 int i = 0;
304 /*
305 * please make sure that entry initial value matches
306 * imx93_mem_map for DRAM1
307 */
308 int entry = imx9_find_dram_entry_in_mem_map();
309 u64 attrs = imx93_mem_map[entry].attrs;
310
311 while (i < CONFIG_NR_DRAM_BANKS &&
312 entry < ARRAY_SIZE(imx93_mem_map)) {
313 if (gd->bd->bi_dram[i].start == 0)
314 break;
315 imx93_mem_map[entry].phys = gd->bd->bi_dram[i].start;
316 imx93_mem_map[entry].virt = gd->bd->bi_dram[i].start;
317 imx93_mem_map[entry].size = gd->bd->bi_dram[i].size;
318 imx93_mem_map[entry].attrs = attrs;
319 debug("Added memory mapping (%d): %llx %llx\n", entry,
320 imx93_mem_map[entry].phys, imx93_mem_map[entry].size);
321 i++; entry++;
322 }
323
324 icache_enable();
325 dcache_enable();
326}
327
328__weak int board_phys_sdram_size(phys_size_t *size)
329{
330 if (!size)
331 return -EINVAL;
332
333 *size = PHYS_SDRAM_SIZE;
334
335#ifdef PHYS_SDRAM_2_SIZE
336 *size += PHYS_SDRAM_2_SIZE;
337#endif
338 return 0;
339}
340
Peng Fanbbcd2c42022-07-26 16:40:39 +0800341int dram_init(void)
342{
Peng Fan1ed3c0a2023-04-28 12:08:20 +0800343 phys_size_t sdram_size;
344 int ret;
345
346 ret = board_phys_sdram_size(&sdram_size);
347 if (ret)
348 return ret;
349
350 /* rom_pointer[1] contains the size of TEE occupies */
351 if (rom_pointer[1])
352 gd->ram_size = sdram_size - rom_pointer[1];
353 else
354 gd->ram_size = sdram_size;
355
356 return 0;
357}
358
359int dram_init_banksize(void)
360{
361 int bank = 0;
362 int ret;
363 phys_size_t sdram_size;
364 phys_size_t sdram_b1_size, sdram_b2_size;
365
366 ret = board_phys_sdram_size(&sdram_size);
367 if (ret)
368 return ret;
369
370 /* Bank 1 can't cross over 4GB space */
371 if (sdram_size > 0x80000000) {
372 sdram_b1_size = 0x80000000;
373 sdram_b2_size = sdram_size - 0x80000000;
374 } else {
375 sdram_b1_size = sdram_size;
376 sdram_b2_size = 0;
377 }
378
379 gd->bd->bi_dram[bank].start = PHYS_SDRAM;
380 if (rom_pointer[1]) {
381 phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
382 phys_size_t optee_size = (size_t)rom_pointer[1];
383
384 gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
385 if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) {
386 if (++bank >= CONFIG_NR_DRAM_BANKS) {
387 puts("CONFIG_NR_DRAM_BANKS is not enough\n");
388 return -1;
389 }
390
391 gd->bd->bi_dram[bank].start = optee_start + optee_size;
392 gd->bd->bi_dram[bank].size = PHYS_SDRAM +
393 sdram_b1_size - gd->bd->bi_dram[bank].start;
394 }
395 } else {
396 gd->bd->bi_dram[bank].size = sdram_b1_size;
397 }
398
399 if (sdram_b2_size) {
400 if (++bank >= CONFIG_NR_DRAM_BANKS) {
401 puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
402 return -1;
403 }
404 gd->bd->bi_dram[bank].start = 0x100000000UL;
405 gd->bd->bi_dram[bank].size = sdram_b2_size;
406 }
Peng Fanbbcd2c42022-07-26 16:40:39 +0800407
408 return 0;
409}
410
Peng Fan1ed3c0a2023-04-28 12:08:20 +0800411phys_size_t get_effective_memsize(void)
412{
413 int ret;
414 phys_size_t sdram_size;
415 phys_size_t sdram_b1_size;
416
417 ret = board_phys_sdram_size(&sdram_size);
418 if (!ret) {
419 /* Bank 1 can't cross over 4GB space */
420 if (sdram_size > 0x80000000)
421 sdram_b1_size = 0x80000000;
422 else
423 sdram_b1_size = sdram_size;
424
425 if (rom_pointer[1]) {
426 /* We will relocate u-boot to top of dram1. TEE position has two cases:
427 * 1. At the top of dram1, Then return the size removed optee size.
428 * 2. In the middle of dram1, return the size of dram1.
429 */
430 if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size))
431 return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
432 }
433
434 return sdram_b1_size;
435 } else {
436 return PHYS_SDRAM_SIZE;
437 }
438}
439
Peng Fanbbcd2c42022-07-26 16:40:39 +0800440void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
441{
Ye Li66baefb2023-04-28 12:08:21 +0800442 u32 val[2] = {};
443 int ret;
444
445 if (dev_id == 0) {
446 ret = fuse_read(39, 3, &val[0]);
447 if (ret)
448 goto err;
449
450 ret = fuse_read(39, 4, &val[1]);
451 if (ret)
452 goto err;
453
454 mac[0] = val[1] >> 8;
455 mac[1] = val[1];
456 mac[2] = val[0] >> 24;
457 mac[3] = val[0] >> 16;
458 mac[4] = val[0] >> 8;
459 mac[5] = val[0];
460
461 } else {
462 ret = fuse_read(39, 5, &val[0]);
463 if (ret)
464 goto err;
465
466 ret = fuse_read(39, 4, &val[1]);
467 if (ret)
468 goto err;
469
470 mac[0] = val[1] >> 24;
471 mac[1] = val[1] >> 16;
472 mac[2] = val[0] >> 24;
473 mac[3] = val[0] >> 16;
474 mac[4] = val[0] >> 8;
475 mac[5] = val[0];
476 }
477
478 debug("%s: MAC%d: %02x.%02x.%02x.%02x.%02x.%02x\n",
479 __func__, dev_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
480 return;
481err:
482 memset(mac, 0, 6);
483 printf("%s: fuse read err: %d\n", __func__, ret);
Peng Fanbbcd2c42022-07-26 16:40:39 +0800484}
485
486int print_cpuinfo(void)
487{
488 u32 cpurev;
489
490 cpurev = get_cpu_rev();
491
492 printf("CPU: i.MX93 rev%d.%d\n", (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0);
493
494 return 0;
495}
496
Peng Fanbbcd2c42022-07-26 16:40:39 +0800497int ft_system_setup(void *blob, struct bd_info *bd)
498{
499 return 0;
500}
Peng Fan3700c472022-07-26 16:40:56 +0800501
502#if defined(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)
503void get_board_serial(struct tag_serialnr *serialnr)
504{
505 printf("UID: 0x%x 0x%x 0x%x 0x%x\n",
506 gd->arch.uid[0], gd->arch.uid[1], gd->arch.uid[2], gd->arch.uid[3]);
507
508 serialnr->low = gd->arch.uid[0];
509 serialnr->high = gd->arch.uid[3];
510}
511#endif
Peng Fanbbcd2c42022-07-26 16:40:39 +0800512
Peng Fanb1815c42023-04-28 12:08:27 +0800513static void save_reset_cause(void)
514{
515 struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE;
516 u32 srsr = readl(&src->srsr);
517
518 /* clear srsr in sec mode */
519 writel(srsr, &src->srsr);
520
521 /* Save value to GPR1 to pass to nonsecure */
522 writel(srsr, &src->gpr[0]);
523}
524
Peng Fanbbcd2c42022-07-26 16:40:39 +0800525int arch_cpu_init(void)
526{
Ye Li9e19ff92022-07-26 16:40:47 +0800527 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
528 /* Disable wdog */
529 init_wdog();
530
Peng Fan28b5cb52022-07-26 16:40:43 +0800531 clock_init();
Ye Li62185922022-07-26 16:40:54 +0800532
533 trdc_early_init();
Peng Fanb1815c42023-04-28 12:08:27 +0800534
535 /* Save SRC SRSR to GPR1 and clear it */
536 save_reset_cause();
Ye Li9e19ff92022-07-26 16:40:47 +0800537 }
Peng Fan28b5cb52022-07-26 16:40:43 +0800538
Peng Fanbbcd2c42022-07-26 16:40:39 +0800539 return 0;
540}
Peng Fan3700c472022-07-26 16:40:56 +0800541
542int imx9_probe_mu(void *ctx, struct event *event)
543{
544 struct udevice *devp;
545 int node, ret;
546 u32 res;
547 struct sentinel_get_info_data info;
548
549 node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx93-mu-s4");
550
551 ret = uclass_get_device_by_of_offset(UCLASS_MISC, node, &devp);
552 if (ret)
553 return ret;
554
555 if (gd->flags & GD_FLG_RELOC)
556 return 0;
557
558 ret = ahab_get_info(&info, &res);
559 if (ret)
560 return ret;
561
562 set_cpu_info(&info);
563
564 return 0;
565}
Simon Glass93074012023-05-04 16:50:45 -0600566EVENT_SPY(EVT_DM_POST_INIT_F, imx9_probe_mu);
Jian Liacf41a32022-07-26 16:40:46 +0800567
568int timer_init(void)
569{
570#ifdef CONFIG_SPL_BUILD
571 struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR;
572 unsigned long freq = readl(&sctr->cntfid0);
573
574 /* Update with accurate clock frequency */
575 asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory");
576
577 clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1,
578 SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG);
579#endif
580
581 gd->arch.tbl = 0;
582 gd->arch.tbu = 0;
583
584 return 0;
585}
Peng Fan65563792022-07-26 16:41:02 +0800586
Ye Li8e8687c2022-07-26 16:41:05 +0800587enum env_location env_get_location(enum env_operation op, int prio)
588{
589 enum boot_device dev = get_boot_device();
590 enum env_location env_loc = ENVL_UNKNOWN;
591
592 if (prio)
593 return env_loc;
594
595 switch (dev) {
596#if defined(CONFIG_ENV_IS_IN_SPI_FLASH)
597 case QSPI_BOOT:
598 env_loc = ENVL_SPI_FLASH;
599 break;
600#endif
601#if defined(CONFIG_ENV_IS_IN_MMC)
602 case SD1_BOOT:
603 case SD2_BOOT:
604 case SD3_BOOT:
605 case MMC1_BOOT:
606 case MMC2_BOOT:
607 case MMC3_BOOT:
608 env_loc = ENVL_MMC;
609 break;
610#endif
611 default:
612#if defined(CONFIG_ENV_IS_NOWHERE)
613 env_loc = ENVL_NOWHERE;
614#endif
615 break;
616 }
617
618 return env_loc;
619}
620
Peng Fan65563792022-07-26 16:41:02 +0800621static int mix_power_init(enum mix_power_domain pd)
622{
623 enum src_mix_slice_id mix_id;
624 enum src_mem_slice_id mem_id;
625 struct src_mix_slice_regs *mix_regs;
626 struct src_mem_slice_regs *mem_regs;
627 struct src_general_regs *global_regs;
628 u32 scr, val;
629
630 switch (pd) {
631 case MIX_PD_MEDIAMIX:
632 mix_id = SRC_MIX_MEDIA;
633 mem_id = SRC_MEM_MEDIA;
634 scr = BIT(5);
635
636 /* Enable S400 handshake */
637 struct blk_ctrl_s_aonmix_regs *s_regs =
638 (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR;
639
640 setbits_le32(&s_regs->lp_handshake[0], BIT(13));
641 break;
642 case MIX_PD_MLMIX:
643 mix_id = SRC_MIX_ML;
644 mem_id = SRC_MEM_ML;
645 scr = BIT(4);
646 break;
647 case MIX_PD_DDRMIX:
648 mix_id = SRC_MIX_DDRMIX;
649 mem_id = SRC_MEM_DDRMIX;
650 scr = BIT(6);
651 break;
652 default:
653 return -EINVAL;
654 }
655
656 mix_regs = (struct src_mix_slice_regs *)(ulong)(SRC_IPS_BASE_ADDR + 0x400 * (mix_id + 1));
657 mem_regs =
658 (struct src_mem_slice_regs *)(ulong)(SRC_IPS_BASE_ADDR + 0x3800 + 0x400 * mem_id);
659 global_regs = (struct src_general_regs *)(ulong)SRC_GLOBAL_RBASE;
660
661 /* Allow NS to set it */
662 setbits_le32(&mix_regs->authen_ctrl, BIT(9));
663
664 clrsetbits_le32(&mix_regs->psw_ack_ctrl[0], BIT(28), BIT(29));
665
666 /* mix reset will be held until boot core write this bit to 1 */
667 setbits_le32(&global_regs->scr, scr);
668
669 /* Enable mem in Low power auto sequence */
670 setbits_le32(&mem_regs->mem_ctrl, BIT(2));
671
672 /* Set the power down state */
673 val = readl(&mix_regs->func_stat);
674 if (val & SRC_MIX_SLICE_FUNC_STAT_PSW_STAT) {
675 /* The mix is default power off, power down it to make PDN_SFT bit
676 * aligned with FUNC STAT
677 */
678 setbits_le32(&mix_regs->slice_sw_ctrl, BIT(31));
679 val = readl(&mix_regs->func_stat);
680
681 /* Since PSW_STAT is 1, can't be used for power off status (SW_CTRL BIT31 set)) */
682 /* Check the MEM STAT change to ensure SSAR is completed */
683 while (!(val & SRC_MIX_SLICE_FUNC_STAT_MEM_STAT))
684 val = readl(&mix_regs->func_stat);
685
686 /* wait few ipg clock cycles to ensure FSM done and power off status is correct */
687 /* About 5 cycles at 24Mhz, 1us is enough */
688 udelay(1);
689 } else {
690 /* The mix is default power on, Do mix power cycle */
691 setbits_le32(&mix_regs->slice_sw_ctrl, BIT(31));
692 val = readl(&mix_regs->func_stat);
693 while (!(val & SRC_MIX_SLICE_FUNC_STAT_PSW_STAT))
694 val = readl(&mix_regs->func_stat);
695 }
696
697 /* power on */
698 clrbits_le32(&mix_regs->slice_sw_ctrl, BIT(31));
699 val = readl(&mix_regs->func_stat);
700 while (val & SRC_MIX_SLICE_FUNC_STAT_ISO_STAT)
701 val = readl(&mix_regs->func_stat);
702
703 return 0;
704}
705
706void disable_isolation(void)
707{
708 struct src_general_regs *global_regs = (struct src_general_regs *)(ulong)SRC_GLOBAL_RBASE;
709 /* clear isolation for usbphy, dsi, csi*/
710 writel(0x0, &global_regs->sp_iso_ctrl);
711}
712
713void soc_power_init(void)
714{
715 mix_power_init(MIX_PD_MEDIAMIX);
716 mix_power_init(MIX_PD_MLMIX);
717
718 disable_isolation();
719}
Peng Fan6d929962022-07-26 16:41:03 +0800720
Peng Fan313af252022-07-26 16:41:04 +0800721bool m33_is_rom_kicked(void)
Peng Fan6d929962022-07-26 16:41:03 +0800722{
723 struct blk_ctrl_s_aonmix_regs *s_regs =
724 (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR;
725
726 if (!(readl(&s_regs->m33_cfg) & BIT(2)))
727 return true;
728
729 return false;
730}
731
732int m33_prepare(void)
733{
734 struct src_mix_slice_regs *mix_regs =
735 (struct src_mix_slice_regs *)(ulong)(SRC_IPS_BASE_ADDR + 0x400 * (SRC_MIX_CM33 + 1));
736 struct src_general_regs *global_regs =
737 (struct src_general_regs *)(ulong)SRC_GLOBAL_RBASE;
738 struct blk_ctrl_s_aonmix_regs *s_regs =
739 (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR;
740 u32 val;
741
742 if (m33_is_rom_kicked())
743 return -EPERM;
744
745 /* Release reset of M33 */
746 setbits_le32(&global_regs->scr, BIT(0));
747
748 /* Check the reset released in M33 MIX func stat */
749 val = readl(&mix_regs->func_stat);
750 while (!(val & SRC_MIX_SLICE_FUNC_STAT_RST_STAT))
751 val = readl(&mix_regs->func_stat);
752
753 /* Release Sentinel TROUT */
754 ahab_release_m33_trout();
755
756 /* Mask WDOG1 IRQ from A55, we use it for M33 reset */
757 setbits_le32(&s_regs->ca55_irq_mask[1], BIT(6));
758
759 /* Turn on WDOG1 clock */
760 ccm_lpcg_on(CCGR_WDG1, 1);
761
762 /* Set sentinel LP handshake for M33 reset */
763 setbits_le32(&s_regs->lp_handshake[0], BIT(6));
764
765 /* Clear M33 TCM for ECC */
766 memset((void *)(ulong)0x201e0000, 0, 0x40000);
767
768 return 0;
769}
Peng Fanb1815c42023-04-28 12:08:27 +0800770
771int psci_sysreset_get_status(struct udevice *dev, char *buf, int size)
772{
773 static const char *reset_cause[] = {
774 "POR ",
775 "JTAG ",
776 "IPP USER ",
777 "WDOG1 ",
778 "WDOG2 ",
779 "WDOG3 ",
780 "WDOG4 ",
781 "WDOG5 ",
782 "TEMPSENSE ",
783 "CSU ",
784 "JTAG_SW ",
785 "M33_REQ ",
786 "M33_LOCKUP ",
787 "UNK ",
788 "UNK ",
789 "UNK "
790 };
791
792 struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE;
793 u32 srsr;
794 u32 i;
795 int res;
796
797 srsr = readl(&src->gpr[0]);
798
799 for (i = ARRAY_SIZE(reset_cause); i > 0; i--) {
800 if (srsr & (BIT(i - 1)))
801 break;
802 }
803
804 res = snprintf(buf, size, "Reset Status: %s\n", i ? reset_cause[i - 1] : "unknown reset");
805 if (res < 0) {
806 dev_err(dev, "Could not write reset status message (err = %d)\n", res);
807 return -EIO;
808 }
809
810 return 0;
811}