xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/param.c (revision 7a00e4e5d962e31e7760ae847627a6bc9bcd1ab0)
1dbf8423eSJoseph Chen // SPDX-License-Identifier: GPL-2.0
2dbf8423eSJoseph Chen /*
3dbf8423eSJoseph Chen  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4dbf8423eSJoseph Chen  */
5dbf8423eSJoseph Chen 
6dbf8423eSJoseph Chen #include <common.h>
76e15146eSJoseph Chen #include <dm.h>
86e15146eSJoseph Chen #include <ram.h>
9dbf8423eSJoseph Chen #include <asm/io.h>
10dbf8423eSJoseph Chen #include <asm/arch/rk_atags.h>
11dbf8423eSJoseph Chen #include <asm/arch/param.h>
12dbf8423eSJoseph Chen 
13dbf8423eSJoseph Chen DECLARE_GLOBAL_DATA_PTR;
14dbf8423eSJoseph Chen 
150453d738SJoseph Chen #define SZ_4GB				0x100000000ULL
160453d738SJoseph Chen 
17*7a00e4e5SJoseph Chen #ifndef CONFIG_SPL_BUILD
18dbf8423eSJoseph Chen #define SDRAM_OFFSET(offset)		(CONFIG_SYS_SDRAM_BASE + (offset))
19dbf8423eSJoseph Chen #define PARAM_DRAM_INFO_OFFSET		(SZ_32M)
20dbf8423eSJoseph Chen #define PARAM_OPTEE_INFO_OFFSET		(SZ_32M + SZ_2M)
21dbf8423eSJoseph Chen 
22dbf8423eSJoseph Chen struct tos_param_t {
23dbf8423eSJoseph Chen 	u32 version;
24dbf8423eSJoseph Chen 	u32 checksum;
25dbf8423eSJoseph Chen 	struct {
26dbf8423eSJoseph Chen 		char name[8];
27dbf8423eSJoseph Chen 		s64 phy_addr;
28dbf8423eSJoseph Chen 		u32 size;
29dbf8423eSJoseph Chen 		u32 flags;
30dbf8423eSJoseph Chen 	} tee_mem;
31dbf8423eSJoseph Chen 	struct {
32dbf8423eSJoseph Chen 		char name[8];
33dbf8423eSJoseph Chen 		s64 phy_addr;
34dbf8423eSJoseph Chen 		u32 size;
35dbf8423eSJoseph Chen 		u32 flags;
36dbf8423eSJoseph Chen 	} drm_mem;
37dbf8423eSJoseph Chen 	s64 reserve[8];
38dbf8423eSJoseph Chen };
39dbf8423eSJoseph Chen 
40dbf8423eSJoseph Chen static uint16_t trust_checksum(const uint8_t *buf, uint16_t len)
41dbf8423eSJoseph Chen {
42dbf8423eSJoseph Chen 	uint16_t i, checksum = 0;
43dbf8423eSJoseph Chen 
44dbf8423eSJoseph Chen 	for (i = 0; i < len; i++) {
45dbf8423eSJoseph Chen 		if (i % 2)
46dbf8423eSJoseph Chen 			checksum += buf[i] << 8;
47dbf8423eSJoseph Chen 		else
48dbf8423eSJoseph Chen 			checksum += buf[i];
49dbf8423eSJoseph Chen 	}
50dbf8423eSJoseph Chen 	checksum = ~checksum;
51dbf8423eSJoseph Chen 
52dbf8423eSJoseph Chen 	return checksum;
53dbf8423eSJoseph Chen }
54dbf8423eSJoseph Chen 
556e15146eSJoseph Chen struct memblock param_parse_atf_mem(void)
56dbf8423eSJoseph Chen {
576e15146eSJoseph Chen 	struct memblock mem;
58dbf8423eSJoseph Chen 
596e15146eSJoseph Chen 	mem.base = 0;
606e15146eSJoseph Chen 	mem.size = 0;
61dbf8423eSJoseph Chen 
62dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
63dbf8423eSJoseph Chen 	struct tag *t = NULL;
64dbf8423eSJoseph Chen 
65dbf8423eSJoseph Chen 	/*
66dbf8423eSJoseph Chen 	 * Get memory region of ATF
67dbf8423eSJoseph Chen 	 *
68dbf8423eSJoseph Chen 	 * 1. New way: atags info;
69dbf8423eSJoseph Chen 	 * 2. Leagcy way: 2MB size and start from ddr 0x0 offset;
70dbf8423eSJoseph Chen 	 */
71dbf8423eSJoseph Chen 	t = atags_get_tag(ATAG_ATF_MEM);
72dbf8423eSJoseph Chen 	if (t && t->u.atf_mem.size) {
736e15146eSJoseph Chen 		mem.base = t->u.atf_mem.phy_addr;
746e15146eSJoseph Chen 		mem.size = t->u.atf_mem.size;
75dbf8423eSJoseph Chen 		/* Sanity */
766e15146eSJoseph Chen 		if (mem.base + mem.size > SDRAM_OFFSET(SZ_1M)) {
77dbf8423eSJoseph Chen 			printf("%s: ATF reserved region is not within 0-1MB "
78dbf8423eSJoseph Chen 			       "offset(0x%08llx-0x%08llx)!\n",
796e15146eSJoseph Chen 			       __func__, (u64)mem.base, (u64)mem.base + mem.size);
806e15146eSJoseph Chen 			return mem;
81dbf8423eSJoseph Chen 		}
82dbf8423eSJoseph Chen 	}
83dbf8423eSJoseph Chen #endif
84dbf8423eSJoseph Chen 
85dbf8423eSJoseph Chen 	/* Legacy */
866e15146eSJoseph Chen 	if (!mem.size) {
87dbf8423eSJoseph Chen 		if (IS_ENABLED(CONFIG_ARM64) ||
88dbf8423eSJoseph Chen 		    IS_ENABLED(CONFIG_ARM64_BOOT_AARCH32)) {
896e15146eSJoseph Chen 			mem.base = SDRAM_OFFSET(0);
906e15146eSJoseph Chen 			mem.size = SZ_1M;
91dbf8423eSJoseph Chen 		}
92dbf8423eSJoseph Chen 	}
93dbf8423eSJoseph Chen 
946e15146eSJoseph Chen 	debug("ATF: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size);
95dbf8423eSJoseph Chen 
966e15146eSJoseph Chen 	return mem;
97dbf8423eSJoseph Chen }
98dbf8423eSJoseph Chen 
996e15146eSJoseph Chen struct memblock param_parse_optee_mem(void)
100dbf8423eSJoseph Chen {
101dbf8423eSJoseph Chen 	struct tos_param_t *tos_parameter;
1026e15146eSJoseph Chen 	struct memblock mem;
103dbf8423eSJoseph Chen 	u32 checksum;
104dbf8423eSJoseph Chen 
1056e15146eSJoseph Chen 	mem.base = 0;
1066e15146eSJoseph Chen 	mem.size = 0;
107dbf8423eSJoseph Chen 
108dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
109dbf8423eSJoseph Chen 	struct tag *t = NULL;
110dbf8423eSJoseph Chen 
111dbf8423eSJoseph Chen 	/*
112dbf8423eSJoseph Chen 	 * Get memory region of OP-TEE
113dbf8423eSJoseph Chen 	 *
114dbf8423eSJoseph Chen 	 * 1. New way: atags info;
115dbf8423eSJoseph Chen 	 * 2. Leagcy way: info in ddr 34M offset;
116dbf8423eSJoseph Chen 	 */
117dbf8423eSJoseph Chen 	t = atags_get_tag(ATAG_TOS_MEM);
118dbf8423eSJoseph Chen 	if (t && (t->u.tos_mem.tee_mem.flags == 1)) {
1196e15146eSJoseph Chen 		mem.base = t->u.tos_mem.tee_mem.phy_addr;
1206e15146eSJoseph Chen 		mem.size = t->u.tos_mem.tee_mem.size;
121dbf8423eSJoseph Chen 	}
122dbf8423eSJoseph Chen #endif
123dbf8423eSJoseph Chen 
124dbf8423eSJoseph Chen 	/* Legacy */
1256e15146eSJoseph Chen 	if (!mem.size) {
126dbf8423eSJoseph Chen 		tos_parameter =
127dbf8423eSJoseph Chen 		(struct tos_param_t *)(SDRAM_OFFSET(PARAM_OPTEE_INFO_OFFSET));
128dbf8423eSJoseph Chen 		checksum =
129dbf8423eSJoseph Chen 		trust_checksum((uint8_t *)(unsigned long)tos_parameter + 8,
130dbf8423eSJoseph Chen 			       sizeof(struct tos_param_t) - 8);
131dbf8423eSJoseph Chen 		if ((checksum == tos_parameter->checksum) &&
132dbf8423eSJoseph Chen 		    (tos_parameter->tee_mem.flags == 1)) {
1336e15146eSJoseph Chen 			mem.base = tos_parameter->tee_mem.phy_addr;
1346e15146eSJoseph Chen 			mem.size = tos_parameter->tee_mem.size;
13507ea4f34SJoseph Chen 		}
13607ea4f34SJoseph Chen 	}
13707ea4f34SJoseph Chen 
1386e15146eSJoseph Chen 	if (mem.size)
139dbf8423eSJoseph Chen 		gd->flags |= GD_FLG_BL32_ENABLED;
140dbf8423eSJoseph Chen 
1416e15146eSJoseph Chen 	debug("TOS: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size);
142dbf8423eSJoseph Chen 
1436e15146eSJoseph Chen 	return mem;
144dbf8423eSJoseph Chen }
145dbf8423eSJoseph Chen 
1466e15146eSJoseph Chen struct memblock param_parse_common_resv_mem(void)
147dbf8423eSJoseph Chen {
1486e15146eSJoseph Chen 	struct memblock mem;
149dbf8423eSJoseph Chen 
150160c99aaSJoseph Chen #if defined(CONFIG_ARM64)
151160c99aaSJoseph Chen 	mem.base = SDRAM_OFFSET(SZ_1M);
152160c99aaSJoseph Chen 	mem.size = SZ_1M;
153160c99aaSJoseph Chen /*
154160c99aaSJoseph Chen  * The ARMv8 platform enabling AArch32 mode should reserve memory the same
155160c99aaSJoseph Chen  * as AArch64 mode(because there is no difference about ATF), only some
156160c99aaSJoseph Chen  * platform has special request, they are: RK3308.
157160c99aaSJoseph Chen  */
158160c99aaSJoseph Chen #elif defined(CONFIG_ARM64_BOOT_AARCH32) && !defined(CONFIG_ROCKCHIP_RK3308)
1596e15146eSJoseph Chen 	mem.base = SDRAM_OFFSET(SZ_1M);
1606e15146eSJoseph Chen 	mem.size = SZ_1M;
1612dd104a5SJoseph Chen #else
1622dd104a5SJoseph Chen 	mem.size = 0;
1632dd104a5SJoseph Chen #endif
1646e15146eSJoseph Chen 	return mem;
165dbf8423eSJoseph Chen }
166dbf8423eSJoseph Chen 
167dbf8423eSJoseph Chen int param_parse_bootdev(char **devtype, char **devnum)
168dbf8423eSJoseph Chen {
169dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
170dbf8423eSJoseph Chen 	struct tag *t;
171dbf8423eSJoseph Chen 
172dbf8423eSJoseph Chen 	t = atags_get_tag(ATAG_BOOTDEV);
173dbf8423eSJoseph Chen 	if (t) {
174dbf8423eSJoseph Chen 		switch (t->u.bootdev.devtype) {
17594aee224SJason Zhu #ifdef CONFIG_DM_MMC
176dbf8423eSJoseph Chen 		case BOOT_TYPE_EMMC:
177dbf8423eSJoseph Chen 			*devtype = "mmc";
178dbf8423eSJoseph Chen 			*devnum = "0";
179dbf8423eSJoseph Chen 			break;
180dbf8423eSJoseph Chen 		case BOOT_TYPE_SD0:
181dbf8423eSJoseph Chen 		case BOOT_TYPE_SD1:
182dbf8423eSJoseph Chen 			*devtype = "mmc";
183dbf8423eSJoseph Chen 			*devnum = "1";
184c9f547d8SJason Zhu 			/*
185c9f547d8SJason Zhu 			 * If preloader does not pass sdupdate value, we treat it
186c9f547d8SJason Zhu 			 * as a unknown card and call the rkimgtest cmd to find
187c9f547d8SJason Zhu 			 * out what it is.
188c9f547d8SJason Zhu 			 *
189c9f547d8SJason Zhu 			 * If preloader pass sdupdate value as an update card,
190c9f547d8SJason Zhu 			 * we just set "sdfwupdate" to bootargs instead of
191c9f547d8SJason Zhu 			 * calling rkimgtest cmd which consumes time.
192c9f547d8SJason Zhu 			 */
193c9f547d8SJason Zhu 			if (t->u.bootdev.sdupdate == SD_UNKNOWN_CARD) {
194c9f547d8SJason Zhu 				run_command("mmc dev 1", 0);
195c9f547d8SJason Zhu 				run_command("rkimgtest mmc 1", 0);
196c9f547d8SJason Zhu 			} else if (t->u.bootdev.sdupdate == SD_UPDATE_CARD) {
197c9f547d8SJason Zhu 				env_update("bootargs", "sdfwupdate");
198c9f547d8SJason Zhu 			}
199dbf8423eSJoseph Chen 			break;
20094aee224SJason Zhu #endif
20144f308bdSJoseph Chen #if defined(CONFIG_RKNAND) || defined(CONFIG_RKNANDC_NAND)
202dbf8423eSJoseph Chen 		case BOOT_TYPE_NAND:
203dbf8423eSJoseph Chen 			*devtype = "rknand";
204dbf8423eSJoseph Chen 			*devnum = "0";
205dbf8423eSJoseph Chen 			break;
20694aee224SJason Zhu #endif
20794aee224SJason Zhu #ifdef CONFIG_RKSFC_NAND
208dbf8423eSJoseph Chen 		case BOOT_TYPE_SPI_NAND:
209dbf8423eSJoseph Chen 			*devtype = "spinand";
210dbf8423eSJoseph Chen 			*devnum = "0";
211dbf8423eSJoseph Chen 			break;
21294aee224SJason Zhu #endif
21394aee224SJason Zhu #ifdef CONFIG_RKSFC_NOR
214dbf8423eSJoseph Chen 		case BOOT_TYPE_SPI_NOR:
215dbf8423eSJoseph Chen 			*devtype = "spinor";
216dbf8423eSJoseph Chen 			*devnum = "1";
217dbf8423eSJoseph Chen 			break;
21894aee224SJason Zhu #endif
21994aee224SJason Zhu #ifdef CONFIG_DM_RAMDISK
220dbf8423eSJoseph Chen 		case BOOT_TYPE_RAM:
221dbf8423eSJoseph Chen 			*devtype = "ramdisk";
222dbf8423eSJoseph Chen 			*devnum = "0";
223dbf8423eSJoseph Chen 			break;
22494aee224SJason Zhu #endif
225c53a0c58SJason Zhu #ifdef CONFIG_NAND
226c53a0c58SJason Zhu 		case BOOT_TYPE_MTD_BLK_NAND:
227c53a0c58SJason Zhu 			*devtype = "mtd";
228c53a0c58SJason Zhu 			*devnum = "0";
229c53a0c58SJason Zhu 			break;
230c53a0c58SJason Zhu #endif
231c53a0c58SJason Zhu #ifdef CONFIG_MTD_SPI_NAND
232c53a0c58SJason Zhu 		case BOOT_TYPE_MTD_BLK_SPI_NAND:
233c53a0c58SJason Zhu 			*devtype = "mtd";
234c53a0c58SJason Zhu 			*devnum = "1";
235c53a0c58SJason Zhu 			break;
236c53a0c58SJason Zhu #endif
237c53a0c58SJason Zhu #ifdef CONFIG_SPI_FLASH_MTD
238c53a0c58SJason Zhu 		case BOOT_TYPE_MTD_BLK_SPI_NOR:
239c53a0c58SJason Zhu 			*devtype = "mtd";
240c53a0c58SJason Zhu 			*devnum = "2";
241c53a0c58SJason Zhu 			break;
242c53a0c58SJason Zhu #endif
243dbf8423eSJoseph Chen 		default:
244dbf8423eSJoseph Chen 			printf("Unknown bootdev type: 0x%x\n",
245dbf8423eSJoseph Chen 			       t->u.bootdev.devtype);
246dbf8423eSJoseph Chen 			return -EINVAL;
247dbf8423eSJoseph Chen 		}
248dbf8423eSJoseph Chen 
249dbf8423eSJoseph Chen 		return 0;
250dbf8423eSJoseph Chen 	}
251dbf8423eSJoseph Chen #endif
252dbf8423eSJoseph Chen 
253dbf8423eSJoseph Chen 	return -ENOSYS;
254dbf8423eSJoseph Chen }
2554e92aae1SJoseph Chen #endif
256b9bc76b4SJoseph Chen 
257ced10dbeSJoseph Chen static phys_size_t ddr_mem_get_usable_size(u64 base, u64 size)
258ced10dbeSJoseph Chen {
2593ceae109SJoseph Chen 	return (base + size >= CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE) ?
2603ceae109SJoseph Chen 	       (CONFIG_SYS_SDRAM_BASE + SDRAM_MAX_SIZE - base) : size;
261ced10dbeSJoseph Chen }
262ced10dbeSJoseph Chen 
263b9bc76b4SJoseph Chen struct memblock *param_parse_ddr_mem(int *out_count)
264b9bc76b4SJoseph Chen {
265b9bc76b4SJoseph Chen 	struct udevice *dev;
266b9bc76b4SJoseph Chen 	struct memblock *mem;
267b9bc76b4SJoseph Chen 	struct ram_info ram;
268b9bc76b4SJoseph Chen 	int i, ret, count;
269b9bc76b4SJoseph Chen 
270b9bc76b4SJoseph Chen 	/*
271b9bc76b4SJoseph Chen 	 * Get memory region of DDR
272b9bc76b4SJoseph Chen 	 *
273b9bc76b4SJoseph Chen 	 * 1. New: atags info;
274b9bc76b4SJoseph Chen 	 * 2. Leagcy: os register;
275b9bc76b4SJoseph Chen 	 */
276b9bc76b4SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
277b9bc76b4SJoseph Chen 	struct tag *t;
2780453d738SJoseph Chen 	u64 base, size;
2790453d738SJoseph Chen 	int n;
280b9bc76b4SJoseph Chen 
281b9bc76b4SJoseph Chen 	t = atags_get_tag(ATAG_DDR_MEM);
282b9bc76b4SJoseph Chen 	if (t && t->u.ddr_mem.count) {
283b9bc76b4SJoseph Chen 		count = t->u.ddr_mem.count;
2840453d738SJoseph Chen 		mem = calloc(count + MEM_RESV_COUNT, sizeof(*mem));
285b9bc76b4SJoseph Chen 		if (!mem) {
286b9bc76b4SJoseph Chen 			printf("Calloc ddr memory failed\n");
287b9bc76b4SJoseph Chen 			return 0;
288b9bc76b4SJoseph Chen 		}
289b9bc76b4SJoseph Chen 
2900453d738SJoseph Chen 		for (i = 0, n = 0; i < count; i++, n++) {
2910453d738SJoseph Chen 			base = t->u.ddr_mem.bank[i];
2920453d738SJoseph Chen 			size = t->u.ddr_mem.bank[i + count];
2930453d738SJoseph Chen 
2940453d738SJoseph Chen 			/* 0~4GB */
2950453d738SJoseph Chen 			if (base < SZ_4GB) {
2960453d738SJoseph Chen 				mem[n].base = base;
2970453d738SJoseph Chen 				mem[n].size = ddr_mem_get_usable_size(base, size);
2980453d738SJoseph Chen 				if (base + size > SZ_4GB) {
2990453d738SJoseph Chen 					n++;
3000453d738SJoseph Chen 					mem[n].base_u64 = SZ_4GB;
3010453d738SJoseph Chen 					mem[n].size_u64 = base + size - SZ_4GB;
3020453d738SJoseph Chen 				}
3030453d738SJoseph Chen 			} else {
3040453d738SJoseph Chen 				/* 4GB+ */
3050453d738SJoseph Chen 				mem[n].base_u64 = base;
3060453d738SJoseph Chen 				mem[n].size_u64 = size;
307b9bc76b4SJoseph Chen 			}
308b9bc76b4SJoseph Chen 
3090453d738SJoseph Chen 			assert(n < count + MEM_RESV_COUNT);
3100453d738SJoseph Chen 		}
3110453d738SJoseph Chen 
3120453d738SJoseph Chen 		*out_count = n;
313b9bc76b4SJoseph Chen 		return mem;
314b9bc76b4SJoseph Chen 	}
315b9bc76b4SJoseph Chen #endif
316b9bc76b4SJoseph Chen 
317b9bc76b4SJoseph Chen 	/* Leagcy */
318b9bc76b4SJoseph Chen 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
319b9bc76b4SJoseph Chen 	if (ret) {
320b9bc76b4SJoseph Chen 		debug("DRAM init failed: %d\n", ret);
321b9bc76b4SJoseph Chen 		return NULL;
322b9bc76b4SJoseph Chen 	}
323b9bc76b4SJoseph Chen 	ret = ram_get_info(dev, &ram);
324b9bc76b4SJoseph Chen 	if (ret) {
325b9bc76b4SJoseph Chen 		debug("Cannot get DRAM size: %d\n", ret);
326b9bc76b4SJoseph Chen 		return NULL;
327b9bc76b4SJoseph Chen 	}
328b9bc76b4SJoseph Chen 
329b9bc76b4SJoseph Chen 	debug("SDRAM base=%lx, size=%lx\n",
330b9bc76b4SJoseph Chen 	      (unsigned long)ram.base, (unsigned long)ram.size);
331b9bc76b4SJoseph Chen 
332b9bc76b4SJoseph Chen 	count = 1;
333b9bc76b4SJoseph Chen 	mem = calloc(1, sizeof(*mem));
334b9bc76b4SJoseph Chen 	if (!mem) {
335b9bc76b4SJoseph Chen 		printf("Calloc ddr memory failed\n");
336b9bc76b4SJoseph Chen 		return 0;
337b9bc76b4SJoseph Chen 	}
338b9bc76b4SJoseph Chen 
339b9bc76b4SJoseph Chen 	for (i = 0; i < count; i++) {
340b9bc76b4SJoseph Chen 		mem[i].base = CONFIG_SYS_SDRAM_BASE;
341ced10dbeSJoseph Chen 		mem[i].size = ddr_mem_get_usable_size(mem[i].base, ram.size);
342b9bc76b4SJoseph Chen 	}
343b9bc76b4SJoseph Chen 
344b9bc76b4SJoseph Chen 	*out_count = count;
345b9bc76b4SJoseph Chen 	return mem;
346b9bc76b4SJoseph Chen }
347