xref: /rk3399_ARM-atf/plat/rockchip/common/params_setup.c (revision 30970e0f2979e297831f8ea27466aa3e67992ce4)
1 /*
2  * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <errno.h>
9 #include <string.h>
10 
11 #include <lib/bl_aux_params/bl_aux_params.h>
12 #include <common/bl_common.h>
13 #include <common/debug.h>
14 #include <drivers/console.h>
15 #include <drivers/gpio.h>
16 #include <libfdt.h>
17 #include <lib/coreboot.h>
18 #include <lib/mmio.h>
19 #include <plat/common/platform.h>
20 
21 #include <plat_params.h>
22 #include <plat_private.h>
23 
24 static struct bl_aux_gpio_info rst_gpio;
25 static struct bl_aux_gpio_info poweroff_gpio;
26 static struct bl_aux_gpio_info suspend_gpio[10];
27 uint32_t suspend_gpio_cnt;
28 static struct bl_aux_rk_apio_info suspend_apio;
29 static uint32_t rk_uart_base = PLAT_RK_UART_BASE;
30 static uint32_t rk_uart_baudrate = PLAT_RK_UART_BAUDRATE;
31 
32 uint32_t rockchip_get_uart_base(void)
33 {
34 	return rk_uart_base;
35 }
36 
37 uint32_t rockchip_get_uart_baudrate(void)
38 {
39 	return rk_uart_baudrate;
40 }
41 
42 #if COREBOOT
43 static int dt_process_fdt(u_register_t param_from_bl2)
44 {
45 	return -ENODEV;
46 }
47 #else
48 static uint8_t fdt_buffer[0x10000];
49 
50 void *plat_get_fdt(void)
51 {
52 	return &fdt_buffer[0];
53 }
54 
55 static void plat_rockchip_dt_process_fdt_uart(void *fdt)
56 {
57 	const char *path_name = "/chosen";
58 	const char *prop_name = "stdout-path";
59 	int node_offset;
60 	int stdout_path_len;
61 	const char *stdout_path;
62 	const char *separator;
63 	const char *baud_start;
64 	char serial_char;
65 	int serial_no;
66 	uint32_t uart_base;
67 	uint32_t baud;
68 
69 	node_offset = fdt_path_offset(fdt, path_name);
70 	if (node_offset < 0)
71 		return;
72 
73 	stdout_path = fdt_getprop(fdt, node_offset, prop_name,
74 				  &stdout_path_len);
75 	if (stdout_path == NULL)
76 		return;
77 
78 	/*
79 	 * We expect something like:
80 	 *   "serial0:baudrate"
81 	 */
82 	if (strncmp("serial", stdout_path, 6) != 0)
83 		return;
84 
85 	serial_char = stdout_path[6];
86 	serial_no = serial_char - '0';
87 
88 	switch (serial_no) {
89 	case 0:
90 		uart_base = UART0_BASE;
91 		break;
92 	case 1:
93 		uart_base = UART1_BASE;
94 		break;
95 	case 2:
96 		uart_base = UART2_BASE;
97 		break;
98 #ifdef UART3_BASE
99 	case 3:
100 		uart_base = UART3_BASE;
101 		break;
102 #endif
103 #ifdef UART4_BASE
104 	case 4:
105 		uart_base = UART4_BASE;
106 		break;
107 #endif
108 #ifdef UART5_BASE
109 	case 5:
110 		uart_base = UART5_BASE;
111 		break;
112 #endif
113 	default:
114 		return;
115 	}
116 
117 	rk_uart_base = uart_base;
118 
119 	separator = strchr(stdout_path, ':');
120 	if (!separator)
121 		return;
122 
123 	baud = 0;
124 	baud_start = separator + 1;
125 	while (*baud_start != '\0') {
126 		/*
127 		 * uart binding is <baud>{<parity>{<bits>{...}}}
128 		 * So the baudrate either is the whole string, or
129 		 * we end in the parity characters.
130 		 */
131 		if (*baud_start == 'n' || *baud_start == 'o' ||
132 		    *baud_start == 'e')
133 			break;
134 
135 		baud = baud * 10 + (*baud_start - '0');
136 		baud_start++;
137 	}
138 
139 	rk_uart_baudrate = baud;
140 }
141 
142 static int dt_process_fdt(u_register_t param_from_bl2)
143 {
144 	void *fdt = plat_get_fdt();
145 	int ret;
146 
147 	ret = fdt_open_into((void *)param_from_bl2, fdt, 0x10000);
148 	if (ret < 0)
149 		return ret;
150 
151 	plat_rockchip_dt_process_fdt_uart(fdt);
152 
153 	return 0;
154 }
155 #endif
156 
157 struct bl_aux_gpio_info *plat_get_rockchip_gpio_reset(void)
158 {
159 	return &rst_gpio;
160 }
161 
162 struct bl_aux_gpio_info *plat_get_rockchip_gpio_poweroff(void)
163 {
164 	return &poweroff_gpio;
165 }
166 
167 struct bl_aux_gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count)
168 {
169 	*count = suspend_gpio_cnt;
170 
171 	return &suspend_gpio[0];
172 }
173 
174 struct bl_aux_rk_apio_info *plat_get_rockchip_suspend_apio(void)
175 {
176 	return &suspend_apio;
177 }
178 
179 static bool rk_aux_param_handler(struct bl_aux_param_header *param)
180 {
181 	/* Store platform parameters for later processing if needed. */
182 	switch (param->type) {
183 	case BL_AUX_PARAM_RK_RESET_GPIO:
184 		rst_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
185 		return true;
186 	case BL_AUX_PARAM_RK_POWEROFF_GPIO:
187 		poweroff_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
188 		return true;
189 	case BL_AUX_PARAM_RK_SUSPEND_GPIO:
190 		if (suspend_gpio_cnt >= ARRAY_SIZE(suspend_gpio)) {
191 			ERROR("Exceeded the supported suspend GPIO number.\n");
192 			return true;
193 		}
194 		suspend_gpio[suspend_gpio_cnt++] =
195 			((struct bl_aux_param_gpio *)param)->gpio;
196 		return true;
197 	case BL_AUX_PARAM_RK_SUSPEND_APIO:
198 		suspend_apio = ((struct bl_aux_param_rk_apio *)param)->apio;
199 		return true;
200 	}
201 
202 	return false;
203 }
204 
205 void params_early_setup(u_register_t plat_param_from_bl2)
206 {
207 	/*
208 	 * Test if this is a FDT passed as a platform-specific parameter
209 	 * block.
210 	 */
211 	if (!dt_process_fdt(plat_param_from_bl2))
212 		return;
213 
214 	bl_aux_params_parse(plat_param_from_bl2, rk_aux_param_handler);
215 }
216