xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/param.c (revision ced10dbe1c0bcf64108ceb8f9435aa2130e0633d)
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 
154e92aae1SJoseph Chen #if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
16dbf8423eSJoseph Chen #define SDRAM_OFFSET(offset)		(CONFIG_SYS_SDRAM_BASE + (offset))
17dbf8423eSJoseph Chen #define PARAM_DRAM_INFO_OFFSET		(SZ_32M)
18dbf8423eSJoseph Chen #define PARAM_OPTEE_INFO_OFFSET		(SZ_32M + SZ_2M)
19dbf8423eSJoseph Chen 
20dbf8423eSJoseph Chen struct tos_param_t {
21dbf8423eSJoseph Chen 	u32 version;
22dbf8423eSJoseph Chen 	u32 checksum;
23dbf8423eSJoseph Chen 	struct {
24dbf8423eSJoseph Chen 		char name[8];
25dbf8423eSJoseph Chen 		s64 phy_addr;
26dbf8423eSJoseph Chen 		u32 size;
27dbf8423eSJoseph Chen 		u32 flags;
28dbf8423eSJoseph Chen 	} tee_mem;
29dbf8423eSJoseph Chen 	struct {
30dbf8423eSJoseph Chen 		char name[8];
31dbf8423eSJoseph Chen 		s64 phy_addr;
32dbf8423eSJoseph Chen 		u32 size;
33dbf8423eSJoseph Chen 		u32 flags;
34dbf8423eSJoseph Chen 	} drm_mem;
35dbf8423eSJoseph Chen 	s64 reserve[8];
36dbf8423eSJoseph Chen };
37dbf8423eSJoseph Chen 
38dbf8423eSJoseph Chen static uint16_t trust_checksum(const uint8_t *buf, uint16_t len)
39dbf8423eSJoseph Chen {
40dbf8423eSJoseph Chen 	uint16_t i, checksum = 0;
41dbf8423eSJoseph Chen 
42dbf8423eSJoseph Chen 	for (i = 0; i < len; i++) {
43dbf8423eSJoseph Chen 		if (i % 2)
44dbf8423eSJoseph Chen 			checksum += buf[i] << 8;
45dbf8423eSJoseph Chen 		else
46dbf8423eSJoseph Chen 			checksum += buf[i];
47dbf8423eSJoseph Chen 	}
48dbf8423eSJoseph Chen 	checksum = ~checksum;
49dbf8423eSJoseph Chen 
50dbf8423eSJoseph Chen 	return checksum;
51dbf8423eSJoseph Chen }
52dbf8423eSJoseph Chen 
536e15146eSJoseph Chen struct memblock param_parse_atf_mem(void)
54dbf8423eSJoseph Chen {
556e15146eSJoseph Chen 	struct memblock mem;
56dbf8423eSJoseph Chen 
576e15146eSJoseph Chen 	mem.base = 0;
586e15146eSJoseph Chen 	mem.size = 0;
59dbf8423eSJoseph Chen 
60dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
61dbf8423eSJoseph Chen 	struct tag *t = NULL;
62dbf8423eSJoseph Chen 
63dbf8423eSJoseph Chen 	/*
64dbf8423eSJoseph Chen 	 * Get memory region of ATF
65dbf8423eSJoseph Chen 	 *
66dbf8423eSJoseph Chen 	 * 1. New way: atags info;
67dbf8423eSJoseph Chen 	 * 2. Leagcy way: 2MB size and start from ddr 0x0 offset;
68dbf8423eSJoseph Chen 	 */
69dbf8423eSJoseph Chen 	t = atags_get_tag(ATAG_ATF_MEM);
70dbf8423eSJoseph Chen 	if (t && t->u.atf_mem.size) {
716e15146eSJoseph Chen 		mem.base = t->u.atf_mem.phy_addr;
726e15146eSJoseph Chen 		mem.size = t->u.atf_mem.size;
73dbf8423eSJoseph Chen 		/* Sanity */
746e15146eSJoseph Chen 		if (mem.base + mem.size > SDRAM_OFFSET(SZ_1M)) {
75dbf8423eSJoseph Chen 			printf("%s: ATF reserved region is not within 0-1MB "
76dbf8423eSJoseph Chen 			       "offset(0x%08llx-0x%08llx)!\n",
776e15146eSJoseph Chen 			       __func__, (u64)mem.base, (u64)mem.base + mem.size);
786e15146eSJoseph Chen 			return mem;
79dbf8423eSJoseph Chen 		}
80dbf8423eSJoseph Chen 	}
81dbf8423eSJoseph Chen #endif
82dbf8423eSJoseph Chen 
83dbf8423eSJoseph Chen 	/* Legacy */
846e15146eSJoseph Chen 	if (!mem.size) {
85dbf8423eSJoseph Chen 		if (IS_ENABLED(CONFIG_ARM64) ||
86dbf8423eSJoseph Chen 		    IS_ENABLED(CONFIG_ARM64_BOOT_AARCH32)) {
876e15146eSJoseph Chen 			mem.base = SDRAM_OFFSET(0);
886e15146eSJoseph Chen 			mem.size = SZ_1M;
89dbf8423eSJoseph Chen 		}
90dbf8423eSJoseph Chen 	}
91dbf8423eSJoseph Chen 
926e15146eSJoseph Chen 	debug("ATF: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size);
93dbf8423eSJoseph Chen 
946e15146eSJoseph Chen 	return mem;
95dbf8423eSJoseph Chen }
96dbf8423eSJoseph Chen 
976e15146eSJoseph Chen struct memblock param_parse_optee_mem(void)
98dbf8423eSJoseph Chen {
99dbf8423eSJoseph Chen 	struct tos_param_t *tos_parameter;
1006e15146eSJoseph Chen 	struct memblock mem;
101dbf8423eSJoseph Chen 	u32 checksum;
102dbf8423eSJoseph Chen 
1036e15146eSJoseph Chen 	mem.base = 0;
1046e15146eSJoseph Chen 	mem.size = 0;
105dbf8423eSJoseph Chen 
106dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
107dbf8423eSJoseph Chen 	struct tag *t = NULL;
108dbf8423eSJoseph Chen 
109dbf8423eSJoseph Chen 	/*
110dbf8423eSJoseph Chen 	 * Get memory region of OP-TEE
111dbf8423eSJoseph Chen 	 *
112dbf8423eSJoseph Chen 	 * 1. New way: atags info;
113dbf8423eSJoseph Chen 	 * 2. Leagcy way: info in ddr 34M offset;
114dbf8423eSJoseph Chen 	 */
115dbf8423eSJoseph Chen 	t = atags_get_tag(ATAG_TOS_MEM);
116dbf8423eSJoseph Chen 	if (t && (t->u.tos_mem.tee_mem.flags == 1)) {
1176e15146eSJoseph Chen 		mem.base = t->u.tos_mem.tee_mem.phy_addr;
1186e15146eSJoseph Chen 		mem.size = t->u.tos_mem.tee_mem.size;
119dbf8423eSJoseph Chen 	}
120dbf8423eSJoseph Chen #endif
121dbf8423eSJoseph Chen 
122dbf8423eSJoseph Chen 	/* Legacy */
1236e15146eSJoseph Chen 	if (!mem.size) {
124dbf8423eSJoseph Chen 		tos_parameter =
125dbf8423eSJoseph Chen 		(struct tos_param_t *)(SDRAM_OFFSET(PARAM_OPTEE_INFO_OFFSET));
126dbf8423eSJoseph Chen 		checksum =
127dbf8423eSJoseph Chen 		trust_checksum((uint8_t *)(unsigned long)tos_parameter + 8,
128dbf8423eSJoseph Chen 			       sizeof(struct tos_param_t) - 8);
129dbf8423eSJoseph Chen 		if ((checksum == tos_parameter->checksum) &&
130dbf8423eSJoseph Chen 		    (tos_parameter->tee_mem.flags == 1)) {
1316e15146eSJoseph Chen 			mem.base = tos_parameter->tee_mem.phy_addr;
1326e15146eSJoseph Chen 			mem.size = tos_parameter->tee_mem.size;
13307ea4f34SJoseph Chen 		}
13407ea4f34SJoseph Chen 	}
13507ea4f34SJoseph Chen 
1366e15146eSJoseph Chen 	if (mem.size)
137dbf8423eSJoseph Chen 		gd->flags |= GD_FLG_BL32_ENABLED;
138dbf8423eSJoseph Chen 
1396e15146eSJoseph Chen 	debug("TOS: 0x%llx - 0x%llx\n", (u64)mem.base, (u64)mem.base + mem.size);
140dbf8423eSJoseph Chen 
1416e15146eSJoseph Chen 	return mem;
142dbf8423eSJoseph Chen }
143dbf8423eSJoseph Chen 
1446e15146eSJoseph Chen struct memblock param_parse_common_resv_mem(void)
145dbf8423eSJoseph Chen {
1466e15146eSJoseph Chen 	struct memblock mem;
147dbf8423eSJoseph Chen 
148160c99aaSJoseph Chen #if defined(CONFIG_ARM64)
149160c99aaSJoseph Chen 	mem.base = SDRAM_OFFSET(SZ_1M);
150160c99aaSJoseph Chen 	mem.size = SZ_1M;
151160c99aaSJoseph Chen /*
152160c99aaSJoseph Chen  * The ARMv8 platform enabling AArch32 mode should reserve memory the same
153160c99aaSJoseph Chen  * as AArch64 mode(because there is no difference about ATF), only some
154160c99aaSJoseph Chen  * platform has special request, they are: RK3308.
155160c99aaSJoseph Chen  */
156160c99aaSJoseph Chen #elif defined(CONFIG_ARM64_BOOT_AARCH32) && !defined(CONFIG_ROCKCHIP_RK3308)
1576e15146eSJoseph Chen 	mem.base = SDRAM_OFFSET(SZ_1M);
1586e15146eSJoseph Chen 	mem.size = SZ_1M;
1592dd104a5SJoseph Chen #else
1602dd104a5SJoseph Chen 	mem.size = 0;
1612dd104a5SJoseph Chen #endif
1626e15146eSJoseph Chen 	return mem;
163dbf8423eSJoseph Chen }
164dbf8423eSJoseph Chen 
165dbf8423eSJoseph Chen int param_parse_bootdev(char **devtype, char **devnum)
166dbf8423eSJoseph Chen {
167dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
168dbf8423eSJoseph Chen 	struct tag *t;
169dbf8423eSJoseph Chen 
170dbf8423eSJoseph Chen 	t = atags_get_tag(ATAG_BOOTDEV);
171dbf8423eSJoseph Chen 	if (t) {
172dbf8423eSJoseph Chen 		switch (t->u.bootdev.devtype) {
17394aee224SJason Zhu #ifdef CONFIG_DM_MMC
174dbf8423eSJoseph Chen 		case BOOT_TYPE_EMMC:
175dbf8423eSJoseph Chen 			*devtype = "mmc";
176dbf8423eSJoseph Chen 			*devnum = "0";
177dbf8423eSJoseph Chen 			break;
178dbf8423eSJoseph Chen 		case BOOT_TYPE_SD0:
179dbf8423eSJoseph Chen 		case BOOT_TYPE_SD1:
180dbf8423eSJoseph Chen 			*devtype = "mmc";
181dbf8423eSJoseph Chen 			*devnum = "1";
182c9f547d8SJason Zhu 			/*
183c9f547d8SJason Zhu 			 * If preloader does not pass sdupdate value, we treat it
184c9f547d8SJason Zhu 			 * as a unknown card and call the rkimgtest cmd to find
185c9f547d8SJason Zhu 			 * out what it is.
186c9f547d8SJason Zhu 			 *
187c9f547d8SJason Zhu 			 * If preloader pass sdupdate value as an update card,
188c9f547d8SJason Zhu 			 * we just set "sdfwupdate" to bootargs instead of
189c9f547d8SJason Zhu 			 * calling rkimgtest cmd which consumes time.
190c9f547d8SJason Zhu 			 */
191c9f547d8SJason Zhu 			if (t->u.bootdev.sdupdate == SD_UNKNOWN_CARD) {
192c9f547d8SJason Zhu 				run_command("mmc dev 1", 0);
193c9f547d8SJason Zhu 				run_command("rkimgtest mmc 1", 0);
194c9f547d8SJason Zhu 			} else if (t->u.bootdev.sdupdate == SD_UPDATE_CARD) {
195c9f547d8SJason Zhu 				env_update("bootargs", "sdfwupdate");
196c9f547d8SJason Zhu 			}
197dbf8423eSJoseph Chen 			break;
19894aee224SJason Zhu #endif
19944f308bdSJoseph Chen #if defined(CONFIG_RKNAND) || defined(CONFIG_RKNANDC_NAND)
200dbf8423eSJoseph Chen 		case BOOT_TYPE_NAND:
201dbf8423eSJoseph Chen 			*devtype = "rknand";
202dbf8423eSJoseph Chen 			*devnum = "0";
203dbf8423eSJoseph Chen 			break;
20494aee224SJason Zhu #endif
20594aee224SJason Zhu #ifdef CONFIG_RKSFC_NAND
206dbf8423eSJoseph Chen 		case BOOT_TYPE_SPI_NAND:
207dbf8423eSJoseph Chen 			*devtype = "spinand";
208dbf8423eSJoseph Chen 			*devnum = "0";
209dbf8423eSJoseph Chen 			break;
21094aee224SJason Zhu #endif
21194aee224SJason Zhu #ifdef CONFIG_RKSFC_NOR
212dbf8423eSJoseph Chen 		case BOOT_TYPE_SPI_NOR:
213dbf8423eSJoseph Chen 			*devtype = "spinor";
214dbf8423eSJoseph Chen 			*devnum = "1";
215dbf8423eSJoseph Chen 			break;
21694aee224SJason Zhu #endif
21794aee224SJason Zhu #ifdef CONFIG_DM_RAMDISK
218dbf8423eSJoseph Chen 		case BOOT_TYPE_RAM:
219dbf8423eSJoseph Chen 			*devtype = "ramdisk";
220dbf8423eSJoseph Chen 			*devnum = "0";
221dbf8423eSJoseph Chen 			break;
22294aee224SJason Zhu #endif
223dbf8423eSJoseph Chen 		default:
224dbf8423eSJoseph Chen 			printf("Unknown bootdev type: 0x%x\n",
225dbf8423eSJoseph Chen 			       t->u.bootdev.devtype);
226dbf8423eSJoseph Chen 			return -EINVAL;
227dbf8423eSJoseph Chen 		}
228dbf8423eSJoseph Chen 
229dbf8423eSJoseph Chen 		return 0;
230dbf8423eSJoseph Chen 	}
231dbf8423eSJoseph Chen #endif
232dbf8423eSJoseph Chen 
233dbf8423eSJoseph Chen 	return -ENOSYS;
234dbf8423eSJoseph Chen }
2354e92aae1SJoseph Chen #endif
236b9bc76b4SJoseph Chen 
237*ced10dbeSJoseph Chen static phys_size_t ddr_mem_get_usable_size(u64 base, u64 size)
238*ced10dbeSJoseph Chen {
239*ced10dbeSJoseph Chen 	return (base + size >= SDRAM_MAX_SIZE) ? (SDRAM_MAX_SIZE - base) : size;
240*ced10dbeSJoseph Chen }
241*ced10dbeSJoseph Chen 
242b9bc76b4SJoseph Chen struct memblock *param_parse_ddr_mem(int *out_count)
243b9bc76b4SJoseph Chen {
244b9bc76b4SJoseph Chen 	struct udevice *dev;
245b9bc76b4SJoseph Chen 	struct memblock *mem;
246b9bc76b4SJoseph Chen 	struct ram_info ram;
247b9bc76b4SJoseph Chen 	int i, ret, count;
248b9bc76b4SJoseph Chen 
249b9bc76b4SJoseph Chen 	/*
250b9bc76b4SJoseph Chen 	 * Get memory region of DDR
251b9bc76b4SJoseph Chen 	 *
252b9bc76b4SJoseph Chen 	 * 1. New: atags info;
253b9bc76b4SJoseph Chen 	 * 2. Leagcy: os register;
254b9bc76b4SJoseph Chen 	 */
255b9bc76b4SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
256b9bc76b4SJoseph Chen 	struct tag *t;
257b9bc76b4SJoseph Chen 
258b9bc76b4SJoseph Chen 	t = atags_get_tag(ATAG_DDR_MEM);
259b9bc76b4SJoseph Chen 	if (t && t->u.ddr_mem.count) {
260b9bc76b4SJoseph Chen 		count = t->u.ddr_mem.count;
261b9bc76b4SJoseph Chen 		mem = calloc(count, sizeof(*mem));
262b9bc76b4SJoseph Chen 		if (!mem) {
263b9bc76b4SJoseph Chen 			printf("Calloc ddr memory failed\n");
264b9bc76b4SJoseph Chen 			return 0;
265b9bc76b4SJoseph Chen 		}
266b9bc76b4SJoseph Chen 
267b9bc76b4SJoseph Chen 		for (i = 0; i < count; i++) {
268b9bc76b4SJoseph Chen 			mem[i].base = t->u.ddr_mem.bank[i];
269*ced10dbeSJoseph Chen 			mem[i].size =
270*ced10dbeSJoseph Chen 			  ddr_mem_get_usable_size(t->u.ddr_mem.bank[i],
271*ced10dbeSJoseph Chen 						  t->u.ddr_mem.bank[i + count]);
272b9bc76b4SJoseph Chen 		}
273b9bc76b4SJoseph Chen 
274b9bc76b4SJoseph Chen 		*out_count = count;
275b9bc76b4SJoseph Chen 		return mem;
276b9bc76b4SJoseph Chen 	}
277b9bc76b4SJoseph Chen #endif
278b9bc76b4SJoseph Chen 
279b9bc76b4SJoseph Chen 	/* Leagcy */
280b9bc76b4SJoseph Chen 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
281b9bc76b4SJoseph Chen 	if (ret) {
282b9bc76b4SJoseph Chen 		debug("DRAM init failed: %d\n", ret);
283b9bc76b4SJoseph Chen 		return NULL;
284b9bc76b4SJoseph Chen 	}
285b9bc76b4SJoseph Chen 	ret = ram_get_info(dev, &ram);
286b9bc76b4SJoseph Chen 	if (ret) {
287b9bc76b4SJoseph Chen 		debug("Cannot get DRAM size: %d\n", ret);
288b9bc76b4SJoseph Chen 		return NULL;
289b9bc76b4SJoseph Chen 	}
290b9bc76b4SJoseph Chen 
291b9bc76b4SJoseph Chen 	debug("SDRAM base=%lx, size=%lx\n",
292b9bc76b4SJoseph Chen 	      (unsigned long)ram.base, (unsigned long)ram.size);
293b9bc76b4SJoseph Chen 
294b9bc76b4SJoseph Chen 	count = 1;
295b9bc76b4SJoseph Chen 	mem = calloc(1, sizeof(*mem));
296b9bc76b4SJoseph Chen 	if (!mem) {
297b9bc76b4SJoseph Chen 		printf("Calloc ddr memory failed\n");
298b9bc76b4SJoseph Chen 		return 0;
299b9bc76b4SJoseph Chen 	}
300b9bc76b4SJoseph Chen 
301b9bc76b4SJoseph Chen 	for (i = 0; i < count; i++) {
302b9bc76b4SJoseph Chen 		mem[i].base = CONFIG_SYS_SDRAM_BASE;
303*ced10dbeSJoseph Chen 		mem[i].size = ddr_mem_get_usable_size(mem[i].base, ram.size);
304b9bc76b4SJoseph Chen 	}
305b9bc76b4SJoseph Chen 
306b9bc76b4SJoseph Chen 	*out_count = count;
307b9bc76b4SJoseph Chen 	return mem;
308b9bc76b4SJoseph Chen }
309