1 // SPDX-License-Identifier: GPL-2.0+ 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> 14 */ 15 16 #include <asm/arch/clock.h> 17 #include <asm/arch/imx-regs.h> 18 #include <asm/arch/iomux.h> 19 #include <asm/arch/mx6-pins.h> 20 #include <asm/arch/mxc_hdmi.h> 21 #include <linux/errno.h> 22 #include <asm/gpio.h> 23 #include <asm/mach-imx/iomux-v3.h> 24 #include <asm/mach-imx/sata.h> 25 #include <asm/mach-imx/video.h> 26 #include <mmc.h> 27 #include <fsl_esdhc.h> 28 #include <malloc.h> 29 #include <miiphy.h> 30 #include <netdev.h> 31 #include <asm/arch/crm_regs.h> 32 #include <asm/io.h> 33 #include <asm/arch/sys_proto.h> 34 #include <spl.h> 35 #include <usb.h> 36 #include <usb/ehci-ci.h> 37 38 DECLARE_GLOBAL_DATA_PTR; 39 40 #define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ 41 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ 42 PAD_CTL_SRE_FAST | PAD_CTL_HYS) 43 44 #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \ 45 PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \ 46 PAD_CTL_SRE_FAST | PAD_CTL_HYS) 47 48 #define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ 49 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) 50 51 #define ENET_PAD_CTRL_PD (PAD_CTL_PUS_100K_DOWN | \ 52 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) 53 54 #define ENET_PAD_CTRL_CLK ((PAD_CTL_PUS_100K_UP & ~PAD_CTL_PKE) | \ 55 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) 56 57 #define ETH_PHY_RESET IMX_GPIO_NR(4, 15) 58 #define USB_H1_VBUS IMX_GPIO_NR(1, 0) 59 60 enum board_type { 61 CUBOXI = 0x00, 62 HUMMINGBOARD = 0x01, 63 HUMMINGBOARD2 = 0x02, 64 UNKNOWN = 0x03, 65 }; 66 67 int dram_init(void) 68 { 69 gd->ram_size = imx_ddr_size(); 70 return 0; 71 } 72 73 static iomux_v3_cfg_t const uart1_pads[] = { 74 IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), 75 IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), 76 }; 77 78 static iomux_v3_cfg_t const usdhc2_pads[] = { 79 IOMUX_PADS(PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)), 80 IOMUX_PADS(PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)), 81 IOMUX_PADS(PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), 82 IOMUX_PADS(PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), 83 IOMUX_PADS(PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), 84 IOMUX_PADS(PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)), 85 }; 86 87 static iomux_v3_cfg_t const board_detect[] = { 88 /* These pins are for sensing if it is a CuBox-i or a HummingBoard */ 89 IOMUX_PADS(PAD_KEY_ROW1__GPIO4_IO09 | MUX_PAD_CTRL(UART_PAD_CTRL)), 90 IOMUX_PADS(PAD_EIM_DA4__GPIO3_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)), 91 IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | MUX_PAD_CTRL(UART_PAD_CTRL)), 92 }; 93 94 static iomux_v3_cfg_t const som_rev_detect[] = { 95 /* These pins are for sensing if it is a CuBox-i or a HummingBoard */ 96 IOMUX_PADS(PAD_CSI0_DAT14__GPIO6_IO00 | MUX_PAD_CTRL(UART_PAD_CTRL)), 97 IOMUX_PADS(PAD_CSI0_DAT18__GPIO6_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)), 98 }; 99 100 static iomux_v3_cfg_t const usb_pads[] = { 101 IOMUX_PADS(PAD_GPIO_0__GPIO1_IO00 | MUX_PAD_CTRL(NO_PAD_CTRL)), 102 }; 103 104 static void setup_iomux_uart(void) 105 { 106 SETUP_IOMUX_PADS(uart1_pads); 107 } 108 109 static struct fsl_esdhc_cfg usdhc_cfg[1] = { 110 {USDHC2_BASE_ADDR}, 111 }; 112 113 int board_mmc_getcd(struct mmc *mmc) 114 { 115 return 1; /* uSDHC2 is always present */ 116 } 117 118 int board_mmc_init(bd_t *bis) 119 { 120 SETUP_IOMUX_PADS(usdhc2_pads); 121 usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR; 122 usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); 123 gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk; 124 125 return fsl_esdhc_initialize(bis, &usdhc_cfg[0]); 126 } 127 128 static iomux_v3_cfg_t const enet_pads[] = { 129 IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL)), 130 IOMUX_PADS(PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL)), 131 /* AR8035 reset */ 132 IOMUX_PADS(PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)), 133 /* AR8035 interrupt */ 134 IOMUX_PADS(PAD_DI0_PIN2__GPIO4_IO18 | MUX_PAD_CTRL(NO_PAD_CTRL)), 135 /* GPIO16 -> AR8035 25MHz */ 136 IOMUX_PADS(PAD_GPIO_16__ENET_REF_CLK | MUX_PAD_CTRL(NO_PAD_CTRL)), 137 IOMUX_PADS(PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(NO_PAD_CTRL)), 138 IOMUX_PADS(PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 139 IOMUX_PADS(PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 140 IOMUX_PADS(PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 141 IOMUX_PADS(PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 142 IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)), 143 /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */ 144 IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL_CLK)), 145 IOMUX_PADS(PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL)), 146 IOMUX_PADS(PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)), 147 IOMUX_PADS(PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)), 148 IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 149 IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)), 150 IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)), 151 IOMUX_PADS(PAD_ENET_RXD0__GPIO1_IO27 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)), 152 IOMUX_PADS(PAD_ENET_RXD1__GPIO1_IO26 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)), 153 }; 154 155 static void setup_iomux_enet(void) 156 { 157 SETUP_IOMUX_PADS(enet_pads); 158 159 gpio_direction_output(ETH_PHY_RESET, 0); 160 mdelay(10); 161 gpio_set_value(ETH_PHY_RESET, 1); 162 udelay(100); 163 } 164 165 int board_phy_config(struct phy_device *phydev) 166 { 167 if (phydev->drv->config) 168 phydev->drv->config(phydev); 169 170 return 0; 171 } 172 173 /* On Cuboxi Ethernet PHY can be located at addresses 0x0 or 0x4 */ 174 #define ETH_PHY_MASK ((1 << 0x0) | (1 << 0x4)) 175 176 int board_eth_init(bd_t *bis) 177 { 178 struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; 179 struct mii_dev *bus; 180 struct phy_device *phydev; 181 182 int ret = enable_fec_anatop_clock(0, ENET_25MHZ); 183 if (ret) 184 return ret; 185 186 /* set gpr1[ENET_CLK_SEL] */ 187 setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK); 188 189 setup_iomux_enet(); 190 191 bus = fec_get_miibus(IMX_FEC_BASE, -1); 192 if (!bus) 193 return -EINVAL; 194 195 phydev = phy_find_by_mask(bus, ETH_PHY_MASK, PHY_INTERFACE_MODE_RGMII); 196 if (!phydev) { 197 ret = -EINVAL; 198 goto free_bus; 199 } 200 201 debug("using phy at address %d\n", phydev->addr); 202 ret = fec_probe(bis, -1, IMX_FEC_BASE, bus, phydev); 203 if (ret) 204 goto free_phydev; 205 206 return 0; 207 208 free_phydev: 209 free(phydev); 210 free_bus: 211 free(bus); 212 return ret; 213 } 214 215 #ifdef CONFIG_VIDEO_IPUV3 216 static void do_enable_hdmi(struct display_info_t const *dev) 217 { 218 imx_enable_hdmi_phy(); 219 } 220 221 struct display_info_t const displays[] = { 222 { 223 .bus = -1, 224 .addr = 0, 225 .pixfmt = IPU_PIX_FMT_RGB24, 226 .detect = detect_hdmi, 227 .enable = do_enable_hdmi, 228 .mode = { 229 .name = "HDMI", 230 /* 1024x768@60Hz (VESA)*/ 231 .refresh = 60, 232 .xres = 1024, 233 .yres = 768, 234 .pixclock = 15384, 235 .left_margin = 160, 236 .right_margin = 24, 237 .upper_margin = 29, 238 .lower_margin = 3, 239 .hsync_len = 136, 240 .vsync_len = 6, 241 .sync = FB_SYNC_EXT, 242 .vmode = FB_VMODE_NONINTERLACED 243 } 244 } 245 }; 246 247 size_t display_count = ARRAY_SIZE(displays); 248 249 static int setup_display(void) 250 { 251 struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; 252 int reg; 253 int timeout = 100000; 254 255 enable_ipu_clock(); 256 imx_setup_hdmi(); 257 258 /* set video pll to 455MHz (24MHz * (37+11/12) / 2) */ 259 setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN); 260 261 reg = readl(&ccm->analog_pll_video); 262 reg &= ~BM_ANADIG_PLL_VIDEO_DIV_SELECT; 263 reg |= BF_ANADIG_PLL_VIDEO_DIV_SELECT(37); 264 reg &= ~BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT; 265 reg |= BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1); 266 writel(reg, &ccm->analog_pll_video); 267 268 writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num); 269 writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom); 270 271 reg &= ~BM_ANADIG_PLL_VIDEO_POWERDOWN; 272 writel(reg, &ccm->analog_pll_video); 273 274 while (timeout--) 275 if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK) 276 break; 277 if (timeout < 0) { 278 printf("Warning: video pll lock timeout!\n"); 279 return -ETIMEDOUT; 280 } 281 282 reg = readl(&ccm->analog_pll_video); 283 reg |= BM_ANADIG_PLL_VIDEO_ENABLE; 284 reg &= ~BM_ANADIG_PLL_VIDEO_BYPASS; 285 writel(reg, &ccm->analog_pll_video); 286 287 /* gate ipu1_di0_clk */ 288 clrbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK); 289 290 /* select video_pll clock / 7 for ipu1_di0_clk -> 65MHz pixclock */ 291 reg = readl(&ccm->chsccdr); 292 reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK | 293 MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK | 294 MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK); 295 reg |= (2 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET) | 296 (6 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) | 297 (0 << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET); 298 writel(reg, &ccm->chsccdr); 299 300 /* enable ipu1_di0_clk */ 301 setbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK); 302 303 return 0; 304 } 305 #endif /* CONFIG_VIDEO_IPUV3 */ 306 307 #ifdef CONFIG_USB_EHCI_MX6 308 static void setup_usb(void) 309 { 310 SETUP_IOMUX_PADS(usb_pads); 311 } 312 313 int board_ehci_hcd_init(int port) 314 { 315 if (port == 1) 316 gpio_direction_output(USB_H1_VBUS, 1); 317 318 return 0; 319 } 320 #endif 321 322 int board_early_init_f(void) 323 { 324 setup_iomux_uart(); 325 326 #ifdef CONFIG_CMD_SATA 327 setup_sata(); 328 #endif 329 330 #ifdef CONFIG_USB_EHCI_MX6 331 setup_usb(); 332 #endif 333 return 0; 334 } 335 336 int board_init(void) 337 { 338 int ret = 0; 339 340 /* address of boot parameters */ 341 gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; 342 343 #ifdef CONFIG_VIDEO_IPUV3 344 ret = setup_display(); 345 #endif 346 347 return ret; 348 } 349 350 static enum board_type board_type(void) 351 { 352 int val1, val2, val3; 353 354 SETUP_IOMUX_PADS(board_detect); 355 356 /* 357 * Machine selection - 358 * Machine val1, val2, val3 359 * ---------------------------- 360 * HB2 x x 0 361 * HB rev 3.x x 0 x 362 * CBi 0 1 x 363 * HB 1 1 x 364 */ 365 366 gpio_direction_input(IMX_GPIO_NR(2, 8)); 367 val3 = gpio_get_value(IMX_GPIO_NR(2, 8)); 368 369 if (val3 == 0) 370 return HUMMINGBOARD2; 371 372 gpio_direction_input(IMX_GPIO_NR(3, 4)); 373 val2 = gpio_get_value(IMX_GPIO_NR(3, 4)); 374 375 if (val2 == 0) 376 return HUMMINGBOARD; 377 378 gpio_direction_input(IMX_GPIO_NR(4, 9)); 379 val1 = gpio_get_value(IMX_GPIO_NR(4, 9)); 380 381 if (val1 == 0) { 382 return CUBOXI; 383 } else { 384 return HUMMINGBOARD; 385 } 386 } 387 388 static bool is_rev_15_som(void) 389 { 390 int val1, val2; 391 SETUP_IOMUX_PADS(som_rev_detect); 392 393 val1 = gpio_get_value(IMX_GPIO_NR(6, 0)); 394 val2 = gpio_get_value(IMX_GPIO_NR(6, 4)); 395 396 if (val1 == 1 && val2 == 0) 397 return true; 398 399 return false; 400 } 401 402 int checkboard(void) 403 { 404 switch (board_type()) { 405 case CUBOXI: 406 puts("Board: MX6 Cubox-i"); 407 break; 408 case HUMMINGBOARD: 409 puts("Board: MX6 HummingBoard"); 410 break; 411 case HUMMINGBOARD2: 412 puts("Board: MX6 HummingBoard2"); 413 break; 414 case UNKNOWN: 415 default: 416 puts("Board: Unknown\n"); 417 goto out; 418 } 419 420 if (is_rev_15_som()) 421 puts(" (som rev 1.5)\n"); 422 else 423 puts("\n"); 424 425 out: 426 return 0; 427 } 428 429 int board_late_init(void) 430 { 431 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 432 switch (board_type()) { 433 case CUBOXI: 434 env_set("board_name", "CUBOXI"); 435 break; 436 case HUMMINGBOARD: 437 env_set("board_name", "HUMMINGBOARD"); 438 break; 439 case HUMMINGBOARD2: 440 env_set("board_name", "HUMMINGBOARD2"); 441 break; 442 case UNKNOWN: 443 default: 444 env_set("board_name", "CUBOXI"); 445 } 446 447 if (is_mx6dq()) 448 env_set("board_rev", "MX6Q"); 449 else 450 env_set("board_rev", "MX6DL"); 451 452 if (is_rev_15_som()) 453 env_set("som_rev", "V15"); 454 #endif 455 456 return 0; 457 } 458 459 #ifdef CONFIG_SPL_BUILD 460 #include <asm/arch/mx6-ddr.h> 461 static const struct mx6dq_iomux_ddr_regs mx6q_ddr_ioregs = { 462 .dram_sdclk_0 = 0x00020030, 463 .dram_sdclk_1 = 0x00020030, 464 .dram_cas = 0x00020030, 465 .dram_ras = 0x00020030, 466 .dram_reset = 0x000c0030, 467 .dram_sdcke0 = 0x00003000, 468 .dram_sdcke1 = 0x00003000, 469 .dram_sdba2 = 0x00000000, 470 .dram_sdodt0 = 0x00003030, 471 .dram_sdodt1 = 0x00003030, 472 .dram_sdqs0 = 0x00000030, 473 .dram_sdqs1 = 0x00000030, 474 .dram_sdqs2 = 0x00000030, 475 .dram_sdqs3 = 0x00000030, 476 .dram_sdqs4 = 0x00000030, 477 .dram_sdqs5 = 0x00000030, 478 .dram_sdqs6 = 0x00000030, 479 .dram_sdqs7 = 0x00000030, 480 .dram_dqm0 = 0x00020030, 481 .dram_dqm1 = 0x00020030, 482 .dram_dqm2 = 0x00020030, 483 .dram_dqm3 = 0x00020030, 484 .dram_dqm4 = 0x00020030, 485 .dram_dqm5 = 0x00020030, 486 .dram_dqm6 = 0x00020030, 487 .dram_dqm7 = 0x00020030, 488 }; 489 490 static const struct mx6sdl_iomux_ddr_regs mx6dl_ddr_ioregs = { 491 .dram_sdclk_0 = 0x00000028, 492 .dram_sdclk_1 = 0x00000028, 493 .dram_cas = 0x00000028, 494 .dram_ras = 0x00000028, 495 .dram_reset = 0x000c0028, 496 .dram_sdcke0 = 0x00003000, 497 .dram_sdcke1 = 0x00003000, 498 .dram_sdba2 = 0x00000000, 499 .dram_sdodt0 = 0x00003030, 500 .dram_sdodt1 = 0x00003030, 501 .dram_sdqs0 = 0x00000028, 502 .dram_sdqs1 = 0x00000028, 503 .dram_sdqs2 = 0x00000028, 504 .dram_sdqs3 = 0x00000028, 505 .dram_sdqs4 = 0x00000028, 506 .dram_sdqs5 = 0x00000028, 507 .dram_sdqs6 = 0x00000028, 508 .dram_sdqs7 = 0x00000028, 509 .dram_dqm0 = 0x00000028, 510 .dram_dqm1 = 0x00000028, 511 .dram_dqm2 = 0x00000028, 512 .dram_dqm3 = 0x00000028, 513 .dram_dqm4 = 0x00000028, 514 .dram_dqm5 = 0x00000028, 515 .dram_dqm6 = 0x00000028, 516 .dram_dqm7 = 0x00000028, 517 }; 518 519 static const struct mx6dq_iomux_grp_regs mx6q_grp_ioregs = { 520 .grp_ddr_type = 0x000C0000, 521 .grp_ddrmode_ctl = 0x00020000, 522 .grp_ddrpke = 0x00000000, 523 .grp_addds = 0x00000030, 524 .grp_ctlds = 0x00000030, 525 .grp_ddrmode = 0x00020000, 526 .grp_b0ds = 0x00000030, 527 .grp_b1ds = 0x00000030, 528 .grp_b2ds = 0x00000030, 529 .grp_b3ds = 0x00000030, 530 .grp_b4ds = 0x00000030, 531 .grp_b5ds = 0x00000030, 532 .grp_b6ds = 0x00000030, 533 .grp_b7ds = 0x00000030, 534 }; 535 536 static const struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = { 537 .grp_ddr_type = 0x000c0000, 538 .grp_ddrmode_ctl = 0x00020000, 539 .grp_ddrpke = 0x00000000, 540 .grp_addds = 0x00000028, 541 .grp_ctlds = 0x00000028, 542 .grp_ddrmode = 0x00020000, 543 .grp_b0ds = 0x00000028, 544 .grp_b1ds = 0x00000028, 545 .grp_b2ds = 0x00000028, 546 .grp_b3ds = 0x00000028, 547 .grp_b4ds = 0x00000028, 548 .grp_b5ds = 0x00000028, 549 .grp_b6ds = 0x00000028, 550 .grp_b7ds = 0x00000028, 551 }; 552 553 /* microSOM with Dual processor and 1GB memory */ 554 static const struct mx6_mmdc_calibration mx6q_1g_mmcd_calib = { 555 .p0_mpwldectrl0 = 0x00000000, 556 .p0_mpwldectrl1 = 0x00000000, 557 .p1_mpwldectrl0 = 0x00000000, 558 .p1_mpwldectrl1 = 0x00000000, 559 .p0_mpdgctrl0 = 0x0314031c, 560 .p0_mpdgctrl1 = 0x023e0304, 561 .p1_mpdgctrl0 = 0x03240330, 562 .p1_mpdgctrl1 = 0x03180260, 563 .p0_mprddlctl = 0x3630323c, 564 .p1_mprddlctl = 0x3436283a, 565 .p0_mpwrdlctl = 0x36344038, 566 .p1_mpwrdlctl = 0x422a423c, 567 }; 568 569 /* microSOM with Quad processor and 2GB memory */ 570 static const struct mx6_mmdc_calibration mx6q_2g_mmcd_calib = { 571 .p0_mpwldectrl0 = 0x00000000, 572 .p0_mpwldectrl1 = 0x00000000, 573 .p1_mpwldectrl0 = 0x00000000, 574 .p1_mpwldectrl1 = 0x00000000, 575 .p0_mpdgctrl0 = 0x0314031c, 576 .p0_mpdgctrl1 = 0x023e0304, 577 .p1_mpdgctrl0 = 0x03240330, 578 .p1_mpdgctrl1 = 0x03180260, 579 .p0_mprddlctl = 0x3630323c, 580 .p1_mprddlctl = 0x3436283a, 581 .p0_mpwrdlctl = 0x36344038, 582 .p1_mpwrdlctl = 0x422a423c, 583 }; 584 585 /* microSOM with Solo processor and 512MB memory */ 586 static const struct mx6_mmdc_calibration mx6dl_512m_mmcd_calib = { 587 .p0_mpwldectrl0 = 0x0045004D, 588 .p0_mpwldectrl1 = 0x003A0047, 589 .p0_mpdgctrl0 = 0x023C0224, 590 .p0_mpdgctrl1 = 0x02000220, 591 .p0_mprddlctl = 0x44444846, 592 .p0_mpwrdlctl = 0x32343032, 593 }; 594 595 /* microSOM with Dual lite processor and 1GB memory */ 596 static const struct mx6_mmdc_calibration mx6dl_1g_mmcd_calib = { 597 .p0_mpwldectrl0 = 0x0045004D, 598 .p0_mpwldectrl1 = 0x003A0047, 599 .p1_mpwldectrl0 = 0x001F001F, 600 .p1_mpwldectrl1 = 0x00210035, 601 .p0_mpdgctrl0 = 0x023C0224, 602 .p0_mpdgctrl1 = 0x02000220, 603 .p1_mpdgctrl0 = 0x02200220, 604 .p1_mpdgctrl1 = 0x02040208, 605 .p0_mprddlctl = 0x44444846, 606 .p1_mprddlctl = 0x4042463C, 607 .p0_mpwrdlctl = 0x32343032, 608 .p1_mpwrdlctl = 0x36363430, 609 }; 610 611 static struct mx6_ddr3_cfg mem_ddr_2g = { 612 .mem_speed = 1600, 613 .density = 2, 614 .width = 16, 615 .banks = 8, 616 .rowaddr = 14, 617 .coladdr = 10, 618 .pagesz = 2, 619 .trcd = 1375, 620 .trcmin = 4875, 621 .trasmin = 3500, 622 }; 623 624 static struct mx6_ddr3_cfg mem_ddr_4g = { 625 .mem_speed = 1600, 626 .density = 4, 627 .width = 16, 628 .banks = 8, 629 .rowaddr = 15, 630 .coladdr = 10, 631 .pagesz = 2, 632 .trcd = 1375, 633 .trcmin = 4875, 634 .trasmin = 3500, 635 }; 636 637 static void ccgr_init(void) 638 { 639 struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; 640 641 writel(0x00C03F3F, &ccm->CCGR0); 642 writel(0x0030FC03, &ccm->CCGR1); 643 writel(0x0FFFC000, &ccm->CCGR2); 644 writel(0x3FF00000, &ccm->CCGR3); 645 writel(0x00FFF300, &ccm->CCGR4); 646 writel(0x0F0000C3, &ccm->CCGR5); 647 writel(0x000003FF, &ccm->CCGR6); 648 } 649 650 static void spl_dram_init(int width) 651 { 652 struct mx6_ddr_sysinfo sysinfo = { 653 /* width of data bus: 0=16, 1=32, 2=64 */ 654 .dsize = width / 32, 655 /* config for full 4GB range so that get_mem_size() works */ 656 .cs_density = 32, /* 32Gb per CS */ 657 .ncs = 1, /* single chip select */ 658 .cs1_mirror = 0, 659 .rtt_wr = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Wr = RZQ/4 */ 660 .rtt_nom = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Nom = RZQ/4 */ 661 .walat = 1, /* Write additional latency */ 662 .ralat = 5, /* Read additional latency */ 663 .mif3_mode = 3, /* Command prediction working mode */ 664 .bi_on = 1, /* Bank interleaving enabled */ 665 .sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */ 666 .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */ 667 .ddr_type = DDR_TYPE_DDR3, 668 .refsel = 1, /* Refresh cycles at 32KHz */ 669 .refr = 7, /* 8 refresh commands per refresh cycle */ 670 }; 671 672 if (is_mx6dq()) 673 mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs); 674 else 675 mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs); 676 677 if (is_cpu_type(MXC_CPU_MX6D)) 678 mx6_dram_cfg(&sysinfo, &mx6q_1g_mmcd_calib, &mem_ddr_2g); 679 else if (is_cpu_type(MXC_CPU_MX6Q)) 680 mx6_dram_cfg(&sysinfo, &mx6q_2g_mmcd_calib, &mem_ddr_4g); 681 else if (is_cpu_type(MXC_CPU_MX6DL)) 682 mx6_dram_cfg(&sysinfo, &mx6dl_1g_mmcd_calib, &mem_ddr_2g); 683 else if (is_cpu_type(MXC_CPU_MX6SOLO)) 684 mx6_dram_cfg(&sysinfo, &mx6dl_512m_mmcd_calib, &mem_ddr_2g); 685 } 686 687 void board_init_f(ulong dummy) 688 { 689 /* setup AIPS and disable watchdog */ 690 arch_cpu_init(); 691 692 ccgr_init(); 693 gpr_init(); 694 695 /* iomux and setup of i2c */ 696 board_early_init_f(); 697 698 /* setup GP timer */ 699 timer_init(); 700 701 /* UART clocks enabled and gd valid - init serial console */ 702 preloader_console_init(); 703 704 /* DDR initialization */ 705 if (is_cpu_type(MXC_CPU_MX6SOLO)) 706 spl_dram_init(32); 707 else 708 spl_dram_init(64); 709 710 /* Clear the BSS. */ 711 memset(__bss_start, 0, __bss_end - __bss_start); 712 713 /* load/boot image from boot device */ 714 board_init_r(NULL, 0); 715 } 716 #endif 717