1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2009
3*4882a593Smuzhiyun * Marvell Semiconductor <www.marvell.com>
4*4882a593Smuzhiyun * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <common.h>
10*4882a593Smuzhiyun #include <netdev.h>
11*4882a593Smuzhiyun #include <asm/cache.h>
12*4882a593Smuzhiyun #include <asm/io.h>
13*4882a593Smuzhiyun #include <asm/arch/cpu.h>
14*4882a593Smuzhiyun #include <asm/arch/soc.h>
15*4882a593Smuzhiyun #include <mvebu_mmc.h>
16*4882a593Smuzhiyun
reset_cpu(unsigned long ignored)17*4882a593Smuzhiyun void reset_cpu(unsigned long ignored)
18*4882a593Smuzhiyun {
19*4882a593Smuzhiyun struct kwcpu_registers *cpureg =
20*4882a593Smuzhiyun (struct kwcpu_registers *)KW_CPU_REG_BASE;
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun writel(readl(&cpureg->rstoutn_mask) | (1 << 2),
23*4882a593Smuzhiyun &cpureg->rstoutn_mask);
24*4882a593Smuzhiyun writel(readl(&cpureg->sys_soft_rst) | 1,
25*4882a593Smuzhiyun &cpureg->sys_soft_rst);
26*4882a593Smuzhiyun while (1) ;
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun /*
30*4882a593Smuzhiyun * Window Size
31*4882a593Smuzhiyun * Used with the Base register to set the address window size and location.
32*4882a593Smuzhiyun * Must be programmed from LSB to MSB as sequence of ones followed by
33*4882a593Smuzhiyun * sequence of zeros. The number of ones specifies the size of the window in
34*4882a593Smuzhiyun * 64 KByte granularity (e.g., a value of 0x00FF specifies 256 = 16 MByte).
35*4882a593Smuzhiyun * NOTE: A value of 0x0 specifies 64-KByte size.
36*4882a593Smuzhiyun */
kw_winctrl_calcsize(unsigned int sizeval)37*4882a593Smuzhiyun unsigned int kw_winctrl_calcsize(unsigned int sizeval)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun int i;
40*4882a593Smuzhiyun unsigned int j = 0;
41*4882a593Smuzhiyun u32 val = sizeval >> 1;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun for (i = 0; val >= 0x10000; i++) {
44*4882a593Smuzhiyun j |= (1 << i);
45*4882a593Smuzhiyun val = val >> 1;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun return (0x0000ffff & j);
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /*
51*4882a593Smuzhiyun * kw_config_adr_windows - Configure address Windows
52*4882a593Smuzhiyun *
53*4882a593Smuzhiyun * There are 8 address windows supported by Kirkwood Soc to addess different
54*4882a593Smuzhiyun * devices. Each window can be configured for size, BAR and remap addr
55*4882a593Smuzhiyun * Below configuration is standard for most of the cases
56*4882a593Smuzhiyun *
57*4882a593Smuzhiyun * If remap function not used, remap_lo must be set as base
58*4882a593Smuzhiyun *
59*4882a593Smuzhiyun * Reference Documentation:
60*4882a593Smuzhiyun * Mbus-L to Mbus Bridge Registers Configuration.
61*4882a593Smuzhiyun * (Sec 25.1 and 25.3 of Datasheet)
62*4882a593Smuzhiyun */
kw_config_adr_windows(void)63*4882a593Smuzhiyun int kw_config_adr_windows(void)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun struct kwwin_registers *winregs =
66*4882a593Smuzhiyun (struct kwwin_registers *)KW_CPU_WIN_BASE;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /* Window 0: PCIE MEM address space */
69*4882a593Smuzhiyun writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 256, KWCPU_TARGET_PCIE,
70*4882a593Smuzhiyun KWCPU_ATTR_PCIE_MEM, KWCPU_WIN_ENABLE), &winregs[0].ctrl);
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun writel(KW_DEFADR_PCI_MEM, &winregs[0].base);
73*4882a593Smuzhiyun writel(KW_DEFADR_PCI_MEM, &winregs[0].remap_lo);
74*4882a593Smuzhiyun writel(0x0, &winregs[0].remap_hi);
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /* Window 1: PCIE IO address space */
77*4882a593Smuzhiyun writel(KWCPU_WIN_CTRL_DATA(1024 * 64, KWCPU_TARGET_PCIE,
78*4882a593Smuzhiyun KWCPU_ATTR_PCIE_IO, KWCPU_WIN_ENABLE), &winregs[1].ctrl);
79*4882a593Smuzhiyun writel(KW_DEFADR_PCI_IO, &winregs[1].base);
80*4882a593Smuzhiyun writel(KW_DEFADR_PCI_IO_REMAP, &winregs[1].remap_lo);
81*4882a593Smuzhiyun writel(0x0, &winregs[1].remap_hi);
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /* Window 2: NAND Flash address space */
84*4882a593Smuzhiyun writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY,
85*4882a593Smuzhiyun KWCPU_ATTR_NANDFLASH, KWCPU_WIN_ENABLE), &winregs[2].ctrl);
86*4882a593Smuzhiyun writel(KW_DEFADR_NANDF, &winregs[2].base);
87*4882a593Smuzhiyun writel(KW_DEFADR_NANDF, &winregs[2].remap_lo);
88*4882a593Smuzhiyun writel(0x0, &winregs[2].remap_hi);
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /* Window 3: SPI Flash address space */
91*4882a593Smuzhiyun writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY,
92*4882a593Smuzhiyun KWCPU_ATTR_SPIFLASH, KWCPU_WIN_ENABLE), &winregs[3].ctrl);
93*4882a593Smuzhiyun writel(KW_DEFADR_SPIF, &winregs[3].base);
94*4882a593Smuzhiyun writel(KW_DEFADR_SPIF, &winregs[3].remap_lo);
95*4882a593Smuzhiyun writel(0x0, &winregs[3].remap_hi);
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /* Window 4: BOOT Memory address space */
98*4882a593Smuzhiyun writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY,
99*4882a593Smuzhiyun KWCPU_ATTR_BOOTROM, KWCPU_WIN_ENABLE), &winregs[4].ctrl);
100*4882a593Smuzhiyun writel(KW_DEFADR_BOOTROM, &winregs[4].base);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /* Window 5: Security SRAM address space */
103*4882a593Smuzhiyun writel(KWCPU_WIN_CTRL_DATA(1024 * 64, KWCPU_TARGET_SASRAM,
104*4882a593Smuzhiyun KWCPU_ATTR_SASRAM, KWCPU_WIN_ENABLE), &winregs[5].ctrl);
105*4882a593Smuzhiyun writel(KW_DEFADR_SASRAM, &winregs[5].base);
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun /* Window 6-7: Disabled */
108*4882a593Smuzhiyun writel(KWCPU_WIN_DISABLE, &winregs[6].ctrl);
109*4882a593Smuzhiyun writel(KWCPU_WIN_DISABLE, &winregs[7].ctrl);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun return 0;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /*
115*4882a593Smuzhiyun * SYSRSTn Duration Counter Support
116*4882a593Smuzhiyun *
117*4882a593Smuzhiyun * Kirkwood SoC implements a hardware-based SYSRSTn duration counter.
118*4882a593Smuzhiyun * When SYSRSTn is asserted low, a SYSRSTn duration counter is running.
119*4882a593Smuzhiyun * The SYSRSTn duration counter is useful for implementing a manufacturer
120*4882a593Smuzhiyun * or factory reset. Upon a long reset assertion that is greater than a
121*4882a593Smuzhiyun * pre-configured environment variable value for sysrstdelay,
122*4882a593Smuzhiyun * The counter value is stored in the SYSRSTn Length Counter Register
123*4882a593Smuzhiyun * The counter is based on the 25-MHz reference clock (40ns)
124*4882a593Smuzhiyun * It is a 29-bit counter, yielding a maximum counting duration of
125*4882a593Smuzhiyun * 2^29/25 MHz (21.4 seconds). When the counter reach its maximum value,
126*4882a593Smuzhiyun * it remains at this value until counter reset is triggered by setting
127*4882a593Smuzhiyun * bit 31 of KW_REG_SYSRST_CNT
128*4882a593Smuzhiyun */
kw_sysrst_action(void)129*4882a593Smuzhiyun static void kw_sysrst_action(void)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun int ret;
132*4882a593Smuzhiyun char *s = env_get("sysrstcmd");
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun if (!s) {
135*4882a593Smuzhiyun debug("Error.. %s failed, check sysrstcmd\n",
136*4882a593Smuzhiyun __FUNCTION__);
137*4882a593Smuzhiyun return;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun debug("Starting %s process...\n", __FUNCTION__);
141*4882a593Smuzhiyun ret = run_command(s, 0);
142*4882a593Smuzhiyun if (ret != 0)
143*4882a593Smuzhiyun debug("Error.. %s failed\n", __FUNCTION__);
144*4882a593Smuzhiyun else
145*4882a593Smuzhiyun debug("%s process finished\n", __FUNCTION__);
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
kw_sysrst_check(void)148*4882a593Smuzhiyun static void kw_sysrst_check(void)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun u32 sysrst_cnt, sysrst_dly;
151*4882a593Smuzhiyun char *s;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /*
154*4882a593Smuzhiyun * no action if sysrstdelay environment variable is not defined
155*4882a593Smuzhiyun */
156*4882a593Smuzhiyun s = env_get("sysrstdelay");
157*4882a593Smuzhiyun if (s == NULL)
158*4882a593Smuzhiyun return;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /* read sysrstdelay value */
161*4882a593Smuzhiyun sysrst_dly = (u32) simple_strtoul(s, NULL, 10);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun /* read SysRst Length counter register (bits 28:0) */
164*4882a593Smuzhiyun sysrst_cnt = (0x1fffffff & readl(KW_REG_SYSRST_CNT));
165*4882a593Smuzhiyun debug("H/w Rst hold time: %d.%d secs\n",
166*4882a593Smuzhiyun sysrst_cnt / SYSRST_CNT_1SEC_VAL,
167*4882a593Smuzhiyun sysrst_cnt % SYSRST_CNT_1SEC_VAL);
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /* clear the counter for next valid read*/
170*4882a593Smuzhiyun writel(1 << 31, KW_REG_SYSRST_CNT);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun /*
173*4882a593Smuzhiyun * sysrst_action:
174*4882a593Smuzhiyun * if H/w Reset key is pressed and hold for time
175*4882a593Smuzhiyun * more than sysrst_dly in seconds
176*4882a593Smuzhiyun */
177*4882a593Smuzhiyun if (sysrst_cnt >= SYSRST_CNT_1SEC_VAL * sysrst_dly)
178*4882a593Smuzhiyun kw_sysrst_action();
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun #if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo(void)182*4882a593Smuzhiyun int print_cpuinfo(void)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun char *rev = "??";
185*4882a593Smuzhiyun u16 devid = (readl(KW_REG_PCIE_DEVID) >> 16) & 0xffff;
186*4882a593Smuzhiyun u8 revid = readl(KW_REG_PCIE_REVID) & 0xff;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun if ((readl(KW_REG_DEVICE_ID) & 0x03) > 2) {
189*4882a593Smuzhiyun printf("Error.. %s:Unsupported Kirkwood SoC 88F%04x\n", __FUNCTION__, devid);
190*4882a593Smuzhiyun return -1;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun switch (revid) {
194*4882a593Smuzhiyun case 0:
195*4882a593Smuzhiyun if (devid == 0x6281)
196*4882a593Smuzhiyun rev = "Z0";
197*4882a593Smuzhiyun else if (devid == 0x6282)
198*4882a593Smuzhiyun rev = "A0";
199*4882a593Smuzhiyun break;
200*4882a593Smuzhiyun case 1:
201*4882a593Smuzhiyun rev = "A1";
202*4882a593Smuzhiyun break;
203*4882a593Smuzhiyun case 2:
204*4882a593Smuzhiyun rev = "A0";
205*4882a593Smuzhiyun break;
206*4882a593Smuzhiyun case 3:
207*4882a593Smuzhiyun rev = "A1";
208*4882a593Smuzhiyun break;
209*4882a593Smuzhiyun default:
210*4882a593Smuzhiyun break;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun printf("SoC: Kirkwood 88F%04x_%s\n", devid, rev);
214*4882a593Smuzhiyun return 0;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun #endif /* CONFIG_DISPLAY_CPUINFO */
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun #ifdef CONFIG_ARCH_CPU_INIT
arch_cpu_init(void)219*4882a593Smuzhiyun int arch_cpu_init(void)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun u32 reg;
222*4882a593Smuzhiyun struct kwcpu_registers *cpureg =
223*4882a593Smuzhiyun (struct kwcpu_registers *)KW_CPU_REG_BASE;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun /* Linux expects` the internal registers to be at 0xf1000000 */
226*4882a593Smuzhiyun writel(KW_REGS_PHY_BASE, KW_OFFSET_REG);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun /* Enable and invalidate L2 cache in write through mode */
229*4882a593Smuzhiyun writel(readl(&cpureg->l2_cfg) | 0x18, &cpureg->l2_cfg);
230*4882a593Smuzhiyun invalidate_l2_cache();
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun kw_config_adr_windows();
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun #ifdef CONFIG_KIRKWOOD_RGMII_PAD_1V8
235*4882a593Smuzhiyun /*
236*4882a593Smuzhiyun * Configures the I/O voltage of the pads connected to Egigabit
237*4882a593Smuzhiyun * Ethernet interface to 1.8V
238*4882a593Smuzhiyun * By default it is set to 3.3V
239*4882a593Smuzhiyun */
240*4882a593Smuzhiyun reg = readl(KW_REG_MPP_OUT_DRV_REG);
241*4882a593Smuzhiyun reg |= (1 << 7);
242*4882a593Smuzhiyun writel(reg, KW_REG_MPP_OUT_DRV_REG);
243*4882a593Smuzhiyun #endif
244*4882a593Smuzhiyun #ifdef CONFIG_KIRKWOOD_EGIGA_INIT
245*4882a593Smuzhiyun /*
246*4882a593Smuzhiyun * Set egiga port0/1 in normal functional mode
247*4882a593Smuzhiyun * This is required becasue on kirkwood by default ports are in reset mode
248*4882a593Smuzhiyun * OS egiga driver may not have provision to set them in normal mode
249*4882a593Smuzhiyun * and if u-boot is build without network support, network may fail at OS level
250*4882a593Smuzhiyun */
251*4882a593Smuzhiyun reg = readl(KWGBE_PORT_SERIAL_CONTROL1_REG(0));
252*4882a593Smuzhiyun reg &= ~(1 << 4); /* Clear PortReset Bit */
253*4882a593Smuzhiyun writel(reg, (KWGBE_PORT_SERIAL_CONTROL1_REG(0)));
254*4882a593Smuzhiyun reg = readl(KWGBE_PORT_SERIAL_CONTROL1_REG(1));
255*4882a593Smuzhiyun reg &= ~(1 << 4); /* Clear PortReset Bit */
256*4882a593Smuzhiyun writel(reg, (KWGBE_PORT_SERIAL_CONTROL1_REG(1)));
257*4882a593Smuzhiyun #endif
258*4882a593Smuzhiyun #ifdef CONFIG_KIRKWOOD_PCIE_INIT
259*4882a593Smuzhiyun /*
260*4882a593Smuzhiyun * Enable PCI Express Port0
261*4882a593Smuzhiyun */
262*4882a593Smuzhiyun reg = readl(&cpureg->ctrl_stat);
263*4882a593Smuzhiyun reg |= (1 << 0); /* Set PEX0En Bit */
264*4882a593Smuzhiyun writel(reg, &cpureg->ctrl_stat);
265*4882a593Smuzhiyun #endif
266*4882a593Smuzhiyun return 0;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun #endif /* CONFIG_ARCH_CPU_INIT */
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /*
271*4882a593Smuzhiyun * SOC specific misc init
272*4882a593Smuzhiyun */
273*4882a593Smuzhiyun #if defined(CONFIG_ARCH_MISC_INIT)
arch_misc_init(void)274*4882a593Smuzhiyun int arch_misc_init(void)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun volatile u32 temp;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun /*CPU streaming & write allocate */
279*4882a593Smuzhiyun temp = readfr_extra_feature_reg();
280*4882a593Smuzhiyun temp &= ~(1 << 28); /* disable wr alloc */
281*4882a593Smuzhiyun writefr_extra_feature_reg(temp);
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun temp = readfr_extra_feature_reg();
284*4882a593Smuzhiyun temp &= ~(1 << 29); /* streaming disabled */
285*4882a593Smuzhiyun writefr_extra_feature_reg(temp);
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun /* L2Cache settings */
288*4882a593Smuzhiyun temp = readfr_extra_feature_reg();
289*4882a593Smuzhiyun /* Disable L2C pre fetch - Set bit 24 */
290*4882a593Smuzhiyun temp |= (1 << 24);
291*4882a593Smuzhiyun /* enable L2C - Set bit 22 */
292*4882a593Smuzhiyun temp |= (1 << 22);
293*4882a593Smuzhiyun writefr_extra_feature_reg(temp);
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun icache_enable();
296*4882a593Smuzhiyun /* Change reset vector to address 0x0 */
297*4882a593Smuzhiyun temp = get_cr();
298*4882a593Smuzhiyun set_cr(temp & ~CR_V);
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun /* checks and execute resset to factory event */
301*4882a593Smuzhiyun kw_sysrst_check();
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun return 0;
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun #endif /* CONFIG_ARCH_MISC_INIT */
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun #ifdef CONFIG_MVGBE
cpu_eth_init(bd_t * bis)308*4882a593Smuzhiyun int cpu_eth_init(bd_t *bis)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun mvgbe_initialize(bis);
311*4882a593Smuzhiyun return 0;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun #endif
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun #ifdef CONFIG_MVEBU_MMC
board_mmc_init(bd_t * bis)316*4882a593Smuzhiyun int board_mmc_init(bd_t *bis)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun mvebu_mmc_init(bis);
319*4882a593Smuzhiyun return 0;
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun #endif /* CONFIG_MVEBU_MMC */
322