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