13a0398d7SOtavio Salvador /*
23a0398d7SOtavio Salvador * Freescale i.MX28 Boot setup
33a0398d7SOtavio Salvador *
43a0398d7SOtavio Salvador * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
53a0398d7SOtavio Salvador * on behalf of DENX Software Engineering GmbH
63a0398d7SOtavio Salvador *
71a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
83a0398d7SOtavio Salvador */
93a0398d7SOtavio Salvador
103a0398d7SOtavio Salvador #include <common.h>
113a0398d7SOtavio Salvador #include <config.h>
123a0398d7SOtavio Salvador #include <asm/io.h>
133a0398d7SOtavio Salvador #include <asm/arch/imx-regs.h>
143a0398d7SOtavio Salvador #include <asm/arch/sys_proto.h>
153a0398d7SOtavio Salvador #include <asm/gpio.h>
1665ed5e85SMarek Vasut #include <linux/compiler.h>
173a0398d7SOtavio Salvador
181e0cf5c3SOtavio Salvador #include "mxs_init.h"
193a0398d7SOtavio Salvador
2065ed5e85SMarek Vasut DECLARE_GLOBAL_DATA_PTR;
219926eb31SMarek Vasut static gd_t gdata __section(".data");
22bb2637beSStefano Babic #ifdef CONFIG_SPL_SERIAL_SUPPORT
239926eb31SMarek Vasut static bd_t bdata __section(".data");
24bb2637beSStefano Babic #endif
2565ed5e85SMarek Vasut
263a0398d7SOtavio Salvador /*
273a0398d7SOtavio Salvador * This delay function is intended to be used only in early stage of boot, where
283a0398d7SOtavio Salvador * clock are not set up yet. The timer used here is reset on every boot and
293a0398d7SOtavio Salvador * takes a few seconds to roll. The boot doesn't take that long, so to keep the
303a0398d7SOtavio Salvador * code simple, it doesn't take rolling into consideration.
313a0398d7SOtavio Salvador */
early_delay(int delay)323a0398d7SOtavio Salvador void early_delay(int delay)
333a0398d7SOtavio Salvador {
34d82f05fcSMarek Vasut struct mxs_digctl_regs *digctl_regs =
35d82f05fcSMarek Vasut (struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
36d82f05fcSMarek Vasut
37d82f05fcSMarek Vasut uint32_t st = readl(&digctl_regs->hw_digctl_microseconds);
383a0398d7SOtavio Salvador st += delay;
39d82f05fcSMarek Vasut while (st > readl(&digctl_regs->hw_digctl_microseconds))
403a0398d7SOtavio Salvador ;
413a0398d7SOtavio Salvador }
423a0398d7SOtavio Salvador
43*5c519934SMarek Vasut #if defined(CONFIG_MX23)
443a0398d7SOtavio Salvador #define MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
45a918a53cSMarek Vasut static const iomux_cfg_t iomux_boot[] = {
46f942f7d9SOtavio Salvador MX23_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD,
47f942f7d9SOtavio Salvador MX23_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD,
48f942f7d9SOtavio Salvador MX23_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD,
49f942f7d9SOtavio Salvador MX23_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD,
50f942f7d9SOtavio Salvador MX23_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD,
51f942f7d9SOtavio Salvador MX23_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD,
523a0398d7SOtavio Salvador };
53*5c519934SMarek Vasut #endif
543a0398d7SOtavio Salvador
mxs_get_bootmode_index(void)55a918a53cSMarek Vasut static uint8_t mxs_get_bootmode_index(void)
563a0398d7SOtavio Salvador {
573a0398d7SOtavio Salvador uint8_t bootmode = 0;
583a0398d7SOtavio Salvador int i;
593a0398d7SOtavio Salvador uint8_t masked;
603a0398d7SOtavio Salvador
6132f9ef3eSJörg Krause #if defined(CONFIG_MX23)
623a0398d7SOtavio Salvador /* Setup IOMUX of bootmode pads to GPIO */
633a0398d7SOtavio Salvador mxs_iomux_setup_multiple_pads(iomux_boot, ARRAY_SIZE(iomux_boot));
643a0398d7SOtavio Salvador
65f942f7d9SOtavio Salvador /* Setup bootmode pins as GPIO input */
66f942f7d9SOtavio Salvador gpio_direction_input(MX23_PAD_LCD_D00__GPIO_1_0);
67f942f7d9SOtavio Salvador gpio_direction_input(MX23_PAD_LCD_D01__GPIO_1_1);
68f942f7d9SOtavio Salvador gpio_direction_input(MX23_PAD_LCD_D02__GPIO_1_2);
69f942f7d9SOtavio Salvador gpio_direction_input(MX23_PAD_LCD_D03__GPIO_1_3);
70f942f7d9SOtavio Salvador gpio_direction_input(MX23_PAD_LCD_D05__GPIO_1_5);
71f942f7d9SOtavio Salvador
72f942f7d9SOtavio Salvador /* Read bootmode pads */
73f942f7d9SOtavio Salvador bootmode |= (gpio_get_value(MX23_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0;
74f942f7d9SOtavio Salvador bootmode |= (gpio_get_value(MX23_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1;
75f942f7d9SOtavio Salvador bootmode |= (gpio_get_value(MX23_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2;
76f942f7d9SOtavio Salvador bootmode |= (gpio_get_value(MX23_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3;
77f942f7d9SOtavio Salvador bootmode |= (gpio_get_value(MX23_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5;
78f942f7d9SOtavio Salvador #elif defined(CONFIG_MX28)
7932f9ef3eSJörg Krause /* The global boot mode will be detected by ROM code and its value
8032f9ef3eSJörg Krause * is stored at the fixed address 0x00019BF0 in OCRAM.
8132f9ef3eSJörg Krause */
8232f9ef3eSJörg Krause #define GLOBAL_BOOT_MODE_ADDR 0x00019BF0
8332f9ef3eSJörg Krause bootmode = __raw_readl(GLOBAL_BOOT_MODE_ADDR);
84f942f7d9SOtavio Salvador #endif
853a0398d7SOtavio Salvador
86fa7a51cbSOtavio Salvador for (i = 0; i < ARRAY_SIZE(mxs_boot_modes); i++) {
87fa7a51cbSOtavio Salvador masked = bootmode & mxs_boot_modes[i].boot_mask;
88fa7a51cbSOtavio Salvador if (masked == mxs_boot_modes[i].boot_pads)
893a0398d7SOtavio Salvador break;
903a0398d7SOtavio Salvador }
913a0398d7SOtavio Salvador
923a0398d7SOtavio Salvador return i;
933a0398d7SOtavio Salvador }
943a0398d7SOtavio Salvador
mxs_spl_fixup_vectors(void)959c2c8a31SMarek Vasut static void mxs_spl_fixup_vectors(void)
969c2c8a31SMarek Vasut {
979c2c8a31SMarek Vasut /*
989c2c8a31SMarek Vasut * Copy our vector table to 0x0, since due to HAB, we cannot
999c2c8a31SMarek Vasut * be loaded to 0x0. We want to have working vectoring though,
1009c2c8a31SMarek Vasut * thus this fixup. Our vectoring table is PIC, so copying is
1019c2c8a31SMarek Vasut * fine.
1029c2c8a31SMarek Vasut */
1039c2c8a31SMarek Vasut extern uint32_t _start;
1040060517aSWolfgang Denk
1050060517aSWolfgang Denk /* cppcheck-suppress nullPointer */
1069c2c8a31SMarek Vasut memcpy(0x0, &_start, 0x60);
1079c2c8a31SMarek Vasut }
1089c2c8a31SMarek Vasut
mxs_spl_console_init(void)1099926eb31SMarek Vasut static void mxs_spl_console_init(void)
1109926eb31SMarek Vasut {
1119926eb31SMarek Vasut #ifdef CONFIG_SPL_SERIAL_SUPPORT
1129926eb31SMarek Vasut gd->bd = &bdata;
1139926eb31SMarek Vasut gd->baudrate = CONFIG_BAUDRATE;
1149926eb31SMarek Vasut serial_init();
1159926eb31SMarek Vasut gd->have_console = 1;
1169926eb31SMarek Vasut #endif
1179926eb31SMarek Vasut }
1189926eb31SMarek Vasut
mxs_common_spl_init(const uint32_t arg,const uint32_t * resptr,const iomux_cfg_t * iomux_setup,const unsigned int iomux_size)1197b8657e2SMarek Vasut void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr,
1207b8657e2SMarek Vasut const iomux_cfg_t *iomux_setup,
1213a0398d7SOtavio Salvador const unsigned int iomux_size)
1223a0398d7SOtavio Salvador {
1231e0cf5c3SOtavio Salvador struct mxs_spl_data *data = (struct mxs_spl_data *)
1241e0cf5c3SOtavio Salvador ((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);
1251e0cf5c3SOtavio Salvador uint8_t bootmode = mxs_get_bootmode_index();
12665ed5e85SMarek Vasut gd = &gdata;
1273a0398d7SOtavio Salvador
1289c2c8a31SMarek Vasut mxs_spl_fixup_vectors();
1299c2c8a31SMarek Vasut
1303a0398d7SOtavio Salvador mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size);
1319c2c8a31SMarek Vasut
1329926eb31SMarek Vasut mxs_spl_console_init();
133950eaf62SGraeme Russ debug("SPL: Serial Console Initialised\n");
1349926eb31SMarek Vasut
1351e0cf5c3SOtavio Salvador mxs_power_init();
1363a0398d7SOtavio Salvador
1371e0cf5c3SOtavio Salvador mxs_mem_init();
1381e0cf5c3SOtavio Salvador data->mem_dram_size = mxs_mem_get_size();
1393a0398d7SOtavio Salvador
1403a0398d7SOtavio Salvador data->boot_mode_idx = bootmode;
1413a0398d7SOtavio Salvador
1421e0cf5c3SOtavio Salvador mxs_power_wait_pswitch();
1432d6286abSGraeme Russ
1442d6286abSGraeme Russ if (mxs_boot_modes[data->boot_mode_idx].boot_pads == MXS_BM_JTAG) {
1452d6286abSGraeme Russ debug("SPL: Waiting for JTAG user\n");
1462d6286abSGraeme Russ asm volatile ("x: b x");
1472d6286abSGraeme Russ }
1483a0398d7SOtavio Salvador }
1493a0398d7SOtavio Salvador
1503a0398d7SOtavio Salvador /* Support aparatus */
board_init_f(unsigned long bootflag)1513a0398d7SOtavio Salvador inline void board_init_f(unsigned long bootflag)
1523a0398d7SOtavio Salvador {
1533a0398d7SOtavio Salvador for (;;)
1543a0398d7SOtavio Salvador ;
1553a0398d7SOtavio Salvador }
1563a0398d7SOtavio Salvador
board_init_r(gd_t * id,ulong dest_addr)1573a0398d7SOtavio Salvador inline void board_init_r(gd_t *id, ulong dest_addr)
1583a0398d7SOtavio Salvador {
1593a0398d7SOtavio Salvador for (;;)
1603a0398d7SOtavio Salvador ;
1613a0398d7SOtavio Salvador }
162