xref: /aosp_15_r20/external/arm-trusted-firmware/plat/rockchip/common/params_setup.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #include <assert.h>
8*54fd6939SJiyong Park #include <errno.h>
9*54fd6939SJiyong Park #include <limits.h>
10*54fd6939SJiyong Park #include <string.h>
11*54fd6939SJiyong Park 
12*54fd6939SJiyong Park #include <lib/bl_aux_params/bl_aux_params.h>
13*54fd6939SJiyong Park #include <common/bl_common.h>
14*54fd6939SJiyong Park #include <common/debug.h>
15*54fd6939SJiyong Park #include <drivers/console.h>
16*54fd6939SJiyong Park #include <drivers/gpio.h>
17*54fd6939SJiyong Park #include <libfdt.h>
18*54fd6939SJiyong Park #include <lib/coreboot.h>
19*54fd6939SJiyong Park #include <lib/mmio.h>
20*54fd6939SJiyong Park #include <plat/common/platform.h>
21*54fd6939SJiyong Park 
22*54fd6939SJiyong Park #include <plat_params.h>
23*54fd6939SJiyong Park #include <plat_private.h>
24*54fd6939SJiyong Park 
25*54fd6939SJiyong Park static struct bl_aux_gpio_info rst_gpio = { .index = UINT_MAX } ;
26*54fd6939SJiyong Park static struct bl_aux_gpio_info poweroff_gpio = { .index = UINT_MAX };
27*54fd6939SJiyong Park static struct bl_aux_gpio_info suspend_gpio[10];
28*54fd6939SJiyong Park uint32_t suspend_gpio_cnt;
29*54fd6939SJiyong Park static struct bl_aux_rk_apio_info suspend_apio;
30*54fd6939SJiyong Park 
31*54fd6939SJiyong Park #if COREBOOT
dt_process_fdt(u_register_t param_from_bl2)32*54fd6939SJiyong Park static int dt_process_fdt(u_register_t param_from_bl2)
33*54fd6939SJiyong Park {
34*54fd6939SJiyong Park 	return -ENODEV;
35*54fd6939SJiyong Park }
36*54fd6939SJiyong Park #else
37*54fd6939SJiyong Park static uint32_t rk_uart_base = PLAT_RK_UART_BASE;
38*54fd6939SJiyong Park static uint32_t rk_uart_baudrate = PLAT_RK_UART_BAUDRATE;
39*54fd6939SJiyong Park static uint32_t rk_uart_clock = PLAT_RK_UART_CLOCK;
40*54fd6939SJiyong Park #define FDT_BUFFER_SIZE 0x20000
41*54fd6939SJiyong Park static uint8_t fdt_buffer[FDT_BUFFER_SIZE];
42*54fd6939SJiyong Park 
plat_get_fdt(void)43*54fd6939SJiyong Park void *plat_get_fdt(void)
44*54fd6939SJiyong Park {
45*54fd6939SJiyong Park 	return &fdt_buffer[0];
46*54fd6939SJiyong Park }
47*54fd6939SJiyong Park 
plat_rockchip_dt_process_fdt_uart(void * fdt)48*54fd6939SJiyong Park static void plat_rockchip_dt_process_fdt_uart(void *fdt)
49*54fd6939SJiyong Park {
50*54fd6939SJiyong Park 	const char *path_name = "/chosen";
51*54fd6939SJiyong Park 	const char *prop_name = "stdout-path";
52*54fd6939SJiyong Park 	int node_offset;
53*54fd6939SJiyong Park 	int stdout_path_len;
54*54fd6939SJiyong Park 	const char *stdout_path;
55*54fd6939SJiyong Park 	const char *separator;
56*54fd6939SJiyong Park 	const char *baud_start;
57*54fd6939SJiyong Park 	char serial_char;
58*54fd6939SJiyong Park 	int serial_no;
59*54fd6939SJiyong Park 	uint32_t uart_base;
60*54fd6939SJiyong Park 	uint32_t baud;
61*54fd6939SJiyong Park 
62*54fd6939SJiyong Park 	node_offset = fdt_path_offset(fdt, path_name);
63*54fd6939SJiyong Park 	if (node_offset < 0)
64*54fd6939SJiyong Park 		return;
65*54fd6939SJiyong Park 
66*54fd6939SJiyong Park 	stdout_path = fdt_getprop(fdt, node_offset, prop_name,
67*54fd6939SJiyong Park 				  &stdout_path_len);
68*54fd6939SJiyong Park 	if (stdout_path == NULL)
69*54fd6939SJiyong Park 		return;
70*54fd6939SJiyong Park 
71*54fd6939SJiyong Park 	/*
72*54fd6939SJiyong Park 	 * We expect something like:
73*54fd6939SJiyong Park 	 *   "serial0:baudrate"
74*54fd6939SJiyong Park 	 */
75*54fd6939SJiyong Park 	if (strncmp("serial", stdout_path, 6) != 0)
76*54fd6939SJiyong Park 		return;
77*54fd6939SJiyong Park 
78*54fd6939SJiyong Park 	serial_char = stdout_path[6];
79*54fd6939SJiyong Park 	serial_no = serial_char - '0';
80*54fd6939SJiyong Park 
81*54fd6939SJiyong Park 	switch (serial_no) {
82*54fd6939SJiyong Park 	case 0:
83*54fd6939SJiyong Park 		uart_base = UART0_BASE;
84*54fd6939SJiyong Park 		break;
85*54fd6939SJiyong Park 	case 1:
86*54fd6939SJiyong Park 		uart_base = UART1_BASE;
87*54fd6939SJiyong Park 		break;
88*54fd6939SJiyong Park 	case 2:
89*54fd6939SJiyong Park 		uart_base = UART2_BASE;
90*54fd6939SJiyong Park 		break;
91*54fd6939SJiyong Park #ifdef UART3_BASE
92*54fd6939SJiyong Park 	case 3:
93*54fd6939SJiyong Park 		uart_base = UART3_BASE;
94*54fd6939SJiyong Park 		break;
95*54fd6939SJiyong Park #endif
96*54fd6939SJiyong Park #ifdef UART4_BASE
97*54fd6939SJiyong Park 	case 4:
98*54fd6939SJiyong Park 		uart_base = UART4_BASE;
99*54fd6939SJiyong Park 		break;
100*54fd6939SJiyong Park #endif
101*54fd6939SJiyong Park #ifdef UART5_BASE
102*54fd6939SJiyong Park 	case 5:
103*54fd6939SJiyong Park 		uart_base = UART5_BASE;
104*54fd6939SJiyong Park 		break;
105*54fd6939SJiyong Park #endif
106*54fd6939SJiyong Park 	default:
107*54fd6939SJiyong Park 		return;
108*54fd6939SJiyong Park 	}
109*54fd6939SJiyong Park 
110*54fd6939SJiyong Park 	rk_uart_base = uart_base;
111*54fd6939SJiyong Park 
112*54fd6939SJiyong Park 	separator = strchr(stdout_path, ':');
113*54fd6939SJiyong Park 	if (!separator)
114*54fd6939SJiyong Park 		return;
115*54fd6939SJiyong Park 
116*54fd6939SJiyong Park 	baud = 0;
117*54fd6939SJiyong Park 	baud_start = separator + 1;
118*54fd6939SJiyong Park 	while (*baud_start != '\0') {
119*54fd6939SJiyong Park 		/*
120*54fd6939SJiyong Park 		 * uart binding is <baud>{<parity>{<bits>{...}}}
121*54fd6939SJiyong Park 		 * So the baudrate either is the whole string, or
122*54fd6939SJiyong Park 		 * we end in the parity characters.
123*54fd6939SJiyong Park 		 */
124*54fd6939SJiyong Park 		if (*baud_start == 'n' || *baud_start == 'o' ||
125*54fd6939SJiyong Park 		    *baud_start == 'e')
126*54fd6939SJiyong Park 			break;
127*54fd6939SJiyong Park 
128*54fd6939SJiyong Park 		baud = baud * 10 + (*baud_start - '0');
129*54fd6939SJiyong Park 		baud_start++;
130*54fd6939SJiyong Park 	}
131*54fd6939SJiyong Park 
132*54fd6939SJiyong Park 	rk_uart_baudrate = baud;
133*54fd6939SJiyong Park }
134*54fd6939SJiyong Park 
dt_process_fdt(u_register_t param_from_bl2)135*54fd6939SJiyong Park static int dt_process_fdt(u_register_t param_from_bl2)
136*54fd6939SJiyong Park {
137*54fd6939SJiyong Park 	void *fdt = plat_get_fdt();
138*54fd6939SJiyong Park 	int ret;
139*54fd6939SJiyong Park 
140*54fd6939SJiyong Park 	ret = fdt_open_into((void *)param_from_bl2, fdt, FDT_BUFFER_SIZE);
141*54fd6939SJiyong Park 	if (ret < 0)
142*54fd6939SJiyong Park 		return ret;
143*54fd6939SJiyong Park 
144*54fd6939SJiyong Park 	plat_rockchip_dt_process_fdt_uart(fdt);
145*54fd6939SJiyong Park 
146*54fd6939SJiyong Park 	return 0;
147*54fd6939SJiyong Park }
148*54fd6939SJiyong Park #endif
149*54fd6939SJiyong Park 
rockchip_get_uart_base(void)150*54fd6939SJiyong Park uint32_t rockchip_get_uart_base(void)
151*54fd6939SJiyong Park {
152*54fd6939SJiyong Park #if COREBOOT
153*54fd6939SJiyong Park 	return coreboot_serial.baseaddr;
154*54fd6939SJiyong Park #else
155*54fd6939SJiyong Park 	return rk_uart_base;
156*54fd6939SJiyong Park #endif
157*54fd6939SJiyong Park }
158*54fd6939SJiyong Park 
rockchip_get_uart_baudrate(void)159*54fd6939SJiyong Park uint32_t rockchip_get_uart_baudrate(void)
160*54fd6939SJiyong Park {
161*54fd6939SJiyong Park #if COREBOOT
162*54fd6939SJiyong Park 	return coreboot_serial.baud;
163*54fd6939SJiyong Park #else
164*54fd6939SJiyong Park 	return rk_uart_baudrate;
165*54fd6939SJiyong Park #endif
166*54fd6939SJiyong Park }
167*54fd6939SJiyong Park 
rockchip_get_uart_clock(void)168*54fd6939SJiyong Park uint32_t rockchip_get_uart_clock(void)
169*54fd6939SJiyong Park {
170*54fd6939SJiyong Park #if COREBOOT
171*54fd6939SJiyong Park 	return coreboot_serial.input_hertz;
172*54fd6939SJiyong Park #else
173*54fd6939SJiyong Park 	return rk_uart_clock;
174*54fd6939SJiyong Park #endif
175*54fd6939SJiyong Park }
176*54fd6939SJiyong Park 
plat_get_rockchip_gpio_reset(void)177*54fd6939SJiyong Park struct bl_aux_gpio_info *plat_get_rockchip_gpio_reset(void)
178*54fd6939SJiyong Park {
179*54fd6939SJiyong Park 	if (rst_gpio.index == UINT_MAX)
180*54fd6939SJiyong Park 		return NULL;
181*54fd6939SJiyong Park 
182*54fd6939SJiyong Park 	return &rst_gpio;
183*54fd6939SJiyong Park }
184*54fd6939SJiyong Park 
plat_get_rockchip_gpio_poweroff(void)185*54fd6939SJiyong Park struct bl_aux_gpio_info *plat_get_rockchip_gpio_poweroff(void)
186*54fd6939SJiyong Park {
187*54fd6939SJiyong Park 	if (poweroff_gpio.index == UINT_MAX)
188*54fd6939SJiyong Park 		return NULL;
189*54fd6939SJiyong Park 
190*54fd6939SJiyong Park 	return &poweroff_gpio;
191*54fd6939SJiyong Park }
192*54fd6939SJiyong Park 
plat_get_rockchip_suspend_gpio(uint32_t * count)193*54fd6939SJiyong Park struct bl_aux_gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count)
194*54fd6939SJiyong Park {
195*54fd6939SJiyong Park 	*count = suspend_gpio_cnt;
196*54fd6939SJiyong Park 
197*54fd6939SJiyong Park 	return &suspend_gpio[0];
198*54fd6939SJiyong Park }
199*54fd6939SJiyong Park 
plat_get_rockchip_suspend_apio(void)200*54fd6939SJiyong Park struct bl_aux_rk_apio_info *plat_get_rockchip_suspend_apio(void)
201*54fd6939SJiyong Park {
202*54fd6939SJiyong Park 	return &suspend_apio;
203*54fd6939SJiyong Park }
204*54fd6939SJiyong Park 
rk_aux_param_handler(struct bl_aux_param_header * param)205*54fd6939SJiyong Park static bool rk_aux_param_handler(struct bl_aux_param_header *param)
206*54fd6939SJiyong Park {
207*54fd6939SJiyong Park 	/* Store platform parameters for later processing if needed. */
208*54fd6939SJiyong Park 	switch (param->type) {
209*54fd6939SJiyong Park 	case BL_AUX_PARAM_RK_RESET_GPIO:
210*54fd6939SJiyong Park 		rst_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
211*54fd6939SJiyong Park 		return true;
212*54fd6939SJiyong Park 	case BL_AUX_PARAM_RK_POWEROFF_GPIO:
213*54fd6939SJiyong Park 		poweroff_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
214*54fd6939SJiyong Park 		return true;
215*54fd6939SJiyong Park 	case BL_AUX_PARAM_RK_SUSPEND_GPIO:
216*54fd6939SJiyong Park 		if (suspend_gpio_cnt >= ARRAY_SIZE(suspend_gpio)) {
217*54fd6939SJiyong Park 			ERROR("Exceeded the supported suspend GPIO number.\n");
218*54fd6939SJiyong Park 			return true;
219*54fd6939SJiyong Park 		}
220*54fd6939SJiyong Park 		suspend_gpio[suspend_gpio_cnt++] =
221*54fd6939SJiyong Park 			((struct bl_aux_param_gpio *)param)->gpio;
222*54fd6939SJiyong Park 		return true;
223*54fd6939SJiyong Park 	case BL_AUX_PARAM_RK_SUSPEND_APIO:
224*54fd6939SJiyong Park 		suspend_apio = ((struct bl_aux_param_rk_apio *)param)->apio;
225*54fd6939SJiyong Park 		return true;
226*54fd6939SJiyong Park 	}
227*54fd6939SJiyong Park 
228*54fd6939SJiyong Park 	return false;
229*54fd6939SJiyong Park }
230*54fd6939SJiyong Park 
params_early_setup(u_register_t plat_param_from_bl2)231*54fd6939SJiyong Park void params_early_setup(u_register_t plat_param_from_bl2)
232*54fd6939SJiyong Park {
233*54fd6939SJiyong Park 	int ret;
234*54fd6939SJiyong Park 
235*54fd6939SJiyong Park 	/*
236*54fd6939SJiyong Park 	 * Test if this is a FDT passed as a platform-specific parameter
237*54fd6939SJiyong Park 	 * block.
238*54fd6939SJiyong Park 	 */
239*54fd6939SJiyong Park 	ret = dt_process_fdt(plat_param_from_bl2);
240*54fd6939SJiyong Park 	if (!ret) {
241*54fd6939SJiyong Park 		return;
242*54fd6939SJiyong Park 	} else if (ret != -FDT_ERR_BADMAGIC) {
243*54fd6939SJiyong Park 		/*
244*54fd6939SJiyong Park 		 * If we found an FDT but couldn't parse it (e.g. corrupt, not
245*54fd6939SJiyong Park 		 * enough space), return and don't attempt to parse the param
246*54fd6939SJiyong Park 		 * as something else, since we know that will also fail. All
247*54fd6939SJiyong Park 		 * we're doing is setting up UART, this doesn't need to be
248*54fd6939SJiyong Park 		 * fatal.
249*54fd6939SJiyong Park 		 */
250*54fd6939SJiyong Park 		WARN("%s: found FDT but could not parse: error %d\n",
251*54fd6939SJiyong Park 		     __func__, ret);
252*54fd6939SJiyong Park 		return;
253*54fd6939SJiyong Park 	}
254*54fd6939SJiyong Park 
255*54fd6939SJiyong Park 	bl_aux_params_parse(plat_param_from_bl2, rk_aux_param_handler);
256*54fd6939SJiyong Park }
257