]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm926ejs/orion5x/cpu.c
Initial support for Marvell Orion5x SoC
[karo-tx-uboot.git] / arch / arm / cpu / arm926ejs / orion5x / cpu.c
1 /*
2  * Copyright (C) 2010 Albert ARIBAUD <albert.aribaud@free.fr>
3  *
4  * Based on original Kirkwood support which is
5  * (C) Copyright 2009
6  * Marvell Semiconductor <www.marvell.com>
7  * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
8  *
9  * See file CREDITS for list of people who contributed to this
10  * project.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25  * MA 02110-1301 USA
26  */
27
28 #include <common.h>
29 #include <netdev.h>
30 #include <asm/cache.h>
31 #include <u-boot/md5.h>
32 #include <asm/arch/orion5x.h>
33 #include <hush.h>
34
35 #define BUFLEN  16
36
37 void reset_cpu(unsigned long ignored)
38 {
39         struct orion5x_cpu_registers *cpureg =
40             (struct orion5x_cpu_registers *)ORION5X_CPU_REG_BASE;
41
42         writel(readl(&cpureg->rstoutn_mask) | (1 << 2),
43                 &cpureg->rstoutn_mask);
44         writel(readl(&cpureg->sys_soft_rst) | 1,
45                 &cpureg->sys_soft_rst);
46         while (1)
47                 ;
48 }
49
50 /*
51  * Window Size
52  * Used with the Base register to set the address window size and location.
53  * Must be programmed from LSB to MSB as sequence of ones followed by
54  * sequence of zeros. The number of ones specifies the size of the window in
55  * 64 KByte granularity (e.g., a value of 0x00FF specifies 256 = 16 MByte).
56  * NOTE: A value of 0x0 specifies 64-KByte size.
57  */
58 unsigned int orion5x_winctrl_calcsize(unsigned int sizeval)
59 {
60         int i;
61         unsigned int j = 0;
62         u32 val = sizeval >> 1;
63
64         for (i = 0; val > 0x10000; i++) {
65                 j |= (1 << i);
66                 val = val >> 1;
67         }
68         return 0x0000ffff & j;
69 }
70
71 /*
72  * orion5x_config_adr_windows - Configure address Windows
73  *
74  * There are 8 address windows supported by Orion5x Soc to addess different
75  * devices. Each window can be configured for size, BAR and remap addr
76  * Below configuration is standard for most of the cases
77  *
78  * If remap function not used, remap_lo must be set as base
79  *
80  * Reference Documentation:
81  * Mbus-L to Mbus Bridge Registers Configuration.
82  * (Sec 25.1 and 25.3 of Datasheet)
83  */
84 int orion5x_config_adr_windows(void)
85 {
86         struct orion5x_win_registers *winregs =
87                 (struct orion5x_win_registers *)ORION5X_CPU_WIN_BASE;
88
89         /* Window 0: PCIE MEM address space */
90         writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_PCIE_MEM,
91                 ORION5X_TARGET_PCIE, ORION5X_ATTR_PCIE_MEM,
92                 ORION5X_WIN_ENABLE), &winregs[0].ctrl);
93         writel(ORION5X_DEFADR_PCIE_MEM, &winregs[0].base);
94         writel(ORION5X_DEFADR_PCIE_MEM_REMAP_LO, &winregs[0].remap_lo);
95         writel(ORION5X_DEFADR_PCIE_MEM_REMAP_HI, &winregs[0].remap_hi);
96
97         /* Window 1: PCIE IO address space */
98         writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_PCIE_IO,
99                 ORION5X_TARGET_PCIE, ORION5X_ATTR_PCIE_IO,
100                 ORION5X_WIN_ENABLE), &winregs[1].ctrl);
101         writel(ORION5X_DEFADR_PCIE_IO, &winregs[1].base);
102         writel(ORION5X_DEFADR_PCIE_IO_REMAP_LO, &winregs[1].remap_lo);
103         writel(ORION5X_DEFADR_PCIE_IO_REMAP_HI, &winregs[1].remap_hi);
104
105         /* Window 2: PCI MEM address space */
106         writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_PCI_MEM,
107                 ORION5X_TARGET_PCI, ORION5X_ATTR_PCI_MEM,
108                 ORION5X_WIN_ENABLE), &winregs[2].ctrl);
109         writel(ORION5X_DEFADR_PCI_MEM, &winregs[2].base);
110
111         /* Window 3: PCI IO address space */
112         writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_PCI_IO,
113                 ORION5X_TARGET_PCI, ORION5X_ATTR_PCI_IO,
114                 ORION5X_WIN_ENABLE), &winregs[3].ctrl);
115         writel(ORION5X_DEFADR_PCI_IO, &winregs[3].base);
116
117         /* Window 4: DEV_CS0 address space */
118         writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_DEV_CS0,
119                 ORION5X_TARGET_DEVICE, ORION5X_ATTR_DEV_CS0,
120                 ORION5X_WIN_ENABLE), &winregs[4].ctrl);
121         writel(ORION5X_DEFADR_DEV_CS0, &winregs[4].base);
122
123         /* Window 5: DEV_CS1 address space */
124         writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_DEV_CS1,
125                 ORION5X_TARGET_DEVICE, ORION5X_ATTR_DEV_CS1,
126                 ORION5X_WIN_ENABLE), &winregs[5].ctrl);
127         writel(ORION5X_DEFADR_DEV_CS1, &winregs[5].base);
128
129         /* Window 6: DEV_CS2 address space */
130         writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_DEV_CS2,
131                 ORION5X_TARGET_DEVICE, ORION5X_ATTR_DEV_CS2,
132                 ORION5X_WIN_ENABLE), &winregs[6].ctrl);
133         writel(ORION5X_DEFADR_DEV_CS2, &winregs[6].base);
134
135         /* Window 7: BOOT Memory address space */
136         writel(ORION5X_CPU_WIN_CTRL_DATA(ORION5X_DEFSZ_BOOTROM,
137                 ORION5X_TARGET_DEVICE, ORION5X_ATTR_BOOTROM,
138                 ORION5X_WIN_ENABLE), &winregs[7].ctrl);
139         writel(ORION5X_DEFADR_BOOTROM, &winregs[7].base);
140
141         return 0;
142 }
143
144 /*
145  * Orion5x identification is done through PCIE space.
146  */
147
148 u32 orion5x_device_id(void)
149 {
150         return readl(PCIE_DEV_ID_OFF) >> 16;
151 }
152
153 u32 orion5x_device_rev(void)
154 {
155         return readl(PCIE_DEV_REV_OFF) & 0xff;
156 }
157
158 #if defined(CONFIG_DISPLAY_CPUINFO)
159
160 /* Display device and revision IDs.
161  * This function must cover all known device/revision
162  * combinations, not only the one for which u-boot is
163  * compiled; this way, one can identify actual HW in
164  * case of a mismatch.
165  */
166 int print_cpuinfo(void)
167 {
168         char dev_str[] = "0x0000";
169         char rev_str[] = "0x00";
170         char *dev_name = NULL;
171         char *rev_name = NULL;
172
173         u32 dev = orion5x_device_id();
174         u32 rev = orion5x_device_rev();
175
176         if (dev == MV88F5181_DEV_ID) {
177                 dev_name = "MV88F5181";
178                 if (rev == MV88F5181_REV_B1)
179                         rev_name = "B1";
180                 else if (rev == MV88F5181L_REV_A1) {
181                         dev_name = "MV88F5181L";
182                         rev_name = "A1";
183                 } else if (rev == MV88F5181L_REV_A0) {
184                         dev_name = "MV88F5181L";
185                         rev_name = "A0";
186                 }
187         } else if (dev == MV88F5182_DEV_ID) {
188                 dev_name = "MV88F5182";
189                 if (rev == MV88F5182_REV_A2)
190                         rev_name = "A2";
191         } else if (dev == MV88F5281_DEV_ID) {
192                 dev_name = "MV88F5281";
193                 if (rev == MV88F5281_REV_D2)
194                         rev_name = "D2";
195                 else if (rev == MV88F5281_REV_D1)
196                         rev_name = "D1";
197                 else if (rev == MV88F5281_REV_D0)
198                         rev_name = "D0";
199         } else if (dev == MV88F6183_DEV_ID) {
200                 dev_name = "MV88F6183";
201                 if (rev == MV88F6183_REV_B0)
202                         rev_name = "B0";
203         }
204         if (dev_name == NULL) {
205                 sprintf(dev_str, "0x%04x", dev);
206                 dev_name = dev_str;
207         }
208         if (rev_name == NULL) {
209                 sprintf(rev_str, "0x%02x", rev);
210                 rev_name = rev_str;
211         }
212
213         printf("SoC:   Orion5x %s-%s\n", dev_name, rev_name);
214
215         return 0;
216 }
217 #endif /* CONFIG_DISPLAY_CPUINFO */
218
219 #ifdef CONFIG_ARCH_CPU_INIT
220 int arch_cpu_init(void)
221 {
222         /* Enable and invalidate L2 cache in write through mode */
223         invalidate_l2_cache();
224
225         orion5x_config_adr_windows();
226
227         return 0;
228 }
229 #endif /* CONFIG_ARCH_CPU_INIT */
230
231 /*
232  * SOC specific misc init
233  */
234 #if defined(CONFIG_ARCH_MISC_INIT)
235 int arch_misc_init(void)
236 {
237         u32 temp;
238
239         /*CPU streaming & write allocate */
240         temp = readfr_extra_feature_reg();
241         temp &= ~(1 << 28);     /* disable wr alloc */
242         writefr_extra_feature_reg(temp);
243
244         temp = readfr_extra_feature_reg();
245         temp &= ~(1 << 29);     /* streaming disabled */
246         writefr_extra_feature_reg(temp);
247
248         /* L2Cache settings */
249         temp = readfr_extra_feature_reg();
250         /* Disable L2C pre fetch - Set bit 24 */
251         temp |= (1 << 24);
252         /* enable L2C - Set bit 22 */
253         temp |= (1 << 22);
254         writefr_extra_feature_reg(temp);
255
256         icache_enable();
257         /* Change reset vector to address 0x0 */
258         temp = get_cr();
259         set_cr(temp & ~CR_V);
260
261         /* Set CPIOs and MPPs - values provided by board
262            include file */
263         writel(ORION5X_MPP_BASE+0x00, ORION5X_MPP0_7);
264         writel(ORION5X_MPP_BASE+0x04, ORION5X_MPP8_15);
265         writel(ORION5X_MPP_BASE+0x50, ORION5X_MPP16_23);
266         writel(ORION5X_GPIO_BASE+0x04, ORION5X_GPIO_OUT_ENABLE);
267
268         return 0;
269 }
270 #endif /* CONFIG_ARCH_MISC_INIT */