xref: /rk3399_ARM-atf/plat/allwinner/common/sunxi_bl31_setup.c (revision c3cf06f1a3a9b9ee8ac7a0ae505f95c45f7dca84)
1 /*
2  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch.h>
8 #include <assert.h>
9 #include <console.h>
10 #include <debug.h>
11 #include <generic_delay_timer.h>
12 #include <gicv2.h>
13 #include <libfdt.h>
14 #include <platform.h>
15 #include <platform_def.h>
16 #include <sunxi_def.h>
17 #include <sunxi_mmap.h>
18 #include <sunxi_private.h>
19 #include <uart_16550.h>
20 
21 
22 static entry_point_info_t bl32_image_ep_info;
23 static entry_point_info_t bl33_image_ep_info;
24 
25 static console_16550_t console;
26 
27 static const gicv2_driver_data_t sunxi_gic_data = {
28 	.gicd_base = SUNXI_GICD_BASE,
29 	.gicc_base = SUNXI_GICC_BASE,
30 };
31 
32 /*
33  * Try to find a DTB loaded in memory by previous stages.
34  *
35  * At the moment we implement a heuristic to find the DTB attached to U-Boot:
36  * U-Boot appends its DTB to the end of the image. Assuming that BL33 is
37  * U-Boot, try to find the size of the U-Boot image to learn the DTB address.
38  * The generic ARMv8 U-Boot image contains the load address and its size
39  * as u64 variables at the beginning of the image. There might be padding
40  * or other headers before that data, so scan the first 2KB after the BL33
41  * entry point to find the load address, which should be followed by the
42  * size. Adding those together gives us the address of the DTB.
43  */
44 static void *sunxi_find_dtb(void)
45 {
46 	uint64_t *u_boot_base;
47 	int i;
48 
49 	u_boot_base = (void *)(SUNXI_DRAM_VIRT_BASE + SUNXI_DRAM_SEC_SIZE);
50 
51 	for (i = 0; i < 2048 / sizeof(uint64_t); i++) {
52 		uint32_t *dtb_base;
53 
54 		if (u_boot_base[i] != PLAT_SUNXI_NS_IMAGE_OFFSET)
55 			continue;
56 
57 		/* Does the suspected U-Boot size look anyhow reasonable? */
58 		if (u_boot_base[i + 1] >= 256 * 1024 * 1024)
59 			continue;
60 
61 		/* end of the image: base address + size */
62 		dtb_base = (void *)((char *)u_boot_base + u_boot_base[i + 1]);
63 
64 		if (fdt_check_header(dtb_base) != 0)
65 			continue;
66 
67 		return dtb_base;
68 	}
69 
70 	return NULL;
71 }
72 
73 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
74 				u_register_t arg2, u_register_t arg3)
75 {
76 	/* Initialize the debug console as soon as possible */
77 	console_16550_register(SUNXI_UART0_BASE, SUNXI_UART0_CLK_IN_HZ,
78 			       SUNXI_UART0_BAUDRATE, &console);
79 
80 #ifdef BL32_BASE
81 	/* Populate entry point information for BL32 */
82 	SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
83 	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
84 	bl32_image_ep_info.pc = BL32_BASE;
85 #endif
86 
87 	/* Populate entry point information for BL33 */
88 	SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
89 	/*
90 	 * Tell BL31 where the non-trusted software image
91 	 * is located and the entry state information
92 	 */
93 	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
94 	bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
95 					  DISABLE_ALL_EXCEPTIONS);
96 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
97 
98 	/* Turn off all secondary CPUs */
99 	sunxi_disable_secondary_cpus(plat_my_core_pos());
100 }
101 
102 void bl31_plat_arch_setup(void)
103 {
104 	sunxi_configure_mmu_el3(0);
105 }
106 
107 void bl31_platform_setup(void)
108 {
109 	const char *soc_name;
110 	uint16_t soc_id = sunxi_read_soc_id();
111 	void *fdt;
112 
113 	switch (soc_id) {
114 	case SUNXI_SOC_A64:
115 		soc_name = "A64/H64/R18";
116 		break;
117 	case SUNXI_SOC_H5:
118 		soc_name = "H5";
119 		break;
120 	case SUNXI_SOC_H6:
121 		soc_name = "H6";
122 		break;
123 	default:
124 		soc_name = "unknown";
125 		break;
126 	}
127 	NOTICE("BL31: Detected Allwinner %s SoC (%04x)\n", soc_name, soc_id);
128 
129 	generic_delay_timer_init();
130 
131 	fdt = sunxi_find_dtb();
132 	if (fdt) {
133 		const char *model;
134 		int length;
135 
136 		model = fdt_getprop(fdt, 0, "model", &length);
137 		NOTICE("BL31: Found U-Boot DTB at %p, model: %s\n", fdt,
138 		     model ?: "unknown");
139 	} else {
140 		NOTICE("BL31: No DTB found.\n");
141 	}
142 
143 	/* Configure the interrupt controller */
144 	gicv2_driver_init(&sunxi_gic_data);
145 	gicv2_distif_init();
146 	gicv2_pcpu_distif_init();
147 	gicv2_cpuif_enable();
148 
149 	sunxi_security_setup();
150 
151 	sunxi_pmic_setup(soc_id, fdt);
152 
153 	INFO("BL31: Platform setup done\n");
154 }
155 
156 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
157 {
158 	assert(sec_state_is_valid(type) != 0);
159 
160 	if (type == NON_SECURE)
161 		return &bl33_image_ep_info;
162 
163 	if ((type == SECURE) && bl32_image_ep_info.pc)
164 		return &bl32_image_ep_info;
165 
166 	return NULL;
167 }
168