1 /* 2 * SPL specific code for Compulab CM-FX6 board 3 * 4 * Copyright (C) 2014, Compulab Ltd - http://compulab.co.il/ 5 * 6 * Author: Nikita Kiryanov <nikita@compulab.co.il> 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11 #include <common.h> 12 #include <spl.h> 13 #include <asm/io.h> 14 #include <asm/gpio.h> 15 #include <asm/arch/mx6-ddr.h> 16 #include <asm/arch/clock.h> 17 #include <asm/arch/sys_proto.h> 18 #include <asm/arch/crm_regs.h> 19 #include <asm/mach-imx/iomux-v3.h> 20 #include <fsl_esdhc.h> 21 #include "common.h" 22 23 DECLARE_GLOBAL_DATA_PTR; 24 25 enum ddr_config { 26 DDR_16BIT_256MB, 27 DDR_32BIT_512MB, 28 DDR_32BIT_1GB, 29 DDR_64BIT_1GB, 30 DDR_64BIT_2GB, 31 DDR_64BIT_4GB, 32 DDR_UNKNOWN, 33 }; 34 35 /* 36 * Below DRAM_RESET[DDR_SEL] = 0 which is incorrect according to 37 * Freescale QRM, but this is exactly the value used by the automatic 38 * calibration script and it works also in all our tests, so we leave 39 * it as is at this point. 40 */ 41 #define CM_FX6_DDR_IOMUX_CFG \ 42 .dram_sdqs0 = 0x00000038, \ 43 .dram_sdqs1 = 0x00000038, \ 44 .dram_sdqs2 = 0x00000038, \ 45 .dram_sdqs3 = 0x00000038, \ 46 .dram_sdqs4 = 0x00000038, \ 47 .dram_sdqs5 = 0x00000038, \ 48 .dram_sdqs6 = 0x00000038, \ 49 .dram_sdqs7 = 0x00000038, \ 50 .dram_dqm0 = 0x00000038, \ 51 .dram_dqm1 = 0x00000038, \ 52 .dram_dqm2 = 0x00000038, \ 53 .dram_dqm3 = 0x00000038, \ 54 .dram_dqm4 = 0x00000038, \ 55 .dram_dqm5 = 0x00000038, \ 56 .dram_dqm6 = 0x00000038, \ 57 .dram_dqm7 = 0x00000038, \ 58 .dram_cas = 0x00000038, \ 59 .dram_ras = 0x00000038, \ 60 .dram_sdclk_0 = 0x00000038, \ 61 .dram_sdclk_1 = 0x00000038, \ 62 .dram_sdcke0 = 0x00003000, \ 63 .dram_sdcke1 = 0x00003000, \ 64 .dram_reset = 0x00000038, \ 65 .dram_sdba2 = 0x00000000, \ 66 .dram_sdodt0 = 0x00000038, \ 67 .dram_sdodt1 = 0x00000038, 68 69 #define CM_FX6_GPR_IOMUX_CFG \ 70 .grp_b0ds = 0x00000038, \ 71 .grp_b1ds = 0x00000038, \ 72 .grp_b2ds = 0x00000038, \ 73 .grp_b3ds = 0x00000038, \ 74 .grp_b4ds = 0x00000038, \ 75 .grp_b5ds = 0x00000038, \ 76 .grp_b6ds = 0x00000038, \ 77 .grp_b7ds = 0x00000038, \ 78 .grp_addds = 0x00000038, \ 79 .grp_ddrmode_ctl = 0x00020000, \ 80 .grp_ddrpke = 0x00000000, \ 81 .grp_ddrmode = 0x00020000, \ 82 .grp_ctlds = 0x00000038, \ 83 .grp_ddr_type = 0x000C0000, 84 85 static struct mx6sdl_iomux_ddr_regs ddr_iomux_s = { CM_FX6_DDR_IOMUX_CFG }; 86 static struct mx6sdl_iomux_grp_regs grp_iomux_s = { CM_FX6_GPR_IOMUX_CFG }; 87 static struct mx6dq_iomux_ddr_regs ddr_iomux_q = { CM_FX6_DDR_IOMUX_CFG }; 88 static struct mx6dq_iomux_grp_regs grp_iomux_q = { CM_FX6_GPR_IOMUX_CFG }; 89 90 static struct mx6_mmdc_calibration cm_fx6_calib_s = { 91 .p0_mpwldectrl0 = 0x005B0061, 92 .p0_mpwldectrl1 = 0x004F0055, 93 .p0_mpdgctrl0 = 0x0314030C, 94 .p0_mpdgctrl1 = 0x025C0268, 95 .p0_mprddlctl = 0x42464646, 96 .p0_mpwrdlctl = 0x36322C34, 97 }; 98 99 static struct mx6_ddr_sysinfo cm_fx6_sysinfo_s = { 100 .cs1_mirror = 1, 101 .cs_density = 16, 102 .bi_on = 1, 103 .rtt_nom = 1, 104 .rtt_wr = 0, 105 .ralat = 5, 106 .walat = 1, 107 .mif3_mode = 3, 108 .rst_to_cke = 0x23, 109 .sde_to_rst = 0x10, 110 .refsel = 1, /* Refresh cycles at 32KHz */ 111 .refr = 7, /* 8 refresh commands per refresh cycle */ 112 }; 113 114 static struct mx6_ddr3_cfg cm_fx6_ddr3_cfg_s = { 115 .mem_speed = 800, 116 .density = 4, 117 .rowaddr = 14, 118 .coladdr = 10, 119 .pagesz = 2, 120 .trcd = 1800, 121 .trcmin = 5200, 122 .trasmin = 3600, 123 .SRT = 0, 124 }; 125 126 static void spl_mx6s_dram_init(enum ddr_config dram_config, bool reset) 127 { 128 if (reset) 129 ((struct mmdc_p_regs *)MX6_MMDC_P0_MDCTL)->mdmisc = 2; 130 131 switch (dram_config) { 132 case DDR_16BIT_256MB: 133 cm_fx6_sysinfo_s.dsize = 0; 134 cm_fx6_sysinfo_s.ncs = 1; 135 break; 136 case DDR_32BIT_512MB: 137 cm_fx6_sysinfo_s.dsize = 1; 138 cm_fx6_sysinfo_s.ncs = 1; 139 break; 140 case DDR_32BIT_1GB: 141 cm_fx6_sysinfo_s.dsize = 1; 142 cm_fx6_sysinfo_s.ncs = 2; 143 break; 144 default: 145 puts("Tried to setup invalid DDR configuration\n"); 146 hang(); 147 } 148 149 mx6_dram_cfg(&cm_fx6_sysinfo_s, &cm_fx6_calib_s, &cm_fx6_ddr3_cfg_s); 150 udelay(100); 151 } 152 153 static struct mx6_mmdc_calibration cm_fx6_calib_q = { 154 .p0_mpwldectrl0 = 0x00630068, 155 .p0_mpwldectrl1 = 0x0068005D, 156 .p0_mpdgctrl0 = 0x04140428, 157 .p0_mpdgctrl1 = 0x037C037C, 158 .p0_mprddlctl = 0x3C30303A, 159 .p0_mpwrdlctl = 0x3A344038, 160 .p1_mpwldectrl0 = 0x0035004C, 161 .p1_mpwldectrl1 = 0x00170026, 162 .p1_mpdgctrl0 = 0x0374037C, 163 .p1_mpdgctrl1 = 0x0350032C, 164 .p1_mprddlctl = 0x30322A3C, 165 .p1_mpwrdlctl = 0x48304A3E, 166 }; 167 168 static struct mx6_ddr_sysinfo cm_fx6_sysinfo_q = { 169 .cs_density = 16, 170 .cs1_mirror = 1, 171 .bi_on = 1, 172 .rtt_nom = 1, 173 .rtt_wr = 0, 174 .ralat = 5, 175 .walat = 1, 176 .mif3_mode = 3, 177 .rst_to_cke = 0x23, 178 .sde_to_rst = 0x10, 179 .refsel = 1, /* Refresh cycles at 32KHz */ 180 .refr = 7, /* 8 refresh commands per refresh cycle */ 181 }; 182 183 static struct mx6_ddr3_cfg cm_fx6_ddr3_cfg_q = { 184 .mem_speed = 1066, 185 .density = 4, 186 .rowaddr = 14, 187 .coladdr = 10, 188 .pagesz = 2, 189 .trcd = 1324, 190 .trcmin = 59500, 191 .trasmin = 9750, 192 .SRT = 0, 193 }; 194 195 static void spl_mx6q_dram_init(enum ddr_config dram_config, bool reset) 196 { 197 if (reset) 198 ((struct mmdc_p_regs *)MX6_MMDC_P0_MDCTL)->mdmisc = 2; 199 200 cm_fx6_ddr3_cfg_q.rowaddr = 14; 201 switch (dram_config) { 202 case DDR_16BIT_256MB: 203 cm_fx6_sysinfo_q.dsize = 0; 204 cm_fx6_sysinfo_q.ncs = 1; 205 break; 206 case DDR_32BIT_512MB: 207 cm_fx6_sysinfo_q.dsize = 1; 208 cm_fx6_sysinfo_q.ncs = 1; 209 break; 210 case DDR_64BIT_1GB: 211 cm_fx6_sysinfo_q.dsize = 2; 212 cm_fx6_sysinfo_q.ncs = 1; 213 break; 214 case DDR_64BIT_2GB: 215 cm_fx6_sysinfo_q.dsize = 2; 216 cm_fx6_sysinfo_q.ncs = 2; 217 break; 218 case DDR_64BIT_4GB: 219 cm_fx6_sysinfo_q.dsize = 2; 220 cm_fx6_sysinfo_q.ncs = 2; 221 cm_fx6_ddr3_cfg_q.rowaddr = 15; 222 break; 223 default: 224 puts("Tried to setup invalid DDR configuration\n"); 225 hang(); 226 } 227 228 mx6_dram_cfg(&cm_fx6_sysinfo_q, &cm_fx6_calib_q, &cm_fx6_ddr3_cfg_q); 229 udelay(100); 230 } 231 232 static int cm_fx6_spl_dram_init(void) 233 { 234 unsigned long bank1_size, bank2_size; 235 236 switch (get_cpu_type()) { 237 case MXC_CPU_MX6SOLO: 238 mx6sdl_dram_iocfg(64, &ddr_iomux_s, &grp_iomux_s); 239 240 spl_mx6s_dram_init(DDR_32BIT_1GB, false); 241 bank1_size = get_ram_size((long int *)PHYS_SDRAM_1, 0x80000000); 242 bank2_size = get_ram_size((long int *)PHYS_SDRAM_2, 0x80000000); 243 if (bank1_size == 0x20000000) { 244 if (bank2_size == 0x20000000) 245 return 0; 246 247 spl_mx6s_dram_init(DDR_32BIT_512MB, true); 248 return 0; 249 } 250 251 spl_mx6s_dram_init(DDR_16BIT_256MB, true); 252 bank1_size = get_ram_size((long int *)PHYS_SDRAM_1, 0x80000000); 253 if (bank1_size == 0x10000000) 254 return 0; 255 256 break; 257 case MXC_CPU_MX6D: 258 case MXC_CPU_MX6Q: 259 mx6dq_dram_iocfg(64, &ddr_iomux_q, &grp_iomux_q); 260 261 spl_mx6q_dram_init(DDR_64BIT_4GB, false); 262 bank1_size = get_ram_size((long int *)PHYS_SDRAM_1, 0x80000000); 263 if (bank1_size == 0x80000000) 264 return 0; 265 266 if (bank1_size == 0x40000000) { 267 bank2_size = get_ram_size((long int *)PHYS_SDRAM_2, 268 0x80000000); 269 if (bank2_size == 0x40000000) { 270 /* Don't do a full reset here */ 271 spl_mx6q_dram_init(DDR_64BIT_2GB, false); 272 } else { 273 spl_mx6q_dram_init(DDR_64BIT_1GB, true); 274 } 275 276 return 0; 277 } 278 279 spl_mx6q_dram_init(DDR_32BIT_512MB, true); 280 bank1_size = get_ram_size((long int *)PHYS_SDRAM_1, 0x80000000); 281 if (bank1_size == 0x20000000) 282 return 0; 283 284 spl_mx6q_dram_init(DDR_16BIT_256MB, true); 285 bank1_size = get_ram_size((long int *)PHYS_SDRAM_1, 0x80000000); 286 if (bank1_size == 0x10000000) 287 return 0; 288 289 break; 290 } 291 292 return -1; 293 } 294 295 static iomux_v3_cfg_t const uart4_pads[] = { 296 IOMUX_PADS(PAD_KEY_COL0__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), 297 IOMUX_PADS(PAD_KEY_ROW0__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), 298 }; 299 300 static void cm_fx6_setup_uart(void) 301 { 302 SETUP_IOMUX_PADS(uart4_pads); 303 enable_uart_clk(1); 304 } 305 306 #ifdef CONFIG_SPL_SPI_SUPPORT 307 static void cm_fx6_setup_ecspi(void) 308 { 309 cm_fx6_set_ecspi_iomux(); 310 enable_spi_clk(1, 0); 311 } 312 #else 313 static void cm_fx6_setup_ecspi(void) { } 314 #endif 315 316 void board_init_f(ulong dummy) 317 { 318 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; 319 320 /* 321 * We don't use DMA in SPL, but we do need it in U-Boot. U-Boot 322 * initializes DMA very early (before all board code), so the only 323 * opportunity we have to initialize APBHDMA clocks is in SPL. 324 */ 325 setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK); 326 enable_usdhc_clk(1, 2); 327 328 arch_cpu_init(); 329 timer_init(); 330 cm_fx6_setup_ecspi(); 331 cm_fx6_setup_uart(); 332 get_clocks(); 333 preloader_console_init(); 334 gpio_direction_output(CM_FX6_GREEN_LED, 1); 335 if (cm_fx6_spl_dram_init()) { 336 puts("!!!ERROR!!! DRAM detection failed!!!\n"); 337 hang(); 338 } 339 } 340 341 void board_boot_order(u32 *spl_boot_list) 342 { 343 spl_boot_list[0] = spl_boot_device(); 344 switch (spl_boot_list[0]) { 345 case BOOT_DEVICE_SPI: 346 spl_boot_list[1] = BOOT_DEVICE_MMC1; 347 break; 348 case BOOT_DEVICE_MMC1: 349 spl_boot_list[1] = BOOT_DEVICE_SPI; 350 break; 351 } 352 } 353 354 #ifdef CONFIG_SPL_MMC_SUPPORT 355 static struct fsl_esdhc_cfg usdhc_cfg = { 356 .esdhc_base = USDHC3_BASE_ADDR, 357 .max_bus_width = 4, 358 }; 359 360 int board_mmc_init(bd_t *bis) 361 { 362 cm_fx6_set_usdhc_iomux(); 363 364 usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); 365 366 return fsl_esdhc_initialize(bis, &usdhc_cfg); 367 } 368 #endif 369