Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | // SPDX-License-Identifier: GPL-2.0+ /* * Freescale i.MX28 Boot setup * * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> * on behalf of DENX Software Engineering GmbH */ #include <config.h> #include <init.h> #include <log.h> #include <serial.h> #include <asm/global_data.h> #include <asm/io.h> #include <asm/arch/imx-regs.h> #include <asm/arch/sys_proto.h> #include <asm/gpio.h> #include <asm/sections.h> #include <asm/system.h> #include <linux/compiler.h> #include "mxs_init.h" DECLARE_GLOBAL_DATA_PTR; static gd_t gdata __section(".data"); #ifdef CONFIG_SPL_SERIAL static struct bd_info bdata __section(".data"); #endif /* * This delay function is intended to be used only in early stage of boot, where * clock are not set up yet. */ void early_delay(int delay) { struct mxs_digctl_regs *digctl_regs = (struct mxs_digctl_regs *)MXS_DIGCTL_BASE; uint32_t st = readl(&digctl_regs->hw_digctl_microseconds); while (readl(&digctl_regs->hw_digctl_microseconds) - st <= delay) ; } #if defined(CONFIG_MX23) #define MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL) static const iomux_cfg_t iomux_boot[] = { MX23_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD, MX23_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD, MX23_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD, MX23_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD, MX23_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD, MX23_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD, }; #endif static uint8_t mxs_get_bootmode_index(void) { uint8_t bootmode = 0; int i; uint8_t masked; #if defined(CONFIG_MX23) /* Setup IOMUX of bootmode pads to GPIO */ mxs_iomux_setup_multiple_pads(iomux_boot, ARRAY_SIZE(iomux_boot)); /* Setup bootmode pins as GPIO input */ gpio_direction_input(MX23_PAD_LCD_D00__GPIO_1_0); gpio_direction_input(MX23_PAD_LCD_D01__GPIO_1_1); gpio_direction_input(MX23_PAD_LCD_D02__GPIO_1_2); gpio_direction_input(MX23_PAD_LCD_D03__GPIO_1_3); gpio_direction_input(MX23_PAD_LCD_D05__GPIO_1_5); /* Read bootmode pads */ bootmode |= (gpio_get_value(MX23_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0; bootmode |= (gpio_get_value(MX23_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1; bootmode |= (gpio_get_value(MX23_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2; bootmode |= (gpio_get_value(MX23_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3; bootmode |= (gpio_get_value(MX23_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5; #elif defined(CONFIG_MX28) /* The global boot mode will be detected by ROM code and its value * is stored at the fixed address 0x00019BF0 in OCRAM. */ #define GLOBAL_BOOT_MODE_ADDR 0x00019BF0 bootmode = __raw_readl(GLOBAL_BOOT_MODE_ADDR); #endif for (i = 0; i < ARRAY_SIZE(mxs_boot_modes); i++) { masked = bootmode & mxs_boot_modes[i].boot_mask; if (masked == mxs_boot_modes[i].boot_pads) break; } return i; } static noinline __attribute__((target("arm"))) void mxs_spl_fixup_vectors(void) { /* * Copy our vector table to 0x0, since due to HAB, we cannot * be loaded to 0x0. We want to have working vectoring though, * thus this fixup. Our vectoring table is PIC, so copying is * fine. */ /* cppcheck-suppress nullPointer */ memcpy(0x0, _start, 0x60); /* Make sure ARM core points to low vectors */ set_cr(get_cr() & ~CR_V); } static void mxs_spl_console_init(void) { #ifdef CONFIG_SPL_SERIAL gd->bd = &bdata; gd->baudrate = CONFIG_BAUDRATE; serial_init(); gd->flags |= GD_FLG_HAVE_CONSOLE; #endif } void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr, const iomux_cfg_t *iomux_setup, const unsigned int iomux_size) { struct mxs_spl_data *data = MXS_SPL_DATA; uint8_t bootmode = mxs_get_bootmode_index(); set_gd(&gdata); mxs_spl_fixup_vectors(); mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size); if (!CONFIG_IS_ENABLED(DM_SERIAL)) { mxs_spl_console_init(); debug("SPL: Serial Console Initialised\n"); } mxs_power_init(); mxs_mem_init(); data->mem_dram_size = mxs_mem_get_size(); data->boot_mode_idx = bootmode; mxs_power_wait_pswitch(); if (mxs_boot_modes[data->boot_mode_idx].boot_pads == MXS_BM_JTAG) { debug("SPL: Waiting for JTAG user\n"); asm volatile ("x: b x"); } } #ifndef CONFIG_SPL_FRAMEWORK /* Support aparatus */ inline void board_init_f(unsigned long bootflag) { for (;;) ; } inline void board_init_r(gd_t *id, ulong dest_addr) { for (;;) ; } #endif |