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