xref: /rk3399_ARM-atf/plat/ti/k3low/common/am62l_bl1_setup.c (revision 2af4468b1642822d17f6df91b1fc466bb4a84051)
1 /*
2  * Copyright (c) 2025-2026, Texas Instruments Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch.h>
8 #include <arch_helpers.h>
9 #include <common/bl_common.h>
10 #include <common/debug.h>
11 #include <errno.h>
12 #include <lib/mmio.h>
13 #include <lib/xlat_tables/xlat_tables_v2.h>
14 #include <ti_sci_transport.h>
15 
16 #include <am62l_ddrss.h>
17 #include <board_config.h>
18 #include <cps_drv_lpddr4.h>
19 #include <k3_console.h>
20 #include <plat_private.h>
21 #include <platform_def.h>
22 #include <plat/common/platform.h>
23 
24 #define WKUP_BOOT_MODE (0x43010030)
25 #define MAIN_PLL_MMR_BASE (0x04060000UL)
26 /*
27  * PLL8 is distinct from PLL0 (which drives DDR at 2 GHz VCO).
28  * PLL8 drives the A53 cores and has a VCO frequency of 2.5 GHz.
29  * HSDIV0 of PLL8 feeds the A53 cluster.
30  */
31 #define MAIN_PLL_MMR_CFG_PLL8_HSDIV_CTRL0 (0x00008080UL)
32 /* bit 15: enable HSDIV0 clock output */
33 #define MAIN_PLL8_HSDIV0_CLKOUT_EN GENMASK(15, 15)
34 /* bits [6:0]: divider value; output = VCO_FREQ / (div + 1) */
35 #define MAIN_PLL8_HSDIV0_DIV_MASK  GENMASK(6, 0)
36 /* div=1 → 2.5 GHz / 2 = 1.25 GHz */
37 #define MAIN_PLL8_HSDIV0_1250MHZ   (MAIN_PLL8_HSDIV0_CLKOUT_EN | U(1))
38 /* div=2 → 2.5 GHz / 3 = 833.33 MHz */
39 #define MAIN_PLL8_HSDIV0_833MHZ    (MAIN_PLL8_HSDIV0_CLKOUT_EN | U(2))
40 #define BL1_DONE_MSG_ID (0x810A)
41 #define BL1_HANDOFF_MAGIC_NUM (0x11112222)
42 #define BL1_MSG_SIZE_FLAG (0x0c000000)
43 
44 #define DEVSTAT_PRIMARY_BOOTMODE_MASK GENMASK(6, 3)
45 #define DEVSTAT_PRIMARY_BOOTMODE_SHIFT (3)
46 #define BOOT_DEVICE_MMC (0x08)
47 #define WKUP_JTAG_DEVICE_ID (WKUP_CTRL_MMR0_BASE + 0x18)
48 #define JTAG_DEV_SPEED_MASK GENMASK(10, 6)
49 #define JTAG_DEV_SPEED_SHIFT (6)
50 
51 #define AM62L3_EFUSE_E_MPU_OPP 5
52 #define AM62L3_EFUSE_O_MPU_OPP 15
53 
54 const mmap_region_t plat_k3_mmap[] = {
55 	K3_MAP_REGION_FLAT(0,	PLAT_PHY_ADDR_SPACE_SIZE,	MT_DEVICE | MT_RW | MT_SECURE),
56 	{ /* sentinel */ }
57 };
58 
59 /**
60  * Handoff message for 2nd stage boot
61  *
62  * @cmdid:	The command ID
63  * @hostid:	Identifies the queue number used for replies to a received message
64  * @sizeandflags:	Flags in LSB 3 bytes and the MSB byte set to size.
65  * @magicnum:	Magic number for payload validation.
66  * @rsvd:	Reserved word.
67  * @imageoffset:	Image offset for block/image mode.
68  * @filename:	File name for filesystem mode.
69  */
70 struct a53_rom_msg {
71 	uint16_t cmdid;
72 	uint8_t  hostid;
73 	uint8_t  seqnum;
74 	uint32_t sizeandflags;
75 	uint32_t magicnum;
76 	uint32_t rsvd;
77 	union {
78 		uint32_t imageoffset[4];
79 		char  filename[32];
80 	} imagelocator;
81 } __packed;
82 
bl1_plat_sec_mem_layout(void)83 meminfo_t *bl1_plat_sec_mem_layout(void)
84 {
85 	/*
86 	 * AM62L BL1 never loads BL2: after DDR init it signals the ROM via
87 	 * the secure transport and enters WFI (see k3_bl1_handoff / bl1_platform_setup).
88 	 * Returning NULL is intentional — the BL2 load path is never reached.
89 	 */
90 	return NULL;
91 }
92 
bl1_early_platform_setup(void)93 void bl1_early_platform_setup(void)
94 {
95 	uint32_t device_id;
96 	uint32_t speed_grade;
97 
98 #if DEBUG
99 	ERROR("AM62L k3low BL1: DEBUG builds are not supported on this platform!\n");
100 	panic();
101 #endif
102 
103 	board_init();
104 	/* Read OPN and set the A53 clock rate */
105 	device_id = mmio_read_32(WKUP_JTAG_DEVICE_ID);
106 	speed_grade = (device_id & JTAG_DEV_SPEED_MASK) >>
107 			JTAG_DEV_SPEED_SHIFT;
108 	if (speed_grade == AM62L3_EFUSE_O_MPU_OPP) {
109 		/* PLL8_HSDIV0 feeds A53, set to 1.25 GHz (PLL8 VCO = 2.5 GHz) */
110 		mmio_write_32(MAIN_PLL_MMR_BASE + MAIN_PLL_MMR_CFG_PLL8_HSDIV_CTRL0,
111 			      MAIN_PLL8_HSDIV0_1250MHZ);
112 	} else {
113 		/* PLL8_HSDIV0 feeds A53, set to 833.33 MHz (PLL8 VCO = 2.5 GHz) */
114 		mmio_write_32(MAIN_PLL_MMR_BASE + MAIN_PLL_MMR_CFG_PLL8_HSDIV_CTRL0,
115 			      MAIN_PLL8_HSDIV0_833MHZ);
116 	}
117 }
118 
bl1_plat_arch_setup(void)119 void bl1_plat_arch_setup(void)
120 {
121 	INFO("K3 BL1 arch setup\n");
122 
123 	const mmap_region_t bl_regions[] = {
124 		MAP_REGION_FLAT(BL1_RO_BASE,
125 				BL_RO_DATA_BASE - BL1_RO_BASE,
126 				MT_CODE | MT_SECURE),
127 		MAP_REGION_FLAT(BL_RO_DATA_BASE,
128 				BL1_RW_BASE - BL_RO_DATA_BASE,
129 				MT_MEMORY | MT_RO | MT_SECURE),
130 		MAP_REGION_FLAT(BL1_RW_BASE,
131 				BL1_RW_LIMIT - BL1_RW_BASE,
132 				MT_MEMORY | MT_RW | MT_SECURE),
133 		{ /* sentinel */ }
134 	};
135 
136 	setup_page_tables(bl_regions, plat_k3_mmap);
137 	enable_mmu_el3(0);
138 }
139 
k3_bl1_handoff(void)140 static void __dead2 k3_bl1_handoff(void)
141 {
142 	struct a53_rom_msg a53_rom_msg_obj = { 0 };
143 	struct ti_sci_msg msg;
144 	volatile uint32_t devstat;
145 	uint32_t boot_mode;
146 
147 	a53_rom_msg_obj.cmdid = BL1_DONE_MSG_ID;
148 	a53_rom_msg_obj.sizeandflags = BL1_MSG_SIZE_FLAG;
149 	a53_rom_msg_obj.magicnum = BL1_HANDOFF_MAGIC_NUM;
150 
151 	devstat = mmio_read_32(WKUP_BOOT_MODE);
152 	boot_mode = (devstat & DEVSTAT_PRIMARY_BOOTMODE_MASK) >>
153 			DEVSTAT_PRIMARY_BOOTMODE_SHIFT;
154 
155 	switch (boot_mode) {
156 	case BOOT_DEVICE_MMC:
157 		/*
158 		 * snprintf writes into a char[] member of a __packed struct.
159 		 * The pointer is naturally byte-aligned so the access is safe,
160 		 * but GCC still warns about address-of-packed-member.
161 		 */
162 #pragma GCC diagnostic push
163 #pragma GCC diagnostic ignored "-Waddress-of-packed-member"
164 		snprintf(a53_rom_msg_obj.imagelocator.filename,
165 			 sizeof(a53_rom_msg_obj.imagelocator.filename),
166 			 "%s%s", "\\", "tispl.bin");
167 #pragma GCC diagnostic pop
168 		break;
169 	default:
170 		a53_rom_msg_obj.imagelocator.imageoffset[0] = K3_SPL_IMG_OFFSET;
171 		break;
172 	}
173 
174 	msg.buf = (uint8_t *)&a53_rom_msg_obj;
175 	msg.len = sizeof(a53_rom_msg_obj);
176 	ti_sci_transport_send(TX_SECURE_TRANSPORT_CHANNEL_ID, &msg);
177 	NOTICE("ENTERING WFI - end of bl1\n");
178 	console_flush();
179 	while (true)
180 		wfi();
181 }
182 
bl1_platform_setup(void)183 void bl1_platform_setup(void)
184 {
185 	/*
186 	 * AM62L uses a non-standard BL1 flow: instead of loading BL2, BL1
187 	 * initialises DDR, then calls k3_bl1_handoff() which sends a message
188 	 * to the ROM over the secure transport and enters WFI. This function
189 	 * therefore never returns; the BL2 load path in the generic BL1 code
190 	 * is dead for this platform.
191 	 */
192 	if (am62l_lpddr4_init() != 0) {
193 		ERROR("DDR init failed\n");
194 		panic();
195 	} else {
196 		NOTICE("DDR init done\n");
197 		k3_bl1_handoff();
198 	}
199 }
200 
platform_mem_init(void)201 void platform_mem_init(void)
202 {
203 }
204 
plat_get_image_source(unsigned int image_id,uintptr_t * dev_handle,uintptr_t * image_spec)205 int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
206 			  uintptr_t *image_spec)
207 {
208 	return -ENOTSUP;
209 }
210