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