diff options
Diffstat (limited to 'arch/arm/boards/tqma6ulx/lowlevel.c')
-rw-r--r-- | arch/arm/boards/tqma6ulx/lowlevel.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/arch/arm/boards/tqma6ulx/lowlevel.c b/arch/arm/boards/tqma6ulx/lowlevel.c new file mode 100644 index 0000000000..5fd997d2ec --- /dev/null +++ b/arch/arm/boards/tqma6ulx/lowlevel.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2019 Rouven Czerwinski, Pengutronix + */ +#define pr_fmt(fmt) "tqma6ul: " fmt + +#include <common.h> +#include <debug_ll.h> +#include <mach/imx/debug_ll.h> +#include <firmware.h> +#include <mach/imx/generic.h> +#include <asm/barebox-arm.h> +#include <mach/imx/esdctl.h> +#include <mach/imx/iomux-mx6ul.h> +#include <asm/cache.h> +#include <pbl/i2c.h> +#include <boards/tq/tq_eeprom.h> +#include <tee/optee.h> + +#include "tqma6ulx.h" + +extern char __dtb_z_imx6ul_tqma6ul2_mba6ulx_start[]; +extern char __dtb_z_imx6ul_tqma6ul2l_mba6ulx_start[]; +extern char __dtb_z_imx6ull_tqma6ull2_mba6ulx_start[]; +extern char __dtb_z_imx6ull_tqma6ull2l_mba6ulx_start[]; + +static void setup_uart(void) +{ + imx6_ungate_all_peripherals(); + + /* + * Default pad configuration on this board, no explicit config needed + */ + imx6_uart_setup((void *)MX6_UART1_BASE_ADDR); + pbl_set_putc(imx_uart_putc, (void *)MX6_UART1_BASE_ADDR); + + pr_debug("\n"); + +} + +static void *read_eeprom(void) +{ + struct pbl_i2c *i2c; + struct tq_eeprom *eeprom; + void __iomem *iomux = (void *)MX6_IOMUXC_BASE_ADDR; + void *fdt = __dtb_z_imx6ul_tqma6ul2l_mba6ulx_start; + + imx_setup_pad(iomux, MX6_PAD_UART2_TX_DATA__I2C4_SCL | MUX_PAD_CTRL(0x1b8b0)); + imx_setup_pad(iomux, MX6_PAD_UART2_RX_DATA__I2C4_SDA | MUX_PAD_CTRL(0x1b8b0)); + + i2c = imx6_i2c_early_init(IOMEM(MX6_I2C4_BASE_ADDR)); + + eeprom = pbl_tq_read_eeprom(i2c, 0x50, I2C_ADDR_16_BIT); + if (!eeprom) { + pr_err("Cannot read EEPROM\n"); + goto out; + } + + pr_info("Board: %s\n", eeprom->id); + + if (!strcmp(eeprom->id, "TQMa6UL2L-AB.0202")) + fdt = __dtb_z_imx6ul_tqma6ul2l_mba6ulx_start; + else + pr_err("Unknown board type\n"); +out: + return fdt; +} + +static void noinline start_mba6ulx(u32 r0) +{ + void *fdt; + int tee_size; + void *tee; + + setup_uart(); + + fdt = read_eeprom(); + + /* Enable normal/secure r/w for TZC380 region0 */ + writel(0xf0000000, 0x021D0108); + + /* + * Chainloading barebox will pass a device tree within the RAM in r0, + * skip OP-TEE early loading in this case + */ + if (IS_ENABLED(CONFIG_FIRMWARE_TQMA6UL_OPTEE) && + !(r0 > MX6_MMDC_P0_BASE_ADDR && + r0 < MX6_MMDC_P0_BASE_ADDR + SZ_256M)) { + get_builtin_firmware(mba6ul_optee_bin, &tee, &tee_size); + + memset((void *)OPTEE_OVERLAY_LOCATION, 0, 0x1000); + + start_optee_early(NULL, tee); + } + + imx6ul_barebox_entry(fdt); +} + +ENTRY_FUNCTION(start_imx6ul_mba6ulx, r0, r1, r2) +{ + + imx6ul_cpu_lowlevel_init(); + + arm_setup_stack(0x00910000); + + if (IS_ENABLED(CONFIG_DEBUG_LL)) { + imx6_uart_setup_ll(); + putc_ll('>'); + } + + relocate_to_current_adr(); + setup_c(); + barrier(); + + start_mba6ulx(r0); +} |