Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
b8ce6fe2 FE |
2 | /* |
3 | * Copyright (C) 2015 Freescale Semiconductor, Inc. | |
4 | * | |
5 | * Author: Fabio Estevam <fabio.estevam@freescale.com> | |
6 | * | |
7 | * Copyright (C) 2013 Jon Nettleton <jon.nettleton@gmail.com> | |
8 | * | |
9 | * Based on SPL code from Solidrun tree, which is: | |
10 | * Author: Tungyi Lin <tungyilin1127@gmail.com> | |
11 | * | |
12 | * Derived from EDM_CF_IMX6 code by TechNexion,Inc | |
13 | * Ported to SolidRun microSOM by Rabeeh Khoury <rabeeh@solid-run.com> | |
b8ce6fe2 FE |
14 | */ |
15 | ||
c3dc39a2 | 16 | #include <common.h> |
4d72caa5 | 17 | #include <image.h> |
5255932f | 18 | #include <init.h> |
f7ae49fc | 19 | #include <log.h> |
90526e9f | 20 | #include <net.h> |
b8ce6fe2 FE |
21 | #include <asm/arch/clock.h> |
22 | #include <asm/arch/imx-regs.h> | |
23 | #include <asm/arch/iomux.h> | |
24 | #include <asm/arch/mx6-pins.h> | |
f68a9c6b | 25 | #include <asm/arch/mxc_hdmi.h> |
9fb625ce | 26 | #include <env.h> |
c05ed00a | 27 | #include <linux/delay.h> |
1221ce45 | 28 | #include <linux/errno.h> |
b8ce6fe2 | 29 | #include <asm/gpio.h> |
552a848e SB |
30 | #include <asm/mach-imx/iomux-v3.h> |
31 | #include <asm/mach-imx/sata.h> | |
32 | #include <asm/mach-imx/video.h> | |
b8ce6fe2 | 33 | #include <mmc.h> |
e37ac717 | 34 | #include <fsl_esdhc_imx.h> |
712be3ee | 35 | #include <malloc.h> |
b8ce6fe2 FE |
36 | #include <miiphy.h> |
37 | #include <netdev.h> | |
38 | #include <asm/arch/crm_regs.h> | |
39 | #include <asm/io.h> | |
40 | #include <asm/arch/sys_proto.h> | |
b8ce6fe2 | 41 | #include <spl.h> |
e1d74379 | 42 | #include <usb.h> |
e162c6b1 | 43 | #include <usb/ehci-ci.h> |
b8ce6fe2 FE |
44 | |
45 | DECLARE_GLOBAL_DATA_PTR; | |
46 | ||
47 | #define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ | |
48 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ | |
49 | PAD_CTL_SRE_FAST | PAD_CTL_HYS) | |
50 | ||
51 | #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \ | |
52 | PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \ | |
53 | PAD_CTL_SRE_FAST | PAD_CTL_HYS) | |
54 | ||
55 | #define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ | |
56 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) | |
57 | ||
58 | #define ENET_PAD_CTRL_PD (PAD_CTL_PUS_100K_DOWN | \ | |
59 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) | |
60 | ||
61 | #define ENET_PAD_CTRL_CLK ((PAD_CTL_PUS_100K_UP & ~PAD_CTL_PKE) | \ | |
62 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) | |
63 | ||
64 | #define ETH_PHY_RESET IMX_GPIO_NR(4, 15) | |
e1d74379 | 65 | #define USB_H1_VBUS IMX_GPIO_NR(1, 0) |
b8ce6fe2 | 66 | |
73708200 JN |
67 | enum board_type { |
68 | CUBOXI = 0x00, | |
69 | HUMMINGBOARD = 0x01, | |
70 | HUMMINGBOARD2 = 0x02, | |
71 | UNKNOWN = 0x03, | |
72 | }; | |
73 | ||
eb9124f5 BS |
74 | static struct gpio_desc board_detect_desc[5]; |
75 | ||
51f957ad JN |
76 | #define MEM_STRIDE 0x4000000 |
77 | static u32 get_ram_size_stride_test(u32 *base, u32 maxsize) | |
78 | { | |
79 | volatile u32 *addr; | |
80 | u32 save[64]; | |
81 | u32 cnt; | |
82 | u32 size; | |
83 | int i = 0; | |
84 | ||
85 | /* First save the data */ | |
86 | for (cnt = 0; cnt < maxsize; cnt += MEM_STRIDE) { | |
87 | addr = (volatile u32 *)((u32)base + cnt); /* pointer arith! */ | |
88 | sync (); | |
89 | save[i++] = *addr; | |
90 | sync (); | |
91 | } | |
92 | ||
93 | /* First write a signature */ | |
94 | * (volatile u32 *)base = 0x12345678; | |
95 | for (size = MEM_STRIDE; size < maxsize; size += MEM_STRIDE) { | |
96 | * (volatile u32 *)((u32)base + size) = size; | |
97 | sync (); | |
98 | if (* (volatile u32 *)((u32)base) == size) { /* We reached the overlapping address */ | |
99 | break; | |
100 | } | |
101 | } | |
102 | ||
103 | /* Restore the data */ | |
104 | for (cnt = (maxsize - MEM_STRIDE); i > 0; cnt -= MEM_STRIDE) { | |
105 | addr = (volatile u32 *)((u32)base + cnt); /* pointer arith! */ | |
106 | sync (); | |
107 | *addr = save[i--]; | |
108 | sync (); | |
109 | } | |
110 | ||
111 | return (size); | |
112 | } | |
113 | ||
b8ce6fe2 FE |
114 | int dram_init(void) |
115 | { | |
51f957ad JN |
116 | u32 max_size = imx_ddr_size(); |
117 | ||
118 | gd->ram_size = get_ram_size_stride_test((u32 *) CONFIG_SYS_SDRAM_BASE, | |
119 | (u32)max_size); | |
120 | ||
b8ce6fe2 FE |
121 | return 0; |
122 | } | |
123 | ||
124 | static iomux_v3_cfg_t const uart1_pads[] = { | |
cfdcc5f7 FE |
125 | IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), |
126 | IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), | |
b8ce6fe2 FE |
127 | }; |
128 | ||
129 | static iomux_v3_cfg_t const usdhc2_pads[] = { | |
cfdcc5f7 FE |
130 | IOMUX_PADS(PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), |
131 | IOMUX_PADS(PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
132 | IOMUX_PADS(PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
133 | IOMUX_PADS(PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
134 | IOMUX_PADS(PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
135 | IOMUX_PADS(PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
b8ce6fe2 FE |
136 | }; |
137 | ||
86e5a7fc JN |
138 | static iomux_v3_cfg_t const usdhc3_pads[] = { |
139 | IOMUX_PADS(PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
140 | IOMUX_PADS(PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
141 | IOMUX_PADS(PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
142 | IOMUX_PADS(PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
143 | IOMUX_PADS(PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
144 | IOMUX_PADS(PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
145 | IOMUX_PADS(PAD_SD3_DAT4__SD3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
146 | IOMUX_PADS(PAD_SD3_DAT5__SD3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
147 | IOMUX_PADS(PAD_SD3_DAT6__SD3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
148 | IOMUX_PADS(PAD_SD3_DAT7__SD3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
149 | IOMUX_PADS(PAD_SD3_RST__SD3_RESET | MUX_PAD_CTRL(USDHC_PAD_CTRL)), | |
150 | }; | |
151 | ||
73708200 | 152 | static iomux_v3_cfg_t const board_detect[] = { |
feb6cc5c FE |
153 | /* These pins are for sensing if it is a CuBox-i or a HummingBoard */ |
154 | IOMUX_PADS(PAD_KEY_ROW1__GPIO4_IO09 | MUX_PAD_CTRL(UART_PAD_CTRL)), | |
155 | IOMUX_PADS(PAD_EIM_DA4__GPIO3_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)), | |
73708200 JN |
156 | IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | MUX_PAD_CTRL(UART_PAD_CTRL)), |
157 | }; | |
158 | ||
159 | static iomux_v3_cfg_t const som_rev_detect[] = { | |
160 | /* These pins are for sensing if it is a CuBox-i or a HummingBoard */ | |
161 | IOMUX_PADS(PAD_CSI0_DAT14__GPIO6_IO00 | MUX_PAD_CTRL(UART_PAD_CTRL)), | |
162 | IOMUX_PADS(PAD_CSI0_DAT18__GPIO6_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)), | |
feb6cc5c FE |
163 | }; |
164 | ||
b8ce6fe2 FE |
165 | static void setup_iomux_uart(void) |
166 | { | |
cfdcc5f7 | 167 | SETUP_IOMUX_PADS(uart1_pads); |
b8ce6fe2 FE |
168 | } |
169 | ||
86e5a7fc JN |
170 | static struct fsl_esdhc_cfg usdhc_cfg = { |
171 | .esdhc_base = USDHC2_BASE_ADDR, | |
172 | .max_bus_width = 4, | |
173 | }; | |
174 | ||
175 | static struct fsl_esdhc_cfg emmc_cfg = { | |
176 | .esdhc_base = USDHC3_BASE_ADDR, | |
177 | .max_bus_width = 8, | |
b8ce6fe2 FE |
178 | }; |
179 | ||
86e5a7fc JN |
180 | int board_mmc_get_env_dev(int devno) |
181 | { | |
eb9124f5 | 182 | return devno; |
86e5a7fc JN |
183 | } |
184 | ||
185 | #define USDHC2_CD_GPIO IMX_GPIO_NR(1, 4) | |
186 | ||
b8ce6fe2 FE |
187 | int board_mmc_getcd(struct mmc *mmc) |
188 | { | |
86e5a7fc JN |
189 | struct fsl_esdhc_cfg *cfg = mmc->priv; |
190 | int ret = 0; | |
191 | ||
192 | switch (cfg->esdhc_base) { | |
193 | case USDHC2_BASE_ADDR: | |
194 | ret = !gpio_get_value(USDHC2_CD_GPIO); | |
195 | break; | |
196 | case USDHC3_BASE_ADDR: | |
19ed6063 | 197 | ret = (mmc_get_op_cond(mmc) < 0) ? 0 : 1; /* eMMC/uSDHC3 has no CD GPIO */ |
86e5a7fc JN |
198 | break; |
199 | } | |
200 | ||
201 | return ret; | |
b8ce6fe2 FE |
202 | } |
203 | ||
86e5a7fc JN |
204 | static int mmc_init_spl(bd_t *bis) |
205 | { | |
206 | struct src *psrc = (struct src *)SRC_BASE_ADDR; | |
207 | unsigned reg = readl(&psrc->sbmr1) >> 11; | |
208 | ||
209 | /* | |
210 | * Upon reading BOOT_CFG register the following map is done: | |
211 | * Bit 11 and 12 of BOOT_CFG register can determine the current | |
212 | * mmc port | |
213 | * 0x1 SD2 | |
214 | * 0x2 SD3 | |
215 | */ | |
216 | switch (reg & 0x3) { | |
217 | case 0x1: | |
218 | SETUP_IOMUX_PADS(usdhc2_pads); | |
219 | usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); | |
220 | gd->arch.sdhc_clk = usdhc_cfg.sdhc_clk; | |
221 | return fsl_esdhc_initialize(bis, &usdhc_cfg); | |
222 | case 0x2: | |
223 | SETUP_IOMUX_PADS(usdhc3_pads); | |
224 | emmc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); | |
225 | gd->arch.sdhc_clk = emmc_cfg.sdhc_clk; | |
226 | return fsl_esdhc_initialize(bis, &emmc_cfg); | |
227 | } | |
228 | ||
229 | return -ENODEV; | |
230 | } | |
231 | ||
232 | int board_mmc_init(bd_t *bis) | |
233 | { | |
234 | if (IS_ENABLED(CONFIG_SPL_BUILD)) | |
235 | return mmc_init_spl(bis); | |
b8ce6fe2 | 236 | |
eb9124f5 | 237 | return 0; |
b8ce6fe2 FE |
238 | } |
239 | ||
240 | static iomux_v3_cfg_t const enet_pads[] = { | |
cfdcc5f7 FE |
241 | IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL)), |
242 | IOMUX_PADS(PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL)), | |
b8ce6fe2 | 243 | /* AR8035 reset */ |
cfdcc5f7 | 244 | IOMUX_PADS(PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)), |
b8ce6fe2 | 245 | /* AR8035 interrupt */ |
cfdcc5f7 | 246 | IOMUX_PADS(PAD_DI0_PIN2__GPIO4_IO18 | MUX_PAD_CTRL(NO_PAD_CTRL)), |
b8ce6fe2 | 247 | /* GPIO16 -> AR8035 25MHz */ |
cfdcc5f7 FE |
248 | IOMUX_PADS(PAD_GPIO_16__ENET_REF_CLK | MUX_PAD_CTRL(NO_PAD_CTRL)), |
249 | IOMUX_PADS(PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(NO_PAD_CTRL)), | |
250 | IOMUX_PADS(PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)), | |
251 | IOMUX_PADS(PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)), | |
252 | IOMUX_PADS(PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), | |
253 | IOMUX_PADS(PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), | |
254 | IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)), | |
b8ce6fe2 | 255 | /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */ |
cfdcc5f7 FE |
256 | IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL_CLK)), |
257 | IOMUX_PADS(PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL)), | |
258 | IOMUX_PADS(PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)), | |
259 | IOMUX_PADS(PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)), | |
260 | IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), | |
261 | IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), | |
262 | IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)), | |
a4d45038 FE |
263 | IOMUX_PADS(PAD_ENET_RXD0__GPIO1_IO27 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)), |
264 | IOMUX_PADS(PAD_ENET_RXD1__GPIO1_IO26 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)), | |
b8ce6fe2 FE |
265 | }; |
266 | ||
267 | static void setup_iomux_enet(void) | |
268 | { | |
eb9124f5 BS |
269 | struct gpio_desc desc; |
270 | int ret; | |
271 | ||
cfdcc5f7 | 272 | SETUP_IOMUX_PADS(enet_pads); |
b8ce6fe2 | 273 | |
eb9124f5 BS |
274 | ret = dm_gpio_lookup_name("GPIO4_15", &desc); |
275 | if (ret) { | |
276 | printf("%s: phy reset lookup failed\n", __func__); | |
277 | return; | |
278 | } | |
279 | ||
280 | ret = dm_gpio_request(&desc, "phy-reset"); | |
281 | if (ret) { | |
282 | printf("%s: phy reset request failed\n", __func__); | |
283 | return; | |
284 | } | |
285 | ||
b8ce6fe2 | 286 | gpio_direction_output(ETH_PHY_RESET, 0); |
4b421d4e | 287 | mdelay(10); |
b8ce6fe2 | 288 | gpio_set_value(ETH_PHY_RESET, 1); |
4b421d4e | 289 | udelay(100); |
eb9124f5 BS |
290 | |
291 | gpio_free_list_nodev(&desc, 1); | |
b8ce6fe2 FE |
292 | } |
293 | ||
294 | int board_phy_config(struct phy_device *phydev) | |
295 | { | |
296 | if (phydev->drv->config) | |
297 | phydev->drv->config(phydev); | |
298 | ||
299 | return 0; | |
300 | } | |
301 | ||
712be3ee FE |
302 | /* On Cuboxi Ethernet PHY can be located at addresses 0x0 or 0x4 */ |
303 | #define ETH_PHY_MASK ((1 << 0x0) | (1 << 0x4)) | |
304 | ||
b8ce6fe2 FE |
305 | int board_eth_init(bd_t *bis) |
306 | { | |
307 | struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; | |
712be3ee FE |
308 | struct mii_dev *bus; |
309 | struct phy_device *phydev; | |
b8ce6fe2 | 310 | |
6d97dc10 | 311 | int ret = enable_fec_anatop_clock(0, ENET_25MHZ); |
b8ce6fe2 FE |
312 | if (ret) |
313 | return ret; | |
314 | ||
315 | /* set gpr1[ENET_CLK_SEL] */ | |
316 | setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK); | |
317 | ||
318 | setup_iomux_enet(); | |
319 | ||
712be3ee FE |
320 | bus = fec_get_miibus(IMX_FEC_BASE, -1); |
321 | if (!bus) | |
322 | return -EINVAL; | |
323 | ||
324 | phydev = phy_find_by_mask(bus, ETH_PHY_MASK, PHY_INTERFACE_MODE_RGMII); | |
325 | if (!phydev) { | |
326 | ret = -EINVAL; | |
327 | goto free_bus; | |
328 | } | |
329 | ||
330 | debug("using phy at address %d\n", phydev->addr); | |
331 | ret = fec_probe(bis, -1, IMX_FEC_BASE, bus, phydev); | |
332 | if (ret) | |
333 | goto free_phydev; | |
334 | ||
335 | return 0; | |
336 | ||
337 | free_phydev: | |
338 | free(phydev); | |
339 | free_bus: | |
340 | free(bus); | |
341 | return ret; | |
b8ce6fe2 FE |
342 | } |
343 | ||
f68a9c6b FE |
344 | #ifdef CONFIG_VIDEO_IPUV3 |
345 | static void do_enable_hdmi(struct display_info_t const *dev) | |
346 | { | |
347 | imx_enable_hdmi_phy(); | |
348 | } | |
349 | ||
350 | struct display_info_t const displays[] = { | |
351 | { | |
352 | .bus = -1, | |
353 | .addr = 0, | |
354 | .pixfmt = IPU_PIX_FMT_RGB24, | |
355 | .detect = detect_hdmi, | |
356 | .enable = do_enable_hdmi, | |
357 | .mode = { | |
358 | .name = "HDMI", | |
359 | /* 1024x768@60Hz (VESA)*/ | |
360 | .refresh = 60, | |
361 | .xres = 1024, | |
362 | .yres = 768, | |
363 | .pixclock = 15384, | |
364 | .left_margin = 160, | |
365 | .right_margin = 24, | |
366 | .upper_margin = 29, | |
367 | .lower_margin = 3, | |
368 | .hsync_len = 136, | |
369 | .vsync_len = 6, | |
370 | .sync = FB_SYNC_EXT, | |
371 | .vmode = FB_VMODE_NONINTERLACED | |
372 | } | |
373 | } | |
374 | }; | |
375 | ||
376 | size_t display_count = ARRAY_SIZE(displays); | |
377 | ||
378 | static int setup_display(void) | |
379 | { | |
380 | struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | |
381 | int reg; | |
382 | int timeout = 100000; | |
383 | ||
384 | enable_ipu_clock(); | |
385 | imx_setup_hdmi(); | |
386 | ||
387 | /* set video pll to 455MHz (24MHz * (37+11/12) / 2) */ | |
388 | setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN); | |
389 | ||
390 | reg = readl(&ccm->analog_pll_video); | |
391 | reg &= ~BM_ANADIG_PLL_VIDEO_DIV_SELECT; | |
392 | reg |= BF_ANADIG_PLL_VIDEO_DIV_SELECT(37); | |
393 | reg &= ~BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT; | |
394 | reg |= BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1); | |
395 | writel(reg, &ccm->analog_pll_video); | |
396 | ||
397 | writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num); | |
398 | writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom); | |
399 | ||
400 | reg &= ~BM_ANADIG_PLL_VIDEO_POWERDOWN; | |
401 | writel(reg, &ccm->analog_pll_video); | |
402 | ||
403 | while (timeout--) | |
404 | if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK) | |
405 | break; | |
406 | if (timeout < 0) { | |
407 | printf("Warning: video pll lock timeout!\n"); | |
408 | return -ETIMEDOUT; | |
409 | } | |
410 | ||
411 | reg = readl(&ccm->analog_pll_video); | |
412 | reg |= BM_ANADIG_PLL_VIDEO_ENABLE; | |
413 | reg &= ~BM_ANADIG_PLL_VIDEO_BYPASS; | |
414 | writel(reg, &ccm->analog_pll_video); | |
415 | ||
416 | /* gate ipu1_di0_clk */ | |
417 | clrbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK); | |
418 | ||
419 | /* select video_pll clock / 7 for ipu1_di0_clk -> 65MHz pixclock */ | |
420 | reg = readl(&ccm->chsccdr); | |
421 | reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK | | |
422 | MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK | | |
423 | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK); | |
424 | reg |= (2 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET) | | |
425 | (6 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) | | |
426 | (0 << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET); | |
427 | writel(reg, &ccm->chsccdr); | |
428 | ||
429 | /* enable ipu1_di0_clk */ | |
430 | setbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK); | |
431 | ||
432 | return 0; | |
433 | } | |
434 | #endif /* CONFIG_VIDEO_IPUV3 */ | |
435 | ||
b8ce6fe2 FE |
436 | int board_early_init_f(void) |
437 | { | |
438 | setup_iomux_uart(); | |
f68a9c6b | 439 | |
ff181563 PR |
440 | #ifdef CONFIG_CMD_SATA |
441 | setup_sata(); | |
442 | #endif | |
ae40e82e | 443 | return 0; |
b8ce6fe2 FE |
444 | } |
445 | ||
446 | int board_init(void) | |
447 | { | |
ae40e82e FE |
448 | int ret = 0; |
449 | ||
b8ce6fe2 FE |
450 | /* address of boot parameters */ |
451 | gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; | |
452 | ||
ae40e82e FE |
453 | #ifdef CONFIG_VIDEO_IPUV3 |
454 | ret = setup_display(); | |
455 | #endif | |
456 | ||
457 | return ret; | |
b8ce6fe2 FE |
458 | } |
459 | ||
eb9124f5 BS |
460 | static int request_detect_gpios(void) |
461 | { | |
462 | int node; | |
463 | int ret; | |
464 | ||
465 | node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, | |
466 | "solidrun,hummingboard-detect"); | |
467 | if (node < 0) | |
468 | return -ENODEV; | |
469 | ||
470 | ret = gpio_request_list_by_name_nodev(offset_to_ofnode(node), | |
471 | "detect-gpios", board_detect_desc, | |
472 | ARRAY_SIZE(board_detect_desc), GPIOD_IS_IN); | |
473 | ||
474 | return ret; | |
475 | } | |
476 | ||
477 | static int free_detect_gpios(void) | |
478 | { | |
479 | return gpio_free_list_nodev(board_detect_desc, | |
480 | ARRAY_SIZE(board_detect_desc)); | |
481 | } | |
482 | ||
73708200 | 483 | static enum board_type board_type(void) |
feb6cc5c | 484 | { |
73708200 | 485 | int val1, val2, val3; |
feb6cc5c | 486 | |
73708200 | 487 | SETUP_IOMUX_PADS(board_detect); |
feb6cc5c FE |
488 | |
489 | /* | |
490 | * Machine selection - | |
73708200 JN |
491 | * Machine val1, val2, val3 |
492 | * ---------------------------- | |
493 | * HB2 x x 0 | |
494 | * HB rev 3.x x 0 x | |
495 | * CBi 0 1 x | |
496 | * HB 1 1 x | |
feb6cc5c FE |
497 | */ |
498 | ||
73708200 JN |
499 | gpio_direction_input(IMX_GPIO_NR(2, 8)); |
500 | val3 = gpio_get_value(IMX_GPIO_NR(2, 8)); | |
feb6cc5c | 501 | |
73708200 JN |
502 | if (val3 == 0) |
503 | return HUMMINGBOARD2; | |
b1e8512e | 504 | |
73708200 JN |
505 | gpio_direction_input(IMX_GPIO_NR(3, 4)); |
506 | val2 = gpio_get_value(IMX_GPIO_NR(3, 4)); | |
b1e8512e | 507 | |
73708200 JN |
508 | if (val2 == 0) |
509 | return HUMMINGBOARD; | |
b1e8512e | 510 | |
73708200 JN |
511 | gpio_direction_input(IMX_GPIO_NR(4, 9)); |
512 | val1 = gpio_get_value(IMX_GPIO_NR(4, 9)); | |
b1e8512e | 513 | |
73708200 JN |
514 | if (val1 == 0) { |
515 | return CUBOXI; | |
516 | } else { | |
517 | return HUMMINGBOARD; | |
518 | } | |
519 | } | |
520 | ||
521 | static bool is_rev_15_som(void) | |
522 | { | |
523 | int val1, val2; | |
524 | SETUP_IOMUX_PADS(som_rev_detect); | |
b1e8512e | 525 | |
73708200 JN |
526 | val1 = gpio_get_value(IMX_GPIO_NR(6, 0)); |
527 | val2 = gpio_get_value(IMX_GPIO_NR(6, 4)); | |
528 | ||
529 | if (val1 == 1 && val2 == 0) | |
b1e8512e | 530 | return true; |
73708200 JN |
531 | |
532 | return false; | |
b1e8512e DG |
533 | } |
534 | ||
19ed6063 JN |
535 | static bool has_emmc(void) |
536 | { | |
537 | struct mmc *mmc; | |
eb9124f5 | 538 | mmc = find_mmc_device(2); |
19ed6063 JN |
539 | if (!mmc) |
540 | return 0; | |
541 | return (mmc_get_op_cond(mmc) < 0) ? 0 : 1; | |
542 | } | |
543 | ||
b8ce6fe2 FE |
544 | int checkboard(void) |
545 | { | |
eb9124f5 BS |
546 | request_detect_gpios(); |
547 | ||
73708200 JN |
548 | switch (board_type()) { |
549 | case CUBOXI: | |
550 | puts("Board: MX6 Cubox-i"); | |
551 | break; | |
552 | case HUMMINGBOARD: | |
553 | puts("Board: MX6 HummingBoard"); | |
554 | break; | |
555 | case HUMMINGBOARD2: | |
556 | puts("Board: MX6 HummingBoard2"); | |
557 | break; | |
558 | case UNKNOWN: | |
559 | default: | |
560 | puts("Board: Unknown\n"); | |
561 | goto out; | |
562 | } | |
563 | ||
564 | if (is_rev_15_som()) | |
565 | puts(" (som rev 1.5)\n"); | |
feb6cc5c | 566 | else |
73708200 | 567 | puts("\n"); |
feb6cc5c | 568 | |
eb9124f5 | 569 | free_detect_gpios(); |
73708200 | 570 | out: |
b8ce6fe2 FE |
571 | return 0; |
572 | } | |
573 | ||
eb9124f5 BS |
574 | /* Override the default implementation, DT model is not accurate */ |
575 | int show_board_info(void) | |
576 | { | |
577 | return checkboard(); | |
578 | } | |
579 | ||
205d5869 FE |
580 | int board_late_init(void) |
581 | { | |
582 | #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG | |
eb9124f5 BS |
583 | request_detect_gpios(); |
584 | ||
73708200 JN |
585 | switch (board_type()) { |
586 | case CUBOXI: | |
587 | env_set("board_name", "CUBOXI"); | |
588 | break; | |
589 | case HUMMINGBOARD: | |
382bee57 | 590 | env_set("board_name", "HUMMINGBOARD"); |
73708200 JN |
591 | break; |
592 | case HUMMINGBOARD2: | |
593 | env_set("board_name", "HUMMINGBOARD2"); | |
594 | break; | |
595 | case UNKNOWN: | |
596 | default: | |
382bee57 | 597 | env_set("board_name", "CUBOXI"); |
73708200 | 598 | } |
205d5869 | 599 | |
4a2f9014 | 600 | if (is_mx6dq()) |
382bee57 | 601 | env_set("board_rev", "MX6Q"); |
205d5869 | 602 | else |
382bee57 | 603 | env_set("board_rev", "MX6DL"); |
73708200 JN |
604 | |
605 | if (is_rev_15_som()) | |
606 | env_set("som_rev", "V15"); | |
19ed6063 JN |
607 | |
608 | if (has_emmc()) | |
609 | env_set("has_emmc", "yes"); | |
610 | ||
eb9124f5 | 611 | free_detect_gpios(); |
205d5869 FE |
612 | #endif |
613 | ||
614 | return 0; | |
615 | } | |
616 | ||
eb9124f5 BS |
617 | /* |
618 | * This is not a perfect match. Avoid dependency on the DM GPIO driver needed | |
619 | * for accurate board detection. Hummingboard2 DT is good enough for U-Boot on | |
620 | * all Hummingboard/Cubox-i platforms. | |
621 | */ | |
622 | int board_fit_config_name_match(const char *name) | |
623 | { | |
624 | char tmp_name[36]; | |
625 | ||
626 | snprintf(tmp_name, sizeof(tmp_name), "%s-hummingboard2-emmc-som-v15", | |
627 | is_mx6dq() ? "imx6q" : "imx6dl"); | |
628 | ||
629 | return strcmp(name, tmp_name); | |
630 | } | |
631 | ||
b8ce6fe2 | 632 | #ifdef CONFIG_SPL_BUILD |
cfdcc5f7 | 633 | #include <asm/arch/mx6-ddr.h> |
8cb6817e | 634 | static const struct mx6dq_iomux_ddr_regs mx6q_ddr_ioregs = { |
b8ce6fe2 FE |
635 | .dram_sdclk_0 = 0x00020030, |
636 | .dram_sdclk_1 = 0x00020030, | |
637 | .dram_cas = 0x00020030, | |
638 | .dram_ras = 0x00020030, | |
b4e9bdcd | 639 | .dram_reset = 0x000c0030, |
b8ce6fe2 FE |
640 | .dram_sdcke0 = 0x00003000, |
641 | .dram_sdcke1 = 0x00003000, | |
642 | .dram_sdba2 = 0x00000000, | |
643 | .dram_sdodt0 = 0x00003030, | |
644 | .dram_sdodt1 = 0x00003030, | |
645 | .dram_sdqs0 = 0x00000030, | |
646 | .dram_sdqs1 = 0x00000030, | |
647 | .dram_sdqs2 = 0x00000030, | |
648 | .dram_sdqs3 = 0x00000030, | |
649 | .dram_sdqs4 = 0x00000030, | |
650 | .dram_sdqs5 = 0x00000030, | |
651 | .dram_sdqs6 = 0x00000030, | |
652 | .dram_sdqs7 = 0x00000030, | |
653 | .dram_dqm0 = 0x00020030, | |
654 | .dram_dqm1 = 0x00020030, | |
655 | .dram_dqm2 = 0x00020030, | |
656 | .dram_dqm3 = 0x00020030, | |
657 | .dram_dqm4 = 0x00020030, | |
658 | .dram_dqm5 = 0x00020030, | |
659 | .dram_dqm6 = 0x00020030, | |
660 | .dram_dqm7 = 0x00020030, | |
661 | }; | |
662 | ||
8cb6817e FE |
663 | static const struct mx6sdl_iomux_ddr_regs mx6dl_ddr_ioregs = { |
664 | .dram_sdclk_0 = 0x00000028, | |
665 | .dram_sdclk_1 = 0x00000028, | |
666 | .dram_cas = 0x00000028, | |
667 | .dram_ras = 0x00000028, | |
668 | .dram_reset = 0x000c0028, | |
669 | .dram_sdcke0 = 0x00003000, | |
670 | .dram_sdcke1 = 0x00003000, | |
671 | .dram_sdba2 = 0x00000000, | |
672 | .dram_sdodt0 = 0x00003030, | |
673 | .dram_sdodt1 = 0x00003030, | |
674 | .dram_sdqs0 = 0x00000028, | |
675 | .dram_sdqs1 = 0x00000028, | |
676 | .dram_sdqs2 = 0x00000028, | |
677 | .dram_sdqs3 = 0x00000028, | |
678 | .dram_sdqs4 = 0x00000028, | |
679 | .dram_sdqs5 = 0x00000028, | |
680 | .dram_sdqs6 = 0x00000028, | |
681 | .dram_sdqs7 = 0x00000028, | |
682 | .dram_dqm0 = 0x00000028, | |
683 | .dram_dqm1 = 0x00000028, | |
684 | .dram_dqm2 = 0x00000028, | |
685 | .dram_dqm3 = 0x00000028, | |
686 | .dram_dqm4 = 0x00000028, | |
687 | .dram_dqm5 = 0x00000028, | |
688 | .dram_dqm6 = 0x00000028, | |
689 | .dram_dqm7 = 0x00000028, | |
690 | }; | |
691 | ||
692 | static const struct mx6dq_iomux_grp_regs mx6q_grp_ioregs = { | |
b8ce6fe2 FE |
693 | .grp_ddr_type = 0x000C0000, |
694 | .grp_ddrmode_ctl = 0x00020000, | |
695 | .grp_ddrpke = 0x00000000, | |
696 | .grp_addds = 0x00000030, | |
697 | .grp_ctlds = 0x00000030, | |
698 | .grp_ddrmode = 0x00020000, | |
699 | .grp_b0ds = 0x00000030, | |
700 | .grp_b1ds = 0x00000030, | |
701 | .grp_b2ds = 0x00000030, | |
702 | .grp_b3ds = 0x00000030, | |
703 | .grp_b4ds = 0x00000030, | |
704 | .grp_b5ds = 0x00000030, | |
705 | .grp_b6ds = 0x00000030, | |
706 | .grp_b7ds = 0x00000030, | |
707 | }; | |
708 | ||
8cb6817e FE |
709 | static const struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = { |
710 | .grp_ddr_type = 0x000c0000, | |
711 | .grp_ddrmode_ctl = 0x00020000, | |
712 | .grp_ddrpke = 0x00000000, | |
713 | .grp_addds = 0x00000028, | |
714 | .grp_ctlds = 0x00000028, | |
715 | .grp_ddrmode = 0x00020000, | |
716 | .grp_b0ds = 0x00000028, | |
717 | .grp_b1ds = 0x00000028, | |
718 | .grp_b2ds = 0x00000028, | |
719 | .grp_b3ds = 0x00000028, | |
720 | .grp_b4ds = 0x00000028, | |
721 | .grp_b5ds = 0x00000028, | |
722 | .grp_b6ds = 0x00000028, | |
723 | .grp_b7ds = 0x00000028, | |
724 | }; | |
725 | ||
726 | /* microSOM with Dual processor and 1GB memory */ | |
727 | static const struct mx6_mmdc_calibration mx6q_1g_mmcd_calib = { | |
b8ce6fe2 FE |
728 | .p0_mpwldectrl0 = 0x00000000, |
729 | .p0_mpwldectrl1 = 0x00000000, | |
730 | .p1_mpwldectrl0 = 0x00000000, | |
731 | .p1_mpwldectrl1 = 0x00000000, | |
732 | .p0_mpdgctrl0 = 0x0314031c, | |
733 | .p0_mpdgctrl1 = 0x023e0304, | |
734 | .p1_mpdgctrl0 = 0x03240330, | |
735 | .p1_mpdgctrl1 = 0x03180260, | |
736 | .p0_mprddlctl = 0x3630323c, | |
737 | .p1_mprddlctl = 0x3436283a, | |
738 | .p0_mpwrdlctl = 0x36344038, | |
739 | .p1_mpwrdlctl = 0x422a423c, | |
740 | }; | |
741 | ||
8cb6817e FE |
742 | /* microSOM with Quad processor and 2GB memory */ |
743 | static const struct mx6_mmdc_calibration mx6q_2g_mmcd_calib = { | |
744 | .p0_mpwldectrl0 = 0x00000000, | |
745 | .p0_mpwldectrl1 = 0x00000000, | |
746 | .p1_mpwldectrl0 = 0x00000000, | |
747 | .p1_mpwldectrl1 = 0x00000000, | |
748 | .p0_mpdgctrl0 = 0x0314031c, | |
749 | .p0_mpdgctrl1 = 0x023e0304, | |
750 | .p1_mpdgctrl0 = 0x03240330, | |
751 | .p1_mpdgctrl1 = 0x03180260, | |
752 | .p0_mprddlctl = 0x3630323c, | |
753 | .p1_mprddlctl = 0x3436283a, | |
754 | .p0_mpwrdlctl = 0x36344038, | |
755 | .p1_mpwrdlctl = 0x422a423c, | |
756 | }; | |
757 | ||
758 | /* microSOM with Solo processor and 512MB memory */ | |
759 | static const struct mx6_mmdc_calibration mx6dl_512m_mmcd_calib = { | |
760 | .p0_mpwldectrl0 = 0x0045004D, | |
761 | .p0_mpwldectrl1 = 0x003A0047, | |
762 | .p0_mpdgctrl0 = 0x023C0224, | |
763 | .p0_mpdgctrl1 = 0x02000220, | |
764 | .p0_mprddlctl = 0x44444846, | |
765 | .p0_mpwrdlctl = 0x32343032, | |
766 | }; | |
767 | ||
768 | /* microSOM with Dual lite processor and 1GB memory */ | |
769 | static const struct mx6_mmdc_calibration mx6dl_1g_mmcd_calib = { | |
770 | .p0_mpwldectrl0 = 0x0045004D, | |
771 | .p0_mpwldectrl1 = 0x003A0047, | |
772 | .p1_mpwldectrl0 = 0x001F001F, | |
773 | .p1_mpwldectrl1 = 0x00210035, | |
774 | .p0_mpdgctrl0 = 0x023C0224, | |
775 | .p0_mpdgctrl1 = 0x02000220, | |
776 | .p1_mpdgctrl0 = 0x02200220, | |
dbab8b8e | 777 | .p1_mpdgctrl1 = 0x02040208, |
8cb6817e FE |
778 | .p0_mprddlctl = 0x44444846, |
779 | .p1_mprddlctl = 0x4042463C, | |
780 | .p0_mpwrdlctl = 0x32343032, | |
781 | .p1_mpwrdlctl = 0x36363430, | |
782 | }; | |
783 | ||
784 | static struct mx6_ddr3_cfg mem_ddr_2g = { | |
b8ce6fe2 FE |
785 | .mem_speed = 1600, |
786 | .density = 2, | |
787 | .width = 16, | |
788 | .banks = 8, | |
789 | .rowaddr = 14, | |
790 | .coladdr = 10, | |
791 | .pagesz = 2, | |
792 | .trcd = 1375, | |
793 | .trcmin = 4875, | |
794 | .trasmin = 3500, | |
b8ce6fe2 FE |
795 | }; |
796 | ||
8cb6817e FE |
797 | static struct mx6_ddr3_cfg mem_ddr_4g = { |
798 | .mem_speed = 1600, | |
799 | .density = 4, | |
800 | .width = 16, | |
801 | .banks = 8, | |
51f957ad | 802 | .rowaddr = 16, |
8cb6817e FE |
803 | .coladdr = 10, |
804 | .pagesz = 2, | |
805 | .trcd = 1375, | |
806 | .trcmin = 4875, | |
807 | .trasmin = 3500, | |
808 | }; | |
809 | ||
b8ce6fe2 FE |
810 | static void ccgr_init(void) |
811 | { | |
812 | struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | |
813 | ||
814 | writel(0x00C03F3F, &ccm->CCGR0); | |
815 | writel(0x0030FC03, &ccm->CCGR1); | |
816 | writel(0x0FFFC000, &ccm->CCGR2); | |
817 | writel(0x3FF00000, &ccm->CCGR3); | |
818 | writel(0x00FFF300, &ccm->CCGR4); | |
819 | writel(0x0F0000C3, &ccm->CCGR5); | |
820 | writel(0x000003FF, &ccm->CCGR6); | |
821 | } | |
822 | ||
8cb6817e | 823 | static void spl_dram_init(int width) |
b8ce6fe2 FE |
824 | { |
825 | struct mx6_ddr_sysinfo sysinfo = { | |
826 | /* width of data bus: 0=16, 1=32, 2=64 */ | |
8cb6817e | 827 | .dsize = width / 32, |
b8ce6fe2 FE |
828 | /* config for full 4GB range so that get_mem_size() works */ |
829 | .cs_density = 32, /* 32Gb per CS */ | |
830 | .ncs = 1, /* single chip select */ | |
831 | .cs1_mirror = 0, | |
832 | .rtt_wr = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Wr = RZQ/4 */ | |
833 | .rtt_nom = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Nom = RZQ/4 */ | |
834 | .walat = 1, /* Write additional latency */ | |
835 | .ralat = 5, /* Read additional latency */ | |
836 | .mif3_mode = 3, /* Command prediction working mode */ | |
837 | .bi_on = 1, /* Bank interleaving enabled */ | |
838 | .sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */ | |
839 | .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */ | |
f2ff8343 | 840 | .ddr_type = DDR_TYPE_DDR3, |
edf00937 FE |
841 | .refsel = 1, /* Refresh cycles at 32KHz */ |
842 | .refr = 7, /* 8 refresh commands per refresh cycle */ | |
b8ce6fe2 FE |
843 | }; |
844 | ||
4a2f9014 | 845 | if (is_mx6dq()) |
8cb6817e FE |
846 | mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs); |
847 | else | |
848 | mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs); | |
849 | ||
850 | if (is_cpu_type(MXC_CPU_MX6D)) | |
851 | mx6_dram_cfg(&sysinfo, &mx6q_1g_mmcd_calib, &mem_ddr_2g); | |
852 | else if (is_cpu_type(MXC_CPU_MX6Q)) | |
853 | mx6_dram_cfg(&sysinfo, &mx6q_2g_mmcd_calib, &mem_ddr_4g); | |
854 | else if (is_cpu_type(MXC_CPU_MX6DL)) | |
dbab8b8e | 855 | mx6_dram_cfg(&sysinfo, &mx6dl_1g_mmcd_calib, &mem_ddr_2g); |
8cb6817e FE |
856 | else if (is_cpu_type(MXC_CPU_MX6SOLO)) |
857 | mx6_dram_cfg(&sysinfo, &mx6dl_512m_mmcd_calib, &mem_ddr_2g); | |
b8ce6fe2 FE |
858 | } |
859 | ||
860 | void board_init_f(ulong dummy) | |
861 | { | |
862 | /* setup AIPS and disable watchdog */ | |
863 | arch_cpu_init(); | |
864 | ||
865 | ccgr_init(); | |
866 | gpr_init(); | |
867 | ||
868 | /* iomux and setup of i2c */ | |
869 | board_early_init_f(); | |
870 | ||
871 | /* setup GP timer */ | |
872 | timer_init(); | |
873 | ||
874 | /* UART clocks enabled and gd valid - init serial console */ | |
875 | preloader_console_init(); | |
876 | ||
877 | /* DDR initialization */ | |
8cb6817e FE |
878 | if (is_cpu_type(MXC_CPU_MX6SOLO)) |
879 | spl_dram_init(32); | |
880 | else | |
881 | spl_dram_init(64); | |
b8ce6fe2 FE |
882 | |
883 | /* Clear the BSS. */ | |
884 | memset(__bss_start, 0, __bss_end - __bss_start); | |
885 | ||
886 | /* load/boot image from boot device */ | |
887 | board_init_r(NULL, 0); | |
888 | } | |
889 | #endif |