Beispiel #1
0
static bool is_mx6q(void)
{
	if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
		return true;
	else
		return false;
}
/* i2c_num can be from 0 - 3 */
int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
{
	u32 reg;
	u32 mask;
	u32 *addr;

	if (i2c_num > 3)
		return -EINVAL;
	if (i2c_num < 3) {
		mask = MXC_CCM_CCGR_CG_MASK
			<< (MXC_CCM_CCGR2_I2C1_SERIAL_OFFSET
			+ (i2c_num << 1));
		reg = __raw_readl(&imx_ccm->CCGR2);
		if (enable)
			reg |= mask;
		else
			reg &= ~mask;
		__raw_writel(reg, &imx_ccm->CCGR2);
	} else {
		if (is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL)) {
			mask = MXC_CCM_CCGR6_I2C4_MASK;
			addr = &imx_ccm->CCGR6;
		} else {
			mask = MXC_CCM_CCGR1_I2C4_SERIAL_MASK;
			addr = &imx_ccm->CCGR1;
		}
		reg = __raw_readl(addr);
		if (enable)
			reg |= mask;
		else
			reg &= ~mask;
		__raw_writel(reg, addr);
	}
	return 0;
}
Beispiel #3
0
int setup_sata(void)
{
	struct iomuxc_base_regs *const iomuxc_regs
		= (struct iomuxc_base_regs *)IOMUXC_BASE_ADDR;
	int ret;

	if (!is_cpu_type(MXC_CPU_MX6Q) && !is_cpu_type(MXC_CPU_MX6D))
		return 1;

	ret = enable_sata_clock();
	if (ret)
		return ret;

	clrsetbits_le32(&iomuxc_regs->gpr[13],
			IOMUXC_GPR13_SATA_MASK,
			IOMUXC_GPR13_SATA_PHY_8_RXEQ_3P0DB
			|IOMUXC_GPR13_SATA_PHY_7_SATA2M
			|IOMUXC_GPR13_SATA_SPEED_3G
			|(3<<IOMUXC_GPR13_SATA_PHY_6_SHIFT)
			|IOMUXC_GPR13_SATA_SATA_PHY_5_SS_DISABLED
			|IOMUXC_GPR13_SATA_SATA_PHY_4_ATTEN_9_16
			|IOMUXC_GPR13_SATA_PHY_3_TXBOOST_0P00_DB
			|IOMUXC_GPR13_SATA_PHY_2_TX_1P104V
			|IOMUXC_GPR13_SATA_PHY_1_SLOW);

	return 0;
}
Beispiel #4
0
static inline int gpt_has_clk_source_osc(void)
{
#if defined(CONFIG_MX6)
	if (((is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) &&
	     (is_soc_rev(CHIP_REV_1_0) > 0)) || is_cpu_type(MXC_CPU_MX6DL) ||
	      is_cpu_type(MXC_CPU_MX6SOLO) || is_cpu_type(MXC_CPU_MX6SX))
		return 1;

	return 0;
#else
	return 0;
#endif
}
Beispiel #5
0
static void spl_dram_init(void)
{
	if (is_cpu_type(MXC_CPU_MX6SOLO)) {
		mx6sdl_dram_iocfg(32, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs);
		mx6_dram_cfg(&mem_s, &mx6s_512m_mmdc_calib, &h5tq2g63dfr);
	} else if (is_cpu_type(MXC_CPU_MX6DL)) {
		mx6sdl_dram_iocfg(64, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs);
		mx6_dram_cfg(&mem_dl, &mx6dl_1g_mmdc_calib, &h5tq2g63dfr);
	} else if (is_cpu_type(MXC_CPU_MX6Q)) {
		mx6dq_dram_iocfg(64, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs);
		mx6_dram_cfg(&mem_q, &mx6q_2g_mmdc_calib, &h5t04g63afr);
	}

	udelay(100);
}
static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
						uint32_t page_oob_size)
{
	int ecc_strength;
	int max_ecc_strength_supported;

	/* Refer to Chapter 17 for i.MX6DQ, Chapter 18 for i.MX6SX */
	if (is_cpu_type(MXC_CPU_MX6SX))
		max_ecc_strength_supported = 62;
	else
		max_ecc_strength_supported = 40;

	/*
	 * Determine the ECC layout with the formula:
	 *	ECC bits per chunk = (total page spare data bits) /
	 *		(bits per ECC level) / (chunks per page)
	 * where:
	 *	total page spare data bits =
	 *		(page oob size - meta data size) * (bits per byte)
	 */
	ecc_strength = ((page_oob_size - MXS_NAND_METADATA_SIZE) * 8)
			/ (galois_field *
			   mxs_nand_ecc_chunk_cnt(page_data_size));

	return min(round_down(ecc_strength, 2), max_ecc_strength_supported);
}
static void i2c_setup_iomux(void)
{
    if (is_cpu_type(MXC_CPU_MX6Q))
        setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6q_i2c_pad_info0);
    else
        setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6dl_i2c_pad_info0);
}
static u32 mxc_get_pll_pfd(enum pll_clocks pll, int pfd_num)
{
	u32 div;
	u64 freq;

	switch (pll) {
	case PLL_BUS:
		if (!is_cpu_type(MXC_CPU_MX6UL)) {
			if (pfd_num == 3) {
				/* No PFD3 on PPL2 */
				return 0;
			}
		}
		div = __raw_readl(&imx_ccm->analog_pfd_528);
		freq = (u64)decode_pll(PLL_BUS, MXC_HCLK);
		break;
	case PLL_USBOTG:
		div = __raw_readl(&imx_ccm->analog_pfd_480);
		freq = (u64)decode_pll(PLL_USBOTG, MXC_HCLK);
		break;
	default:
		/* No PFD on other PLL					     */
		return 0;
	}

	return lldiv(freq * 18, (div & ANATOP_PFD_FRAC_MASK(pfd_num)) >>
			      ANATOP_PFD_FRAC_SHIFT(pfd_num));
}
Beispiel #9
0
void dram_init_banksize(void)
{
	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
	gd->bd->bi_dram[1].start = PHYS_SDRAM_2;

	switch (gd->ram_size) {
	case 0x10000000: /* DDR_16BIT_256MB */
		gd->bd->bi_dram[0].size = 0x10000000;
		gd->bd->bi_dram[1].size = 0;
		break;
	case 0x20000000: /* DDR_32BIT_512MB */
		gd->bd->bi_dram[0].size = 0x20000000;
		gd->bd->bi_dram[1].size = 0;
		break;
	case 0x40000000:
		if (is_cpu_type(MXC_CPU_MX6SOLO)) { /* DDR_32BIT_1GB */
			gd->bd->bi_dram[0].size = 0x20000000;
			gd->bd->bi_dram[1].size = 0x20000000;
		} else { /* DDR_64BIT_1GB */
			gd->bd->bi_dram[0].size = 0x40000000;
			gd->bd->bi_dram[1].size = 0;
		}
		break;
	case 0x80000000: /* DDR_64BIT_2GB */
		gd->bd->bi_dram[0].size = 0x40000000;
		gd->bd->bi_dram[1].size = 0x40000000;
		break;
	case 0xEFF00000: /* DDR_64BIT_4GB */
		gd->bd->bi_dram[0].size = 0x70000000;
		gd->bd->bi_dram[1].size = 0x7FF00000;
		break;
	}
}
Beispiel #10
0
int checkboard(void)
{
	printf("Model: Toradex Colibri iMX7%c\n",
	       is_cpu_type(MXC_CPU_MX7D) ? 'D' : 'S');

	return 0;
}
Beispiel #11
0
int board_late_init(void)
{
#ifdef CONFIG_CMD_BMODE
	add_board_boot_modes(board_boot_modes);
#endif

#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
	setenv("board_name", "SABRESD");

	if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
		setenv("board_rev", "MX6Q");
	else if (is_cpu_type(MXC_CPU_MX6DL) || is_cpu_type(MXC_CPU_MX6SOLO))
		setenv("board_rev", "MX6DL");
#endif

	return 0;
}
Beispiel #12
0
int checkboard(void)
{
	if (is_cpu_type(MXC_CPU_MX6Q))
		puts("Board: Udoo Quad\n");
	else
		puts("Board: Udoo DualLite\n");

	return 0;
}
Beispiel #13
0
int board_late_init(void)
{
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
	if (is_cpu_type(MXC_CPU_MX6Q))
		env_set("board_rev", "MX6Q");
	else
		env_set("board_rev", "MX6DL");
#endif
	return 0;
}
Beispiel #14
0
int board_init(void)
{
	/* address of boot parameters */
	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;

#ifdef CONFIG_SATA
	if (is_cpu_type(MXC_CPU_MX6Q))
		setup_sata();
#endif
	return 0;
}
Beispiel #15
0
static void spl_dram_init(void)
{
	if (is_cpu_type(MXC_CPU_MX6DL)) {
		mt41k128m16jt_125.mem_speed = 800;
		mem_qdl.rtt_nom = 1;
		mem_qdl.rtt_wr = 1;

		mx6sdl_dram_iocfg(64, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs);
		mx6_dram_cfg(&mem_qdl, &mx6dl_1g_mmdc_calib, &mt41k128m16jt_125);
	} else if (is_cpu_type(MXC_CPU_MX6Q)) {
		mt41k128m16jt_125.mem_speed = 1066;
		mem_qdl.rtt_nom = 2;
		mem_qdl.rtt_wr = 2;

		mx6dq_dram_iocfg(64, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs);
		mx6_dram_cfg(&mem_qdl, &mx6q_1g_mmdc_calib, &mt41k128m16jt_125);
	}

	udelay(100);
}
Beispiel #16
0
void setup_ventana_i2c(void)
{
	if (is_cpu_type(MXC_CPU_MX6Q)) {
		setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6q_i2c_pad_info0);
		setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6q_i2c_pad_info1);
		setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6q_i2c_pad_info2);
	} else {
		setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6dl_i2c_pad_info0);
		setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6dl_i2c_pad_info1);
		setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6dl_i2c_pad_info2);
	}
}
Beispiel #17
0
int board_early_init_f(void)
{
	setup_iomux_uart();
#if defined(CONFIG_VIDEO_IPUV3)
	setup_display();
#endif
#ifdef CONFIG_CMD_SATA
	/* Only mx6q wandboard has SATA */
	if (is_cpu_type(MXC_CPU_MX6Q))
		setup_sata();
#endif

	return 0;
}
void enable_uart_clk(unsigned char enable)
{
	u32 mask;

	if (is_cpu_type(MXC_CPU_MX6UL))
		mask = MXC_CCM_CCGR5_UART_MASK;
	else
		mask = MXC_CCM_CCGR5_UART_MASK | MXC_CCM_CCGR5_UART_SERIAL_MASK;

	if (enable)
		setbits_le32(&imx_ccm->CCGR5, mask);
	else
		clrbits_le32(&imx_ccm->CCGR5, mask);
}
void enable_enet_clk(unsigned char enable)
{
	u32 mask, *addr;

	if (is_cpu_type(MXC_CPU_MX6UL)) {
		mask = MXC_CCM_CCGR3_ENET_MASK;
		addr = &imx_ccm->CCGR3;
	} else {
		mask = MXC_CCM_CCGR1_ENET_MASK;
		addr = &imx_ccm->CCGR1;
	}

	if (enable)
		setbits_le32(addr, mask);
	else
		clrbits_le32(addr, mask);
}
Beispiel #20
0
int board_ehci_hcd_init(int port)
{
	switch (port) {
	case 0:
		break;
	case 1:
		if (is_cpu_type(MXC_CPU_MX7S))
			return -ENODEV;

		imx_iomux_v3_setup_multiple_pads(usb_otg2_pads,
						 ARRAY_SIZE(usb_otg2_pads));
		break;
	default:
		return -EINVAL;
	}
	return 0;
}
Beispiel #21
0
int checkboard(void)
{
	char it[] = " IT";
	int minc, maxc;

	switch (get_cpu_temp_grade(&minc, &maxc)) {
	case TEMP_AUTOMOTIVE:
	case TEMP_INDUSTRIAL:
		break;
	case TEMP_EXTCOMMERCIAL:
	default:
		it[0] = 0;
	};
	printf("Model: Toradex Apalis iMX6 %s %s%s\n",
	       is_cpu_type(MXC_CPU_MX6D) ? "Dual" : "Quad",
	       (gd->ram_size == 0x80000000) ? "2GB" :
	       (gd->ram_size == 0x40000000) ? "1GB" : "512MB", it);
	return 0;
}
Beispiel #22
0
void spl_board_init(void)
{
#if 0
	int i;
	u32 const *regs ;
	int num_regs;
	unsigned char mac_address[6];
        imx_get_mac_from_fuse(0,mac_address);
	printf("ethaddr: %pM\n", mac_address);

	if (is_cpu_type(MXC_CPU_MX6Q)) {
#if 1
		regs = mx6q_1g;
		num_regs = ARRAY_SIZE(mx6q_1g);
#else
		regs = mx6q_2g;
		num_regs = ARRAY_SIZE(mx6q_2g);
#endif
	} else {
#if CONFIG_DDR_MB == 512
		regs = mx6dl_512m;
		num_regs = ARRAY_SIZE(mx6dl_512m);
printf("Configuring for 512MiB narrow memory bus\n");
#elif CONFIG_DDR_MB == 1024
		regs = mx6dl_1gn;
		num_regs = ARRAY_SIZE(mx6dl_1gn);
printf("Configuring for 1GiB narrow memory bus\n");
#elif CONFIG_DDR_MB == 2048
		regs = mx6dl_2g;
		num_regs = ARRAY_SIZE(mx6dl_2g);
printf("Configuring for 2GiB wide memory bus\n");
#endif
	}
	for (i=0; i < num_regs; i+=2) {
		writel(regs[i+1],regs[i]);
	}
        dram_init();
#endif
	printf("%s\n", __func__);
}
Beispiel #23
0
void mx6_dram_cfg(const struct mx6_ddr_sysinfo *i,
                  const struct mx6_mmdc_calibration *c,
                  const struct mx6_ddr3_cfg *m)
{
    volatile struct mmdc_p_regs *mmdc0;
    volatile struct mmdc_p_regs *mmdc1;
    u32 reg;
    u8 tcke, tcksrx, tcksre, txpdll, taofpd, taonpd, trrd;
    u8 todtlon, taxpd, tanpd, tcwl, txp, tfaw, tcl;
    u8 todt_idle_off = 0x4; /* from DDR3 Script Aid spreadsheet */
    u16 trcd, trc, tras, twr, tmrd, trtp, trp, twtr, trfc, txs, txpr;
    u16 CS0_END;
    u16 tdllk = 0x1ff; /* DLL locking time: 512 cycles (JEDEC DDR3) */
    u8 coladdr;
    int clkper; /* clock period in picoseconds */
    int clock; /* clock freq in mHz */
    int cs;

    mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
    mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR;

    /* MX6D/MX6Q: 1066 MHz memory clock, clkper = 1.894ns = 1894ps */
    if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) {
        clock = 528;
        tcwl = 4;
    }
    /* MX6S/MX6DL: 800 MHz memory clock, clkper = 2.5ns = 2500ps */
    else {
        clock = 400;
        tcwl = 3;
    }
    clkper = (1000*1000)/clock; /* ps */
    todtlon = tcwl;
    taxpd = tcwl;
    tanpd = tcwl;
    tcwl = tcwl;

    switch (m->density) {
    case 1: /* 1Gb per chip */
        trfc = DIV_ROUND_UP(110000, clkper) - 1;
        txs = DIV_ROUND_UP(120000, clkper) - 1;
        break;
    case 2: /* 2Gb per chip */
        trfc = DIV_ROUND_UP(160000, clkper) - 1;
        txs = DIV_ROUND_UP(170000, clkper) - 1;
        break;
    case 4: /* 4Gb per chip */
        trfc = DIV_ROUND_UP(260000, clkper) - 1;
        txs = DIV_ROUND_UP(270000, clkper) - 1;
        break;
    case 8: /* 8Gb per chip */
        trfc = DIV_ROUND_UP(350000, clkper) - 1;
        txs = DIV_ROUND_UP(360000, clkper) - 1;
        break;
    default:
        /* invalid density */
        printf("invalid chip density\n");
        hang();
        break;
    }
    txpr = txs;

    switch (m->mem_speed) {
    case 800:
        txp = DIV_ROUND_UP(MAX(3*clkper, 7500), clkper) - 1;
        tcke = DIV_ROUND_UP(MAX(3*clkper, 7500), clkper) - 1;
        if (m->pagesz == 1) {
            tfaw = DIV_ROUND_UP(40000, clkper) - 1;
            trrd = DIV_ROUND_UP(MAX(4*clkper, 10000), clkper) - 1;
        } else {
            tfaw = DIV_ROUND_UP(50000, clkper) - 1;
            trrd = DIV_ROUND_UP(MAX(4*clkper, 10000), clkper) - 1;
        }
        break;
    case 1066:
        txp = DIV_ROUND_UP(MAX(3*clkper, 7500), clkper) - 1;
        tcke = DIV_ROUND_UP(MAX(3*clkper, 5625), clkper) - 1;
        if (m->pagesz == 1) {
            tfaw = DIV_ROUND_UP(37500, clkper) - 1;
            trrd = DIV_ROUND_UP(MAX(4*clkper, 7500), clkper) - 1;
        } else {
            tfaw = DIV_ROUND_UP(50000, clkper) - 1;
            trrd = DIV_ROUND_UP(MAX(4*clkper, 10000), clkper) - 1;
        }
        break;
    case 1333:
        txp = DIV_ROUND_UP(MAX(3*clkper, 6000), clkper) - 1;
        tcke = DIV_ROUND_UP(MAX(3*clkper, 5625), clkper) - 1;
        if (m->pagesz == 1) {
            tfaw = DIV_ROUND_UP(30000, clkper) - 1;
            trrd = DIV_ROUND_UP(MAX(4*clkper, 6000), clkper) - 1;
        } else {
            tfaw = DIV_ROUND_UP(45000, clkper) - 1;
            trrd = DIV_ROUND_UP(MAX(4*clkper, 7500), clkper) - 1;
        }
        break;
    case 1600:
        txp = DIV_ROUND_UP(MAX(3*clkper, 6000), clkper) - 1;
        tcke = DIV_ROUND_UP(MAX(3*clkper, 5000), clkper) - 1;
        if (m->pagesz == 1) {
            tfaw = DIV_ROUND_UP(30000, clkper) - 1;
            trrd = DIV_ROUND_UP(MAX(4*clkper, 6000), clkper) - 1;
        } else {
            tfaw = DIV_ROUND_UP(40000, clkper) - 1;
            trrd = DIV_ROUND_UP(MAX(4*clkper, 7500), clkper) - 1;
        }
        break;
    default:
        printf("invalid memory speed\n");
        hang();
        break;
    }
    txpdll = DIV_ROUND_UP(MAX(10*clkper, 24000), clkper) - 1;
    tcl = DIV_ROUND_UP(m->trcd, clkper/10) - 3;
    tcksre = DIV_ROUND_UP(MAX(5*clkper, 10000), clkper);
    tcksrx = tcksre;
    taonpd = DIV_ROUND_UP(2000, clkper) - 1;
    taofpd = taonpd;
    trp = DIV_ROUND_UP(m->trcd, clkper/10) - 1;
    trcd = trp;
    trc = DIV_ROUND_UP(m->trcmin, clkper/10) - 1;
    tras = DIV_ROUND_UP(m->trasmin, clkper/10) - 1;
    twr = DIV_ROUND_UP(15000, clkper) - 1;
    tmrd = DIV_ROUND_UP(MAX(12*clkper, 15000), clkper) - 1;
    twtr = ROUND(MAX(4*clkper, 7500)/clkper, 1) - 1;
    trtp = twtr;
    CS0_END = ((4*i->cs_density) <= 120) ? (4*i->cs_density)+7 : 127;
    debug("density:%d Gb (%d Gb per chip)\n", i->cs_density, m->density);
    debug("clock: %dMHz (%d ps)\n", clock, clkper);
    debug("memspd:%d\n", m->mem_speed);
    debug("tcke=%d\n", tcke);
    debug("tcksrx=%d\n", tcksrx);
    debug("tcksre=%d\n", tcksre);
    debug("taofpd=%d\n", taofpd);
    debug("taonpd=%d\n", taonpd);
    debug("todtlon=%d\n", todtlon);
    debug("tanpd=%d\n", tanpd);
    debug("taxpd=%d\n", taxpd);
    debug("trfc=%d\n", trfc);
    debug("txs=%d\n", txs);
    debug("txp=%d\n", txp);
    debug("txpdll=%d\n", txpdll);
    debug("tfaw=%d\n", tfaw);
    debug("tcl=%d\n", tcl);
    debug("trcd=%d\n", trcd);
    debug("trp=%d\n", trp);
    debug("trc=%d\n", trc);
    debug("tras=%d\n", tras);
    debug("twr=%d\n", twr);
    debug("tmrd=%d\n", tmrd);
    debug("tcwl=%d\n", tcwl);
    debug("tdllk=%d\n", tdllk);
    debug("trtp=%d\n", trtp);
    debug("twtr=%d\n", twtr);
    debug("trrd=%d\n", trrd);
    debug("txpr=%d\n", txpr);
    debug("CS0_END=%d\n", CS0_END);
    debug("ncs=%d\n", i->ncs);
    debug("Rtt_wr=%d\n", i->rtt_wr);
    debug("Rtt_nom=%d\n", i->rtt_nom);
    debug("SRT=%d\n", m->SRT);
    debug("tcl=%d\n", tcl);
    debug("twr=%d\n", twr);

    /*
     * board-specific configuration:
     *  These values are determined empirically and vary per board layout
     *  see:
     *   appnote, ddr3 spreadsheet
     */
    mmdc0->mpwldectrl0 = c->p0_mpwldectrl0;
    mmdc0->mpwldectrl1 = c->p0_mpwldectrl1;
    mmdc0->mpdgctrl0 = c->p0_mpdgctrl0;
    mmdc0->mpdgctrl1 = c->p0_mpdgctrl1;
    mmdc0->mprddlctl = c->p0_mprddlctl;
    mmdc0->mpwrdlctl = c->p0_mpwrdlctl;
    if (i->dsize > 1) {
        mmdc1->mpwldectrl0 = c->p1_mpwldectrl0;
        mmdc1->mpwldectrl1 = c->p1_mpwldectrl1;
        mmdc1->mpdgctrl0 = c->p1_mpdgctrl0;
        mmdc1->mpdgctrl1 = c->p1_mpdgctrl1;
        mmdc1->mprddlctl = c->p1_mprddlctl;
        mmdc1->mpwrdlctl = c->p1_mpwrdlctl;
    }

    /* Read data DQ Byte0-3 delay */
    mmdc0->mprddqby0dl = (u32)0x33333333;
    mmdc0->mprddqby1dl = (u32)0x33333333;
    if (i->dsize > 0) {
        mmdc0->mprddqby2dl = (u32)0x33333333;
        mmdc0->mprddqby3dl = (u32)0x33333333;
    }
    if (i->dsize > 1) {
        mmdc1->mprddqby0dl = (u32)0x33333333;
        mmdc1->mprddqby1dl = (u32)0x33333333;
        mmdc1->mprddqby2dl = (u32)0x33333333;
        mmdc1->mprddqby3dl = (u32)0x33333333;
    }

    /* MMDC Termination: rtt_nom:2 RZQ/2(120ohm), rtt_nom:1 RZQ/4(60ohm) */
    reg = (i->rtt_nom == 2) ? 0x00011117 : 0x00022227;
    mmdc0->mpodtctrl = reg;
    if (i->dsize > 1)
        mmdc1->mpodtctrl = reg;

    /* complete calibration */
    reg = (1 << 11); /* Force measurement on delay-lines */
    mmdc0->mpmur0 = reg;
    if (i->dsize > 1)
        mmdc1->mpmur0 = reg;

    /* Step 1: configuration request */
    mmdc0->mdscr = (u32)(1 << 15); /* config request */

    /* Step 2: Timing configuration */
    reg = (trfc << 24) | (txs << 16) | (txp << 13) | (txpdll << 9) |
          (tfaw << 4) | tcl;
    mmdc0->mdcfg0 = reg;
    reg = (trcd << 29) | (trp << 26) | (trc << 21) | (tras << 16) |
          (1 << 15) |		/* trpa */
          (twr << 9) | (tmrd << 5) | tcwl;
    mmdc0->mdcfg1 = reg;
    reg = (tdllk << 16) | (trtp << 6) | (twtr << 3) | trrd;
    mmdc0->mdcfg2 = reg;
    reg = (taofpd << 27) | (taonpd << 24) | (tanpd << 20) | (taxpd << 16) |
          (todtlon << 12) | (todt_idle_off << 4);
    mmdc0->mdotc = reg;
    mmdc0->mdasp = CS0_END; /* CS addressing */

    /* Step 3: Configure DDR type */
    reg = (i->cs1_mirror << 19) | (i->walat << 16) | (i->bi_on << 12) |
          (i->mif3_mode << 9) | (i->ralat << 6);
    mmdc0->mdmisc = reg;

    /* Step 4: Configure delay while leaving reset */
    reg = (txpr << 16) | (i->sde_to_rst << 8) | (i->rst_to_cke << 0);
    mmdc0->mdor = reg;

    /* Step 5: Configure DDR physical parameters (density and burst len) */
    coladdr = m->coladdr;
    if (m->coladdr == 8)		/* 8-bit COL is 0x3 */
        coladdr += 4;
    else if (m->coladdr == 12)	/* 12-bit COL is 0x4 */
        coladdr += 1;
    reg = (m->rowaddr - 11) << 24 |		/* ROW */
          (coladdr - 9) << 20 |		/* COL */
          (1 << 19) |			/* Burst Length = 8 for DDR3 */
          (i->dsize << 16);			/* DDR data bus size */
    mmdc0->mdctl = reg;

    /* Step 6: Perform ZQ calibration */
    reg = (u32)0xa1390001; /* one-time HW ZQ calib */
    mmdc0->mpzqhwctrl = reg;
    if (i->dsize > 1)
        mmdc1->mpzqhwctrl = reg;

    /* Step 7: Enable MMDC with desired chip select */
    reg = mmdc0->mdctl |
          (1 << 31) |			/* SDE_0 for CS0 */
          ((i->ncs == 2) ? 1 : 0) << 30;	/* SDE_1 for CS1 */
    mmdc0->mdctl = reg;

    /* Step 8: Write Mode Registers to Init DDR3 devices */
    for (cs = 0; cs < i->ncs; cs++) {
        /* MR2 */
        reg = (i->rtt_wr & 3) << 9 | (m->SRT & 1) << 7 |
              ((tcwl - 3) & 3) << 3;
        mmdc0->mdscr = (u32)MR(reg, 2, 3, cs);
        /* MR3 */
        mmdc0->mdscr = (u32)MR(0, 3, 3, cs);
        /* MR1 */
        reg = ((i->rtt_nom & 1) ? 1 : 0) << 2 |
              ((i->rtt_nom & 2) ? 1 : 0) << 6;
        mmdc0->mdscr = (u32)MR(reg, 1, 3, cs);
        reg = ((tcl - 1) << 4) |	/* CAS */
              (1 << 8)   |		/* DLL Reset */
              ((twr - 3) << 9);		/* Write Recovery */
        /* MR0 */
        mmdc0->mdscr = (u32)MR(reg, 0, 3, cs);
        /* ZQ calibration */
        reg = (1 << 10);
        mmdc0->mdscr = (u32)MR(reg, 0, 4, cs);
    }

    /* Step 10: Power down control and self-refresh */
    reg = (tcke & 0x7) << 16 |
          5            << 12 |  /* PWDT_1: 256 cycles */
          5            <<  8 |  /* PWDT_0: 256 cycles */
          1            <<  6 |  /* BOTH_CS_PD */
          (tcksrx & 0x7) << 3 |
          (tcksre & 0x7);
    mmdc0->mdpdc = reg;
    mmdc0->mapsr = (u32)0x00011006; /* ADOPT power down enabled */

    /* Step 11: Configure ZQ calibration: one-time and periodic 1ms */
    mmdc0->mpzqhwctrl = (u32)0xa1390003;
    if (i->dsize > 1)
        mmdc1->mpzqhwctrl = (u32)0xa1390003;

    /* Step 12: Configure and activate periodic refresh */
    reg = (1 << 14) |	/* REF_SEL: Periodic refresh cycles of 32kHz */
          (7 << 11);	/* REFR: Refresh Rate - 8 refreshes */
    mmdc0->mdref = reg;

    /* Step 13: Deassert config request - init complete */
    mmdc0->mdscr = (u32)0x00000000;

    /* wait for auto-ZQ calibration to complete */
    mdelay(1);
}
Beispiel #24
0
static void spl_dram_init(int width, int size_mb, int board_model)
{
	struct mx6_ddr3_cfg *mem = NULL;
	struct mx6_mmdc_calibration *calib = NULL;
	struct mx6_ddr_sysinfo sysinfo = {
		/* width of data bus:0=16,1=32,2=64 */
		.dsize = width/32,
		/* config for full 4GB range so that get_mem_size() works */
		.cs_density = 32, /* 32Gb per CS */
		/* single chip select */
		.ncs = 1,
		.cs1_mirror = 0,
		.rtt_wr = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Wr = RZQ/4 */
#ifdef RTT_NOM_120OHM
		.rtt_nom = 2 /*DDR3_RTT_120_OHM*/,	/* RTT_Nom = RZQ/2 */
#else
		.rtt_nom = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Nom = RZQ/4 */
#endif
		.walat = 1,	/* Write additional latency */
		.ralat = 5,	/* Read additional latency */
		.mif3_mode = 3,	/* Command prediction working mode */
		.bi_on = 1,	/* Bank interleaving enabled */
		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
		.pd_fast_exit = 1, /* enable precharge power-down fast exit */
		.ddr_type = DDR_TYPE_DDR3,
	};

	/*
	 * MMDC Calibration requires the following data:
	 *   mx6_mmdc_calibration - board-specific calibration (routing delays)
	 *      these calibration values depend on board routing, SoC, and DDR
	 *   mx6_ddr_sysinfo - board-specific memory architecture (width/cs/etc)
	 *   mx6_ddr_cfg - chip specific timing/layout details
	 */
	if (width == 16 && size_mb == 128) {
		mem = &mt41k64m16jt_125;
		if (is_cpu_type(MXC_CPU_MX6Q))
			;
		else
			calib = &mx6sdl_64x16_mmdc_calib;
		debug("1gB density\n");
	} else if (width == 16 && size_mb == 256) {
		/* 1x 2Gb density chip - same calib as 2x 2Gb */
		mem = &mt41k128m16jt_125;
		if (is_cpu_type(MXC_CPU_MX6Q))
			calib = &mx6dq_128x32_mmdc_calib;
		else
			calib = &mx6sdl_128x32_mmdc_calib;
		debug("2gB density\n");
	} else if (width == 16 && size_mb == 512) {
		mem = &mt41k256m16ha_125;
		if (is_cpu_type(MXC_CPU_MX6Q))
			calib = &mx6dq_256x16_mmdc_calib;
		else
			calib = &mx6sdl_256x16_mmdc_calib;
		debug("4gB density\n");
	} else if (width == 32 && size_mb == 256) {
		/* Same calib as width==16, size==128 */
		mem = &mt41k64m16jt_125;
		if (is_cpu_type(MXC_CPU_MX6Q))
			;
		else
			calib = &mx6sdl_64x16_mmdc_calib;
		debug("1gB density\n");
	} else if (width == 32 && size_mb == 512) {
		mem = &mt41k128m16jt_125;
		if (is_cpu_type(MXC_CPU_MX6Q))
			calib = &mx6dq_128x32_mmdc_calib;
		else
			calib = &mx6sdl_128x32_mmdc_calib;
		debug("2gB density\n");
	}  else if (width == 32 && size_mb == 1024) {
		mem = &mt41k256m16ha_125;
		if (is_cpu_type(MXC_CPU_MX6Q))
			calib = &mx6dq_256x32_mmdc_calib;
		else
			calib = &mx6sdl_256x32_mmdc_calib;
		debug("4gB density\n");
	} else if (width == 64 && size_mb == 512) {
		mem = &mt41k64m16jt_125;
		debug("1gB density\n");
	} else if (width == 64 && size_mb == 1024) {
		mem = &mt41k128m16jt_125;
		if (is_cpu_type(MXC_CPU_MX6Q))
			calib = &mx6dq_128x64_mmdc_calib;
		else
			calib = &mx6sdl_128x64_mmdc_calib;
		debug("2gB density\n");
	} else if (width == 64 && size_mb == 2048) {
		mem = &mt41k256m16ha_125;
		if (is_cpu_type(MXC_CPU_MX6Q))
			calib = &mx6dq_256x64_mmdc_calib;
		debug("4gB density\n");
	}

	if (!(mem && calib)) {
		puts("Error: Invalid Calibration/Board Configuration\n");
		printf("MEM    : %s\n", mem ? "OKAY" : "NULL");
		printf("CALIB  : %s\n", calib ? "OKAY" : "NULL");
		printf("CPUTYPE: %s\n",
		       is_cpu_type(MXC_CPU_MX6Q) ? "IMX6Q" : "IMX6DL");
		printf("SIZE_MB: %d\n", size_mb);
		printf("WIDTH  : %d\n", width);
		hang();
	}

	if (is_cpu_type(MXC_CPU_MX6Q))
		mx6dq_dram_iocfg(width, &mx6dq_ddr_ioregs,
				 &mx6dq_grp_ioregs);
	else
		mx6sdl_dram_iocfg(width, &mx6sdl_ddr_ioregs,
				  &mx6sdl_grp_ioregs);
	mx6_dram_cfg(&sysinfo, calib, mem);
}

static void ccgr_init(void)
{
	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;

	writel(0x00C03F3F, &ccm->CCGR0);
	writel(0x0030FC03, &ccm->CCGR1);
	writel(0x0FFFC000, &ccm->CCGR2);
	writel(0x3FF00000, &ccm->CCGR3);
	writel(0xFFFFF300, &ccm->CCGR4);	/* enable NAND/GPMI/BCH clks */
	writel(0x0F0000C3, &ccm->CCGR5);
	writel(0x000003FF, &ccm->CCGR6);
}

static void gpr_init(void)
{
	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;

	/* enable AXI cache for VDOA/VPU/IPU */
	writel(0xF00000CF, &iomux->gpr[4]);
	/* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
	writel(0x007F007F, &iomux->gpr[6]);
	writel(0x007F007F, &iomux->gpr[7]);
}

/*
 * called from C runtime startup code (arch/arm/lib/crt0.S:_main)
 * - we have a stack and a place to store GD, both in SRAM
 * - no variable global data is available
 */
void board_init_f(ulong dummy)
{
	struct ventana_board_info ventana_info;
	int board_model;

	/* setup clock gating */
	ccgr_init();

	/* setup AIPS and disable watchdog */
	arch_cpu_init();

	/* setup AXI */
	gpr_init();

	/* iomux and setup of i2c */
	setup_iomux_uart();
	setup_ventana_i2c();

	/* setup GP timer */
	timer_init();

	/* UART clocks enabled and gd valid - init serial console */
	preloader_console_init();

	/* read/validate EEPROM info to determine board model and SDRAM cfg */
	board_model = read_eeprom(CONFIG_I2C_GSC, &ventana_info);

	/* configure model-specific gpio */
	setup_iomux_gpio(board_model, &ventana_info);

	/* provide some some default: 32bit 128MB */
	if (GW_UNKNOWN == board_model)
		hang();

	/* configure MMDC for SDRAM width/size and per-model calibration */
	spl_dram_init(8 << ventana_info.sdram_width,
		      16 << ventana_info.sdram_size,
		      board_model);

	/* Clear the BSS. */
	memset(__bss_start, 0, __bss_end - __bss_start);

	/* disable boot watchdog */
	gsc_boot_wd_disable();
}

/* called from board_init_r after gd setup if CONFIG_SPL_BOARD_INIT defined */
/* its our chance to print info about boot device */
void spl_board_init(void)
{
	/* determine boot device from SRC_SBMR1 (BOOT_CFG[4:1]) or SRC_GPR9 */
	u32 boot_device = spl_boot_device();

	switch (boot_device) {
	case BOOT_DEVICE_MMC1:
		puts("Booting from MMC\n");
		break;
	case BOOT_DEVICE_NAND:
		puts("Booting from NAND\n");
		break;
	case BOOT_DEVICE_SATA:
		puts("Booting from SATA\n");
		break;
	default:
		puts("Unknown boot device\n");
	}

	/* PMIC init */
	setup_pmic();
}
Beispiel #25
0
uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size)
{
    uint32_t load_addr = 0;
    size_t bytes;
    ptrdiff_t ivt_offset = 0;
    int result = 0;
    ulong start;
    hab_rvt_authenticate_image_t *hab_rvt_authenticate_image;
    hab_rvt_entry_t *hab_rvt_entry;
    hab_rvt_exit_t *hab_rvt_exit;

    hab_rvt_authenticate_image = hab_rvt_authenticate_image_p;
    hab_rvt_entry = hab_rvt_entry_p;
    hab_rvt_exit = hab_rvt_exit_p;

    if (is_hab_enabled()) {
        printf("\nAuthenticate image from DDR location 0x%x...\n",
               ddr_start);

        hab_caam_clock_enable(1);

        if (hab_rvt_entry() == HAB_SUCCESS) {
            /* If not already aligned, Align to ALIGN_SIZE */
            ivt_offset = (image_size + ALIGN_SIZE - 1) &
                         ~(ALIGN_SIZE - 1);

            start = ddr_start;
            bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
#ifdef DEBUG
            printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n",
                   ivt_offset, ddr_start + ivt_offset);
            puts("Dumping IVT\n");
            print_buffer(ddr_start + ivt_offset,
                         (void *)(ddr_start + ivt_offset),
                         4, 0x8, 0);

            puts("Dumping CSF Header\n");
            print_buffer(ddr_start + ivt_offset+IVT_SIZE,
                         (void *)(ddr_start + ivt_offset+IVT_SIZE),
                         4, 0x10, 0);

            get_hab_status();

            puts("\nCalling authenticate_image in ROM\n");
            printf("\tivt_offset = 0x%x\n", ivt_offset);
            printf("\tstart = 0x%08lx\n", start);
            printf("\tbytes = 0x%x\n", bytes);
#endif
            /*
             * If the MMU is enabled, we have to notify the ROM
             * code, or it won't flush the caches when needed.
             * This is done, by setting the "pu_irom_mmu_enabled"
             * word to 1. You can find its address by looking in
             * the ROM map. This is critical for
             * authenticate_image(). If MMU is enabled, without
             * setting this bit, authentication will fail and may
             * crash.
             */
            /* Check MMU enabled */
            if (get_cr() & CR_M) {
                if (is_cpu_type(MXC_CPU_MX6Q) ||
                        is_cpu_type(MXC_CPU_MX6D)) {
                    /*
                     * This won't work on Rev 1.0.0 of
                     * i.MX6Q/D, since their ROM doesn't
                     * do cache flushes. don't think any
                     * exist, so we ignore them.
                     */
                    if (!is_mx6dqp())
                        writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
                } else if (is_cpu_type(MXC_CPU_MX6DL) ||
                           is_cpu_type(MXC_CPU_MX6SOLO)) {
                    writel(1, MX6DLS_PU_IROM_MMU_EN_VAR);
                } else if (is_cpu_type(MXC_CPU_MX6SL)) {
                    writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
                }
            }

            load_addr = (uint32_t)hab_rvt_authenticate_image(
                            HAB_CID_UBOOT,
                            ivt_offset, (void **)&start,
                            (size_t *)&bytes, NULL);
            if (hab_rvt_exit() != HAB_SUCCESS) {
                puts("hab exit function fail\n");
                load_addr = 0;
            }
        } else {
            puts("hab entry function fail\n");
        }

        hab_caam_clock_enable(0);

        get_hab_status();
    } else {
        puts("hab fuse not enabled\n");
    }

    if ((!is_hab_enabled()) || (load_addr != 0))
        result = 1;

    return result;
}
Beispiel #26
0
int __cpuinit mt_smp_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
    unsigned long timeout;

    pr_crit("[AT]Boot slave CPU\n");

    atomic_inc(&hotplug_cpu_count);
    pr_crit("[AT11]Boot slave CPU %d\n",cpu);
    /*
     * Set synchronisation state between this boot processor
     * and the secondary one
     */
    spin_lock(&boot_lock);
    pr_crit("mt_smp_boot_secondary, cpu: %d\n", cpu);
    HOTPLUG_INFO("mt_smp_boot_secondary, cpu: %d\n", cpu);
    /*
     * The secondary processor is waiting to be released from
     * the holding pen - release it, then wait for it to flag
     * that it has been released by resetting pen_release.
     *
     * Note that "pen_release" is the hardware CPU ID, whereas
     * "cpu" is Linux's internal ID.
     */
    /*
     * This is really belt and braces; we hold unintended secondary
     * CPUs in the holding pen until we're ready for them.  However,
     * since we haven't sent them a soft interrupt, they shouldn't
     * be there.
     */
    write_pen_release(cpu);

#if defined(CONFIG_TRUSTONIC_TEE_SUPPORT)
    if(cpu >=1 && cpu <=3)
        mt_secure_call(MC_FC_SET_RESET_VECTOR, virt_to_phys(mt_secondary_startup), cpu, 0);
#else
    mt_smp_set_boot_addr(virt_to_phys(mt_secondary_startup), cpu);
#endif

    switch(cpu)
    {
    case 1:
#ifdef CONFIG_MTK_FPGA
        mt_reg_sync_writel(SLAVE1_MAGIC_NUM, SLAVE1_MAGIC_REG);
        HOTPLUG_INFO("SLAVE1_MAGIC_NUM:%x\n", SLAVE1_MAGIC_NUM);
#endif
        spm_mtcmos_ctrl_cpu1(STA_POWER_ON, 1);
        break;
    case 2:
#ifdef CONFIG_MTK_FPGA
        mt_reg_sync_writel(SLAVE2_MAGIC_NUM, SLAVE2_MAGIC_REG);
        HOTPLUG_INFO("SLAVE2_MAGIC_NUM:%x\n", SLAVE2_MAGIC_NUM);
#endif
        spm_mtcmos_ctrl_cpu2(STA_POWER_ON, 1);
        break;
    case 3:
#ifdef CONFIG_MTK_FPGA
        mt_reg_sync_writel(SLAVE3_MAGIC_NUM, SLAVE3_MAGIC_REG);
        HOTPLUG_INFO("SLAVE3_MAGIC_NUM:%x\n", SLAVE3_MAGIC_NUM);
#endif
        spm_mtcmos_ctrl_cpu3(STA_POWER_ON, 1);
        break;
    default:
        break;

    }

    //smp_cross_call(cpumask_of(cpu));

    /*
     * Now the secondary core is starting up let it run its
     * calibrations, then wait for it to finish
     */
    spin_unlock(&boot_lock);

    timeout = jiffies + (1 * HZ);
    while (time_before(jiffies, timeout)) {
        smp_rmb();
        if (pen_release == -1)
            break;

        udelay(1000);
    }

    if (pen_release == -1)
    {
#if 0
        //FIXME: update to the right register names
        pr_emerg("SPM_CA7_CPU0_PWR_CON: 0x%08x\n", REG_READ(SPM_CA7_CPU0_PWR_CON));
        pr_emerg("SPM_CA7_CPU1_PWR_CON: 0x%08x\n", REG_READ(SPM_CA7_CPU1_PWR_CON));
        pr_emerg("SPM_CA7_CPU2_PWR_CON: 0x%08x\n", REG_READ(SPM_CA7_CPU2_PWR_CON));
        pr_emerg("SPM_CA7_CPU3_PWR_CON: 0x%08x\n", REG_READ(SPM_CA7_CPU3_PWR_CON));
        pr_emerg("SPM_CA7_DBG_PWR_CON: 0x%08x\n", REG_READ(SPM_CA7_DBG_PWR_CON));
        pr_emerg("SPM_CA7_CPUTOP_PWR_CON: 0x%08x\n", REG_READ(SPM_CA7_CPUTOP_PWR_CON));
        pr_emerg("SPM_CA15_CPU0_PWR_CON: 0x%08x\n", REG_READ(SPM_CA15_CPU0_PWR_CON));
        pr_emerg("SPM_CA15_CPU1_PWR_CON: 0x%08x\n", REG_READ(SPM_CA15_CPU1_PWR_CON));
        pr_emerg("SPM_CA15_CPU2_PWR_CON: 0x%08x\n", REG_READ(SPM_CA15_CPU2_PWR_CON));
        pr_emerg("SPM_CA15_CPU3_PWR_CON: 0x%08x\n", REG_READ(SPM_CA15_CPU3_PWR_CON));
        pr_emerg("SPM_CA15_CPUTOP_PWR_CON: 0x%08x\n", REG_READ(SPM_CA15_CPUTOP_PWR_CON));
#endif
        return 0;
    }
    else
    {
#if 0
        //FIXME: how k2 debug monitor
        if (is_cpu_type(CA7_TYPEID))
        {
            //write back stage pc on ca7
            mt_reg_sync_writel(cpu + 8, DBG_MON_CTL);
            pr_emerg("CPU%u, DBG_MON_CTL: 0x%08x, DBG_MON_DATA: 0x%08x\n", cpu, *(volatile u32 *)(DBG_MON_CTL), *(volatile u32 *)(DBG_MON_DATA));
        }
        else
        {
            //decode statge pc on ca15l
            mt_reg_sync_writel(3+ (cpu - 4) * 4, CA15L_MON_SEL);
            pr_emerg("CPU%u, CA15L_MON_SEL: 0x%08x, CA15L_MON: 0x%08x\n", cpu, *(volatile u32 *)(CA15L_MON_SEL), *(volatile u32 *)(CA15L_MON));
        }
#endif

        on_each_cpu((smp_call_func_t)dump_stack, NULL, 0);
        atomic_dec(&hotplug_cpu_count);
        return -ENOSYS;
    }
}
Beispiel #27
0
void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
		  const struct mx6_mmdc_calibration *calib,
		  const struct mx6_ddr3_cfg *ddr3_cfg)
{
	volatile struct mmdc_p_regs *mmdc0;
#ifndef CONFIG_MX6SX
	volatile struct mmdc_p_regs *mmdc1;
#endif
	u32 val;
	u8 tcke, tcksrx, tcksre, txpdll, taofpd, taonpd, trrd;
	u8 todtlon, taxpd, tanpd, tcwl, txp, tfaw, tcl;
	u8 todt_idle_off = 0x4; /* from DDR3 Script Aid spreadsheet */
	u16 trcd, trc, tras, twr, tmrd, trtp, trp, twtr, trfc, txs, txpr;
	u16 cs0_end;
	u16 tdllk = 0x1ff; /* DLL locking time: 512 cycles (JEDEC DDR3) */
	u8 coladdr;
	int clkper; /* clock period in picoseconds */
	int clock; /* clock freq in MHz */
	int cs;
	u16 mem_speed = ddr3_cfg->mem_speed;

	mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
#ifndef CONFIG_MX6SX
	mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR;
#endif

	/* Limit mem_speed for MX6D/MX6Q */
	if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) {
		if (mem_speed > 1066)
			mem_speed = 1066; /* 1066 MT/s */

		tcwl = 4;
	}
	/* Limit mem_speed for MX6S/MX6DL */
	else {
		if (mem_speed > 800)
			mem_speed = 800;  /* 800 MT/s */

		tcwl = 3;
	}

	clock = mem_speed / 2;
	/*
	 * Data rate of 1066 MT/s requires 533 MHz DDR3 clock, but MX6D/Q supports
	 * up to 528 MHz, so reduce the clock to fit chip specs
	 */
	if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) {
		if (clock > 528)
			clock = 528; /* 528 MHz */
	}

	clkper = (1000 * 1000) / clock; /* pico seconds */
	todtlon = tcwl;
	taxpd = tcwl;
	tanpd = tcwl;

	switch (ddr3_cfg->density) {
	case 1: /* 1Gb per chip */
		trfc = DIV_ROUND_UP(110000, clkper) - 1;
		txs = DIV_ROUND_UP(120000, clkper) - 1;
		break;
	case 2: /* 2Gb per chip */
		trfc = DIV_ROUND_UP(160000, clkper) - 1;
		txs = DIV_ROUND_UP(170000, clkper) - 1;
		break;
	case 4: /* 4Gb per chip */
		trfc = DIV_ROUND_UP(260000, clkper) - 1;
		txs = DIV_ROUND_UP(270000, clkper) - 1;
		break;
	case 8: /* 8Gb per chip */
		trfc = DIV_ROUND_UP(350000, clkper) - 1;
		txs = DIV_ROUND_UP(360000, clkper) - 1;
		break;
	default:
		/* invalid density */
		puts("invalid chip density\n");
		hang();
		break;
	}
	txpr = txs;

	switch (mem_speed) {
	case 800:
		txp = DIV_ROUND_UP(max(3 * clkper, 7500), clkper) - 1;
		tcke = DIV_ROUND_UP(max(3 * clkper, 7500), clkper) - 1;
		if (ddr3_cfg->pagesz == 1) {
			tfaw = DIV_ROUND_UP(40000, clkper) - 1;
			trrd = DIV_ROUND_UP(max(4 * clkper, 10000), clkper) - 1;
		} else {
			tfaw = DIV_ROUND_UP(50000, clkper) - 1;
			trrd = DIV_ROUND_UP(max(4 * clkper, 10000), clkper) - 1;
		}
		break;
	case 1066:
		txp = DIV_ROUND_UP(max(3 * clkper, 7500), clkper) - 1;
		tcke = DIV_ROUND_UP(max(3 * clkper, 5625), clkper) - 1;
		if (ddr3_cfg->pagesz == 1) {
			tfaw = DIV_ROUND_UP(37500, clkper) - 1;
			trrd = DIV_ROUND_UP(max(4 * clkper, 7500), clkper) - 1;
		} else {
			tfaw = DIV_ROUND_UP(50000, clkper) - 1;
			trrd = DIV_ROUND_UP(max(4 * clkper, 10000), clkper) - 1;
		}
		break;
	default:
		puts("invalid memory speed\n");
		hang();
		break;
	}
	txpdll = DIV_ROUND_UP(max(10 * clkper, 24000), clkper) - 1;
	tcksre = DIV_ROUND_UP(max(5 * clkper, 10000), clkper);
	taonpd = DIV_ROUND_UP(2000, clkper) - 1;
	tcksrx = tcksre;
	taofpd = taonpd;
	twr  = DIV_ROUND_UP(15000, clkper) - 1;
	tmrd = DIV_ROUND_UP(max(12 * clkper, 15000), clkper) - 1;
	trc  = DIV_ROUND_UP(ddr3_cfg->trcmin, clkper / 10) - 1;
	tras = DIV_ROUND_UP(ddr3_cfg->trasmin, clkper / 10) - 1;
	tcl  = DIV_ROUND_UP(ddr3_cfg->trcd, clkper / 10) - 3;
	trp  = DIV_ROUND_UP(ddr3_cfg->trcd, clkper / 10) - 1;
	twtr = ROUND(max(4 * clkper, 7500) / clkper, 1) - 1;
	trcd = trp;
	trtp = twtr;
	cs0_end = 4 * sysinfo->cs_density - 1;

	debug("density:%d Gb (%d Gb per chip)\n",
	      sysinfo->cs_density, ddr3_cfg->density);
	debug("clock: %dMHz (%d ps)\n", clock, clkper);
	debug("memspd:%d\n", mem_speed);
	debug("tcke=%d\n", tcke);
	debug("tcksrx=%d\n", tcksrx);
	debug("tcksre=%d\n", tcksre);
	debug("taofpd=%d\n", taofpd);
	debug("taonpd=%d\n", taonpd);
	debug("todtlon=%d\n", todtlon);
	debug("tanpd=%d\n", tanpd);
	debug("taxpd=%d\n", taxpd);
	debug("trfc=%d\n", trfc);
	debug("txs=%d\n", txs);
	debug("txp=%d\n", txp);
	debug("txpdll=%d\n", txpdll);
	debug("tfaw=%d\n", tfaw);
	debug("tcl=%d\n", tcl);
	debug("trcd=%d\n", trcd);
	debug("trp=%d\n", trp);
	debug("trc=%d\n", trc);
	debug("tras=%d\n", tras);
	debug("twr=%d\n", twr);
	debug("tmrd=%d\n", tmrd);
	debug("tcwl=%d\n", tcwl);
	debug("tdllk=%d\n", tdllk);
	debug("trtp=%d\n", trtp);
	debug("twtr=%d\n", twtr);
	debug("trrd=%d\n", trrd);
	debug("txpr=%d\n", txpr);
	debug("cs0_end=%d\n", cs0_end);
	debug("ncs=%d\n", sysinfo->ncs);
	debug("Rtt_wr=%d\n", sysinfo->rtt_wr);
	debug("Rtt_nom=%d\n", sysinfo->rtt_nom);
	debug("SRT=%d\n", ddr3_cfg->SRT);
	debug("tcl=%d\n", tcl);
	debug("twr=%d\n", twr);

	/*
	 * board-specific configuration:
	 *  These values are determined empirically and vary per board layout
	 *  see:
	 *   appnote, ddr3 spreadsheet
	 */
	mmdc0->mpwldectrl0 = calib->p0_mpwldectrl0;
	mmdc0->mpwldectrl1 = calib->p0_mpwldectrl1;
	mmdc0->mpdgctrl0 = calib->p0_mpdgctrl0;
	mmdc0->mpdgctrl1 = calib->p0_mpdgctrl1;
	mmdc0->mprddlctl = calib->p0_mprddlctl;
	mmdc0->mpwrdlctl = calib->p0_mpwrdlctl;
	if (sysinfo->dsize > 1) {
		MMDC1(mpwldectrl0, calib->p1_mpwldectrl0);
		MMDC1(mpwldectrl1, calib->p1_mpwldectrl1);
		MMDC1(mpdgctrl0, calib->p1_mpdgctrl0);
		MMDC1(mpdgctrl1, calib->p1_mpdgctrl1);
		MMDC1(mprddlctl, calib->p1_mprddlctl);
		MMDC1(mpwrdlctl, calib->p1_mpwrdlctl);
	}

	/* Read data DQ Byte0-3 delay */
	mmdc0->mprddqby0dl = 0x33333333;
	mmdc0->mprddqby1dl = 0x33333333;
	if (sysinfo->dsize > 0) {
		mmdc0->mprddqby2dl = 0x33333333;
		mmdc0->mprddqby3dl = 0x33333333;
	}

	if (sysinfo->dsize > 1) {
		MMDC1(mprddqby0dl, 0x33333333);
		MMDC1(mprddqby1dl, 0x33333333);
		MMDC1(mprddqby2dl, 0x33333333);
		MMDC1(mprddqby3dl, 0x33333333);
	}

	/* MMDC Termination: rtt_nom:2 RZQ/2(120ohm), rtt_nom:1 RZQ/4(60ohm) */
	val = (sysinfo->rtt_nom == 2) ? 0x00011117 : 0x00022227;
	mmdc0->mpodtctrl = val;
	if (sysinfo->dsize > 1)
		MMDC1(mpodtctrl, val);

	/* complete calibration */
	val = (1 << 11); /* Force measurement on delay-lines */
	mmdc0->mpmur0 = val;
	if (sysinfo->dsize > 1)
		MMDC1(mpmur0, val);

	/* Step 1: configuration request */
	mmdc0->mdscr = (u32)(1 << 15); /* config request */

	/* Step 2: Timing configuration */
	mmdc0->mdcfg0 = (trfc << 24) | (txs << 16) | (txp << 13) |
			(txpdll << 9) | (tfaw << 4) | tcl;
	mmdc0->mdcfg1 = (trcd << 29) | (trp << 26) | (trc << 21) |
			(tras << 16) | (1 << 15) /* trpa */ |
			(twr << 9) | (tmrd << 5) | tcwl;
	mmdc0->mdcfg2 = (tdllk << 16) | (trtp << 6) | (twtr << 3) | trrd;
	mmdc0->mdotc = (taofpd << 27) | (taonpd << 24) | (tanpd << 20) |
		       (taxpd << 16) | (todtlon << 12) | (todt_idle_off << 4);
	mmdc0->mdasp = cs0_end; /* CS addressing */

	/* Step 3: Configure DDR type */
	mmdc0->mdmisc = (sysinfo->cs1_mirror << 19) | (sysinfo->walat << 16) |
			(sysinfo->bi_on << 12) | (sysinfo->mif3_mode << 9) |
			(sysinfo->ralat << 6);

	/* Step 4: Configure delay while leaving reset */
	mmdc0->mdor = (txpr << 16) | (sysinfo->sde_to_rst << 8) |
		      (sysinfo->rst_to_cke << 0);

	/* Step 5: Configure DDR physical parameters (density and burst len) */
	coladdr = ddr3_cfg->coladdr;
	if (ddr3_cfg->coladdr == 8)		/* 8-bit COL is 0x3 */
		coladdr += 4;
	else if (ddr3_cfg->coladdr == 12)	/* 12-bit COL is 0x4 */
		coladdr += 1;
	mmdc0->mdctl =  (ddr3_cfg->rowaddr - 11) << 24 |	/* ROW */
			(coladdr - 9) << 20 |			/* COL */
			(1 << 19) |		/* Burst Length = 8 for DDR3 */
			(sysinfo->dsize << 16);		/* DDR data bus size */

	/* Step 6: Perform ZQ calibration */
	val = 0xa1390001; /* one-time HW ZQ calib */
	mmdc0->mpzqhwctrl = val;
	if (sysinfo->dsize > 1)
		MMDC1(mpzqhwctrl, val);

	/* Step 7: Enable MMDC with desired chip select */
	mmdc0->mdctl |= (1 << 31) |			     /* SDE_0 for CS0 */
			((sysinfo->ncs == 2) ? 1 : 0) << 30; /* SDE_1 for CS1 */

	/* Step 8: Write Mode Registers to Init DDR3 devices */
	for (cs = 0; cs < sysinfo->ncs; cs++) {
		/* MR2 */
		val = (sysinfo->rtt_wr & 3) << 9 | (ddr3_cfg->SRT & 1) << 7 |
		      ((tcwl - 3) & 3) << 3;
		debug("MR2 CS%d: 0x%08x\n", cs, (u32)MR(val, 2, 3, cs));
		mmdc0->mdscr = MR(val, 2, 3, cs);
		/* MR3 */
		debug("MR3 CS%d: 0x%08x\n", cs, (u32)MR(0, 3, 3, cs));
		mmdc0->mdscr = MR(0, 3, 3, cs);
		/* MR1 */
		val = ((sysinfo->rtt_nom & 1) ? 1 : 0) << 2 |
		      ((sysinfo->rtt_nom & 2) ? 1 : 0) << 6;
		debug("MR1 CS%d: 0x%08x\n", cs, (u32)MR(val, 1, 3, cs));
		mmdc0->mdscr = MR(val, 1, 3, cs);
		/* MR0 */
		val = ((tcl - 1) << 4) |	/* CAS */
		      (1 << 8)   |		/* DLL Reset */
		      ((twr - 3) << 9) |	/* Write Recovery */
		      (sysinfo->pd_fast_exit << 12); /* Precharge PD PLL on */
		debug("MR0 CS%d: 0x%08x\n", cs, (u32)MR(val, 0, 3, cs));
		mmdc0->mdscr = MR(val, 0, 3, cs);
		/* ZQ calibration */
		val = (1 << 10);
		mmdc0->mdscr = MR(val, 0, 4, cs);
	}

	/* Step 10: Power down control and self-refresh */
	mmdc0->mdpdc = (tcke & 0x7) << 16 |
			5            << 12 |  /* PWDT_1: 256 cycles */
			5            <<  8 |  /* PWDT_0: 256 cycles */
			1            <<  6 |  /* BOTH_CS_PD */
			(tcksrx & 0x7) << 3 |
			(tcksre & 0x7);
	if (!sysinfo->pd_fast_exit)
		mmdc0->mdpdc |= (1 << 7); /* SLOW_PD */
	mmdc0->mapsr = 0x00001006; /* ADOPT power down enabled */

	/* Step 11: Configure ZQ calibration: one-time and periodic 1ms */
	val = 0xa1390003;
	mmdc0->mpzqhwctrl = val;
	if (sysinfo->dsize > 1)
		MMDC1(mpzqhwctrl, val);

	/* Step 12: Configure and activate periodic refresh */
	mmdc0->mdref = (1 << 14) | /* REF_SEL: Periodic refresh cycle: 32kHz */
		       (7 << 11);  /* REFR: Refresh Rate - 8 refreshes */

	/* Step 13: Deassert config request - init complete */
	mmdc0->mdscr = 0x00000000;

	/* wait for auto-ZQ calibration to complete */
	mdelay(1);
}
Beispiel #28
0
/* setup GPIO pinmux and default configuration per baseboard and env */
void setup_board_gpio(int board, struct ventana_board_info *info)
{
	const char *s;
	char arg[10];
	size_t len;
	int i;
	int quiet = simple_strtol(getenv("quiet"), NULL, 10);

	if (board >= GW_UNKNOWN)
		return;

	/* RS232_EN# */
	if (gpio_cfg[board].rs232_en) {
		gpio_direction_output(gpio_cfg[board].rs232_en,
				      (hwconfig("rs232")) ? 0 : 1);
	}

	/* MSATA Enable */
	if (gpio_cfg[board].msata_en && is_cpu_type(MXC_CPU_MX6Q)) {
		gpio_direction_output(GP_MSATA_SEL,
				      (hwconfig("msata")) ? 1 : 0);
	}

	/* USBOTG Select (PCISKT or FrontPanel) */
	if (gpio_cfg[board].usb_sel) {
		gpio_direction_output(gpio_cfg[board].usb_sel,
				      (hwconfig("usb_pcisel")) ? 1 : 0);
	}

	/*
	 * Configure DIO pinmux/padctl registers
	 * see IMX6DQRM/IMX6SDLRM IOMUXC_SW_PAD_CTL_PAD_* register definitions
	 */
	for (i = 0; i < gpio_cfg[board].dio_num; i++) {
		struct dio_cfg *cfg = &gpio_cfg[board].dio_cfg[i];
		iomux_v3_cfg_t ctrl = DIO_PAD_CFG;
		unsigned cputype = is_cpu_type(MXC_CPU_MX6Q) ? 0 : 1;

		if (!cfg->gpio_padmux[0] && !cfg->gpio_padmux[1])
			continue;
		sprintf(arg, "dio%d", i);
		if (!hwconfig(arg))
			continue;
		s = hwconfig_subarg(arg, "padctrl", &len);
		if (s) {
			ctrl = MUX_PAD_CTRL(simple_strtoul(s, NULL, 16)
					    & 0x1ffff) | MUX_MODE_SION;
		}
		if (hwconfig_subarg_cmp(arg, "mode", "gpio")) {
			if (!quiet) {
				printf("DIO%d:  GPIO%d_IO%02d (gpio-%d)\n", i,
				       (cfg->gpio_param/32)+1,
				       cfg->gpio_param%32,
				       cfg->gpio_param);
			}
			imx_iomux_v3_setup_pad(cfg->gpio_padmux[cputype] |
					       ctrl);
			gpio_requestf(cfg->gpio_param, "dio%d", i);
			gpio_direction_input(cfg->gpio_param);
		} else if (hwconfig_subarg_cmp(arg, "mode", "pwm") &&
			   cfg->pwm_padmux) {
			if (!cfg->pwm_param) {
				printf("DIO%d:  Error: pwm config invalid\n",
					i);
				continue;
			}
			if (!quiet)
				printf("DIO%d:  pwm%d\n", i, cfg->pwm_param);
			imx_iomux_v3_setup_pad(cfg->pwm_padmux[cputype] |
					       MUX_PAD_CTRL(ctrl));
		}
	}

	if (!quiet) {
		if (gpio_cfg[board].msata_en && is_cpu_type(MXC_CPU_MX6Q)) {
			printf("MSATA: %s\n", (hwconfig("msata") ?
			       "enabled" : "disabled"));
		}
		if (gpio_cfg[board].rs232_en) {
			printf("RS232: %s\n", (hwconfig("rs232")) ?
			       "enabled" : "disabled");
		}
	}
}
static void spl_dram_init(int width, int size, int board_model)
{
    struct mx6_ddr3_cfg *mem = &mt41k128m16jt_125;
    struct mx6_mmdc_calibration *calib;
    struct mx6_ddr_sysinfo sysinfo = {
        /* width of data bus:0=16,1=32,2=64 */
        .dsize = width/32,
        /* config for full 4GB range so that get_mem_size() works */
        .cs_density = 32, /* 32Gb per CS */
        /* single chip select */
        .ncs = 1,
        .cs1_mirror = 0,
        .rtt_wr = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Wr = RZQ/4 */
#ifdef RTT_NOM_120OHM
        .rtt_nom = 2 /*DDR3_RTT_120_OHM*/,	/* RTT_Nom = RZQ/2 */
#else
        .rtt_nom = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Nom = RZQ/4 */
#endif
        .walat = 1,	/* Write additional latency */
        .ralat = 5,	/* Read additional latency */
        .mif3_mode = 3,	/* Command prediction working mode */
        .bi_on = 1,	/* Bank interleaving enabled */
        .sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
        .rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
    };

    /*
     * MMDC Calibration requires the following data:
     *   mx6_mmdc_calibration - board-specific calibration (routing delays)
     *   mx6_ddr_sysinfo - board-specific memory architecture (width/cs/etc)
     *   mx6_ddr_cfg - chip specific timing/layout details
     */
    switch (board_model) {
    default:
    case GW51xx:
        if (is_cpu_type(MXC_CPU_MX6Q))
            calib = &gw51xxq_mmdc_calib;
        else
            calib = &gw51xxdl_mmdc_calib;
        break;
    case GW52xx:
        calib = &gw52xxdl_mmdc_calib;
        break;
    case GW53xx:
        if (is_cpu_type(MXC_CPU_MX6Q))
            calib = &gw53xxq_mmdc_calib;
        else
            calib = &gw53xxdl_mmdc_calib;
        break;
    case GW54xx:
        calib = &gw54xxq_mmdc_calib;
        break;
    }

    if (is_cpu_type(MXC_CPU_MX6Q))
        mx6dq_dram_iocfg(width, &mx6dq_ddr_ioregs,
                         &mx6dq_grp_ioregs);
    else
        mx6sdl_dram_iocfg(width, &mx6sdl_ddr_ioregs,
                          &mx6sdl_grp_ioregs);
    mx6_dram_cfg(&sysinfo, calib, mem);
}

/*
 * called from C runtime startup code (arch/arm/lib/crt0.S:_main)
 * - we have a stack and a place to store GD, both in SRAM
 * - no variable global data is available
 */
void board_init_f(ulong dummy)
{
    struct ventana_board_info ventana_info;
    int board_model;

    /*
     * Zero out global data:
     *  - this shoudl be done by crt0.S
     *  - failure to zero it will cause i2c_setup to fail
     */
    memset((void *)gd, 0, sizeof(struct global_data));

    /* setup AIPS and disable watchdog */
    arch_cpu_init();

    /* iomux and setup of i2c */
    board_early_init_f();
    i2c_setup_iomux();

    /* setup GP timer */
    timer_init();

    /* UART clocks enabled and gd valid - init serial console */
    preloader_console_init();

    /* read/validate EEPROM info to determine board model and SDRAM cfg */
    board_model = read_eeprom(I2C_GSC, &ventana_info);

    /* provide some some default: 32bit 128MB */
    if (GW_UNKNOWN == board_model) {
        ventana_info.sdram_width = 2;
        ventana_info.sdram_size = 3;
    }

    /* configure MMDC for SDRAM width/size and per-model calibration */
    spl_dram_init(8 << ventana_info.sdram_width,
                  16 << ventana_info.sdram_size,
                  board_model);

    /* Clear the BSS. */
    memset(__bss_start, 0, __bss_end - __bss_start);

    /* load/boot image from boot device */
    board_init_r(NULL, 0);
}

void reset_cpu(ulong addr)
{
}
Beispiel #30
0
/*
 * This section requires the differentiation between Solidrun mx6 boards, but
 * for now, it will configure only for the mx6dual hummingboard version.
 */
static void spl_dram_init(int width)
{
	struct mx6_ddr_sysinfo sysinfo = {
		/* width of data bus: 0=16, 1=32, 2=64 */
		.dsize = width / 32,
		/* config for full 4GB range so that get_mem_size() works */
		.cs_density = 32,	/* 32Gb per CS */
		.ncs = 1,		/* single chip select */
		.cs1_mirror = 0,
		.rtt_wr = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Wr = RZQ/4 */
		.rtt_nom = 1 /*DDR3_RTT_60_OHM*/,	/* RTT_Nom = RZQ/4 */
		.walat = 1,	/* Write additional latency */
		.ralat = 5,	/* Read additional latency */
		.mif3_mode = 3,	/* Command prediction working mode */
		.bi_on = 1,	/* Bank interleaving enabled */
		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
	};

	if (is_cpu_type(MXC_CPU_MX6D) || is_cpu_type(MXC_CPU_MX6Q))
		mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs);
	else
		mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs);

	if (is_cpu_type(MXC_CPU_MX6D))
		mx6_dram_cfg(&sysinfo, &mx6q_1g_mmcd_calib, &mem_ddr_2g);
	else if (is_cpu_type(MXC_CPU_MX6Q))
		mx6_dram_cfg(&sysinfo, &mx6q_2g_mmcd_calib, &mem_ddr_4g);
	else if (is_cpu_type(MXC_CPU_MX6DL))
		mx6_dram_cfg(&sysinfo, &mx6q_1g_mmcd_calib, &mem_ddr_2g);
	else if (is_cpu_type(MXC_CPU_MX6SOLO))
		mx6_dram_cfg(&sysinfo, &mx6dl_512m_mmcd_calib, &mem_ddr_2g);
}

void board_init_f(ulong dummy)
{
	/* setup AIPS and disable watchdog */
	arch_cpu_init();

	ccgr_init();
	gpr_init();

	/* iomux and setup of i2c */
	board_early_init_f();

	/* setup GP timer */
	timer_init();

	/* UART clocks enabled and gd valid - init serial console */
	preloader_console_init();

	/* DDR initialization */
	if (is_cpu_type(MXC_CPU_MX6SOLO))
		spl_dram_init(32);
	else
		spl_dram_init(64);

	/* Clear the BSS. */
	memset(__bss_start, 0, __bss_end - __bss_start);

	/* load/boot image from boot device */
	board_init_r(NULL, 0);
}