blob: 64e8ac610e5e8a00784048e27fc031bbcbe159f3 [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>
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 Fan3700c472022-07-26 16:40:56 +0800154static void set_cpu_info(struct sentinel_get_info_data *info)
155{
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
555int imx9_probe_mu(void *ctx, struct event *event)
556{
557 struct udevice *devp;
558 int node, ret;
559 u32 res;
560 struct sentinel_get_info_data info;
561
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
571 ret = ahab_get_info(&info, &res);
572 if (ret)
573 return ret;
574
575 set_cpu_info(&info);
576
577 return 0;
578}
Simon Glass93074012023-05-04 16:50:45 -0600579EVENT_SPY(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();
603 enum env_location env_loc = ENVL_UNKNOWN;
604
605 if (prio)
606 return env_loc;
607
608 switch (dev) {
609#if defined(CONFIG_ENV_IS_IN_SPI_FLASH)
610 case QSPI_BOOT:
611 env_loc = ENVL_SPI_FLASH;
612 break;
613#endif
614#if defined(CONFIG_ENV_IS_IN_MMC)
615 case SD1_BOOT:
616 case SD2_BOOT:
617 case SD3_BOOT:
618 case MMC1_BOOT:
619 case MMC2_BOOT:
620 case MMC3_BOOT:
621 env_loc = ENVL_MMC;
622 break;
623#endif
624 default:
625#if defined(CONFIG_ENV_IS_NOWHERE)
626 env_loc = ENVL_NOWHERE;
627#endif
628 break;
629 }
630
631 return env_loc;
632}
633
Peng Fan65563792022-07-26 16:41:02 +0800634static int mix_power_init(enum mix_power_domain pd)
635{
636 enum src_mix_slice_id mix_id;
637 enum src_mem_slice_id mem_id;
638 struct src_mix_slice_regs *mix_regs;
639 struct src_mem_slice_regs *mem_regs;
640 struct src_general_regs *global_regs;
641 u32 scr, val;
642
643 switch (pd) {
644 case MIX_PD_MEDIAMIX:
645 mix_id = SRC_MIX_MEDIA;
646 mem_id = SRC_MEM_MEDIA;
647 scr = BIT(5);
648
649 /* Enable S400 handshake */
650 struct blk_ctrl_s_aonmix_regs *s_regs =
651 (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR;
652
653 setbits_le32(&s_regs->lp_handshake[0], BIT(13));
654 break;
655 case MIX_PD_MLMIX:
656 mix_id = SRC_MIX_ML;
657 mem_id = SRC_MEM_ML;
658 scr = BIT(4);
659 break;
660 case MIX_PD_DDRMIX:
661 mix_id = SRC_MIX_DDRMIX;
662 mem_id = SRC_MEM_DDRMIX;
663 scr = BIT(6);
664 break;
665 default:
666 return -EINVAL;
667 }
668
669 mix_regs = (struct src_mix_slice_regs *)(ulong)(SRC_IPS_BASE_ADDR + 0x400 * (mix_id + 1));
670 mem_regs =
671 (struct src_mem_slice_regs *)(ulong)(SRC_IPS_BASE_ADDR + 0x3800 + 0x400 * mem_id);
672 global_regs = (struct src_general_regs *)(ulong)SRC_GLOBAL_RBASE;
673
674 /* Allow NS to set it */
675 setbits_le32(&mix_regs->authen_ctrl, BIT(9));
676
677 clrsetbits_le32(&mix_regs->psw_ack_ctrl[0], BIT(28), BIT(29));
678
679 /* mix reset will be held until boot core write this bit to 1 */
680 setbits_le32(&global_regs->scr, scr);
681
682 /* Enable mem in Low power auto sequence */
683 setbits_le32(&mem_regs->mem_ctrl, BIT(2));
684
685 /* Set the power down state */
686 val = readl(&mix_regs->func_stat);
687 if (val & SRC_MIX_SLICE_FUNC_STAT_PSW_STAT) {
688 /* The mix is default power off, power down it to make PDN_SFT bit
689 * aligned with FUNC STAT
690 */
691 setbits_le32(&mix_regs->slice_sw_ctrl, BIT(31));
692 val = readl(&mix_regs->func_stat);
693
694 /* Since PSW_STAT is 1, can't be used for power off status (SW_CTRL BIT31 set)) */
695 /* Check the MEM STAT change to ensure SSAR is completed */
696 while (!(val & SRC_MIX_SLICE_FUNC_STAT_MEM_STAT))
697 val = readl(&mix_regs->func_stat);
698
699 /* wait few ipg clock cycles to ensure FSM done and power off status is correct */
700 /* About 5 cycles at 24Mhz, 1us is enough */
701 udelay(1);
702 } else {
703 /* The mix is default power on, Do mix power cycle */
704 setbits_le32(&mix_regs->slice_sw_ctrl, BIT(31));
705 val = readl(&mix_regs->func_stat);
706 while (!(val & SRC_MIX_SLICE_FUNC_STAT_PSW_STAT))
707 val = readl(&mix_regs->func_stat);
708 }
709
710 /* power on */
711 clrbits_le32(&mix_regs->slice_sw_ctrl, BIT(31));
712 val = readl(&mix_regs->func_stat);
713 while (val & SRC_MIX_SLICE_FUNC_STAT_ISO_STAT)
714 val = readl(&mix_regs->func_stat);
715
716 return 0;
717}
718
719void disable_isolation(void)
720{
721 struct src_general_regs *global_regs = (struct src_general_regs *)(ulong)SRC_GLOBAL_RBASE;
722 /* clear isolation for usbphy, dsi, csi*/
723 writel(0x0, &global_regs->sp_iso_ctrl);
724}
725
726void soc_power_init(void)
727{
728 mix_power_init(MIX_PD_MEDIAMIX);
729 mix_power_init(MIX_PD_MLMIX);
730
731 disable_isolation();
732}
Peng Fan6d929962022-07-26 16:41:03 +0800733
Peng Fan313af252022-07-26 16:41:04 +0800734bool m33_is_rom_kicked(void)
Peng Fan6d929962022-07-26 16:41:03 +0800735{
736 struct blk_ctrl_s_aonmix_regs *s_regs =
737 (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR;
738
739 if (!(readl(&s_regs->m33_cfg) & BIT(2)))
740 return true;
741
742 return false;
743}
744
745int m33_prepare(void)
746{
747 struct src_mix_slice_regs *mix_regs =
748 (struct src_mix_slice_regs *)(ulong)(SRC_IPS_BASE_ADDR + 0x400 * (SRC_MIX_CM33 + 1));
749 struct src_general_regs *global_regs =
750 (struct src_general_regs *)(ulong)SRC_GLOBAL_RBASE;
751 struct blk_ctrl_s_aonmix_regs *s_regs =
752 (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR;
753 u32 val;
754
755 if (m33_is_rom_kicked())
756 return -EPERM;
757
758 /* Release reset of M33 */
759 setbits_le32(&global_regs->scr, BIT(0));
760
761 /* Check the reset released in M33 MIX func stat */
762 val = readl(&mix_regs->func_stat);
763 while (!(val & SRC_MIX_SLICE_FUNC_STAT_RST_STAT))
764 val = readl(&mix_regs->func_stat);
765
766 /* Release Sentinel TROUT */
767 ahab_release_m33_trout();
768
769 /* Mask WDOG1 IRQ from A55, we use it for M33 reset */
770 setbits_le32(&s_regs->ca55_irq_mask[1], BIT(6));
771
772 /* Turn on WDOG1 clock */
773 ccm_lpcg_on(CCGR_WDG1, 1);
774
775 /* Set sentinel LP handshake for M33 reset */
776 setbits_le32(&s_regs->lp_handshake[0], BIT(6));
777
778 /* Clear M33 TCM for ECC */
779 memset((void *)(ulong)0x201e0000, 0, 0x40000);
780
781 return 0;
782}
Peng Fanb1815c42023-04-28 12:08:27 +0800783
784int psci_sysreset_get_status(struct udevice *dev, char *buf, int size)
785{
786 static const char *reset_cause[] = {
787 "POR ",
788 "JTAG ",
789 "IPP USER ",
790 "WDOG1 ",
791 "WDOG2 ",
792 "WDOG3 ",
793 "WDOG4 ",
794 "WDOG5 ",
795 "TEMPSENSE ",
796 "CSU ",
797 "JTAG_SW ",
798 "M33_REQ ",
799 "M33_LOCKUP ",
800 "UNK ",
801 "UNK ",
802 "UNK "
803 };
804
805 struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE;
806 u32 srsr;
807 u32 i;
808 int res;
809
810 srsr = readl(&src->gpr[0]);
811
812 for (i = ARRAY_SIZE(reset_cause); i > 0; i--) {
813 if (srsr & (BIT(i - 1)))
814 break;
815 }
816
817 res = snprintf(buf, size, "Reset Status: %s\n", i ? reset_cause[i - 1] : "unknown reset");
818 if (res < 0) {
819 dev_err(dev, "Could not write reset status message (err = %d)\n", res);
820 return -EIO;
821 }
822
823 return 0;
824}