]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm926ejs/mxs/spl_boot.c
arm: mxs: Properly set GD pointer in SPL
[karo-tx-uboot.git] / arch / arm / cpu / arm926ejs / mxs / spl_boot.c
1 /*
2  * Freescale i.MX28 Boot setup
3  *
4  * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
5  * on behalf of DENX Software Engineering GmbH
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <config.h>
12 #include <asm/io.h>
13 #include <asm/arch/imx-regs.h>
14 #include <asm/arch/sys_proto.h>
15 #include <asm/gpio.h>
16 #include <linux/compiler.h>
17
18 #include "mxs_init.h"
19
20 DECLARE_GLOBAL_DATA_PTR;
21 gd_t gdata __section(".data");
22
23 /*
24  * This delay function is intended to be used only in early stage of boot, where
25  * clock are not set up yet. The timer used here is reset on every boot and
26  * takes a few seconds to roll. The boot doesn't take that long, so to keep the
27  * code simple, it doesn't take rolling into consideration.
28  */
29 void early_delay(int delay)
30 {
31         struct mxs_digctl_regs *digctl_regs =
32                 (struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
33
34         uint32_t st = readl(&digctl_regs->hw_digctl_microseconds);
35         st += delay;
36         while (st > readl(&digctl_regs->hw_digctl_microseconds))
37                 ;
38 }
39
40 #define MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
41 static const iomux_cfg_t iomux_boot[] = {
42 #if defined(CONFIG_MX23)
43         MX23_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD,
44         MX23_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD,
45         MX23_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD,
46         MX23_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD,
47         MX23_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD,
48         MX23_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD,
49 #elif defined(CONFIG_MX28)
50         MX28_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD,
51         MX28_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD,
52         MX28_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD,
53         MX28_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD,
54         MX28_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD,
55         MX28_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD,
56 #endif
57 };
58
59 static uint8_t mxs_get_bootmode_index(void)
60 {
61         uint8_t bootmode = 0;
62         int i;
63         uint8_t masked;
64
65         /* Setup IOMUX of bootmode pads to GPIO */
66         mxs_iomux_setup_multiple_pads(iomux_boot, ARRAY_SIZE(iomux_boot));
67
68 #if defined(CONFIG_MX23)
69         /* Setup bootmode pins as GPIO input */
70         gpio_direction_input(MX23_PAD_LCD_D00__GPIO_1_0);
71         gpio_direction_input(MX23_PAD_LCD_D01__GPIO_1_1);
72         gpio_direction_input(MX23_PAD_LCD_D02__GPIO_1_2);
73         gpio_direction_input(MX23_PAD_LCD_D03__GPIO_1_3);
74         gpio_direction_input(MX23_PAD_LCD_D05__GPIO_1_5);
75
76         /* Read bootmode pads */
77         bootmode |= (gpio_get_value(MX23_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0;
78         bootmode |= (gpio_get_value(MX23_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1;
79         bootmode |= (gpio_get_value(MX23_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2;
80         bootmode |= (gpio_get_value(MX23_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3;
81         bootmode |= (gpio_get_value(MX23_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5;
82 #elif defined(CONFIG_MX28)
83         /* Setup bootmode pins as GPIO input */
84         gpio_direction_input(MX28_PAD_LCD_D00__GPIO_1_0);
85         gpio_direction_input(MX28_PAD_LCD_D01__GPIO_1_1);
86         gpio_direction_input(MX28_PAD_LCD_D02__GPIO_1_2);
87         gpio_direction_input(MX28_PAD_LCD_D03__GPIO_1_3);
88         gpio_direction_input(MX28_PAD_LCD_D04__GPIO_1_4);
89         gpio_direction_input(MX28_PAD_LCD_D05__GPIO_1_5);
90
91         /* Read bootmode pads */
92         bootmode |= (gpio_get_value(MX28_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0;
93         bootmode |= (gpio_get_value(MX28_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1;
94         bootmode |= (gpio_get_value(MX28_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2;
95         bootmode |= (gpio_get_value(MX28_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3;
96         bootmode |= (gpio_get_value(MX28_PAD_LCD_D04__GPIO_1_4) ? 1 : 0) << 4;
97         bootmode |= (gpio_get_value(MX28_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5;
98 #endif
99
100         for (i = 0; i < ARRAY_SIZE(mxs_boot_modes); i++) {
101                 masked = bootmode & mxs_boot_modes[i].boot_mask;
102                 if (masked == mxs_boot_modes[i].boot_pads)
103                         break;
104         }
105
106         return i;
107 }
108
109 static void mxs_spl_fixup_vectors(void)
110 {
111         /*
112          * Copy our vector table to 0x0, since due to HAB, we cannot
113          * be loaded to 0x0. We want to have working vectoring though,
114          * thus this fixup. Our vectoring table is PIC, so copying is
115          * fine.
116          */
117         extern uint32_t _start;
118         memcpy(0x0, &_start, 0x60);
119 }
120
121 void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr,
122                          const iomux_cfg_t *iomux_setup,
123                          const unsigned int iomux_size)
124 {
125         struct mxs_spl_data *data = (struct mxs_spl_data *)
126                 ((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);
127         uint8_t bootmode = mxs_get_bootmode_index();
128         gd = &gdata;
129
130         mxs_spl_fixup_vectors();
131
132         mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size);
133
134         mxs_power_init();
135
136         mxs_mem_init();
137         data->mem_dram_size = mxs_mem_get_size();
138
139         data->boot_mode_idx = bootmode;
140
141         mxs_power_wait_pswitch();
142 }
143
144 /* Support aparatus */
145 inline void board_init_f(unsigned long bootflag)
146 {
147         for (;;)
148                 ;
149 }
150
151 inline void board_init_r(gd_t *id, ulong dest_addr)
152 {
153         for (;;)
154                 ;
155 }