Home | History | Annotate | Download | only in mxs
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Freescale i.MX28 Boot setup
      4  *
      5  * Copyright (C) 2011 Marek Vasut <marek.vasut (at) gmail.com>
      6  * on behalf of DENX Software Engineering GmbH
      7  */
      8 
      9 #include <common.h>
     10 #include <config.h>
     11 #include <asm/io.h>
     12 #include <asm/arch/imx-regs.h>
     13 #include <asm/arch/sys_proto.h>
     14 #include <asm/gpio.h>
     15 #include <linux/compiler.h>
     16 
     17 #include "mxs_init.h"
     18 
     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");
     23 #endif
     24 
     25 /*
     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.
     30  */
     31 void early_delay(int delay)
     32 {
     33 	struct mxs_digctl_regs *digctl_regs =
     34 		(struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
     35 
     36 	uint32_t st = readl(&digctl_regs->hw_digctl_microseconds);
     37 	st += delay;
     38 	while (st > readl(&digctl_regs->hw_digctl_microseconds))
     39 		;
     40 }
     41 
     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,
     51 };
     52 #endif
     53 
     54 static uint8_t mxs_get_bootmode_index(void)
     55 {
     56 	uint8_t bootmode = 0;
     57 	int i;
     58 	uint8_t masked;
     59 
     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));
     63 
     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);
     70 
     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.
     80 	 */
     81 #define GLOBAL_BOOT_MODE_ADDR 0x00019BF0
     82 	bootmode = __raw_readl(GLOBAL_BOOT_MODE_ADDR);
     83 #endif
     84 
     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)
     88 			break;
     89 	}
     90 
     91 	return i;
     92 }
     93 
     94 static void mxs_spl_fixup_vectors(void)
     95 {
     96 	/*
     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
    100 	 * fine.
    101 	 */
    102 	extern uint32_t _start;
    103 
    104 	/* cppcheck-suppress nullPointer */
    105 	memcpy(0x0, &_start, 0x60);
    106 }
    107 
    108 static void mxs_spl_console_init(void)
    109 {
    110 #ifdef CONFIG_SPL_SERIAL_SUPPORT
    111 	gd->bd = &bdata;
    112 	gd->baudrate = CONFIG_BAUDRATE;
    113 	serial_init();
    114 	gd->have_console = 1;
    115 #endif
    116 }
    117 
    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)
    121 {
    122 	struct mxs_spl_data *data = MXS_SPL_DATA;
    123 	uint8_t bootmode = mxs_get_bootmode_index();
    124 	gd = &gdata;
    125 
    126 	mxs_spl_fixup_vectors();
    127 
    128 	mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size);
    129 
    130 	mxs_spl_console_init();
    131 	debug("SPL: Serial Console Initialised\n");
    132 
    133 	mxs_power_init();
    134 
    135 	mxs_mem_init();
    136 	data->mem_dram_size = mxs_mem_get_size();
    137 
    138 	data->boot_mode_idx = bootmode;
    139 
    140 	mxs_power_wait_pswitch();
    141 
    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");
    145 	}
    146 }
    147 
    148 #ifndef CONFIG_SPL_FRAMEWORK
    149 /* Support aparatus */
    150 inline void board_init_f(unsigned long bootflag)
    151 {
    152 	for (;;)
    153 		;
    154 }
    155 
    156 inline void board_init_r(gd_t *id, ulong dest_addr)
    157 {
    158 	for (;;)
    159 		;
    160 }
    161 #endif
    162