1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2022 Josua Mayer <josua@solid-run.com>
5 * Copyright (C) 2015 Freescale Semiconductor, Inc.
7 * Author: Fabio Estevam <fabio.estevam@freescale.com>
9 * Copyright (C) 2013 Jon Nettleton <jon.nettleton@gmail.com>
11 * Based on SPL code from Solidrun tree, which is:
12 * Author: Tungyi Lin <tungyilin1127@gmail.com>
14 * Derived from EDM_CF_IMX6 code by TechNexion,Inc
15 * Ported to SolidRun microSOM by Rabeeh Khoury <rabeeh@solid-run.com>
22 #include <asm/arch/clock.h>
23 #include <asm/arch/imx-regs.h>
24 #include <asm/arch/iomux.h>
25 #include <asm/arch/mx6-pins.h>
26 #include <asm/arch/mxc_hdmi.h>
28 #include <asm/global_data.h>
29 #include <linux/delay.h>
30 #include <linux/errno.h>
32 #include <asm/mach-imx/iomux-v3.h>
33 #include <asm/mach-imx/sata.h>
34 #include <asm/mach-imx/video.h>
36 #include <fsl_esdhc_imx.h>
38 #include <asm/arch/crm_regs.h>
40 #include <asm/arch/sys_proto.h>
43 #include <usb/ehci-ci.h>
47 DECLARE_GLOBAL_DATA_PTR
;
49 #define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
50 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
51 PAD_CTL_SRE_FAST | PAD_CTL_HYS)
53 #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
54 PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \
55 PAD_CTL_SRE_FAST | PAD_CTL_HYS)
57 #define USB_H1_VBUS IMX_GPIO_NR(1, 0)
66 static struct gpio_desc board_detect_desc
[5];
68 #define MEM_STRIDE 0x4000000
69 static u32
get_ram_size_stride_test(u32
*base
, u32 maxsize
)
77 /* First save the data */
78 for (cnt
= 0; cnt
< maxsize
; cnt
+= MEM_STRIDE
) {
79 addr
= (volatile u32
*)((u32
)base
+ cnt
); /* pointer arith! */
85 /* First write a signature */
86 * (volatile u32
*)base
= 0x12345678;
87 for (size
= MEM_STRIDE
; size
< maxsize
; size
+= MEM_STRIDE
) {
88 * (volatile u32
*)((u32
)base
+ size
) = size
;
90 if (* (volatile u32
*)((u32
)base
) == size
) { /* We reached the overlapping address */
95 /* Restore the data */
96 for (cnt
= (maxsize
- MEM_STRIDE
); i
> 0; cnt
-= MEM_STRIDE
) {
97 addr
= (volatile u32
*)((u32
)base
+ cnt
); /* pointer arith! */
108 u32 max_size
= imx_ddr_size();
110 gd
->ram_size
= get_ram_size_stride_test((u32
*) CFG_SYS_SDRAM_BASE
,
116 static iomux_v3_cfg_t
const uart1_pads
[] = {
117 IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA
| MUX_PAD_CTRL(UART_PAD_CTRL
)),
118 IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA
| MUX_PAD_CTRL(UART_PAD_CTRL
)),
121 static iomux_v3_cfg_t
const usdhc2_pads
[] = {
122 IOMUX_PADS(PAD_SD2_CLK__SD2_CLK
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
123 IOMUX_PADS(PAD_SD2_CMD__SD2_CMD
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
124 IOMUX_PADS(PAD_SD2_DAT0__SD2_DATA0
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
125 IOMUX_PADS(PAD_SD2_DAT1__SD2_DATA1
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
126 IOMUX_PADS(PAD_SD2_DAT2__SD2_DATA2
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
127 IOMUX_PADS(PAD_SD2_DAT3__SD2_DATA3
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
130 static iomux_v3_cfg_t
const usdhc3_pads
[] = {
131 IOMUX_PADS(PAD_SD3_CLK__SD3_CLK
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
132 IOMUX_PADS(PAD_SD3_CMD__SD3_CMD
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
133 IOMUX_PADS(PAD_SD3_DAT0__SD3_DATA0
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
134 IOMUX_PADS(PAD_SD3_DAT1__SD3_DATA1
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
135 IOMUX_PADS(PAD_SD3_DAT2__SD3_DATA2
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
136 IOMUX_PADS(PAD_SD3_DAT3__SD3_DATA3
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
137 IOMUX_PADS(PAD_SD3_DAT4__SD3_DATA4
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
138 IOMUX_PADS(PAD_SD3_DAT5__SD3_DATA5
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
139 IOMUX_PADS(PAD_SD3_DAT6__SD3_DATA6
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
140 IOMUX_PADS(PAD_SD3_DAT7__SD3_DATA7
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
141 IOMUX_PADS(PAD_SD3_RST__SD3_RESET
| MUX_PAD_CTRL(USDHC_PAD_CTRL
)),
144 static iomux_v3_cfg_t
const board_detect
[] = {
145 /* These pins are for sensing if it is a CuBox-i or a HummingBoard */
146 IOMUX_PADS(PAD_KEY_ROW1__GPIO4_IO09
| MUX_PAD_CTRL(UART_PAD_CTRL
)),
147 IOMUX_PADS(PAD_EIM_DA4__GPIO3_IO04
| MUX_PAD_CTRL(UART_PAD_CTRL
)),
148 IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08
| MUX_PAD_CTRL(UART_PAD_CTRL
)),
151 static iomux_v3_cfg_t
const som_rev_detect
[] = {
152 /* These pins are for sensing if it is a CuBox-i or a HummingBoard */
153 IOMUX_PADS(PAD_CSI0_DAT14__GPIO6_IO00
| MUX_PAD_CTRL(UART_PAD_CTRL
)),
154 IOMUX_PADS(PAD_CSI0_DAT18__GPIO6_IO04
| MUX_PAD_CTRL(UART_PAD_CTRL
)),
157 static void setup_iomux_uart(void)
159 SETUP_IOMUX_PADS(uart1_pads
);
162 int board_mmc_get_env_dev(int devno
)
167 #ifdef CONFIG_VIDEO_IPUV3
168 static void do_enable_hdmi(struct display_info_t
const *dev
)
170 imx_enable_hdmi_phy();
173 struct display_info_t
const displays
[] = {
177 .pixfmt
= IPU_PIX_FMT_RGB24
,
178 .detect
= detect_hdmi
,
179 .enable
= do_enable_hdmi
,
182 /* 1024x768@60Hz (VESA)*/
194 .vmode
= FB_VMODE_NONINTERLACED
199 size_t display_count
= ARRAY_SIZE(displays
);
201 static int setup_display(void)
203 struct mxc_ccm_reg
*ccm
= (struct mxc_ccm_reg
*)CCM_BASE_ADDR
;
205 int timeout
= 100000;
210 /* set video pll to 455MHz (24MHz * (37+11/12) / 2) */
211 setbits_le32(&ccm
->analog_pll_video
, BM_ANADIG_PLL_VIDEO_POWERDOWN
);
213 reg
= readl(&ccm
->analog_pll_video
);
214 reg
&= ~BM_ANADIG_PLL_VIDEO_DIV_SELECT
;
215 reg
|= BF_ANADIG_PLL_VIDEO_DIV_SELECT(37);
216 reg
&= ~BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT
;
217 reg
|= BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1);
218 writel(reg
, &ccm
->analog_pll_video
);
220 writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm
->analog_pll_video_num
);
221 writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm
->analog_pll_video_denom
);
223 reg
&= ~BM_ANADIG_PLL_VIDEO_POWERDOWN
;
224 writel(reg
, &ccm
->analog_pll_video
);
227 if (readl(&ccm
->analog_pll_video
) & BM_ANADIG_PLL_VIDEO_LOCK
)
230 printf("Warning: video pll lock timeout!\n");
234 reg
= readl(&ccm
->analog_pll_video
);
235 reg
|= BM_ANADIG_PLL_VIDEO_ENABLE
;
236 reg
&= ~BM_ANADIG_PLL_VIDEO_BYPASS
;
237 writel(reg
, &ccm
->analog_pll_video
);
239 /* gate ipu1_di0_clk */
240 clrbits_le32(&ccm
->CCGR3
, MXC_CCM_CCGR3_LDB_DI0_MASK
);
242 /* select video_pll clock / 7 for ipu1_di0_clk -> 65MHz pixclock */
243 reg
= readl(&ccm
->chsccdr
);
244 reg
&= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK
|
245 MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK
|
246 MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK
);
247 reg
|= (2 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET
) |
248 (6 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET
) |
249 (0 << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET
);
250 writel(reg
, &ccm
->chsccdr
);
252 /* enable ipu1_di0_clk */
253 setbits_le32(&ccm
->CCGR3
, MXC_CCM_CCGR3_LDB_DI0_MASK
);
257 #endif /* CONFIG_VIDEO_IPUV3 */
259 static int setup_fec(void)
261 struct iomuxc
*const iomuxc_regs
= (struct iomuxc
*)IOMUXC_BASE_ADDR
;
264 ret
= enable_fec_anatop_clock(0, ENET_25MHZ
);
268 /* set gpr1[ENET_CLK_SEL] */
269 setbits_le32(&iomuxc_regs
->gpr
[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK
);
274 int board_early_init_f(void)
290 /* address of boot parameters */
291 gd
->bd
->bi_boot_params
= CFG_SYS_SDRAM_BASE
+ 0x100;
293 #ifdef CONFIG_VIDEO_IPUV3
294 ret
= setup_display();
300 static int request_detect_gpios(void)
305 node
= fdt_node_offset_by_compatible(gd
->fdt_blob
, 0,
306 "solidrun,hummingboard-detect");
310 ret
= gpio_request_list_by_name_nodev(offset_to_ofnode(node
),
311 "detect-gpios", board_detect_desc
,
312 ARRAY_SIZE(board_detect_desc
), GPIOD_IS_IN
);
317 static int free_detect_gpios(void)
319 return gpio_free_list_nodev(board_detect_desc
,
320 ARRAY_SIZE(board_detect_desc
));
323 static enum board_type
board_type(void)
325 int val1
, val2
, val3
;
327 SETUP_IOMUX_PADS(board_detect
);
330 * Machine selection -
331 * Machine val1, val2, val3
332 * ----------------------------
339 gpio_direction_input(IMX_GPIO_NR(2, 8));
340 val3
= gpio_get_value(IMX_GPIO_NR(2, 8));
343 return HUMMINGBOARD2
;
345 gpio_direction_input(IMX_GPIO_NR(3, 4));
346 val2
= gpio_get_value(IMX_GPIO_NR(3, 4));
351 gpio_direction_input(IMX_GPIO_NR(4, 9));
352 val1
= gpio_get_value(IMX_GPIO_NR(4, 9));
361 static bool is_rev_15_som(void)
364 SETUP_IOMUX_PADS(som_rev_detect
);
366 val1
= gpio_get_value(IMX_GPIO_NR(6, 0));
367 val2
= gpio_get_value(IMX_GPIO_NR(6, 4));
369 if (val1
== 1 && val2
== 0)
375 static bool has_emmc(void)
378 mmc
= find_mmc_device(2);
381 return (mmc_get_op_cond(mmc
, true) < 0) ? 0 : 1;
386 request_detect_gpios();
388 switch (board_type()) {
390 puts("Board: MX6 Cubox-i");
393 puts("Board: MX6 HummingBoard");
396 puts("Board: MX6 HummingBoard2");
400 puts("Board: Unknown\n");
405 puts(" (som rev 1.5)\n");
414 static int find_ethernet_phy(void)
416 struct mii_dev
*bus
= NULL
;
417 struct phy_device
*phydev
= NULL
;
418 int phy_addr
= -ENOENT
;
420 #ifdef CONFIG_FEC_MXC
421 bus
= fec_get_miibus(ENET_BASE_ADDR
, -1);
425 // scan address 0, 1, 4
426 phydev
= phy_find_by_mask(bus
, 0b00010011);
431 pr_debug("%s: detected ethernet phy at address %d\n", __func__
, phydev
->addr
);
432 phy_addr
= phydev
->addr
;
440 #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
442 * Configure the correct ethernet PHYs nodes in device-tree:
443 * - AR8035 at addresses 0 or 4: Cubox
444 * - AR8035 at address 0: HummingBoard, HummingBoard 2
445 * - ADIN1300 at address 1: since SoM rev 1.9
447 int ft_board_setup(void *fdt
, struct bd_info
*bd
)
449 int node_phy0
, node_phy1
, node_phy4
;
451 bool enable_phy0
= false, enable_phy1
= false, enable_phy4
= false;
452 enum board_type board
;
455 request_detect_gpios();
456 board
= board_type();
460 phy
= find_ethernet_phy();
461 if (phy
== 0 || phy
== 4) {
466 /* atheros phy may appear only at address 0 */
471 /* atheros phy may appear at either address 0 or 4 */
474 } else if (phy
== 1) {
477 pr_err("%s: couldn't detect ethernet phy, not patching dtb!\n", __func__
);
481 // update all phy nodes status
482 node_phy0
= fdt_path_offset(fdt
, "/soc/bus@2100000/ethernet@2188000/mdio/ethernet-phy@0");
483 ret
= fdt_setprop_string(fdt
, node_phy0
, "status", enable_phy0
? "okay" : "disabled");
484 if (ret
< 0 && enable_phy0
)
485 pr_err("%s: failed to enable ethernet phy at address 0 in dtb!\n", __func__
);
486 node_phy1
= fdt_path_offset(fdt
, "/soc/bus@2100000/ethernet@2188000/mdio/ethernet-phy@1");
487 ret
= fdt_setprop_string(fdt
, node_phy1
, "status", enable_phy1
? "okay" : "disabled");
488 if (ret
< 0 && enable_phy1
)
489 pr_err("%s: failed to enable ethernet phy at address 1 in dtb!\n", __func__
);
490 node_phy4
= fdt_path_offset(fdt
, "/soc/bus@2100000/ethernet@2188000/mdio/ethernet-phy@4");
491 ret
= fdt_setprop_string(fdt
, node_phy4
, "status", enable_phy4
? "okay" : "disabled");
492 if (ret
< 0 && enable_phy4
)
493 pr_err("%s: failed to enable ethernet phy at address 4 in dtb!\n", __func__
);
499 /* Override the default implementation, DT model is not accurate */
500 int show_board_info(void)
505 int board_late_init(void)
507 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
508 request_detect_gpios();
510 switch (board_type()) {
512 env_set("board_name", "CUBOXI");
515 env_set("board_name", "HUMMINGBOARD");
518 env_set("board_name", "HUMMINGBOARD2");
522 env_set("board_name", "CUBOXI");
526 env_set("board_rev", "MX6Q");
528 env_set("board_rev", "MX6DL");
531 env_set("som_rev", "V15");
534 env_set("has_emmc", "yes");
543 * This is not a perfect match. Avoid dependency on the DM GPIO driver needed
544 * for accurate board detection. Hummingboard2 DT is good enough for U-Boot on
545 * all Hummingboard/Cubox-i platforms.
547 int board_fit_config_name_match(const char *name
)
551 snprintf(tmp_name
, sizeof(tmp_name
), "%s-hummingboard2-emmc-som-v15",
552 is_mx6dq() ? "imx6q" : "imx6dl");
554 return strcmp(name
, tmp_name
);
557 void board_boot_order(u32
*spl_boot_list
)
559 struct src
*psrc
= (struct src
*)SRC_BASE_ADDR
;
560 unsigned int reg
= readl(&psrc
->sbmr1
) >> 11;
561 u32 boot_mode
= imx6_src_get_boot_mode() & IMX6_BMODE_MASK
;
562 unsigned int bmode
= readl(&src_base
->sbmr2
);
564 /* If bmode is serial or USB phy is active, return serial */
565 if (((bmode
>> 24) & 0x03) == 0x01 || is_usbotg_phy_active()) {
566 spl_boot_list
[0] = BOOT_DEVICE_BOARD
;
570 switch (boot_mode
>> IMX6_BMODE_SHIFT
) {
574 case IMX6_BMODE_EMMC
:
576 * Upon reading BOOT_CFG register the following map is done:
577 * Bit 11 and 12 of BOOT_CFG register can determine the current
583 reg
&= 0x3; /* Only care about bottom 2 bits */
586 SETUP_IOMUX_PADS(usdhc2_pads
);
587 spl_boot_list
[0] = BOOT_DEVICE_MMC1
;
590 SETUP_IOMUX_PADS(usdhc3_pads
);
591 spl_boot_list
[0] = BOOT_DEVICE_MMC2
;
596 /* By default use USB downloader */
597 spl_boot_list
[0] = BOOT_DEVICE_BOARD
;
601 /* As a last resort, use serial downloader */
602 spl_boot_list
[1] = BOOT_DEVICE_BOARD
;
605 #ifdef CONFIG_SPL_BUILD
606 #include <asm/arch/mx6-ddr.h>
607 static const struct mx6dq_iomux_ddr_regs mx6q_ddr_ioregs
= {
608 .dram_sdclk_0
= 0x00020030,
609 .dram_sdclk_1
= 0x00020030,
610 .dram_cas
= 0x00020030,
611 .dram_ras
= 0x00020030,
612 .dram_reset
= 0x000c0030,
613 .dram_sdcke0
= 0x00003000,
614 .dram_sdcke1
= 0x00003000,
615 .dram_sdba2
= 0x00000000,
616 .dram_sdodt0
= 0x00003030,
617 .dram_sdodt1
= 0x00003030,
618 .dram_sdqs0
= 0x00000030,
619 .dram_sdqs1
= 0x00000030,
620 .dram_sdqs2
= 0x00000030,
621 .dram_sdqs3
= 0x00000030,
622 .dram_sdqs4
= 0x00000030,
623 .dram_sdqs5
= 0x00000030,
624 .dram_sdqs6
= 0x00000030,
625 .dram_sdqs7
= 0x00000030,
626 .dram_dqm0
= 0x00020030,
627 .dram_dqm1
= 0x00020030,
628 .dram_dqm2
= 0x00020030,
629 .dram_dqm3
= 0x00020030,
630 .dram_dqm4
= 0x00020030,
631 .dram_dqm5
= 0x00020030,
632 .dram_dqm6
= 0x00020030,
633 .dram_dqm7
= 0x00020030,
636 static const struct mx6sdl_iomux_ddr_regs mx6dl_ddr_ioregs
= {
637 .dram_sdclk_0
= 0x00000028,
638 .dram_sdclk_1
= 0x00000028,
639 .dram_cas
= 0x00000028,
640 .dram_ras
= 0x00000028,
641 .dram_reset
= 0x000c0028,
642 .dram_sdcke0
= 0x00003000,
643 .dram_sdcke1
= 0x00003000,
644 .dram_sdba2
= 0x00000000,
645 .dram_sdodt0
= 0x00003030,
646 .dram_sdodt1
= 0x00003030,
647 .dram_sdqs0
= 0x00000028,
648 .dram_sdqs1
= 0x00000028,
649 .dram_sdqs2
= 0x00000028,
650 .dram_sdqs3
= 0x00000028,
651 .dram_sdqs4
= 0x00000028,
652 .dram_sdqs5
= 0x00000028,
653 .dram_sdqs6
= 0x00000028,
654 .dram_sdqs7
= 0x00000028,
655 .dram_dqm0
= 0x00000028,
656 .dram_dqm1
= 0x00000028,
657 .dram_dqm2
= 0x00000028,
658 .dram_dqm3
= 0x00000028,
659 .dram_dqm4
= 0x00000028,
660 .dram_dqm5
= 0x00000028,
661 .dram_dqm6
= 0x00000028,
662 .dram_dqm7
= 0x00000028,
665 static const struct mx6dq_iomux_grp_regs mx6q_grp_ioregs
= {
666 .grp_ddr_type
= 0x000C0000,
667 .grp_ddrmode_ctl
= 0x00020000,
668 .grp_ddrpke
= 0x00000000,
669 .grp_addds
= 0x00000030,
670 .grp_ctlds
= 0x00000030,
671 .grp_ddrmode
= 0x00020000,
672 .grp_b0ds
= 0x00000030,
673 .grp_b1ds
= 0x00000030,
674 .grp_b2ds
= 0x00000030,
675 .grp_b3ds
= 0x00000030,
676 .grp_b4ds
= 0x00000030,
677 .grp_b5ds
= 0x00000030,
678 .grp_b6ds
= 0x00000030,
679 .grp_b7ds
= 0x00000030,
682 static const struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs
= {
683 .grp_ddr_type
= 0x000c0000,
684 .grp_ddrmode_ctl
= 0x00020000,
685 .grp_ddrpke
= 0x00000000,
686 .grp_addds
= 0x00000028,
687 .grp_ctlds
= 0x00000028,
688 .grp_ddrmode
= 0x00020000,
689 .grp_b0ds
= 0x00000028,
690 .grp_b1ds
= 0x00000028,
691 .grp_b2ds
= 0x00000028,
692 .grp_b3ds
= 0x00000028,
693 .grp_b4ds
= 0x00000028,
694 .grp_b5ds
= 0x00000028,
695 .grp_b6ds
= 0x00000028,
696 .grp_b7ds
= 0x00000028,
699 /* microSOM with Dual processor and 1GB memory */
700 static const struct mx6_mmdc_calibration mx6q_1g_mmcd_calib
= {
701 .p0_mpwldectrl0
= 0x00000000,
702 .p0_mpwldectrl1
= 0x00000000,
703 .p1_mpwldectrl0
= 0x00000000,
704 .p1_mpwldectrl1
= 0x00000000,
705 .p0_mpdgctrl0
= 0x0314031c,
706 .p0_mpdgctrl1
= 0x023e0304,
707 .p1_mpdgctrl0
= 0x03240330,
708 .p1_mpdgctrl1
= 0x03180260,
709 .p0_mprddlctl
= 0x3630323c,
710 .p1_mprddlctl
= 0x3436283a,
711 .p0_mpwrdlctl
= 0x36344038,
712 .p1_mpwrdlctl
= 0x422a423c,
715 /* microSOM with Quad processor and 2GB memory */
716 static const struct mx6_mmdc_calibration mx6q_2g_mmcd_calib
= {
717 .p0_mpwldectrl0
= 0x00000000,
718 .p0_mpwldectrl1
= 0x00000000,
719 .p1_mpwldectrl0
= 0x00000000,
720 .p1_mpwldectrl1
= 0x00000000,
721 .p0_mpdgctrl0
= 0x0314031c,
722 .p0_mpdgctrl1
= 0x023e0304,
723 .p1_mpdgctrl0
= 0x03240330,
724 .p1_mpdgctrl1
= 0x03180260,
725 .p0_mprddlctl
= 0x3630323c,
726 .p1_mprddlctl
= 0x3436283a,
727 .p0_mpwrdlctl
= 0x36344038,
728 .p1_mpwrdlctl
= 0x422a423c,
731 /* microSOM with Solo processor and 512MB memory */
732 static const struct mx6_mmdc_calibration mx6dl_512m_mmcd_calib
= {
733 .p0_mpwldectrl0
= 0x0045004D,
734 .p0_mpwldectrl1
= 0x003A0047,
735 .p0_mpdgctrl0
= 0x023C0224,
736 .p0_mpdgctrl1
= 0x02000220,
737 .p0_mprddlctl
= 0x44444846,
738 .p0_mpwrdlctl
= 0x32343032,
741 /* microSOM with Dual lite processor and 1GB memory */
742 static const struct mx6_mmdc_calibration mx6dl_1g_mmcd_calib
= {
743 .p0_mpwldectrl0
= 0x0045004D,
744 .p0_mpwldectrl1
= 0x003A0047,
745 .p1_mpwldectrl0
= 0x001F001F,
746 .p1_mpwldectrl1
= 0x00210035,
747 .p0_mpdgctrl0
= 0x023C0224,
748 .p0_mpdgctrl1
= 0x02000220,
749 .p1_mpdgctrl0
= 0x02200220,
750 .p1_mpdgctrl1
= 0x02040208,
751 .p0_mprddlctl
= 0x44444846,
752 .p1_mprddlctl
= 0x4042463C,
753 .p0_mpwrdlctl
= 0x32343032,
754 .p1_mpwrdlctl
= 0x36363430,
757 static struct mx6_ddr3_cfg mem_ddr_2g
= {
770 static struct mx6_ddr3_cfg mem_ddr_4g
= {
783 static void ccgr_init(void)
785 struct mxc_ccm_reg
*ccm
= (struct mxc_ccm_reg
*)CCM_BASE_ADDR
;
787 writel(0x00C03F3F, &ccm
->CCGR0
);
788 writel(0x0030FC03, &ccm
->CCGR1
);
789 writel(0x0FFFC000, &ccm
->CCGR2
);
790 writel(0x3FF00000, &ccm
->CCGR3
);
791 writel(0x00FFF300, &ccm
->CCGR4
);
792 writel(0x0F0000C3, &ccm
->CCGR5
);
793 writel(0x000003FF, &ccm
->CCGR6
);
796 static void spl_dram_init(int width
)
798 struct mx6_ddr_sysinfo sysinfo
= {
799 /* width of data bus: 0=16, 1=32, 2=64 */
801 /* config for full 4GB range so that get_mem_size() works */
802 .cs_density
= 32, /* 32Gb per CS */
803 .ncs
= 1, /* single chip select */
805 .rtt_wr
= 1 /*DDR3_RTT_60_OHM*/, /* RTT_Wr = RZQ/4 */
806 .rtt_nom
= 1 /*DDR3_RTT_60_OHM*/, /* RTT_Nom = RZQ/4 */
807 .walat
= 1, /* Write additional latency */
808 .ralat
= 5, /* Read additional latency */
809 .mif3_mode
= 3, /* Command prediction working mode */
810 .bi_on
= 1, /* Bank interleaving enabled */
811 .sde_to_rst
= 0x10, /* 14 cycles, 200us (JEDEC default) */
812 .rst_to_cke
= 0x23, /* 33 cycles, 500us (JEDEC default) */
813 .ddr_type
= DDR_TYPE_DDR3
,
814 .refsel
= 1, /* Refresh cycles at 32KHz */
815 .refr
= 7, /* 8 refresh commands per refresh cycle */
819 mx6dq_dram_iocfg(width
, &mx6q_ddr_ioregs
, &mx6q_grp_ioregs
);
821 mx6sdl_dram_iocfg(width
, &mx6dl_ddr_ioregs
, &mx6sdl_grp_ioregs
);
823 if (is_cpu_type(MXC_CPU_MX6D
))
824 mx6_dram_cfg(&sysinfo
, &mx6q_1g_mmcd_calib
, &mem_ddr_2g
);
825 else if (is_cpu_type(MXC_CPU_MX6Q
))
826 mx6_dram_cfg(&sysinfo
, &mx6q_2g_mmcd_calib
, &mem_ddr_4g
);
827 else if (is_cpu_type(MXC_CPU_MX6DL
))
828 mx6_dram_cfg(&sysinfo
, &mx6dl_1g_mmcd_calib
, &mem_ddr_2g
);
829 else if (is_cpu_type(MXC_CPU_MX6SOLO
))
830 mx6_dram_cfg(&sysinfo
, &mx6dl_512m_mmcd_calib
, &mem_ddr_2g
);
833 void board_init_f(ulong dummy
)
835 /* setup AIPS and disable watchdog */
841 /* iomux and setup of i2c */
842 board_early_init_f();
847 /* Enable device tree and early DM support*/
850 /* UART clocks enabled and gd valid - init serial console */
851 preloader_console_init();
853 /* DDR initialization */
854 if (is_cpu_type(MXC_CPU_MX6SOLO
))
860 memset(__bss_start
, 0, __bss_end
- __bss_start
);
862 /* load/boot image from boot device */
863 board_init_r(NULL
, 0);