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