1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2016 Amarula Solutions B.V. 4 * Copyright (C) 2016 Engicam S.r.l. 5 * Author: Jagan Teki <jagan@amarulasolutions.com> 6 */ 7 8#include <common.h> 9#include <image.h> 10#include <init.h> 11#include <serial.h> 12#include <spl.h> 13#include <linux/delay.h> 14 15#include <asm/io.h> 16#include <asm/gpio.h> 17#include <linux/sizes.h> 18 19#include <asm/arch/clock.h> 20#include <asm/arch/crm_regs.h> 21#include <asm/arch/iomux.h> 22#include <asm/arch/mx6-ddr.h> 23#include <asm/arch/mx6-pins.h> 24#include <asm/arch/sys_proto.h> 25 26#include <asm/mach-imx/iomux-v3.h> 27#include <asm/mach-imx/video.h> 28 29#ifdef CONFIG_SPL_LOAD_FIT 30int board_fit_config_name_match(const char *name) 31{ 32 if (is_mx6dq() && !strcmp(name, "imx6q-icore")) 33 return 0; 34 else if (is_mx6dq() && !strcmp(name, "imx6q-icore-rqs")) 35 return 0; 36 else if (is_mx6dq() && !strcmp(name, "imx6q-icore-mipi")) 37 return 0; 38 else if ((is_mx6dl() || is_mx6solo()) && !strcmp(name, "imx6dl-icore")) 39 return 0; 40 else if ((is_mx6dl() || is_mx6solo()) && !strcmp(name, "imx6dl-icore-rqs")) 41 return 0; 42 else if ((is_mx6dl() || is_mx6solo()) && !strcmp(name, "imx6dl-icore-mipi")) 43 return 0; 44 else 45 return -1; 46} 47#endif 48 49#ifdef CONFIG_ENV_IS_IN_MMC 50void board_boot_order(u32 *spl_boot_list) 51{ 52 u32 bmode = imx6_src_get_boot_mode(); 53 u8 boot_dev = BOOT_DEVICE_MMC1; 54 55 switch ((bmode & IMX6_BMODE_MASK) >> IMX6_BMODE_SHIFT) { 56 case IMX6_BMODE_SD: 57 case IMX6_BMODE_ESD: 58 /* SD/eSD - BOOT_DEVICE_MMC1 */ 59 break; 60 case IMX6_BMODE_MMC: 61 case IMX6_BMODE_EMMC: 62 /* MMC/eMMC */ 63 boot_dev = BOOT_DEVICE_MMC2; 64 break; 65 default: 66 /* Default - BOOT_DEVICE_MMC1 */ 67 printf("Wrong board boot order\n"); 68 break; 69 } 70 71 spl_boot_list[0] = boot_dev; 72} 73#endif 74 75#ifdef CONFIG_SPL_OS_BOOT 76int spl_start_uboot(void) 77{ 78 /* break into full u-boot on 'c' */ 79 if (serial_tstc() && serial_getc() == 'c') 80 return 1; 81 82 return 0; 83} 84#endif 85 86#ifdef CONFIG_MX6QDL 87/* 88 * Driving strength: 89 * 0x30 == 40 Ohm 90 * 0x28 == 48 Ohm 91 */ 92#define IMX6DQ_DRIVE_STRENGTH 0x30 93#define IMX6SDL_DRIVE_STRENGTH 0x28 94 95/* configure MX6Q/DUAL mmdc DDR io registers */ 96static struct mx6dq_iomux_ddr_regs mx6dq_ddr_ioregs = { 97 .dram_sdqs0 = IMX6DQ_DRIVE_STRENGTH, 98 .dram_sdqs1 = IMX6DQ_DRIVE_STRENGTH, 99 .dram_sdqs2 = IMX6DQ_DRIVE_STRENGTH, 100 .dram_sdqs3 = IMX6DQ_DRIVE_STRENGTH, 101 .dram_sdqs4 = IMX6DQ_DRIVE_STRENGTH, 102 .dram_sdqs5 = IMX6DQ_DRIVE_STRENGTH, 103 .dram_sdqs6 = IMX6DQ_DRIVE_STRENGTH, 104 .dram_sdqs7 = IMX6DQ_DRIVE_STRENGTH, 105 .dram_dqm0 = IMX6DQ_DRIVE_STRENGTH, 106 .dram_dqm1 = IMX6DQ_DRIVE_STRENGTH, 107 .dram_dqm2 = IMX6DQ_DRIVE_STRENGTH, 108 .dram_dqm3 = IMX6DQ_DRIVE_STRENGTH, 109 .dram_dqm4 = IMX6DQ_DRIVE_STRENGTH, 110 .dram_dqm5 = IMX6DQ_DRIVE_STRENGTH, 111 .dram_dqm6 = IMX6DQ_DRIVE_STRENGTH, 112 .dram_dqm7 = IMX6DQ_DRIVE_STRENGTH, 113 .dram_cas = IMX6DQ_DRIVE_STRENGTH, 114 .dram_ras = IMX6DQ_DRIVE_STRENGTH, 115 .dram_sdclk_0 = IMX6DQ_DRIVE_STRENGTH, 116 .dram_sdclk_1 = IMX6DQ_DRIVE_STRENGTH, 117 .dram_reset = IMX6DQ_DRIVE_STRENGTH, 118 .dram_sdcke0 = IMX6DQ_DRIVE_STRENGTH, 119 .dram_sdcke1 = IMX6DQ_DRIVE_STRENGTH, 120 .dram_sdba2 = 0x00000000, 121 .dram_sdodt0 = IMX6DQ_DRIVE_STRENGTH, 122 .dram_sdodt1 = IMX6DQ_DRIVE_STRENGTH, 123}; 124 125/* configure MX6Q/DUAL mmdc GRP io registers */ 126static struct mx6dq_iomux_grp_regs mx6dq_grp_ioregs = { 127 .grp_b0ds = IMX6DQ_DRIVE_STRENGTH, 128 .grp_b1ds = IMX6DQ_DRIVE_STRENGTH, 129 .grp_b2ds = IMX6DQ_DRIVE_STRENGTH, 130 .grp_b3ds = IMX6DQ_DRIVE_STRENGTH, 131 .grp_b4ds = IMX6DQ_DRIVE_STRENGTH, 132 .grp_b5ds = IMX6DQ_DRIVE_STRENGTH, 133 .grp_b6ds = IMX6DQ_DRIVE_STRENGTH, 134 .grp_b7ds = IMX6DQ_DRIVE_STRENGTH, 135 .grp_addds = IMX6DQ_DRIVE_STRENGTH, 136 .grp_ddrmode_ctl = 0x00020000, 137 .grp_ddrpke = 0x00000000, 138 .grp_ddrmode = 0x00020000, 139 .grp_ctlds = IMX6DQ_DRIVE_STRENGTH, 140 .grp_ddr_type = 0x000c0000, 141}; 142 143/* configure MX6SOLO/DUALLITE mmdc DDR io registers */ 144struct mx6sdl_iomux_ddr_regs mx6sdl_ddr_ioregs = { 145 .dram_sdclk_0 = IMX6SDL_DRIVE_STRENGTH, 146 .dram_sdclk_1 = IMX6SDL_DRIVE_STRENGTH, 147 .dram_cas = IMX6SDL_DRIVE_STRENGTH, 148 .dram_ras = IMX6SDL_DRIVE_STRENGTH, 149 .dram_reset = IMX6SDL_DRIVE_STRENGTH, 150 .dram_sdcke0 = IMX6SDL_DRIVE_STRENGTH, 151 .dram_sdcke1 = IMX6SDL_DRIVE_STRENGTH, 152 .dram_sdba2 = 0x00000000, 153 .dram_sdodt0 = IMX6SDL_DRIVE_STRENGTH, 154 .dram_sdodt1 = IMX6SDL_DRIVE_STRENGTH, 155 .dram_sdqs0 = IMX6SDL_DRIVE_STRENGTH, 156 .dram_sdqs1 = IMX6SDL_DRIVE_STRENGTH, 157 .dram_sdqs2 = IMX6SDL_DRIVE_STRENGTH, 158 .dram_sdqs3 = IMX6SDL_DRIVE_STRENGTH, 159 .dram_sdqs4 = IMX6SDL_DRIVE_STRENGTH, 160 .dram_sdqs5 = IMX6SDL_DRIVE_STRENGTH, 161 .dram_sdqs6 = IMX6SDL_DRIVE_STRENGTH, 162 .dram_sdqs7 = IMX6SDL_DRIVE_STRENGTH, 163 .dram_dqm0 = IMX6SDL_DRIVE_STRENGTH, 164 .dram_dqm1 = IMX6SDL_DRIVE_STRENGTH, 165 .dram_dqm2 = IMX6SDL_DRIVE_STRENGTH, 166 .dram_dqm3 = IMX6SDL_DRIVE_STRENGTH, 167 .dram_dqm4 = IMX6SDL_DRIVE_STRENGTH, 168 .dram_dqm5 = IMX6SDL_DRIVE_STRENGTH, 169 .dram_dqm6 = IMX6SDL_DRIVE_STRENGTH, 170 .dram_dqm7 = IMX6SDL_DRIVE_STRENGTH, 171}; 172 173/* configure MX6SOLO/DUALLITE mmdc GRP io registers */ 174struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = { 175 .grp_ddr_type = 0x000c0000, 176 .grp_ddrmode_ctl = 0x00020000, 177 .grp_ddrpke = 0x00000000, 178 .grp_addds = IMX6SDL_DRIVE_STRENGTH, 179 .grp_ctlds = IMX6SDL_DRIVE_STRENGTH, 180 .grp_ddrmode = 0x00020000, 181 .grp_b0ds = IMX6SDL_DRIVE_STRENGTH, 182 .grp_b1ds = IMX6SDL_DRIVE_STRENGTH, 183 .grp_b2ds = IMX6SDL_DRIVE_STRENGTH, 184 .grp_b3ds = IMX6SDL_DRIVE_STRENGTH, 185 .grp_b4ds = IMX6SDL_DRIVE_STRENGTH, 186 .grp_b5ds = IMX6SDL_DRIVE_STRENGTH, 187 .grp_b6ds = IMX6SDL_DRIVE_STRENGTH, 188 .grp_b7ds = IMX6SDL_DRIVE_STRENGTH, 189}; 190 191/* mt41j256 */ 192static struct mx6_ddr3_cfg mt41j256 = { 193 .mem_speed = 1066, 194 .density = 2, 195 .width = 16, 196 .banks = 8, 197 .rowaddr = 13, 198 .coladdr = 10, 199 .pagesz = 2, 200 .trcd = 1375, 201 .trcmin = 4875, 202 .trasmin = 3500, 203 .SRT = 0, 204}; 205 206static struct mx6_mmdc_calibration mx6dq_mmdc_calib = { 207 .p0_mpwldectrl0 = 0x000E0009, 208 .p0_mpwldectrl1 = 0x0018000E, 209 .p1_mpwldectrl0 = 0x00000007, 210 .p1_mpwldectrl1 = 0x00000000, 211 .p0_mpdgctrl0 = 0x43280334, 212 .p0_mpdgctrl1 = 0x031C0314, 213 .p1_mpdgctrl0 = 0x4318031C, 214 .p1_mpdgctrl1 = 0x030C0258, 215 .p0_mprddlctl = 0x3E343A40, 216 .p1_mprddlctl = 0x383C3844, 217 .p0_mpwrdlctl = 0x40404440, 218 .p1_mpwrdlctl = 0x4C3E4446, 219}; 220 221/* DDR 64bit */ 222static struct mx6_ddr_sysinfo mem_q = { 223 .ddr_type = DDR_TYPE_DDR3, 224 .dsize = 2, 225 .cs1_mirror = 0, 226 /* config for full 4GB range so that get_mem_size() works */ 227 .cs_density = 32, 228 .ncs = 1, 229 .bi_on = 1, 230 .rtt_nom = 2, 231 .rtt_wr = 2, 232 .ralat = 5, 233 .walat = 0, 234 .mif3_mode = 3, 235 .rst_to_cke = 0x23, 236 .sde_to_rst = 0x10, 237}; 238 239static struct mx6_mmdc_calibration mx6dl_mmdc_calib = { 240 .p0_mpwldectrl0 = 0x001F0024, 241 .p0_mpwldectrl1 = 0x00110018, 242 .p1_mpwldectrl0 = 0x001F0024, 243 .p1_mpwldectrl1 = 0x00110018, 244 .p0_mpdgctrl0 = 0x4230022C, 245 .p0_mpdgctrl1 = 0x02180220, 246 .p1_mpdgctrl0 = 0x42440248, 247 .p1_mpdgctrl1 = 0x02300238, 248 .p0_mprddlctl = 0x44444A48, 249 .p1_mprddlctl = 0x46484A42, 250 .p0_mpwrdlctl = 0x38383234, 251 .p1_mpwrdlctl = 0x3C34362E, 252}; 253 254/* DDR 64bit 1GB */ 255static struct mx6_ddr_sysinfo mem_dl = { 256 .dsize = 2, 257 .cs1_mirror = 0, 258 /* config for full 4GB range so that get_mem_size() works */ 259 .cs_density = 32, 260 .ncs = 1, 261 .bi_on = 1, 262 .rtt_nom = 1, 263 .rtt_wr = 1, 264 .ralat = 5, 265 .walat = 0, 266 .mif3_mode = 3, 267 .rst_to_cke = 0x23, 268 .sde_to_rst = 0x10, 269}; 270 271/* DDR 32bit 512MB */ 272static struct mx6_ddr_sysinfo mem_s = { 273 .dsize = 1, 274 .cs1_mirror = 0, 275 /* config for full 4GB range so that get_mem_size() works */ 276 .cs_density = 32, 277 .ncs = 1, 278 .bi_on = 1, 279 .rtt_nom = 1, 280 .rtt_wr = 1, 281 .ralat = 5, 282 .walat = 0, 283 .mif3_mode = 3, 284 .rst_to_cke = 0x23, 285 .sde_to_rst = 0x10, 286}; 287#endif /* CONFIG_MX6QDL */ 288 289#ifdef CONFIG_MX6UL 290static struct mx6ul_iomux_grp_regs mx6_grp_ioregs = { 291 .grp_addds = 0x00000030, 292 .grp_ddrmode_ctl = 0x00020000, 293 .grp_b0ds = 0x00000030, 294 .grp_ctlds = 0x00000030, 295 .grp_b1ds = 0x00000030, 296 .grp_ddrpke = 0x00000000, 297 .grp_ddrmode = 0x00020000, 298 .grp_ddr_type = 0x000c0000, 299}; 300 301static struct mx6ul_iomux_ddr_regs mx6_ddr_ioregs = { 302 .dram_dqm0 = 0x00000030, 303 .dram_dqm1 = 0x00000030, 304 .dram_ras = 0x00000030, 305 .dram_cas = 0x00000030, 306 .dram_odt0 = 0x00000030, 307 .dram_odt1 = 0x00000030, 308 .dram_sdba2 = 0x00000000, 309 .dram_sdclk_0 = 0x00000008, 310 .dram_sdqs0 = 0x00000038, 311 .dram_sdqs1 = 0x00000030, 312 .dram_reset = 0x00000030, 313}; 314 315static struct mx6_mmdc_calibration mx6_mmcd_calib = { 316 .p0_mpwldectrl0 = 0x00070007, 317 .p0_mpdgctrl0 = 0x41490145, 318 .p0_mprddlctl = 0x40404546, 319 .p0_mpwrdlctl = 0x4040524D, 320}; 321 322struct mx6_ddr_sysinfo ddr_sysinfo = { 323 .dsize = 0, 324 .cs_density = 20, 325 .ncs = 1, 326 .cs1_mirror = 0, 327 .rtt_wr = 2, 328 .rtt_nom = 1, /* RTT_Nom = RZQ/2 */ 329 .walat = 1, /* Write additional latency */ 330 .ralat = 5, /* Read additional latency */ 331 .mif3_mode = 3, /* Command prediction working mode */ 332 .bi_on = 1, /* Bank interleaving enabled */ 333 .sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */ 334 .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */ 335 .ddr_type = DDR_TYPE_DDR3, 336}; 337 338static struct mx6_ddr3_cfg mem_ddr = { 339 .mem_speed = 800, 340 .density = 4, 341 .width = 16, 342 .banks = 8, 343#ifdef TARGET_MX6UL_ISIOT 344 .rowaddr = 15, 345#else 346 .rowaddr = 13, 347#endif 348 .coladdr = 10, 349 .pagesz = 2, 350 .trcd = 1375, 351 .trcmin = 4875, 352 .trasmin = 3500, 353}; 354#endif /* CONFIG_MX6UL */ 355 356static void ccgr_init(void) 357{ 358 struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; 359 360#ifdef CONFIG_MX6QDL 361 writel(0x00003F3F, &ccm->CCGR0); 362 writel(0x0030FC00, &ccm->CCGR1); 363 writel(0x000FC000, &ccm->CCGR2); 364 writel(0x3F300000, &ccm->CCGR3); 365 writel(0xFF00F300, &ccm->CCGR4); 366 writel(0x0F0000C3, &ccm->CCGR5); 367 writel(0x000003CC, &ccm->CCGR6); 368#elif CONFIG_MX6UL 369 writel(0x00c03f3f, &ccm->CCGR0); 370 writel(0xfcffff00, &ccm->CCGR1); 371 writel(0x0cffffcc, &ccm->CCGR2); 372 writel(0x3f3c3030, &ccm->CCGR3); 373 writel(0xff00fffc, &ccm->CCGR4); 374 writel(0x033f30ff, &ccm->CCGR5); 375 writel(0x00c00fff, &ccm->CCGR6); 376#endif 377} 378 379static void spl_dram_init(void) 380{ 381#ifdef CONFIG_MX6QDL 382 if (is_mx6solo()) { 383 mx6sdl_dram_iocfg(32, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs); 384 mx6_dram_cfg(&mem_s, &mx6dl_mmdc_calib, &mt41j256); 385 } else if (is_mx6dl()) { 386 mx6sdl_dram_iocfg(64, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs); 387 mx6_dram_cfg(&mem_dl, &mx6dl_mmdc_calib, &mt41j256); 388 } else if (is_mx6dq()) { 389 mx6dq_dram_iocfg(64, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs); 390 mx6_dram_cfg(&mem_q, &mx6dq_mmdc_calib, &mt41j256); 391 } 392#elif CONFIG_MX6UL 393 mx6ul_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs); 394 mx6_dram_cfg(&ddr_sysinfo, &mx6_mmcd_calib, &mem_ddr); 395#endif 396 397 udelay(100); 398} 399 400void board_init_f(ulong dummy) 401{ 402 ccgr_init(); 403 404 /* setup AIPS and disable watchdog */ 405 arch_cpu_init(); 406 407 if (!(is_mx6ul())) 408 gpr_init(); 409 410 /* setup GP timer */ 411 timer_init(); 412 413 /* Enable device tree and early DM support*/ 414 spl_early_init(); 415 416 /* UART clocks enabled and gd valid - init serial console */ 417 preloader_console_init(); 418 419 /* DDR initialization */ 420 spl_dram_init(); 421} 422