blob: 6a96f9ecdb5315a45577e5b966c4b1f0a9ecffdf [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Fabio Estevam1d97a592015-04-20 14:48:57 -03002/*
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>
Fabio Estevam1d97a592015-04-20 14:48:57 -030014 */
15
Simon Glassa7b51302019-11-14 12:57:46 -070016#include <init.h>
Fabio Estevam1d97a592015-04-20 14:48:57 -030017#include <asm/arch/clock.h>
18#include <asm/arch/imx-regs.h>
19#include <asm/arch/iomux.h>
20#include <asm/arch/mx6-pins.h>
Fabio Estevam239fd312015-04-29 22:28:09 -030021#include <asm/arch/mxc_hdmi.h>
Simon Glass5e6201b2019-08-01 09:46:51 -060022#include <env.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090023#include <linux/errno.h>
Fabio Estevam1d97a592015-04-20 14:48:57 -030024#include <asm/gpio.h>
Stefano Babic33731bc2017-06-29 10:16:06 +020025#include <asm/mach-imx/iomux-v3.h>
26#include <asm/mach-imx/sata.h>
27#include <asm/mach-imx/video.h>
Fabio Estevam1d97a592015-04-20 14:48:57 -030028#include <mmc.h>
Yangbo Lu73340382019-06-21 11:42:28 +080029#include <fsl_esdhc_imx.h>
Fabio Estevam444f0012015-05-04 11:22:55 -030030#include <malloc.h>
Fabio Estevam1d97a592015-04-20 14:48:57 -030031#include <miiphy.h>
32#include <netdev.h>
33#include <asm/arch/crm_regs.h>
34#include <asm/io.h>
35#include <asm/arch/sys_proto.h>
Fabio Estevam1d97a592015-04-20 14:48:57 -030036#include <spl.h>
Fabio Estevam729bbb82015-04-29 22:28:10 -030037#include <usb.h>
Mateusz Kulikowski3add69e2016-03-31 23:12:23 +020038#include <usb/ehci-ci.h>
Fabio Estevam1d97a592015-04-20 14:48:57 -030039
40DECLARE_GLOBAL_DATA_PTR;
41
42#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
43 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
44 PAD_CTL_SRE_FAST | PAD_CTL_HYS)
45
46#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
47 PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \
48 PAD_CTL_SRE_FAST | PAD_CTL_HYS)
49
50#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
51 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
52
53#define ENET_PAD_CTRL_PD (PAD_CTL_PUS_100K_DOWN | \
54 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
55
56#define ENET_PAD_CTRL_CLK ((PAD_CTL_PUS_100K_UP & ~PAD_CTL_PKE) | \
57 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
58
59#define ETH_PHY_RESET IMX_GPIO_NR(4, 15)
Fabio Estevam729bbb82015-04-29 22:28:10 -030060#define USB_H1_VBUS IMX_GPIO_NR(1, 0)
Fabio Estevam1d97a592015-04-20 14:48:57 -030061
Jon Nettleton30cba092018-06-07 16:17:36 +030062enum board_type {
63 CUBOXI = 0x00,
64 HUMMINGBOARD = 0x01,
65 HUMMINGBOARD2 = 0x02,
66 UNKNOWN = 0x03,
67};
68
Baruch Siach6d3f68c2019-11-10 14:38:07 +020069static struct gpio_desc board_detect_desc[5];
70
Jon Nettletondfe7fab2018-06-07 16:17:37 +030071#define MEM_STRIDE 0x4000000
72static u32 get_ram_size_stride_test(u32 *base, u32 maxsize)
73{
74 volatile u32 *addr;
75 u32 save[64];
76 u32 cnt;
77 u32 size;
78 int i = 0;
79
80 /* First save the data */
81 for (cnt = 0; cnt < maxsize; cnt += MEM_STRIDE) {
82 addr = (volatile u32 *)((u32)base + cnt); /* pointer arith! */
83 sync ();
84 save[i++] = *addr;
85 sync ();
86 }
87
88 /* First write a signature */
89 * (volatile u32 *)base = 0x12345678;
90 for (size = MEM_STRIDE; size < maxsize; size += MEM_STRIDE) {
91 * (volatile u32 *)((u32)base + size) = size;
92 sync ();
93 if (* (volatile u32 *)((u32)base) == size) { /* We reached the overlapping address */
94 break;
95 }
96 }
97
98 /* Restore the data */
99 for (cnt = (maxsize - MEM_STRIDE); i > 0; cnt -= MEM_STRIDE) {
100 addr = (volatile u32 *)((u32)base + cnt); /* pointer arith! */
101 sync ();
102 *addr = save[i--];
103 sync ();
104 }
105
106 return (size);
107}
108
Fabio Estevam1d97a592015-04-20 14:48:57 -0300109int dram_init(void)
110{
Jon Nettletondfe7fab2018-06-07 16:17:37 +0300111 u32 max_size = imx_ddr_size();
112
113 gd->ram_size = get_ram_size_stride_test((u32 *) CONFIG_SYS_SDRAM_BASE,
114 (u32)max_size);
115
Fabio Estevam1d97a592015-04-20 14:48:57 -0300116 return 0;
117}
118
119static iomux_v3_cfg_t const uart1_pads[] = {
Fabio Estevam5f402c42015-04-25 18:47:17 -0300120 IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
121 IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
Fabio Estevam1d97a592015-04-20 14:48:57 -0300122};
123
124static iomux_v3_cfg_t const usdhc2_pads[] = {
Fabio Estevam5f402c42015-04-25 18:47:17 -0300125 IOMUX_PADS(PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
126 IOMUX_PADS(PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
127 IOMUX_PADS(PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
128 IOMUX_PADS(PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
129 IOMUX_PADS(PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
130 IOMUX_PADS(PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
Fabio Estevam1d97a592015-04-20 14:48:57 -0300131};
132
Jon Nettleton08d38cb2018-06-11 15:26:20 +0300133static iomux_v3_cfg_t const usdhc3_pads[] = {
134 IOMUX_PADS(PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
135 IOMUX_PADS(PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
136 IOMUX_PADS(PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
137 IOMUX_PADS(PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
138 IOMUX_PADS(PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
139 IOMUX_PADS(PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
140 IOMUX_PADS(PAD_SD3_DAT4__SD3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
141 IOMUX_PADS(PAD_SD3_DAT5__SD3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
142 IOMUX_PADS(PAD_SD3_DAT6__SD3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
143 IOMUX_PADS(PAD_SD3_DAT7__SD3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
144 IOMUX_PADS(PAD_SD3_RST__SD3_RESET | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
145};
146
Jon Nettleton30cba092018-06-07 16:17:36 +0300147static iomux_v3_cfg_t const board_detect[] = {
Fabio Estevam7a2f9cd2015-04-25 18:47:19 -0300148 /* These pins are for sensing if it is a CuBox-i or a HummingBoard */
149 IOMUX_PADS(PAD_KEY_ROW1__GPIO4_IO09 | MUX_PAD_CTRL(UART_PAD_CTRL)),
150 IOMUX_PADS(PAD_EIM_DA4__GPIO3_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)),
Jon Nettleton30cba092018-06-07 16:17:36 +0300151 IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | MUX_PAD_CTRL(UART_PAD_CTRL)),
152};
153
154static iomux_v3_cfg_t const som_rev_detect[] = {
155 /* These pins are for sensing if it is a CuBox-i or a HummingBoard */
156 IOMUX_PADS(PAD_CSI0_DAT14__GPIO6_IO00 | MUX_PAD_CTRL(UART_PAD_CTRL)),
157 IOMUX_PADS(PAD_CSI0_DAT18__GPIO6_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)),
Fabio Estevam7a2f9cd2015-04-25 18:47:19 -0300158};
159
Fabio Estevam1d97a592015-04-20 14:48:57 -0300160static void setup_iomux_uart(void)
161{
Fabio Estevam5f402c42015-04-25 18:47:17 -0300162 SETUP_IOMUX_PADS(uart1_pads);
Fabio Estevam1d97a592015-04-20 14:48:57 -0300163}
164
Jon Nettleton08d38cb2018-06-11 15:26:20 +0300165static struct fsl_esdhc_cfg usdhc_cfg = {
166 .esdhc_base = USDHC2_BASE_ADDR,
167 .max_bus_width = 4,
168};
169
170static struct fsl_esdhc_cfg emmc_cfg = {
171 .esdhc_base = USDHC3_BASE_ADDR,
172 .max_bus_width = 8,
Fabio Estevam1d97a592015-04-20 14:48:57 -0300173};
174
Jon Nettleton08d38cb2018-06-11 15:26:20 +0300175int board_mmc_get_env_dev(int devno)
176{
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200177 return devno;
Jon Nettleton08d38cb2018-06-11 15:26:20 +0300178}
179
180#define USDHC2_CD_GPIO IMX_GPIO_NR(1, 4)
181
Fabio Estevam1d97a592015-04-20 14:48:57 -0300182int board_mmc_getcd(struct mmc *mmc)
183{
Jon Nettleton08d38cb2018-06-11 15:26:20 +0300184 struct fsl_esdhc_cfg *cfg = mmc->priv;
185 int ret = 0;
186
187 switch (cfg->esdhc_base) {
188 case USDHC2_BASE_ADDR:
189 ret = !gpio_get_value(USDHC2_CD_GPIO);
190 break;
191 case USDHC3_BASE_ADDR:
Jon Nettleton51182112018-06-11 15:26:22 +0300192 ret = (mmc_get_op_cond(mmc) < 0) ? 0 : 1; /* eMMC/uSDHC3 has no CD GPIO */
Jon Nettleton08d38cb2018-06-11 15:26:20 +0300193 break;
194 }
195
196 return ret;
Fabio Estevam1d97a592015-04-20 14:48:57 -0300197}
198
Jon Nettleton08d38cb2018-06-11 15:26:20 +0300199static int mmc_init_spl(bd_t *bis)
200{
201 struct src *psrc = (struct src *)SRC_BASE_ADDR;
202 unsigned reg = readl(&psrc->sbmr1) >> 11;
203
204 /*
205 * Upon reading BOOT_CFG register the following map is done:
206 * Bit 11 and 12 of BOOT_CFG register can determine the current
207 * mmc port
208 * 0x1 SD2
209 * 0x2 SD3
210 */
211 switch (reg & 0x3) {
212 case 0x1:
213 SETUP_IOMUX_PADS(usdhc2_pads);
214 usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
215 gd->arch.sdhc_clk = usdhc_cfg.sdhc_clk;
216 return fsl_esdhc_initialize(bis, &usdhc_cfg);
217 case 0x2:
218 SETUP_IOMUX_PADS(usdhc3_pads);
219 emmc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
220 gd->arch.sdhc_clk = emmc_cfg.sdhc_clk;
221 return fsl_esdhc_initialize(bis, &emmc_cfg);
222 }
223
224 return -ENODEV;
225}
226
227int board_mmc_init(bd_t *bis)
228{
229 if (IS_ENABLED(CONFIG_SPL_BUILD))
230 return mmc_init_spl(bis);
Fabio Estevam1d97a592015-04-20 14:48:57 -0300231
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200232 return 0;
Fabio Estevam1d97a592015-04-20 14:48:57 -0300233}
234
235static iomux_v3_cfg_t const enet_pads[] = {
Fabio Estevam5f402c42015-04-25 18:47:17 -0300236 IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL)),
237 IOMUX_PADS(PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL)),
Fabio Estevam1d97a592015-04-20 14:48:57 -0300238 /* AR8035 reset */
Fabio Estevam5f402c42015-04-25 18:47:17 -0300239 IOMUX_PADS(PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
Fabio Estevam1d97a592015-04-20 14:48:57 -0300240 /* AR8035 interrupt */
Fabio Estevam5f402c42015-04-25 18:47:17 -0300241 IOMUX_PADS(PAD_DI0_PIN2__GPIO4_IO18 | MUX_PAD_CTRL(NO_PAD_CTRL)),
Fabio Estevam1d97a592015-04-20 14:48:57 -0300242 /* GPIO16 -> AR8035 25MHz */
Fabio Estevam5f402c42015-04-25 18:47:17 -0300243 IOMUX_PADS(PAD_GPIO_16__ENET_REF_CLK | MUX_PAD_CTRL(NO_PAD_CTRL)),
244 IOMUX_PADS(PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(NO_PAD_CTRL)),
245 IOMUX_PADS(PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
246 IOMUX_PADS(PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
247 IOMUX_PADS(PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
248 IOMUX_PADS(PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
249 IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)),
Fabio Estevam1d97a592015-04-20 14:48:57 -0300250 /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
Fabio Estevam5f402c42015-04-25 18:47:17 -0300251 IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL_CLK)),
252 IOMUX_PADS(PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL)),
253 IOMUX_PADS(PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
254 IOMUX_PADS(PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
255 IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
256 IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
257 IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
Fabio Estevama6aac042015-05-04 11:22:56 -0300258 IOMUX_PADS(PAD_ENET_RXD0__GPIO1_IO27 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
259 IOMUX_PADS(PAD_ENET_RXD1__GPIO1_IO26 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
Fabio Estevam1d97a592015-04-20 14:48:57 -0300260};
261
262static void setup_iomux_enet(void)
263{
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200264 struct gpio_desc desc;
265 int ret;
266
Fabio Estevam5f402c42015-04-25 18:47:17 -0300267 SETUP_IOMUX_PADS(enet_pads);
Fabio Estevam1d97a592015-04-20 14:48:57 -0300268
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200269 ret = dm_gpio_lookup_name("GPIO4_15", &desc);
270 if (ret) {
271 printf("%s: phy reset lookup failed\n", __func__);
272 return;
273 }
274
275 ret = dm_gpio_request(&desc, "phy-reset");
276 if (ret) {
277 printf("%s: phy reset request failed\n", __func__);
278 return;
279 }
280
Fabio Estevam1d97a592015-04-20 14:48:57 -0300281 gpio_direction_output(ETH_PHY_RESET, 0);
Fabio Estevam355b28f2016-01-04 21:38:08 -0200282 mdelay(10);
Fabio Estevam1d97a592015-04-20 14:48:57 -0300283 gpio_set_value(ETH_PHY_RESET, 1);
Fabio Estevam355b28f2016-01-04 21:38:08 -0200284 udelay(100);
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200285
286 gpio_free_list_nodev(&desc, 1);
Fabio Estevam1d97a592015-04-20 14:48:57 -0300287}
288
289int board_phy_config(struct phy_device *phydev)
290{
291 if (phydev->drv->config)
292 phydev->drv->config(phydev);
293
294 return 0;
295}
296
Fabio Estevam444f0012015-05-04 11:22:55 -0300297/* On Cuboxi Ethernet PHY can be located at addresses 0x0 or 0x4 */
298#define ETH_PHY_MASK ((1 << 0x0) | (1 << 0x4))
299
Fabio Estevam1d97a592015-04-20 14:48:57 -0300300int board_eth_init(bd_t *bis)
301{
302 struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
Fabio Estevam444f0012015-05-04 11:22:55 -0300303 struct mii_dev *bus;
304 struct phy_device *phydev;
Fabio Estevam1d97a592015-04-20 14:48:57 -0300305
Peng Fan967a83b2015-08-12 17:46:50 +0800306 int ret = enable_fec_anatop_clock(0, ENET_25MHZ);
Fabio Estevam1d97a592015-04-20 14:48:57 -0300307 if (ret)
308 return ret;
309
310 /* set gpr1[ENET_CLK_SEL] */
311 setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK);
312
313 setup_iomux_enet();
314
Fabio Estevam444f0012015-05-04 11:22:55 -0300315 bus = fec_get_miibus(IMX_FEC_BASE, -1);
316 if (!bus)
317 return -EINVAL;
318
319 phydev = phy_find_by_mask(bus, ETH_PHY_MASK, PHY_INTERFACE_MODE_RGMII);
320 if (!phydev) {
321 ret = -EINVAL;
322 goto free_bus;
323 }
324
325 debug("using phy at address %d\n", phydev->addr);
326 ret = fec_probe(bis, -1, IMX_FEC_BASE, bus, phydev);
327 if (ret)
328 goto free_phydev;
329
330 return 0;
331
332free_phydev:
333 free(phydev);
334free_bus:
335 free(bus);
336 return ret;
Fabio Estevam1d97a592015-04-20 14:48:57 -0300337}
338
Fabio Estevam239fd312015-04-29 22:28:09 -0300339#ifdef CONFIG_VIDEO_IPUV3
340static void do_enable_hdmi(struct display_info_t const *dev)
341{
342 imx_enable_hdmi_phy();
343}
344
345struct display_info_t const displays[] = {
346 {
347 .bus = -1,
348 .addr = 0,
349 .pixfmt = IPU_PIX_FMT_RGB24,
350 .detect = detect_hdmi,
351 .enable = do_enable_hdmi,
352 .mode = {
353 .name = "HDMI",
354 /* 1024x768@60Hz (VESA)*/
355 .refresh = 60,
356 .xres = 1024,
357 .yres = 768,
358 .pixclock = 15384,
359 .left_margin = 160,
360 .right_margin = 24,
361 .upper_margin = 29,
362 .lower_margin = 3,
363 .hsync_len = 136,
364 .vsync_len = 6,
365 .sync = FB_SYNC_EXT,
366 .vmode = FB_VMODE_NONINTERLACED
367 }
368 }
369};
370
371size_t display_count = ARRAY_SIZE(displays);
372
373static int setup_display(void)
374{
375 struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
376 int reg;
377 int timeout = 100000;
378
379 enable_ipu_clock();
380 imx_setup_hdmi();
381
382 /* set video pll to 455MHz (24MHz * (37+11/12) / 2) */
383 setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
384
385 reg = readl(&ccm->analog_pll_video);
386 reg &= ~BM_ANADIG_PLL_VIDEO_DIV_SELECT;
387 reg |= BF_ANADIG_PLL_VIDEO_DIV_SELECT(37);
388 reg &= ~BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT;
389 reg |= BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1);
390 writel(reg, &ccm->analog_pll_video);
391
392 writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num);
393 writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom);
394
395 reg &= ~BM_ANADIG_PLL_VIDEO_POWERDOWN;
396 writel(reg, &ccm->analog_pll_video);
397
398 while (timeout--)
399 if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK)
400 break;
401 if (timeout < 0) {
402 printf("Warning: video pll lock timeout!\n");
403 return -ETIMEDOUT;
404 }
405
406 reg = readl(&ccm->analog_pll_video);
407 reg |= BM_ANADIG_PLL_VIDEO_ENABLE;
408 reg &= ~BM_ANADIG_PLL_VIDEO_BYPASS;
409 writel(reg, &ccm->analog_pll_video);
410
411 /* gate ipu1_di0_clk */
412 clrbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
413
414 /* select video_pll clock / 7 for ipu1_di0_clk -> 65MHz pixclock */
415 reg = readl(&ccm->chsccdr);
416 reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK |
417 MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK |
418 MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
419 reg |= (2 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET) |
420 (6 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) |
421 (0 << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
422 writel(reg, &ccm->chsccdr);
423
424 /* enable ipu1_di0_clk */
425 setbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
426
427 return 0;
428}
429#endif /* CONFIG_VIDEO_IPUV3 */
430
Fabio Estevam1d97a592015-04-20 14:48:57 -0300431int board_early_init_f(void)
432{
433 setup_iomux_uart();
Fabio Estevam239fd312015-04-29 22:28:09 -0300434
Peter Robinson8576fbc2017-07-01 18:44:03 +0100435#ifdef CONFIG_CMD_SATA
436 setup_sata();
437#endif
Fabio Estevamf82f20c2017-09-22 23:45:31 -0300438 return 0;
Fabio Estevam1d97a592015-04-20 14:48:57 -0300439}
440
441int board_init(void)
442{
Fabio Estevamf82f20c2017-09-22 23:45:31 -0300443 int ret = 0;
444
Fabio Estevam1d97a592015-04-20 14:48:57 -0300445 /* address of boot parameters */
446 gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
447
Fabio Estevamf82f20c2017-09-22 23:45:31 -0300448#ifdef CONFIG_VIDEO_IPUV3
449 ret = setup_display();
450#endif
451
452 return ret;
Fabio Estevam1d97a592015-04-20 14:48:57 -0300453}
454
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200455static int request_detect_gpios(void)
456{
457 int node;
458 int ret;
459
460 node = fdt_node_offset_by_compatible(gd->fdt_blob, 0,
461 "solidrun,hummingboard-detect");
462 if (node < 0)
463 return -ENODEV;
464
465 ret = gpio_request_list_by_name_nodev(offset_to_ofnode(node),
466 "detect-gpios", board_detect_desc,
467 ARRAY_SIZE(board_detect_desc), GPIOD_IS_IN);
468
469 return ret;
470}
471
472static int free_detect_gpios(void)
473{
474 return gpio_free_list_nodev(board_detect_desc,
475 ARRAY_SIZE(board_detect_desc));
476}
477
Jon Nettleton30cba092018-06-07 16:17:36 +0300478static enum board_type board_type(void)
Fabio Estevam7a2f9cd2015-04-25 18:47:19 -0300479{
Jon Nettleton30cba092018-06-07 16:17:36 +0300480 int val1, val2, val3;
Fabio Estevam7a2f9cd2015-04-25 18:47:19 -0300481
Jon Nettleton30cba092018-06-07 16:17:36 +0300482 SETUP_IOMUX_PADS(board_detect);
Fabio Estevam7a2f9cd2015-04-25 18:47:19 -0300483
484 /*
485 * Machine selection -
Jon Nettleton30cba092018-06-07 16:17:36 +0300486 * Machine val1, val2, val3
487 * ----------------------------
488 * HB2 x x 0
489 * HB rev 3.x x 0 x
490 * CBi 0 1 x
491 * HB 1 1 x
Fabio Estevam7a2f9cd2015-04-25 18:47:19 -0300492 */
493
Jon Nettleton30cba092018-06-07 16:17:36 +0300494 gpio_direction_input(IMX_GPIO_NR(2, 8));
495 val3 = gpio_get_value(IMX_GPIO_NR(2, 8));
Fabio Estevam7a2f9cd2015-04-25 18:47:19 -0300496
Jon Nettleton30cba092018-06-07 16:17:36 +0300497 if (val3 == 0)
498 return HUMMINGBOARD2;
Dennis Gilmore52e61ba2017-08-24 10:49:43 -0500499
Jon Nettleton30cba092018-06-07 16:17:36 +0300500 gpio_direction_input(IMX_GPIO_NR(3, 4));
501 val2 = gpio_get_value(IMX_GPIO_NR(3, 4));
Dennis Gilmore52e61ba2017-08-24 10:49:43 -0500502
Jon Nettleton30cba092018-06-07 16:17:36 +0300503 if (val2 == 0)
504 return HUMMINGBOARD;
Dennis Gilmore52e61ba2017-08-24 10:49:43 -0500505
Jon Nettleton30cba092018-06-07 16:17:36 +0300506 gpio_direction_input(IMX_GPIO_NR(4, 9));
507 val1 = gpio_get_value(IMX_GPIO_NR(4, 9));
Dennis Gilmore52e61ba2017-08-24 10:49:43 -0500508
Jon Nettleton30cba092018-06-07 16:17:36 +0300509 if (val1 == 0) {
510 return CUBOXI;
511 } else {
512 return HUMMINGBOARD;
513 }
514}
515
516static bool is_rev_15_som(void)
517{
518 int val1, val2;
519 SETUP_IOMUX_PADS(som_rev_detect);
Dennis Gilmore52e61ba2017-08-24 10:49:43 -0500520
Jon Nettleton30cba092018-06-07 16:17:36 +0300521 val1 = gpio_get_value(IMX_GPIO_NR(6, 0));
522 val2 = gpio_get_value(IMX_GPIO_NR(6, 4));
523
524 if (val1 == 1 && val2 == 0)
Dennis Gilmore52e61ba2017-08-24 10:49:43 -0500525 return true;
Jon Nettleton30cba092018-06-07 16:17:36 +0300526
527 return false;
Dennis Gilmore52e61ba2017-08-24 10:49:43 -0500528}
529
Jon Nettleton51182112018-06-11 15:26:22 +0300530static bool has_emmc(void)
531{
532 struct mmc *mmc;
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200533 mmc = find_mmc_device(2);
Jon Nettleton51182112018-06-11 15:26:22 +0300534 if (!mmc)
535 return 0;
536 return (mmc_get_op_cond(mmc) < 0) ? 0 : 1;
537}
538
Fabio Estevam1d97a592015-04-20 14:48:57 -0300539int checkboard(void)
540{
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200541 request_detect_gpios();
542
Jon Nettleton30cba092018-06-07 16:17:36 +0300543 switch (board_type()) {
544 case CUBOXI:
545 puts("Board: MX6 Cubox-i");
546 break;
547 case HUMMINGBOARD:
548 puts("Board: MX6 HummingBoard");
549 break;
550 case HUMMINGBOARD2:
551 puts("Board: MX6 HummingBoard2");
552 break;
553 case UNKNOWN:
554 default:
555 puts("Board: Unknown\n");
556 goto out;
557 }
558
559 if (is_rev_15_som())
560 puts(" (som rev 1.5)\n");
Fabio Estevam7a2f9cd2015-04-25 18:47:19 -0300561 else
Jon Nettleton30cba092018-06-07 16:17:36 +0300562 puts("\n");
Fabio Estevam7a2f9cd2015-04-25 18:47:19 -0300563
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200564 free_detect_gpios();
Jon Nettleton30cba092018-06-07 16:17:36 +0300565out:
Fabio Estevam1d97a592015-04-20 14:48:57 -0300566 return 0;
567}
568
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200569/* Override the default implementation, DT model is not accurate */
570int show_board_info(void)
571{
572 return checkboard();
573}
574
Fabio Estevam9887c1a2015-04-25 18:47:21 -0300575int board_late_init(void)
576{
577#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200578 request_detect_gpios();
579
Jon Nettleton30cba092018-06-07 16:17:36 +0300580 switch (board_type()) {
581 case CUBOXI:
582 env_set("board_name", "CUBOXI");
583 break;
584 case HUMMINGBOARD:
Simon Glass6a38e412017-08-03 12:22:09 -0600585 env_set("board_name", "HUMMINGBOARD");
Jon Nettleton30cba092018-06-07 16:17:36 +0300586 break;
587 case HUMMINGBOARD2:
588 env_set("board_name", "HUMMINGBOARD2");
589 break;
590 case UNKNOWN:
591 default:
Simon Glass6a38e412017-08-03 12:22:09 -0600592 env_set("board_name", "CUBOXI");
Jon Nettleton30cba092018-06-07 16:17:36 +0300593 }
Fabio Estevam9887c1a2015-04-25 18:47:21 -0300594
Breno Limaba776122016-07-22 09:11:30 -0300595 if (is_mx6dq())
Simon Glass6a38e412017-08-03 12:22:09 -0600596 env_set("board_rev", "MX6Q");
Fabio Estevam9887c1a2015-04-25 18:47:21 -0300597 else
Simon Glass6a38e412017-08-03 12:22:09 -0600598 env_set("board_rev", "MX6DL");
Jon Nettleton30cba092018-06-07 16:17:36 +0300599
600 if (is_rev_15_som())
601 env_set("som_rev", "V15");
Jon Nettleton51182112018-06-11 15:26:22 +0300602
603 if (has_emmc())
604 env_set("has_emmc", "yes");
605
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200606 free_detect_gpios();
Fabio Estevam9887c1a2015-04-25 18:47:21 -0300607#endif
608
609 return 0;
610}
611
Baruch Siach6d3f68c2019-11-10 14:38:07 +0200612/*
613 * This is not a perfect match. Avoid dependency on the DM GPIO driver needed
614 * for accurate board detection. Hummingboard2 DT is good enough for U-Boot on
615 * all Hummingboard/Cubox-i platforms.
616 */
617int board_fit_config_name_match(const char *name)
618{
619 char tmp_name[36];
620
621 snprintf(tmp_name, sizeof(tmp_name), "%s-hummingboard2-emmc-som-v15",
622 is_mx6dq() ? "imx6q" : "imx6dl");
623
624 return strcmp(name, tmp_name);
625}
626
Fabio Estevam1d97a592015-04-20 14:48:57 -0300627#ifdef CONFIG_SPL_BUILD
Fabio Estevam5f402c42015-04-25 18:47:17 -0300628#include <asm/arch/mx6-ddr.h>
Fabio Estevamcb601912015-04-25 18:47:18 -0300629static const struct mx6dq_iomux_ddr_regs mx6q_ddr_ioregs = {
Fabio Estevam1d97a592015-04-20 14:48:57 -0300630 .dram_sdclk_0 = 0x00020030,
631 .dram_sdclk_1 = 0x00020030,
632 .dram_cas = 0x00020030,
633 .dram_ras = 0x00020030,
Jon Nettletoncd2020d2018-04-10 17:05:35 -0300634 .dram_reset = 0x000c0030,
Fabio Estevam1d97a592015-04-20 14:48:57 -0300635 .dram_sdcke0 = 0x00003000,
636 .dram_sdcke1 = 0x00003000,
637 .dram_sdba2 = 0x00000000,
638 .dram_sdodt0 = 0x00003030,
639 .dram_sdodt1 = 0x00003030,
640 .dram_sdqs0 = 0x00000030,
641 .dram_sdqs1 = 0x00000030,
642 .dram_sdqs2 = 0x00000030,
643 .dram_sdqs3 = 0x00000030,
644 .dram_sdqs4 = 0x00000030,
645 .dram_sdqs5 = 0x00000030,
646 .dram_sdqs6 = 0x00000030,
647 .dram_sdqs7 = 0x00000030,
648 .dram_dqm0 = 0x00020030,
649 .dram_dqm1 = 0x00020030,
650 .dram_dqm2 = 0x00020030,
651 .dram_dqm3 = 0x00020030,
652 .dram_dqm4 = 0x00020030,
653 .dram_dqm5 = 0x00020030,
654 .dram_dqm6 = 0x00020030,
655 .dram_dqm7 = 0x00020030,
656};
657
Fabio Estevamcb601912015-04-25 18:47:18 -0300658static const struct mx6sdl_iomux_ddr_regs mx6dl_ddr_ioregs = {
659 .dram_sdclk_0 = 0x00000028,
660 .dram_sdclk_1 = 0x00000028,
661 .dram_cas = 0x00000028,
662 .dram_ras = 0x00000028,
663 .dram_reset = 0x000c0028,
664 .dram_sdcke0 = 0x00003000,
665 .dram_sdcke1 = 0x00003000,
666 .dram_sdba2 = 0x00000000,
667 .dram_sdodt0 = 0x00003030,
668 .dram_sdodt1 = 0x00003030,
669 .dram_sdqs0 = 0x00000028,
670 .dram_sdqs1 = 0x00000028,
671 .dram_sdqs2 = 0x00000028,
672 .dram_sdqs3 = 0x00000028,
673 .dram_sdqs4 = 0x00000028,
674 .dram_sdqs5 = 0x00000028,
675 .dram_sdqs6 = 0x00000028,
676 .dram_sdqs7 = 0x00000028,
677 .dram_dqm0 = 0x00000028,
678 .dram_dqm1 = 0x00000028,
679 .dram_dqm2 = 0x00000028,
680 .dram_dqm3 = 0x00000028,
681 .dram_dqm4 = 0x00000028,
682 .dram_dqm5 = 0x00000028,
683 .dram_dqm6 = 0x00000028,
684 .dram_dqm7 = 0x00000028,
685};
686
687static const struct mx6dq_iomux_grp_regs mx6q_grp_ioregs = {
Fabio Estevam1d97a592015-04-20 14:48:57 -0300688 .grp_ddr_type = 0x000C0000,
689 .grp_ddrmode_ctl = 0x00020000,
690 .grp_ddrpke = 0x00000000,
691 .grp_addds = 0x00000030,
692 .grp_ctlds = 0x00000030,
693 .grp_ddrmode = 0x00020000,
694 .grp_b0ds = 0x00000030,
695 .grp_b1ds = 0x00000030,
696 .grp_b2ds = 0x00000030,
697 .grp_b3ds = 0x00000030,
698 .grp_b4ds = 0x00000030,
699 .grp_b5ds = 0x00000030,
700 .grp_b6ds = 0x00000030,
701 .grp_b7ds = 0x00000030,
702};
703
Fabio Estevamcb601912015-04-25 18:47:18 -0300704static const struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = {
705 .grp_ddr_type = 0x000c0000,
706 .grp_ddrmode_ctl = 0x00020000,
707 .grp_ddrpke = 0x00000000,
708 .grp_addds = 0x00000028,
709 .grp_ctlds = 0x00000028,
710 .grp_ddrmode = 0x00020000,
711 .grp_b0ds = 0x00000028,
712 .grp_b1ds = 0x00000028,
713 .grp_b2ds = 0x00000028,
714 .grp_b3ds = 0x00000028,
715 .grp_b4ds = 0x00000028,
716 .grp_b5ds = 0x00000028,
717 .grp_b6ds = 0x00000028,
718 .grp_b7ds = 0x00000028,
719};
720
721/* microSOM with Dual processor and 1GB memory */
722static const struct mx6_mmdc_calibration mx6q_1g_mmcd_calib = {
723 .p0_mpwldectrl0 = 0x00000000,
724 .p0_mpwldectrl1 = 0x00000000,
725 .p1_mpwldectrl0 = 0x00000000,
726 .p1_mpwldectrl1 = 0x00000000,
727 .p0_mpdgctrl0 = 0x0314031c,
728 .p0_mpdgctrl1 = 0x023e0304,
729 .p1_mpdgctrl0 = 0x03240330,
730 .p1_mpdgctrl1 = 0x03180260,
731 .p0_mprddlctl = 0x3630323c,
732 .p1_mprddlctl = 0x3436283a,
733 .p0_mpwrdlctl = 0x36344038,
734 .p1_mpwrdlctl = 0x422a423c,
735};
736
737/* microSOM with Quad processor and 2GB memory */
738static const struct mx6_mmdc_calibration mx6q_2g_mmcd_calib = {
Fabio Estevam1d97a592015-04-20 14:48:57 -0300739 .p0_mpwldectrl0 = 0x00000000,
740 .p0_mpwldectrl1 = 0x00000000,
741 .p1_mpwldectrl0 = 0x00000000,
742 .p1_mpwldectrl1 = 0x00000000,
743 .p0_mpdgctrl0 = 0x0314031c,
744 .p0_mpdgctrl1 = 0x023e0304,
745 .p1_mpdgctrl0 = 0x03240330,
746 .p1_mpdgctrl1 = 0x03180260,
747 .p0_mprddlctl = 0x3630323c,
748 .p1_mprddlctl = 0x3436283a,
749 .p0_mpwrdlctl = 0x36344038,
750 .p1_mpwrdlctl = 0x422a423c,
751};
752
Fabio Estevamcb601912015-04-25 18:47:18 -0300753/* microSOM with Solo processor and 512MB memory */
754static const struct mx6_mmdc_calibration mx6dl_512m_mmcd_calib = {
755 .p0_mpwldectrl0 = 0x0045004D,
756 .p0_mpwldectrl1 = 0x003A0047,
757 .p0_mpdgctrl0 = 0x023C0224,
758 .p0_mpdgctrl1 = 0x02000220,
759 .p0_mprddlctl = 0x44444846,
760 .p0_mpwrdlctl = 0x32343032,
761};
762
763/* microSOM with Dual lite processor and 1GB memory */
764static const struct mx6_mmdc_calibration mx6dl_1g_mmcd_calib = {
765 .p0_mpwldectrl0 = 0x0045004D,
766 .p0_mpwldectrl1 = 0x003A0047,
767 .p1_mpwldectrl0 = 0x001F001F,
768 .p1_mpwldectrl1 = 0x00210035,
769 .p0_mpdgctrl0 = 0x023C0224,
770 .p0_mpdgctrl1 = 0x02000220,
771 .p1_mpdgctrl0 = 0x02200220,
Fabio Estevam4461e1e2015-05-29 13:00:36 -0300772 .p1_mpdgctrl1 = 0x02040208,
Fabio Estevamcb601912015-04-25 18:47:18 -0300773 .p0_mprddlctl = 0x44444846,
774 .p1_mprddlctl = 0x4042463C,
775 .p0_mpwrdlctl = 0x32343032,
776 .p1_mpwrdlctl = 0x36363430,
777};
778
779static struct mx6_ddr3_cfg mem_ddr_2g = {
Fabio Estevam1d97a592015-04-20 14:48:57 -0300780 .mem_speed = 1600,
781 .density = 2,
782 .width = 16,
783 .banks = 8,
784 .rowaddr = 14,
785 .coladdr = 10,
786 .pagesz = 2,
787 .trcd = 1375,
788 .trcmin = 4875,
789 .trasmin = 3500,
Fabio Estevam1d97a592015-04-20 14:48:57 -0300790};
791
Fabio Estevamcb601912015-04-25 18:47:18 -0300792static struct mx6_ddr3_cfg mem_ddr_4g = {
793 .mem_speed = 1600,
794 .density = 4,
795 .width = 16,
796 .banks = 8,
Jon Nettletondfe7fab2018-06-07 16:17:37 +0300797 .rowaddr = 16,
Fabio Estevamcb601912015-04-25 18:47:18 -0300798 .coladdr = 10,
799 .pagesz = 2,
800 .trcd = 1375,
801 .trcmin = 4875,
802 .trasmin = 3500,
803};
804
Fabio Estevam1d97a592015-04-20 14:48:57 -0300805static void ccgr_init(void)
806{
807 struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
808
809 writel(0x00C03F3F, &ccm->CCGR0);
810 writel(0x0030FC03, &ccm->CCGR1);
811 writel(0x0FFFC000, &ccm->CCGR2);
812 writel(0x3FF00000, &ccm->CCGR3);
813 writel(0x00FFF300, &ccm->CCGR4);
814 writel(0x0F0000C3, &ccm->CCGR5);
815 writel(0x000003FF, &ccm->CCGR6);
816}
817
Fabio Estevamcb601912015-04-25 18:47:18 -0300818static void spl_dram_init(int width)
Fabio Estevam1d97a592015-04-20 14:48:57 -0300819{
820 struct mx6_ddr_sysinfo sysinfo = {
821 /* width of data bus: 0=16, 1=32, 2=64 */
Fabio Estevamcb601912015-04-25 18:47:18 -0300822 .dsize = width / 32,
Fabio Estevam1d97a592015-04-20 14:48:57 -0300823 /* config for full 4GB range so that get_mem_size() works */
824 .cs_density = 32, /* 32Gb per CS */
825 .ncs = 1, /* single chip select */
826 .cs1_mirror = 0,
827 .rtt_wr = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Wr = RZQ/4 */
828 .rtt_nom = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Nom = RZQ/4 */
829 .walat = 1, /* Write additional latency */
830 .ralat = 5, /* Read additional latency */
831 .mif3_mode = 3, /* Command prediction working mode */
832 .bi_on = 1, /* Bank interleaving enabled */
833 .sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */
834 .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */
Peng Fan77e86952015-08-17 16:11:03 +0800835 .ddr_type = DDR_TYPE_DDR3,
Fabio Estevamcb3c1212016-08-29 20:37:15 -0300836 .refsel = 1, /* Refresh cycles at 32KHz */
837 .refr = 7, /* 8 refresh commands per refresh cycle */
Fabio Estevam1d97a592015-04-20 14:48:57 -0300838 };
839
Breno Limaba776122016-07-22 09:11:30 -0300840 if (is_mx6dq())
Fabio Estevamcb601912015-04-25 18:47:18 -0300841 mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs);
842 else
843 mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs);
844
845 if (is_cpu_type(MXC_CPU_MX6D))
846 mx6_dram_cfg(&sysinfo, &mx6q_1g_mmcd_calib, &mem_ddr_2g);
847 else if (is_cpu_type(MXC_CPU_MX6Q))
848 mx6_dram_cfg(&sysinfo, &mx6q_2g_mmcd_calib, &mem_ddr_4g);
849 else if (is_cpu_type(MXC_CPU_MX6DL))
Fabio Estevam4461e1e2015-05-29 13:00:36 -0300850 mx6_dram_cfg(&sysinfo, &mx6dl_1g_mmcd_calib, &mem_ddr_2g);
Fabio Estevamcb601912015-04-25 18:47:18 -0300851 else if (is_cpu_type(MXC_CPU_MX6SOLO))
852 mx6_dram_cfg(&sysinfo, &mx6dl_512m_mmcd_calib, &mem_ddr_2g);
Fabio Estevam1d97a592015-04-20 14:48:57 -0300853}
854
855void board_init_f(ulong dummy)
856{
857 /* setup AIPS and disable watchdog */
858 arch_cpu_init();
859
860 ccgr_init();
861 gpr_init();
862
863 /* iomux and setup of i2c */
864 board_early_init_f();
865
866 /* setup GP timer */
867 timer_init();
868
869 /* UART clocks enabled and gd valid - init serial console */
870 preloader_console_init();
871
872 /* DDR initialization */
Fabio Estevamcb601912015-04-25 18:47:18 -0300873 if (is_cpu_type(MXC_CPU_MX6SOLO))
874 spl_dram_init(32);
875 else
876 spl_dram_init(64);
Fabio Estevam1d97a592015-04-20 14:48:57 -0300877
878 /* Clear the BSS. */
879 memset(__bss_start, 0, __bss_end - __bss_start);
880
881 /* load/boot image from boot device */
882 board_init_r(NULL, 0);
883}
884#endif