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