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 31 uint32_t rockchip_get_uart_base(void) 32 { 33 return rk_uart_base; 34 } 35 36 #if COREBOOT 37 static int dt_process_fdt(u_register_t param_from_bl2) 38 { 39 return -ENODEV; 40 } 41 #else 42 static uint8_t fdt_buffer[0x10000]; 43 44 void *plat_get_fdt(void) 45 { 46 return &fdt_buffer[0]; 47 } 48 49 static void plat_rockchip_dt_process_fdt_uart(void *fdt) 50 { 51 const char *path_name = "/chosen"; 52 const char *prop_name = "stdout-path"; 53 int node_offset; 54 int stdout_path_len; 55 const char *stdout_path; 56 char serial_char; 57 int serial_no; 58 uint32_t uart_base; 59 60 node_offset = fdt_path_offset(fdt, path_name); 61 if (node_offset < 0) 62 return; 63 64 stdout_path = fdt_getprop(fdt, node_offset, prop_name, 65 &stdout_path_len); 66 if (stdout_path == NULL) 67 return; 68 69 /* 70 * We expect something like: 71 * "serial0:..."" 72 */ 73 if (strncmp("serial", stdout_path, 6) != 0) 74 return; 75 76 serial_char = stdout_path[6]; 77 serial_no = serial_char - '0'; 78 79 switch (serial_no) { 80 case 0: 81 uart_base = UART0_BASE; 82 break; 83 case 1: 84 uart_base = UART1_BASE; 85 break; 86 case 2: 87 uart_base = UART2_BASE; 88 break; 89 #ifdef UART3_BASE 90 case 3: 91 uart_base = UART3_BASE; 92 break; 93 #endif 94 #ifdef UART4_BASE 95 case 4: 96 uart_base = UART4_BASE; 97 break; 98 #endif 99 #ifdef UART5_BASE 100 case 5: 101 uart_base = UART5_BASE; 102 break; 103 #endif 104 default: 105 return; 106 } 107 108 rk_uart_base = uart_base; 109 } 110 111 static int dt_process_fdt(u_register_t param_from_bl2) 112 { 113 void *fdt = plat_get_fdt(); 114 int ret; 115 116 ret = fdt_open_into((void *)param_from_bl2, fdt, 0x10000); 117 if (ret < 0) 118 return ret; 119 120 plat_rockchip_dt_process_fdt_uart(fdt); 121 122 return 0; 123 } 124 #endif 125 126 struct bl_aux_gpio_info *plat_get_rockchip_gpio_reset(void) 127 { 128 return &rst_gpio; 129 } 130 131 struct bl_aux_gpio_info *plat_get_rockchip_gpio_poweroff(void) 132 { 133 return &poweroff_gpio; 134 } 135 136 struct bl_aux_gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count) 137 { 138 *count = suspend_gpio_cnt; 139 140 return &suspend_gpio[0]; 141 } 142 143 struct bl_aux_rk_apio_info *plat_get_rockchip_suspend_apio(void) 144 { 145 return &suspend_apio; 146 } 147 148 static bool rk_aux_param_handler(struct bl_aux_param_header *param) 149 { 150 /* Store platform parameters for later processing if needed. */ 151 switch (param->type) { 152 case BL_AUX_PARAM_RK_RESET_GPIO: 153 rst_gpio = ((struct bl_aux_param_gpio *)param)->gpio; 154 return true; 155 case BL_AUX_PARAM_RK_POWEROFF_GPIO: 156 poweroff_gpio = ((struct bl_aux_param_gpio *)param)->gpio; 157 return true; 158 case BL_AUX_PARAM_RK_SUSPEND_GPIO: 159 if (suspend_gpio_cnt >= ARRAY_SIZE(suspend_gpio)) { 160 ERROR("Exceeded the supported suspend GPIO number.\n"); 161 return true; 162 } 163 suspend_gpio[suspend_gpio_cnt++] = 164 ((struct bl_aux_param_gpio *)param)->gpio; 165 return true; 166 case BL_AUX_PARAM_RK_SUSPEND_APIO: 167 suspend_apio = ((struct bl_aux_param_rk_apio *)param)->apio; 168 return true; 169 } 170 171 return false; 172 } 173 174 void params_early_setup(u_register_t plat_param_from_bl2) 175 { 176 /* 177 * Test if this is a FDT passed as a platform-specific parameter 178 * block. 179 */ 180 if (!dt_process_fdt(plat_param_from_bl2)) 181 return; 182 183 bl_aux_params_parse(plat_param_from_bl2, rk_aux_param_handler); 184 } 185