xref: /rk3399_rockchip-uboot/arch/arm/cpu/arm926ejs/spear/spl.c (revision 9730bcdc2f6c237fde66b7d81681e380ef0bdedf)
14ae8bc43SStefan Roese /*
24ae8bc43SStefan Roese  * Copyright (C) 2011
34ae8bc43SStefan Roese  * Heiko Schocher, DENX Software Engineering, hs@denx.de.
44ae8bc43SStefan Roese  *
54ae8bc43SStefan Roese  * Copyright (C) 2012 Stefan Roese <sr@denx.de>
64ae8bc43SStefan Roese  *
71a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
84ae8bc43SStefan Roese  */
94ae8bc43SStefan Roese 
104ae8bc43SStefan Roese #include <common.h>
112fbdbda1SStefan Roese #include <spl.h>
124ae8bc43SStefan Roese #include <version.h>
134ae8bc43SStefan Roese #include <asm/io.h>
144ae8bc43SStefan Roese #include <asm/arch/hardware.h>
154ae8bc43SStefan Roese #include <asm/arch/spr_defs.h>
164ae8bc43SStefan Roese #include <asm/arch/spr_misc.h>
174ae8bc43SStefan Roese #include <asm/arch/spr_syscntl.h>
182fbdbda1SStefan Roese #include <linux/mtd/st_smi.h>
194ae8bc43SStefan Roese 
ddr_clock_init(void)204ae8bc43SStefan Roese static void ddr_clock_init(void)
214ae8bc43SStefan Roese {
224ae8bc43SStefan Roese 	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
234ae8bc43SStefan Roese 	u32 clkenb, ddrpll;
244ae8bc43SStefan Roese 
254ae8bc43SStefan Roese 	clkenb = readl(&misc_p->periph1_clken);
264ae8bc43SStefan Roese 	clkenb &= ~PERIPH_MPMCMSK;
274ae8bc43SStefan Roese 	clkenb |= PERIPH_MPMC_WE;
284ae8bc43SStefan Roese 
294ae8bc43SStefan Roese 	/* Intentionally done twice */
304ae8bc43SStefan Roese 	writel(clkenb, &misc_p->periph1_clken);
314ae8bc43SStefan Roese 	writel(clkenb, &misc_p->periph1_clken);
324ae8bc43SStefan Roese 
334ae8bc43SStefan Roese 	ddrpll = readl(&misc_p->pll_ctr_reg);
344ae8bc43SStefan Roese 	ddrpll &= ~MEM_CLK_SEL_MSK;
354ae8bc43SStefan Roese #if (CONFIG_DDR_HCLK)
364ae8bc43SStefan Roese 	ddrpll |= MEM_CLK_HCLK;
374ae8bc43SStefan Roese #elif (CONFIG_DDR_2HCLK)
384ae8bc43SStefan Roese 	ddrpll |= MEM_CLK_2HCLK;
394ae8bc43SStefan Roese #elif (CONFIG_DDR_PLL2)
404ae8bc43SStefan Roese 	ddrpll |= MEM_CLK_PLL2;
414ae8bc43SStefan Roese #else
424ae8bc43SStefan Roese #error "please define one of CONFIG_DDR_(HCLK|2HCLK|PLL2)"
434ae8bc43SStefan Roese #endif
444ae8bc43SStefan Roese 	writel(ddrpll, &misc_p->pll_ctr_reg);
454ae8bc43SStefan Roese 
464ae8bc43SStefan Roese 	writel(readl(&misc_p->periph1_clken) | PERIPH_MPMC_EN,
474ae8bc43SStefan Roese 			&misc_p->periph1_clken);
484ae8bc43SStefan Roese }
494ae8bc43SStefan Roese 
mpmc_init_values(void)504ae8bc43SStefan Roese static void mpmc_init_values(void)
514ae8bc43SStefan Roese {
524ae8bc43SStefan Roese 	u32 i;
534ae8bc43SStefan Roese 	u32 *mpmc_reg_p = (u32 *)CONFIG_SPEAR_MPMCBASE;
544ae8bc43SStefan Roese 	u32 *mpmc_val_p = &mpmc_conf_vals[0];
554ae8bc43SStefan Roese 
564ae8bc43SStefan Roese 	for (i = 0; i < CONFIG_SPEAR_MPMCREGS; i++, mpmc_reg_p++, mpmc_val_p++)
574ae8bc43SStefan Roese 		writel(*mpmc_val_p, mpmc_reg_p);
584ae8bc43SStefan Roese 
594ae8bc43SStefan Roese 	mpmc_reg_p = (u32 *)CONFIG_SPEAR_MPMCBASE;
604ae8bc43SStefan Roese 
614ae8bc43SStefan Roese 	/*
624ae8bc43SStefan Roese 	 * MPMC controller start
634ae8bc43SStefan Roese 	 * MPMC waiting for DLLLOCKREG high
644ae8bc43SStefan Roese 	 */
654ae8bc43SStefan Roese 	writel(0x01000100, &mpmc_reg_p[7]);
664ae8bc43SStefan Roese 
674ae8bc43SStefan Roese 	while (!(readl(&mpmc_reg_p[3]) & 0x10000))
684ae8bc43SStefan Roese 		;
694ae8bc43SStefan Roese }
704ae8bc43SStefan Roese 
mpmc_init(void)714ae8bc43SStefan Roese static void mpmc_init(void)
724ae8bc43SStefan Roese {
734ae8bc43SStefan Roese 	/* Clock related settings for DDR */
744ae8bc43SStefan Roese 	ddr_clock_init();
754ae8bc43SStefan Roese 
764ae8bc43SStefan Roese 	/*
774ae8bc43SStefan Roese 	 * DDR pad register bits are different for different SoCs
784ae8bc43SStefan Roese 	 * Compensation values are also handled separately
794ae8bc43SStefan Roese 	 */
804ae8bc43SStefan Roese 	plat_ddr_init();
814ae8bc43SStefan Roese 
824ae8bc43SStefan Roese 	/* Initialize mpmc register values */
834ae8bc43SStefan Roese 	mpmc_init_values();
844ae8bc43SStefan Roese }
854ae8bc43SStefan Roese 
pll_init(void)864ae8bc43SStefan Roese static void pll_init(void)
874ae8bc43SStefan Roese {
884ae8bc43SStefan Roese 	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
894ae8bc43SStefan Roese 
904ae8bc43SStefan Roese 	/* Initialize PLLs */
914ae8bc43SStefan Roese 	writel(FREQ_332, &misc_p->pll1_frq);
924ae8bc43SStefan Roese 	writel(0x1C0A, &misc_p->pll1_cntl);
934ae8bc43SStefan Roese 	writel(0x1C0E, &misc_p->pll1_cntl);
944ae8bc43SStefan Roese 	writel(0x1C06, &misc_p->pll1_cntl);
954ae8bc43SStefan Roese 	writel(0x1C0E, &misc_p->pll1_cntl);
964ae8bc43SStefan Roese 
974ae8bc43SStefan Roese 	writel(FREQ_332, &misc_p->pll2_frq);
984ae8bc43SStefan Roese 	writel(0x1C0A, &misc_p->pll2_cntl);
994ae8bc43SStefan Roese 	writel(0x1C0E, &misc_p->pll2_cntl);
1004ae8bc43SStefan Roese 	writel(0x1C06, &misc_p->pll2_cntl);
1014ae8bc43SStefan Roese 	writel(0x1C0E, &misc_p->pll2_cntl);
1024ae8bc43SStefan Roese 
1034ae8bc43SStefan Roese 	/* wait for pll locks */
1044ae8bc43SStefan Roese 	while (!(readl(&misc_p->pll1_cntl) & 0x1))
1054ae8bc43SStefan Roese 		;
1064ae8bc43SStefan Roese 	while (!(readl(&misc_p->pll2_cntl) & 0x1))
1074ae8bc43SStefan Roese 		;
1084ae8bc43SStefan Roese }
1094ae8bc43SStefan Roese 
mac_init(void)1104ae8bc43SStefan Roese static void mac_init(void)
1114ae8bc43SStefan Roese {
1124ae8bc43SStefan Roese 	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
1134ae8bc43SStefan Roese 
1144ae8bc43SStefan Roese 	writel(readl(&misc_p->periph1_clken) & (~PERIPH_GMAC),
1154ae8bc43SStefan Roese 			&misc_p->periph1_clken);
1164ae8bc43SStefan Roese 
1174ae8bc43SStefan Roese 	writel(SYNTH23, &misc_p->gmac_synth_clk);
1184ae8bc43SStefan Roese 
1194ae8bc43SStefan Roese 	switch (get_socrev()) {
1204ae8bc43SStefan Roese 	case SOC_SPEAR600_AA:
1214ae8bc43SStefan Roese 	case SOC_SPEAR600_AB:
1224ae8bc43SStefan Roese 	case SOC_SPEAR600_BA:
1234ae8bc43SStefan Roese 	case SOC_SPEAR600_BB:
1244ae8bc43SStefan Roese 	case SOC_SPEAR600_BC:
1254ae8bc43SStefan Roese 	case SOC_SPEAR600_BD:
1264ae8bc43SStefan Roese 		writel(0x0, &misc_p->gmac_ctr_reg);
1274ae8bc43SStefan Roese 		break;
1284ae8bc43SStefan Roese 
1294ae8bc43SStefan Roese 	case SOC_SPEAR300:
1304ae8bc43SStefan Roese 	case SOC_SPEAR310:
1314ae8bc43SStefan Roese 	case SOC_SPEAR320:
1324ae8bc43SStefan Roese 		writel(0x4, &misc_p->gmac_ctr_reg);
1334ae8bc43SStefan Roese 		break;
1344ae8bc43SStefan Roese 	}
1354ae8bc43SStefan Roese 
1364ae8bc43SStefan Roese 	writel(readl(&misc_p->periph1_clken) | PERIPH_GMAC,
1374ae8bc43SStefan Roese 			&misc_p->periph1_clken);
1384ae8bc43SStefan Roese 
1394ae8bc43SStefan Roese 	writel(readl(&misc_p->periph1_rst) | PERIPH_GMAC,
1404ae8bc43SStefan Roese 			&misc_p->periph1_rst);
1414ae8bc43SStefan Roese 	writel(readl(&misc_p->periph1_rst) & (~PERIPH_GMAC),
1424ae8bc43SStefan Roese 			&misc_p->periph1_rst);
1434ae8bc43SStefan Roese }
1444ae8bc43SStefan Roese 
sys_init(void)1454ae8bc43SStefan Roese static void sys_init(void)
1464ae8bc43SStefan Roese {
1474ae8bc43SStefan Roese 	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
1484ae8bc43SStefan Roese 	struct syscntl_regs *syscntl_p =
1494ae8bc43SStefan Roese 		(struct syscntl_regs *)CONFIG_SPEAR_SYSCNTLBASE;
1504ae8bc43SStefan Roese 
1514ae8bc43SStefan Roese 	/* Set system state to SLOW */
1524ae8bc43SStefan Roese 	writel(SLOW, &syscntl_p->scctrl);
1534ae8bc43SStefan Roese 	writel(PLL_TIM << 3, &syscntl_p->scpllctrl);
1544ae8bc43SStefan Roese 
1554ae8bc43SStefan Roese 	/* Initialize PLLs */
1564ae8bc43SStefan Roese 	pll_init();
1574ae8bc43SStefan Roese 
1584ae8bc43SStefan Roese 	/*
1594ae8bc43SStefan Roese 	 * Ethernet configuration
1604ae8bc43SStefan Roese 	 * To be done only if the tftp boot is not selected already
1614ae8bc43SStefan Roese 	 * Boot code ensures the correct configuration in tftp booting
1624ae8bc43SStefan Roese 	 */
1634ae8bc43SStefan Roese 	if (!tftp_boot_selected())
1644ae8bc43SStefan Roese 		mac_init();
1654ae8bc43SStefan Roese 
1664ae8bc43SStefan Roese 	writel(RTC_DISABLE | PLLTIMEEN, &misc_p->periph_clk_cfg);
1674ae8bc43SStefan Roese 	writel(0x555, &misc_p->amba_clk_cfg);
1684ae8bc43SStefan Roese 
1694ae8bc43SStefan Roese 	writel(NORMAL, &syscntl_p->scctrl);
1704ae8bc43SStefan Roese 
1714ae8bc43SStefan Roese 	/* Wait for system to switch to normal mode */
1724ae8bc43SStefan Roese 	while (((readl(&syscntl_p->scctrl) >> MODE_SHIFT) & MODE_MASK)
1734ae8bc43SStefan Roese 		!= NORMAL)
1744ae8bc43SStefan Roese 		;
1754ae8bc43SStefan Roese }
1764ae8bc43SStefan Roese 
1774ae8bc43SStefan Roese /*
1784ae8bc43SStefan Roese  * get_socrev
1794ae8bc43SStefan Roese  *
1804ae8bc43SStefan Roese  * Get SoC Revision.
1814ae8bc43SStefan Roese  * @return SOC_SPEARXXX
1824ae8bc43SStefan Roese  */
get_socrev(void)1834ae8bc43SStefan Roese int get_socrev(void)
1844ae8bc43SStefan Roese {
1854ae8bc43SStefan Roese #if defined(CONFIG_SPEAR600)
1864ae8bc43SStefan Roese 	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
1874ae8bc43SStefan Roese 	u32 soc_id = readl(&misc_p->soc_core_id);
1884ae8bc43SStefan Roese 	u32 pri_socid = (soc_id >> SOC_PRI_SHFT) & 0xFF;
1894ae8bc43SStefan Roese 	u32 sec_socid = (soc_id >> SOC_SEC_SHFT) & 0xFF;
1904ae8bc43SStefan Roese 
1914ae8bc43SStefan Roese 	if ((pri_socid == 'B') && (sec_socid == 'B'))
1924ae8bc43SStefan Roese 		return SOC_SPEAR600_BB;
1934ae8bc43SStefan Roese 	else if ((pri_socid == 'B') && (sec_socid == 'C'))
1944ae8bc43SStefan Roese 		return SOC_SPEAR600_BC;
1954ae8bc43SStefan Roese 	else if ((pri_socid == 'B') && (sec_socid == 'D'))
1964ae8bc43SStefan Roese 		return SOC_SPEAR600_BD;
1974ae8bc43SStefan Roese 	else if (soc_id == 0)
1984ae8bc43SStefan Roese 		return SOC_SPEAR600_BA;
1994ae8bc43SStefan Roese 	else
2004ae8bc43SStefan Roese 		return SOC_SPEAR_NA;
2014ae8bc43SStefan Roese #elif defined(CONFIG_SPEAR300)
2024ae8bc43SStefan Roese 	return SOC_SPEAR300;
2034ae8bc43SStefan Roese #elif defined(CONFIG_SPEAR310)
2044ae8bc43SStefan Roese 	return SOC_SPEAR310;
2054ae8bc43SStefan Roese #elif defined(CONFIG_SPEAR320)
2064ae8bc43SStefan Roese 	return SOC_SPEAR320;
2074ae8bc43SStefan Roese #endif
2084ae8bc43SStefan Roese }
2094ae8bc43SStefan Roese 
2102fbdbda1SStefan Roese /*
2112fbdbda1SStefan Roese  * SNOR (Serial NOR flash) related functions
2122fbdbda1SStefan Roese  */
snor_init(void)2132fbdbda1SStefan Roese static void snor_init(void)
2142fbdbda1SStefan Roese {
2152fbdbda1SStefan Roese 	struct smi_regs *const smicntl =
2162fbdbda1SStefan Roese 		(struct smi_regs * const)CONFIG_SYS_SMI_BASE;
2172fbdbda1SStefan Roese 
2182fbdbda1SStefan Roese 	/* Setting the fast mode values. SMI working at 166/4 = 41.5 MHz */
2192fbdbda1SStefan Roese 	writel(HOLD1 | FAST_MODE | BANK_EN | DSEL_TIME | PRESCAL4,
2202fbdbda1SStefan Roese 	       &smicntl->smi_cr1);
2212fbdbda1SStefan Roese }
2222fbdbda1SStefan Roese 
spl_boot_device(void)2232fbdbda1SStefan Roese u32 spl_boot_device(void)
2242fbdbda1SStefan Roese {
225*9730bcdcSxypron.glpk@gmx.de 	u32 mode = 0;
2262fbdbda1SStefan Roese 
2272fbdbda1SStefan Roese 	/* Currently only SNOR is supported as the only */
2282fbdbda1SStefan Roese 	if (snor_boot_selected()) {
2292fbdbda1SStefan Roese 		/* SNOR-SMI initialization */
2302fbdbda1SStefan Roese 		snor_init();
2312fbdbda1SStefan Roese 
2322fbdbda1SStefan Roese 		mode = BOOT_DEVICE_NOR;
2332fbdbda1SStefan Roese 	}
2342fbdbda1SStefan Roese 
2352fbdbda1SStefan Roese 	return mode;
2362fbdbda1SStefan Roese }
2372fbdbda1SStefan Roese 
board_init_f(ulong dummy)2382fbdbda1SStefan Roese void board_init_f(ulong dummy)
2394ae8bc43SStefan Roese {
2404ae8bc43SStefan Roese 	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
2414ae8bc43SStefan Roese 
2424ae8bc43SStefan Roese 	/* Initialize PLLs */
2434ae8bc43SStefan Roese 	sys_init();
2444ae8bc43SStefan Roese 
2452fbdbda1SStefan Roese 	preloader_console_init();
2462fbdbda1SStefan Roese 	arch_cpu_init();
2474ae8bc43SStefan Roese 
2484ae8bc43SStefan Roese 	/* Enable IPs (release reset) */
2494ae8bc43SStefan Roese 	writel(PERIPH_RST_ALL, &misc_p->periph1_rst);
2504ae8bc43SStefan Roese 
2514ae8bc43SStefan Roese 	/* Initialize MPMC */
2522fbdbda1SStefan Roese 	puts("Configure DDR\n");
2534ae8bc43SStefan Roese 	mpmc_init();
2542fbdbda1SStefan Roese 	spear_late_init();
2554ae8bc43SStefan Roese 
2562fbdbda1SStefan Roese 	board_init_r(NULL, 0);
2574ae8bc43SStefan Roese }
258