xref: /OK3568_Linux_fs/u-boot/arch/arm/mach-kirkwood/cpu.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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