xref: /rk3399_rockchip-uboot/arch/arm/cpu/arm926ejs/mxs/spl_boot.c (revision 5c5199349987b2f931f9ae57da62d7b304f9ee32)
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