1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
23a0398d7SOtavio Salvador /*
33a0398d7SOtavio Salvador * Freescale i.MX28 Boot setup
43a0398d7SOtavio Salvador *
53a0398d7SOtavio Salvador * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
63a0398d7SOtavio Salvador * on behalf of DENX Software Engineering GmbH
73a0398d7SOtavio Salvador */
83a0398d7SOtavio Salvador
93a0398d7SOtavio Salvador #include <common.h>
103a0398d7SOtavio Salvador #include <config.h>
113a0398d7SOtavio Salvador #include <asm/io.h>
123a0398d7SOtavio Salvador #include <asm/arch/imx-regs.h>
133a0398d7SOtavio Salvador #include <asm/arch/sys_proto.h>
143a0398d7SOtavio Salvador #include <asm/gpio.h>
1565ed5e85SMarek Vasut #include <linux/compiler.h>
163a0398d7SOtavio Salvador
171e0cf5c3SOtavio Salvador #include "mxs_init.h"
183a0398d7SOtavio Salvador
1965ed5e85SMarek Vasut DECLARE_GLOBAL_DATA_PTR;
209926eb31SMarek Vasut static gd_t gdata __section(".data");
21bb2637beSStefano Babic #ifdef CONFIG_SPL_SERIAL_SUPPORT
229926eb31SMarek Vasut static bd_t bdata __section(".data");
23bb2637beSStefano Babic #endif
2465ed5e85SMarek Vasut
253a0398d7SOtavio Salvador /*
263a0398d7SOtavio Salvador * This delay function is intended to be used only in early stage of boot, where
273a0398d7SOtavio Salvador * clock are not set up yet. The timer used here is reset on every boot and
283a0398d7SOtavio Salvador * takes a few seconds to roll. The boot doesn't take that long, so to keep the
293a0398d7SOtavio Salvador * code simple, it doesn't take rolling into consideration.
303a0398d7SOtavio Salvador */
early_delay(int delay)313a0398d7SOtavio Salvador void early_delay(int delay)
323a0398d7SOtavio Salvador {
33d82f05fcSMarek Vasut struct mxs_digctl_regs *digctl_regs =
34d82f05fcSMarek Vasut (struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
35d82f05fcSMarek Vasut
36d82f05fcSMarek Vasut uint32_t st = readl(&digctl_regs->hw_digctl_microseconds);
373a0398d7SOtavio Salvador st += delay;
38d82f05fcSMarek Vasut while (st > readl(&digctl_regs->hw_digctl_microseconds))
393a0398d7SOtavio Salvador ;
403a0398d7SOtavio Salvador }
413a0398d7SOtavio Salvador
425c519934SMarek Vasut #if defined(CONFIG_MX23)
433a0398d7SOtavio Salvador #define MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
44a918a53cSMarek Vasut static const iomux_cfg_t iomux_boot[] = {
45f942f7d9SOtavio Salvador MX23_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD,
46f942f7d9SOtavio Salvador MX23_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD,
47f942f7d9SOtavio Salvador MX23_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD,
48f942f7d9SOtavio Salvador MX23_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD,
49f942f7d9SOtavio Salvador MX23_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD,
50f942f7d9SOtavio Salvador MX23_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD,
513a0398d7SOtavio Salvador };
525c519934SMarek Vasut #endif
533a0398d7SOtavio Salvador
mxs_get_bootmode_index(void)54a918a53cSMarek Vasut static uint8_t mxs_get_bootmode_index(void)
553a0398d7SOtavio Salvador {
563a0398d7SOtavio Salvador uint8_t bootmode = 0;
573a0398d7SOtavio Salvador int i;
583a0398d7SOtavio Salvador uint8_t masked;
593a0398d7SOtavio Salvador
6032f9ef3eSJörg Krause #if defined(CONFIG_MX23)
613a0398d7SOtavio Salvador /* Setup IOMUX of bootmode pads to GPIO */
623a0398d7SOtavio Salvador mxs_iomux_setup_multiple_pads(iomux_boot, ARRAY_SIZE(iomux_boot));
633a0398d7SOtavio Salvador
64f942f7d9SOtavio Salvador /* Setup bootmode pins as GPIO input */
65f942f7d9SOtavio Salvador gpio_direction_input(MX23_PAD_LCD_D00__GPIO_1_0);
66f942f7d9SOtavio Salvador gpio_direction_input(MX23_PAD_LCD_D01__GPIO_1_1);
67f942f7d9SOtavio Salvador gpio_direction_input(MX23_PAD_LCD_D02__GPIO_1_2);
68f942f7d9SOtavio Salvador gpio_direction_input(MX23_PAD_LCD_D03__GPIO_1_3);
69f942f7d9SOtavio Salvador gpio_direction_input(MX23_PAD_LCD_D05__GPIO_1_5);
70f942f7d9SOtavio Salvador
71f942f7d9SOtavio Salvador /* Read bootmode pads */
72f942f7d9SOtavio Salvador bootmode |= (gpio_get_value(MX23_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0;
73f942f7d9SOtavio Salvador bootmode |= (gpio_get_value(MX23_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1;
74f942f7d9SOtavio Salvador bootmode |= (gpio_get_value(MX23_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2;
75f942f7d9SOtavio Salvador bootmode |= (gpio_get_value(MX23_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3;
76f942f7d9SOtavio Salvador bootmode |= (gpio_get_value(MX23_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5;
77f942f7d9SOtavio Salvador #elif defined(CONFIG_MX28)
7832f9ef3eSJörg Krause /* The global boot mode will be detected by ROM code and its value
7932f9ef3eSJörg Krause * is stored at the fixed address 0x00019BF0 in OCRAM.
8032f9ef3eSJörg Krause */
8132f9ef3eSJörg Krause #define GLOBAL_BOOT_MODE_ADDR 0x00019BF0
8232f9ef3eSJörg Krause bootmode = __raw_readl(GLOBAL_BOOT_MODE_ADDR);
83f942f7d9SOtavio Salvador #endif
843a0398d7SOtavio Salvador
85fa7a51cbSOtavio Salvador for (i = 0; i < ARRAY_SIZE(mxs_boot_modes); i++) {
86fa7a51cbSOtavio Salvador masked = bootmode & mxs_boot_modes[i].boot_mask;
87fa7a51cbSOtavio Salvador if (masked == mxs_boot_modes[i].boot_pads)
883a0398d7SOtavio Salvador break;
893a0398d7SOtavio Salvador }
903a0398d7SOtavio Salvador
913a0398d7SOtavio Salvador return i;
923a0398d7SOtavio Salvador }
933a0398d7SOtavio Salvador
mxs_spl_fixup_vectors(void)949c2c8a31SMarek Vasut static void mxs_spl_fixup_vectors(void)
959c2c8a31SMarek Vasut {
969c2c8a31SMarek Vasut /*
979c2c8a31SMarek Vasut * Copy our vector table to 0x0, since due to HAB, we cannot
989c2c8a31SMarek Vasut * be loaded to 0x0. We want to have working vectoring though,
999c2c8a31SMarek Vasut * thus this fixup. Our vectoring table is PIC, so copying is
1009c2c8a31SMarek Vasut * fine.
1019c2c8a31SMarek Vasut */
1029c2c8a31SMarek Vasut extern uint32_t _start;
1030060517aSWolfgang Denk
1040060517aSWolfgang Denk /* cppcheck-suppress nullPointer */
1059c2c8a31SMarek Vasut memcpy(0x0, &_start, 0x60);
1069c2c8a31SMarek Vasut }
1079c2c8a31SMarek Vasut
mxs_spl_console_init(void)1089926eb31SMarek Vasut static void mxs_spl_console_init(void)
1099926eb31SMarek Vasut {
1109926eb31SMarek Vasut #ifdef CONFIG_SPL_SERIAL_SUPPORT
1119926eb31SMarek Vasut gd->bd = &bdata;
1129926eb31SMarek Vasut gd->baudrate = CONFIG_BAUDRATE;
1139926eb31SMarek Vasut serial_init();
1149926eb31SMarek Vasut gd->have_console = 1;
1159926eb31SMarek Vasut #endif
1169926eb31SMarek Vasut }
1179926eb31SMarek Vasut
mxs_common_spl_init(const uint32_t arg,const uint32_t * resptr,const iomux_cfg_t * iomux_setup,const unsigned int iomux_size)1187b8657e2SMarek Vasut void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr,
1197b8657e2SMarek Vasut const iomux_cfg_t *iomux_setup,
1203a0398d7SOtavio Salvador const unsigned int iomux_size)
1213a0398d7SOtavio Salvador {
12233ea1193SMans Rullgard struct mxs_spl_data *data = MXS_SPL_DATA;
1231e0cf5c3SOtavio Salvador uint8_t bootmode = mxs_get_bootmode_index();
12465ed5e85SMarek Vasut gd = &gdata;
1253a0398d7SOtavio Salvador
1269c2c8a31SMarek Vasut mxs_spl_fixup_vectors();
1279c2c8a31SMarek Vasut
1283a0398d7SOtavio Salvador mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size);
1299c2c8a31SMarek Vasut
1309926eb31SMarek Vasut mxs_spl_console_init();
131950eaf62SGraeme Russ debug("SPL: Serial Console Initialised\n");
1329926eb31SMarek Vasut
1331e0cf5c3SOtavio Salvador mxs_power_init();
1343a0398d7SOtavio Salvador
1351e0cf5c3SOtavio Salvador mxs_mem_init();
1361e0cf5c3SOtavio Salvador data->mem_dram_size = mxs_mem_get_size();
1373a0398d7SOtavio Salvador
1383a0398d7SOtavio Salvador data->boot_mode_idx = bootmode;
1393a0398d7SOtavio Salvador
1401e0cf5c3SOtavio Salvador mxs_power_wait_pswitch();
1412d6286abSGraeme Russ
1422d6286abSGraeme Russ if (mxs_boot_modes[data->boot_mode_idx].boot_pads == MXS_BM_JTAG) {
1432d6286abSGraeme Russ debug("SPL: Waiting for JTAG user\n");
1442d6286abSGraeme Russ asm volatile ("x: b x");
1452d6286abSGraeme Russ }
1463a0398d7SOtavio Salvador }
1473a0398d7SOtavio Salvador
14807a8f79eSMans Rullgard #ifndef CONFIG_SPL_FRAMEWORK
1493a0398d7SOtavio Salvador /* Support aparatus */
board_init_f(unsigned long bootflag)1503a0398d7SOtavio Salvador inline void board_init_f(unsigned long bootflag)
1513a0398d7SOtavio Salvador {
1523a0398d7SOtavio Salvador for (;;)
1533a0398d7SOtavio Salvador ;
1543a0398d7SOtavio Salvador }
1553a0398d7SOtavio Salvador
board_init_r(gd_t * id,ulong dest_addr)1563a0398d7SOtavio Salvador inline void board_init_r(gd_t *id, ulong dest_addr)
1573a0398d7SOtavio Salvador {
1583a0398d7SOtavio Salvador for (;;)
1593a0398d7SOtavio Salvador ;
1603a0398d7SOtavio Salvador }
16107a8f79eSMans Rullgard #endif
162