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> 11*2fbdbda1SStefan 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> 18*2fbdbda1SStefan Roese #include <linux/mtd/st_smi.h> 194ae8bc43SStefan Roese 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 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 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 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 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 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 */ 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 210*2fbdbda1SStefan Roese /* 211*2fbdbda1SStefan Roese * SNOR (Serial NOR flash) related functions 212*2fbdbda1SStefan Roese */ 213*2fbdbda1SStefan Roese static void snor_init(void) 214*2fbdbda1SStefan Roese { 215*2fbdbda1SStefan Roese struct smi_regs *const smicntl = 216*2fbdbda1SStefan Roese (struct smi_regs * const)CONFIG_SYS_SMI_BASE; 217*2fbdbda1SStefan Roese 218*2fbdbda1SStefan Roese /* Setting the fast mode values. SMI working at 166/4 = 41.5 MHz */ 219*2fbdbda1SStefan Roese writel(HOLD1 | FAST_MODE | BANK_EN | DSEL_TIME | PRESCAL4, 220*2fbdbda1SStefan Roese &smicntl->smi_cr1); 221*2fbdbda1SStefan Roese } 222*2fbdbda1SStefan Roese 223*2fbdbda1SStefan Roese u32 spl_boot_device(void) 224*2fbdbda1SStefan Roese { 225*2fbdbda1SStefan Roese u32 mode; 226*2fbdbda1SStefan Roese 227*2fbdbda1SStefan Roese /* Currently only SNOR is supported as the only */ 228*2fbdbda1SStefan Roese if (snor_boot_selected()) { 229*2fbdbda1SStefan Roese /* SNOR-SMI initialization */ 230*2fbdbda1SStefan Roese snor_init(); 231*2fbdbda1SStefan Roese 232*2fbdbda1SStefan Roese mode = BOOT_DEVICE_NOR; 233*2fbdbda1SStefan Roese } 234*2fbdbda1SStefan Roese 235*2fbdbda1SStefan Roese return mode; 236*2fbdbda1SStefan Roese } 237*2fbdbda1SStefan Roese 238*2fbdbda1SStefan 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 245*2fbdbda1SStefan Roese preloader_console_init(); 246*2fbdbda1SStefan 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 */ 252*2fbdbda1SStefan Roese puts("Configure DDR\n"); 2534ae8bc43SStefan Roese mpmc_init(); 254*2fbdbda1SStefan Roese spear_late_init(); 2554ae8bc43SStefan Roese 256*2fbdbda1SStefan Roese board_init_r(NULL, 0); 2574ae8bc43SStefan Roese } 258