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