summaryrefslogtreecommitdiffstats
path: root/plat/rockchip/common/params_setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'plat/rockchip/common/params_setup.c')
-rw-r--r--plat/rockchip/common/params_setup.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/plat/rockchip/common/params_setup.c b/plat/rockchip/common/params_setup.c
new file mode 100644
index 0000000..68054ad
--- /dev/null
+++ b/plat/rockchip/common/params_setup.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+
+#include <lib/bl_aux_params/bl_aux_params.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/gpio.h>
+#include <libfdt.h>
+#include <lib/coreboot.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <plat_params.h>
+#include <plat_private.h>
+
+static struct bl_aux_gpio_info rst_gpio = { .index = UINT_MAX } ;
+static struct bl_aux_gpio_info poweroff_gpio = { .index = UINT_MAX };
+static struct bl_aux_gpio_info suspend_gpio[10];
+uint32_t suspend_gpio_cnt;
+static struct bl_aux_rk_apio_info suspend_apio;
+
+#if COREBOOT
+static int dt_process_fdt(u_register_t param_from_bl2)
+{
+ return -ENODEV;
+}
+#else
+static uint32_t rk_uart_base = PLAT_RK_UART_BASE;
+static uint32_t rk_uart_baudrate = PLAT_RK_UART_BAUDRATE;
+static uint32_t rk_uart_clock = PLAT_RK_UART_CLOCK;
+#define FDT_BUFFER_SIZE 0x20000
+static uint64_t fdt_buffer[FDT_BUFFER_SIZE / 8];
+
+void *plat_get_fdt(void)
+{
+ return &fdt_buffer[0];
+}
+
+static void plat_rockchip_dt_process_fdt_uart(void *fdt)
+{
+ const char *path_name = "/chosen";
+ const char *prop_name = "stdout-path";
+ int node_offset;
+ int stdout_path_len;
+ const char *stdout_path;
+ const char *separator;
+ const char *baud_start;
+ char serial_char;
+ int serial_no;
+ uint32_t uart_base;
+ uint32_t baud;
+
+ node_offset = fdt_path_offset(fdt, path_name);
+ if (node_offset < 0)
+ return;
+
+ stdout_path = fdt_getprop(fdt, node_offset, prop_name,
+ &stdout_path_len);
+ if (stdout_path == NULL)
+ return;
+
+ /*
+ * We expect something like:
+ * "serial0:baudrate"
+ */
+ if (strncmp("serial", stdout_path, 6) != 0)
+ return;
+
+ serial_char = stdout_path[6];
+ serial_no = serial_char - '0';
+
+ switch (serial_no) {
+ case 0:
+ uart_base = UART0_BASE;
+ break;
+ case 1:
+ uart_base = UART1_BASE;
+ break;
+ case 2:
+ uart_base = UART2_BASE;
+ break;
+#ifdef UART3_BASE
+ case 3:
+ uart_base = UART3_BASE;
+ break;
+#endif
+#ifdef UART4_BASE
+ case 4:
+ uart_base = UART4_BASE;
+ break;
+#endif
+#ifdef UART5_BASE
+ case 5:
+ uart_base = UART5_BASE;
+ break;
+#endif
+ default:
+ return;
+ }
+
+ rk_uart_base = uart_base;
+
+ separator = strchr(stdout_path, ':');
+ if (!separator)
+ return;
+
+ baud = 0;
+ baud_start = separator + 1;
+ while (*baud_start != '\0') {
+ /*
+ * uart binding is <baud>{<parity>{<bits>{...}}}
+ * So the baudrate either is the whole string, or
+ * we end in the parity characters.
+ */
+ if (*baud_start == 'n' || *baud_start == 'o' ||
+ *baud_start == 'e')
+ break;
+
+ baud = baud * 10 + (*baud_start - '0');
+ baud_start++;
+ }
+
+ rk_uart_baudrate = baud;
+}
+
+static int dt_process_fdt(u_register_t param_from_bl2)
+{
+ void *fdt = plat_get_fdt();
+ int ret;
+
+ ret = fdt_open_into((void *)param_from_bl2, fdt, FDT_BUFFER_SIZE);
+ if (ret < 0)
+ return ret;
+
+ plat_rockchip_dt_process_fdt_uart(fdt);
+
+ return 0;
+}
+#endif
+
+uint32_t rockchip_get_uart_base(void)
+{
+#if COREBOOT
+ return coreboot_serial.baseaddr;
+#else
+ return rk_uart_base;
+#endif
+}
+
+uint32_t rockchip_get_uart_baudrate(void)
+{
+#if COREBOOT
+ return coreboot_serial.baud;
+#else
+ return rk_uart_baudrate;
+#endif
+}
+
+uint32_t rockchip_get_uart_clock(void)
+{
+#if COREBOOT
+ return coreboot_serial.input_hertz;
+#else
+ return rk_uart_clock;
+#endif
+}
+
+struct bl_aux_gpio_info *plat_get_rockchip_gpio_reset(void)
+{
+ if (rst_gpio.index == UINT_MAX)
+ return NULL;
+
+ return &rst_gpio;
+}
+
+struct bl_aux_gpio_info *plat_get_rockchip_gpio_poweroff(void)
+{
+ if (poweroff_gpio.index == UINT_MAX)
+ return NULL;
+
+ return &poweroff_gpio;
+}
+
+struct bl_aux_gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count)
+{
+ *count = suspend_gpio_cnt;
+
+ return &suspend_gpio[0];
+}
+
+struct bl_aux_rk_apio_info *plat_get_rockchip_suspend_apio(void)
+{
+ return &suspend_apio;
+}
+
+static bool rk_aux_param_handler(struct bl_aux_param_header *param)
+{
+ /* Store platform parameters for later processing if needed. */
+ switch (param->type) {
+ case BL_AUX_PARAM_RK_RESET_GPIO:
+ rst_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
+ return true;
+ case BL_AUX_PARAM_RK_POWEROFF_GPIO:
+ poweroff_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
+ return true;
+ case BL_AUX_PARAM_RK_SUSPEND_GPIO:
+ if (suspend_gpio_cnt >= ARRAY_SIZE(suspend_gpio)) {
+ ERROR("Exceeded the supported suspend GPIO number.\n");
+ return true;
+ }
+ suspend_gpio[suspend_gpio_cnt++] =
+ ((struct bl_aux_param_gpio *)param)->gpio;
+ return true;
+ case BL_AUX_PARAM_RK_SUSPEND_APIO:
+ suspend_apio = ((struct bl_aux_param_rk_apio *)param)->apio;
+ return true;
+ }
+
+ return false;
+}
+
+void params_early_setup(u_register_t plat_param_from_bl2)
+{
+ int ret;
+
+ /*
+ * Test if this is a FDT passed as a platform-specific parameter
+ * block.
+ */
+ ret = dt_process_fdt(plat_param_from_bl2);
+ if (!ret) {
+ return;
+ } else if (ret != -FDT_ERR_BADMAGIC) {
+ /*
+ * If we found an FDT but couldn't parse it (e.g. corrupt, not
+ * enough space), return and don't attempt to parse the param
+ * as something else, since we know that will also fail. All
+ * we're doing is setting up UART, this doesn't need to be
+ * fatal.
+ */
+ WARN("%s: found FDT but could not parse: error %d\n",
+ __func__, ret);
+ return;
+ }
+
+ bl_aux_params_parse(plat_param_from_bl2, rk_aux_param_handler);
+}