SPDX: Convert all of our single license tags to Linux Kernel style
[platform/kernel/u-boot.git] / arch / arm / cpu / arm926ejs / spear / spl.c
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
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
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
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
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
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
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  */
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  */
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
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
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 }