1 /* 2 * Copyright (C) 2011 3 * Heiko Schocher, DENX Software Engineering, hs@denx.de. 4 * 5 * Copyright (C) 2012 Stefan Roese <sr@denx.de> 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 #include <common.h> 11 #include <version.h> 12 #include <asm/io.h> 13 #include <asm/arch/hardware.h> 14 #include <asm/arch/spr_defs.h> 15 #include <asm/arch/spr_misc.h> 16 #include <asm/arch/spr_syscntl.h> 17 18 static void ddr_clock_init(void) 19 { 20 struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; 21 u32 clkenb, ddrpll; 22 23 clkenb = readl(&misc_p->periph1_clken); 24 clkenb &= ~PERIPH_MPMCMSK; 25 clkenb |= PERIPH_MPMC_WE; 26 27 /* Intentionally done twice */ 28 writel(clkenb, &misc_p->periph1_clken); 29 writel(clkenb, &misc_p->periph1_clken); 30 31 ddrpll = readl(&misc_p->pll_ctr_reg); 32 ddrpll &= ~MEM_CLK_SEL_MSK; 33 #if (CONFIG_DDR_HCLK) 34 ddrpll |= MEM_CLK_HCLK; 35 #elif (CONFIG_DDR_2HCLK) 36 ddrpll |= MEM_CLK_2HCLK; 37 #elif (CONFIG_DDR_PLL2) 38 ddrpll |= MEM_CLK_PLL2; 39 #else 40 #error "please define one of CONFIG_DDR_(HCLK|2HCLK|PLL2)" 41 #endif 42 writel(ddrpll, &misc_p->pll_ctr_reg); 43 44 writel(readl(&misc_p->periph1_clken) | PERIPH_MPMC_EN, 45 &misc_p->periph1_clken); 46 } 47 48 static void mpmc_init_values(void) 49 { 50 u32 i; 51 u32 *mpmc_reg_p = (u32 *)CONFIG_SPEAR_MPMCBASE; 52 u32 *mpmc_val_p = &mpmc_conf_vals[0]; 53 54 for (i = 0; i < CONFIG_SPEAR_MPMCREGS; i++, mpmc_reg_p++, mpmc_val_p++) 55 writel(*mpmc_val_p, mpmc_reg_p); 56 57 mpmc_reg_p = (u32 *)CONFIG_SPEAR_MPMCBASE; 58 59 /* 60 * MPMC controller start 61 * MPMC waiting for DLLLOCKREG high 62 */ 63 writel(0x01000100, &mpmc_reg_p[7]); 64 65 while (!(readl(&mpmc_reg_p[3]) & 0x10000)) 66 ; 67 } 68 69 static void mpmc_init(void) 70 { 71 /* Clock related settings for DDR */ 72 ddr_clock_init(); 73 74 /* 75 * DDR pad register bits are different for different SoCs 76 * Compensation values are also handled separately 77 */ 78 plat_ddr_init(); 79 80 /* Initialize mpmc register values */ 81 mpmc_init_values(); 82 } 83 84 static void pll_init(void) 85 { 86 struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; 87 88 /* Initialize PLLs */ 89 writel(FREQ_332, &misc_p->pll1_frq); 90 writel(0x1C0A, &misc_p->pll1_cntl); 91 writel(0x1C0E, &misc_p->pll1_cntl); 92 writel(0x1C06, &misc_p->pll1_cntl); 93 writel(0x1C0E, &misc_p->pll1_cntl); 94 95 writel(FREQ_332, &misc_p->pll2_frq); 96 writel(0x1C0A, &misc_p->pll2_cntl); 97 writel(0x1C0E, &misc_p->pll2_cntl); 98 writel(0x1C06, &misc_p->pll2_cntl); 99 writel(0x1C0E, &misc_p->pll2_cntl); 100 101 /* wait for pll locks */ 102 while (!(readl(&misc_p->pll1_cntl) & 0x1)) 103 ; 104 while (!(readl(&misc_p->pll2_cntl) & 0x1)) 105 ; 106 } 107 108 static void mac_init(void) 109 { 110 struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; 111 112 writel(readl(&misc_p->periph1_clken) & (~PERIPH_GMAC), 113 &misc_p->periph1_clken); 114 115 writel(SYNTH23, &misc_p->gmac_synth_clk); 116 117 switch (get_socrev()) { 118 case SOC_SPEAR600_AA: 119 case SOC_SPEAR600_AB: 120 case SOC_SPEAR600_BA: 121 case SOC_SPEAR600_BB: 122 case SOC_SPEAR600_BC: 123 case SOC_SPEAR600_BD: 124 writel(0x0, &misc_p->gmac_ctr_reg); 125 break; 126 127 case SOC_SPEAR300: 128 case SOC_SPEAR310: 129 case SOC_SPEAR320: 130 writel(0x4, &misc_p->gmac_ctr_reg); 131 break; 132 } 133 134 writel(readl(&misc_p->periph1_clken) | PERIPH_GMAC, 135 &misc_p->periph1_clken); 136 137 writel(readl(&misc_p->periph1_rst) | PERIPH_GMAC, 138 &misc_p->periph1_rst); 139 writel(readl(&misc_p->periph1_rst) & (~PERIPH_GMAC), 140 &misc_p->periph1_rst); 141 } 142 143 static void sys_init(void) 144 { 145 struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; 146 struct syscntl_regs *syscntl_p = 147 (struct syscntl_regs *)CONFIG_SPEAR_SYSCNTLBASE; 148 149 /* Set system state to SLOW */ 150 writel(SLOW, &syscntl_p->scctrl); 151 writel(PLL_TIM << 3, &syscntl_p->scpllctrl); 152 153 /* Initialize PLLs */ 154 pll_init(); 155 156 /* 157 * Ethernet configuration 158 * To be done only if the tftp boot is not selected already 159 * Boot code ensures the correct configuration in tftp booting 160 */ 161 if (!tftp_boot_selected()) 162 mac_init(); 163 164 writel(RTC_DISABLE | PLLTIMEEN, &misc_p->periph_clk_cfg); 165 writel(0x555, &misc_p->amba_clk_cfg); 166 167 writel(NORMAL, &syscntl_p->scctrl); 168 169 /* Wait for system to switch to normal mode */ 170 while (((readl(&syscntl_p->scctrl) >> MODE_SHIFT) & MODE_MASK) 171 != NORMAL) 172 ; 173 } 174 175 /* 176 * get_socrev 177 * 178 * Get SoC Revision. 179 * @return SOC_SPEARXXX 180 */ 181 int get_socrev(void) 182 { 183 #if defined(CONFIG_SPEAR600) 184 struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; 185 u32 soc_id = readl(&misc_p->soc_core_id); 186 u32 pri_socid = (soc_id >> SOC_PRI_SHFT) & 0xFF; 187 u32 sec_socid = (soc_id >> SOC_SEC_SHFT) & 0xFF; 188 189 if ((pri_socid == 'B') && (sec_socid == 'B')) 190 return SOC_SPEAR600_BB; 191 else if ((pri_socid == 'B') && (sec_socid == 'C')) 192 return SOC_SPEAR600_BC; 193 else if ((pri_socid == 'B') && (sec_socid == 'D')) 194 return SOC_SPEAR600_BD; 195 else if (soc_id == 0) 196 return SOC_SPEAR600_BA; 197 else 198 return SOC_SPEAR_NA; 199 #elif defined(CONFIG_SPEAR300) 200 return SOC_SPEAR300; 201 #elif defined(CONFIG_SPEAR310) 202 return SOC_SPEAR310; 203 #elif defined(CONFIG_SPEAR320) 204 return SOC_SPEAR320; 205 #endif 206 } 207 208 void lowlevel_init(void) 209 { 210 struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; 211 const char *u_boot_rev = U_BOOT_VERSION; 212 213 /* Initialize PLLs */ 214 sys_init(); 215 216 /* Initialize UART */ 217 serial_init(); 218 219 /* Print U-Boot SPL version string */ 220 serial_puts("\nU-Boot SPL "); 221 /* Avoid a second "U-Boot" coming from this string */ 222 u_boot_rev = &u_boot_rev[7]; 223 serial_puts(u_boot_rev); 224 serial_puts(" ("); 225 serial_puts(U_BOOT_DATE); 226 serial_puts(" - "); 227 serial_puts(U_BOOT_TIME); 228 serial_puts(")\n"); 229 230 #if defined(CONFIG_OS_BOOT) 231 writel(readl(&misc_p->periph1_clken) | PERIPH_UART1, 232 &misc_p->periph1_clken); 233 #endif 234 235 /* Enable IPs (release reset) */ 236 writel(PERIPH_RST_ALL, &misc_p->periph1_rst); 237 238 /* Initialize MPMC */ 239 serial_puts("Configure DDR\n"); 240 mpmc_init(); 241 242 /* SoC specific initialization */ 243 soc_init(); 244 } 245 246 void spear_late_init(void) 247 { 248 struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; 249 250 writel(0x80000007, &misc_p->arb_icm_ml1); 251 writel(0x80000007, &misc_p->arb_icm_ml2); 252 writel(0x80000007, &misc_p->arb_icm_ml3); 253 writel(0x80000007, &misc_p->arb_icm_ml4); 254 writel(0x80000007, &misc_p->arb_icm_ml5); 255 writel(0x80000007, &misc_p->arb_icm_ml6); 256 writel(0x80000007, &misc_p->arb_icm_ml7); 257 writel(0x80000007, &misc_p->arb_icm_ml8); 258 writel(0x80000007, &misc_p->arb_icm_ml9); 259 } 260