xref: /openbmc/u-boot/arch/arm/cpu/arm926ejs/mxs/spl_boot.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
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