1 // SPDX-License-Identifier: GPL-2.0+
3 * Freescale i.MX28 Boot setup
5 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
6 * on behalf of DENX Software Engineering GmbH
12 #include <asm/arch/imx-regs.h>
13 #include <asm/arch/sys_proto.h>
15 #include <linux/compiler.h>
19 DECLARE_GLOBAL_DATA_PTR
;
20 static gd_t gdata
__section(".data");
21 #ifdef CONFIG_SPL_SERIAL_SUPPORT
22 static bd_t bdata
__section(".data");
26 * This delay function is intended to be used only in early stage of boot, where
27 * clock are not set up yet. The timer used here is reset on every boot and
28 * takes a few seconds to roll. The boot doesn't take that long, so to keep the
29 * code simple, it doesn't take rolling into consideration.
31 void early_delay(int delay
)
33 struct mxs_digctl_regs
*digctl_regs
=
34 (struct mxs_digctl_regs
*)MXS_DIGCTL_BASE
;
36 uint32_t st
= readl(&digctl_regs
->hw_digctl_microseconds
);
38 while (st
> readl(&digctl_regs
->hw_digctl_microseconds
))
42 #if defined(CONFIG_MX23)
43 #define MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
44 static const iomux_cfg_t iomux_boot
[] = {
45 MX23_PAD_LCD_D00__GPIO_1_0
| MUX_CONFIG_BOOTMODE_PAD
,
46 MX23_PAD_LCD_D01__GPIO_1_1
| MUX_CONFIG_BOOTMODE_PAD
,
47 MX23_PAD_LCD_D02__GPIO_1_2
| MUX_CONFIG_BOOTMODE_PAD
,
48 MX23_PAD_LCD_D03__GPIO_1_3
| MUX_CONFIG_BOOTMODE_PAD
,
49 MX23_PAD_LCD_D04__GPIO_1_4
| MUX_CONFIG_BOOTMODE_PAD
,
50 MX23_PAD_LCD_D05__GPIO_1_5
| MUX_CONFIG_BOOTMODE_PAD
,
54 static uint8_t mxs_get_bootmode_index(void)
60 #if defined(CONFIG_MX23)
61 /* Setup IOMUX of bootmode pads to GPIO */
62 mxs_iomux_setup_multiple_pads(iomux_boot
, ARRAY_SIZE(iomux_boot
));
64 /* Setup bootmode pins as GPIO input */
65 gpio_direction_input(MX23_PAD_LCD_D00__GPIO_1_0
);
66 gpio_direction_input(MX23_PAD_LCD_D01__GPIO_1_1
);
67 gpio_direction_input(MX23_PAD_LCD_D02__GPIO_1_2
);
68 gpio_direction_input(MX23_PAD_LCD_D03__GPIO_1_3
);
69 gpio_direction_input(MX23_PAD_LCD_D05__GPIO_1_5
);
71 /* Read bootmode pads */
72 bootmode
|= (gpio_get_value(MX23_PAD_LCD_D00__GPIO_1_0
) ? 1 : 0) << 0;
73 bootmode
|= (gpio_get_value(MX23_PAD_LCD_D01__GPIO_1_1
) ? 1 : 0) << 1;
74 bootmode
|= (gpio_get_value(MX23_PAD_LCD_D02__GPIO_1_2
) ? 1 : 0) << 2;
75 bootmode
|= (gpio_get_value(MX23_PAD_LCD_D03__GPIO_1_3
) ? 1 : 0) << 3;
76 bootmode
|= (gpio_get_value(MX23_PAD_LCD_D05__GPIO_1_5
) ? 1 : 0) << 5;
77 #elif defined(CONFIG_MX28)
78 /* The global boot mode will be detected by ROM code and its value
79 * is stored at the fixed address 0x00019BF0 in OCRAM.
81 #define GLOBAL_BOOT_MODE_ADDR 0x00019BF0
82 bootmode
= __raw_readl(GLOBAL_BOOT_MODE_ADDR
);
85 for (i
= 0; i
< ARRAY_SIZE(mxs_boot_modes
); i
++) {
86 masked
= bootmode
& mxs_boot_modes
[i
].boot_mask
;
87 if (masked
== mxs_boot_modes
[i
].boot_pads
)
94 static void mxs_spl_fixup_vectors(void)
97 * Copy our vector table to 0x0, since due to HAB, we cannot
98 * be loaded to 0x0. We want to have working vectoring though,
99 * thus this fixup. Our vectoring table is PIC, so copying is
102 extern uint32_t _start
;
104 /* cppcheck-suppress nullPointer */
105 memcpy(0x0, &_start
, 0x60);
108 static void mxs_spl_console_init(void)
110 #ifdef CONFIG_SPL_SERIAL_SUPPORT
112 gd
->baudrate
= CONFIG_BAUDRATE
;
114 gd
->have_console
= 1;
118 void mxs_common_spl_init(const uint32_t arg
, const uint32_t *resptr
,
119 const iomux_cfg_t
*iomux_setup
,
120 const unsigned int iomux_size
)
122 struct mxs_spl_data
*data
= MXS_SPL_DATA
;
123 uint8_t bootmode
= mxs_get_bootmode_index();
126 mxs_spl_fixup_vectors();
128 mxs_iomux_setup_multiple_pads(iomux_setup
, iomux_size
);
130 mxs_spl_console_init();
131 debug("SPL: Serial Console Initialised\n");
136 data
->mem_dram_size
= mxs_mem_get_size();
138 data
->boot_mode_idx
= bootmode
;
140 mxs_power_wait_pswitch();
142 if (mxs_boot_modes
[data
->boot_mode_idx
].boot_pads
== MXS_BM_JTAG
) {
143 debug("SPL: Waiting for JTAG user\n");
144 asm volatile ("x: b x");
148 #ifndef CONFIG_SPL_FRAMEWORK
149 /* Support aparatus */
150 inline void board_init_f(unsigned long bootflag
)
156 inline void board_init_r(gd_t
*id
, ulong dest_addr
)