xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/param.c (revision 4e92aae1f9ac4962fe2f928aff4e64767bc8b05b)
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 
15*4e92aae1SJoseph 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 
1486e15146eSJoseph Chen 	mem.base = SDRAM_OFFSET(SZ_1M);
1496e15146eSJoseph Chen 	mem.size = SZ_1M;
150dbf8423eSJoseph Chen 
1516e15146eSJoseph Chen 	return mem;
152dbf8423eSJoseph Chen }
153dbf8423eSJoseph Chen 
154dbf8423eSJoseph Chen int param_parse_bootdev(char **devtype, char **devnum)
155dbf8423eSJoseph Chen {
156dbf8423eSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
157dbf8423eSJoseph Chen 	struct tag *t;
158dbf8423eSJoseph Chen 
159dbf8423eSJoseph Chen 	t = atags_get_tag(ATAG_BOOTDEV);
160dbf8423eSJoseph Chen 	if (t) {
161dbf8423eSJoseph Chen 		switch (t->u.bootdev.devtype) {
162dbf8423eSJoseph Chen 		case BOOT_TYPE_EMMC:
163dbf8423eSJoseph Chen 			*devtype = "mmc";
164dbf8423eSJoseph Chen 			*devnum = "0";
165dbf8423eSJoseph Chen 			break;
166dbf8423eSJoseph Chen 		case BOOT_TYPE_SD0:
167dbf8423eSJoseph Chen 		case BOOT_TYPE_SD1:
168dbf8423eSJoseph Chen 			*devtype = "mmc";
169dbf8423eSJoseph Chen 			*devnum = "1";
170dbf8423eSJoseph Chen 			break;
171dbf8423eSJoseph Chen 		case BOOT_TYPE_NAND:
172dbf8423eSJoseph Chen 			*devtype = "rknand";
173dbf8423eSJoseph Chen 			*devnum = "0";
174dbf8423eSJoseph Chen 			break;
175dbf8423eSJoseph Chen 		case BOOT_TYPE_SPI_NAND:
176dbf8423eSJoseph Chen 			*devtype = "spinand";
177dbf8423eSJoseph Chen 			*devnum = "0";
178dbf8423eSJoseph Chen 			break;
179dbf8423eSJoseph Chen 		case BOOT_TYPE_SPI_NOR:
180dbf8423eSJoseph Chen 			*devtype = "spinor";
181dbf8423eSJoseph Chen 			*devnum = "1";
182dbf8423eSJoseph Chen 			break;
183dbf8423eSJoseph Chen 		case BOOT_TYPE_RAM:
184dbf8423eSJoseph Chen 			*devtype = "ramdisk";
185dbf8423eSJoseph Chen 			*devnum = "0";
186dbf8423eSJoseph Chen 			break;
187dbf8423eSJoseph Chen 		default:
188dbf8423eSJoseph Chen 			printf("Unknown bootdev type: 0x%x\n",
189dbf8423eSJoseph Chen 			       t->u.bootdev.devtype);
190dbf8423eSJoseph Chen 			return -EINVAL;
191dbf8423eSJoseph Chen 		}
192dbf8423eSJoseph Chen 
193dbf8423eSJoseph Chen 		return 0;
194dbf8423eSJoseph Chen 	}
195dbf8423eSJoseph Chen #endif
196dbf8423eSJoseph Chen 
197dbf8423eSJoseph Chen 	return -ENOSYS;
198dbf8423eSJoseph Chen }
199*4e92aae1SJoseph Chen #endif
200b9bc76b4SJoseph Chen 
201b9bc76b4SJoseph Chen struct memblock *param_parse_ddr_mem(int *out_count)
202b9bc76b4SJoseph Chen {
203b9bc76b4SJoseph Chen 	struct udevice *dev;
204b9bc76b4SJoseph Chen 	struct memblock *mem;
205b9bc76b4SJoseph Chen 	struct ram_info ram;
206b9bc76b4SJoseph Chen 	int i, ret, count;
207b9bc76b4SJoseph Chen 
208b9bc76b4SJoseph Chen 	/*
209b9bc76b4SJoseph Chen 	 * Get memory region of DDR
210b9bc76b4SJoseph Chen 	 *
211b9bc76b4SJoseph Chen 	 * 1. New: atags info;
212b9bc76b4SJoseph Chen 	 * 2. Leagcy: os register;
213b9bc76b4SJoseph Chen 	 */
214b9bc76b4SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
215b9bc76b4SJoseph Chen 	struct tag *t;
216b9bc76b4SJoseph Chen 
217b9bc76b4SJoseph Chen 	t = atags_get_tag(ATAG_DDR_MEM);
218b9bc76b4SJoseph Chen 	if (t && t->u.ddr_mem.count) {
219b9bc76b4SJoseph Chen 		count = t->u.ddr_mem.count;
220b9bc76b4SJoseph Chen 		mem = calloc(count, sizeof(*mem));
221b9bc76b4SJoseph Chen 		if (!mem) {
222b9bc76b4SJoseph Chen 			printf("Calloc ddr memory failed\n");
223b9bc76b4SJoseph Chen 			return 0;
224b9bc76b4SJoseph Chen 		}
225b9bc76b4SJoseph Chen 
226b9bc76b4SJoseph Chen 		for (i = 0; i < count; i++) {
227b9bc76b4SJoseph Chen 			mem[i].base = t->u.ddr_mem.bank[i];
228b9bc76b4SJoseph Chen 			mem[i].size = t->u.ddr_mem.bank[i + count];
229b9bc76b4SJoseph Chen 		}
230b9bc76b4SJoseph Chen 
231b9bc76b4SJoseph Chen 		*out_count = count;
232b9bc76b4SJoseph Chen 		return mem;
233b9bc76b4SJoseph Chen 	}
234b9bc76b4SJoseph Chen #endif
235b9bc76b4SJoseph Chen 
236b9bc76b4SJoseph Chen 	/* Leagcy */
237b9bc76b4SJoseph Chen 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
238b9bc76b4SJoseph Chen 	if (ret) {
239b9bc76b4SJoseph Chen 		debug("DRAM init failed: %d\n", ret);
240b9bc76b4SJoseph Chen 		return NULL;
241b9bc76b4SJoseph Chen 	}
242b9bc76b4SJoseph Chen 	ret = ram_get_info(dev, &ram);
243b9bc76b4SJoseph Chen 	if (ret) {
244b9bc76b4SJoseph Chen 		debug("Cannot get DRAM size: %d\n", ret);
245b9bc76b4SJoseph Chen 		return NULL;
246b9bc76b4SJoseph Chen 	}
247b9bc76b4SJoseph Chen 
248b9bc76b4SJoseph Chen 	debug("SDRAM base=%lx, size=%lx\n",
249b9bc76b4SJoseph Chen 	      (unsigned long)ram.base, (unsigned long)ram.size);
250b9bc76b4SJoseph Chen 
251b9bc76b4SJoseph Chen 	count = 1;
252b9bc76b4SJoseph Chen 	mem = calloc(1, sizeof(*mem));
253b9bc76b4SJoseph Chen 	if (!mem) {
254b9bc76b4SJoseph Chen 		printf("Calloc ddr memory failed\n");
255b9bc76b4SJoseph Chen 		return 0;
256b9bc76b4SJoseph Chen 	}
257b9bc76b4SJoseph Chen 
258b9bc76b4SJoseph Chen 	for (i = 0; i < count; i++) {
259b9bc76b4SJoseph Chen 		mem[i].base = CONFIG_SYS_SDRAM_BASE;
260b9bc76b4SJoseph Chen 		mem[i].size = ram.size;
261b9bc76b4SJoseph Chen 	}
262b9bc76b4SJoseph Chen 
263b9bc76b4SJoseph Chen 	*out_count = count;
264b9bc76b4SJoseph Chen 	return mem;
265b9bc76b4SJoseph Chen }
266