Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * setup.c | |
3 | * | |
4 | * BRIEF MODULE DESCRIPTION | |
5 | * Momentum Computer Ocelot-3 board dependent boot routines | |
6 | * | |
ff28cbd2 | 7 | * Copyright (C) 1996, 1997, 01, 05 - 06 Ralf Baechle |
1da177e4 LT |
8 | * Copyright (C) 2000 RidgeRun, Inc. |
9 | * Copyright (C) 2001 Red Hat, Inc. | |
10 | * Copyright (C) 2002 Momentum Computer | |
11 | * | |
12 | * Author: Matthew Dharm, Momentum Computer | |
13 | * mdharm@momenco.com | |
14 | * | |
15 | * Louis Hamilton, Red Hat, Inc. | |
16 | * hamilton@redhat.com [MIPS64 modifications] | |
17 | * | |
18 | * Author: RidgeRun, Inc. | |
19 | * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com | |
20 | * | |
21 | * Copyright 2001 MontaVista Software Inc. | |
22 | * Author: jsun@mvista.com or jsun@junsun.net | |
23 | * | |
24 | * Copyright 2004 PMC-Sierra | |
25 | * Author: Manish Lachwani (lachwani@pmc-sierra.com) | |
26 | * | |
27 | * Copyright (C) 2004 MontaVista Software Inc. | |
28 | * Author: Manish Lachwani, mlachwani@mvista.com | |
29 | * | |
30 | * This program is free software; you can redistribute it and/or modify it | |
31 | * under the terms of the GNU General Public License as published by the | |
32 | * Free Software Foundation; either version 2 of the License, or (at your | |
33 | * option) any later version. | |
34 | * | |
35 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
36 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
37 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | |
38 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
39 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
40 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |
41 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
42 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
43 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
44 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
45 | * | |
46 | * You should have received a copy of the GNU General Public License along | |
47 | * with this program; if not, write to the Free Software Foundation, Inc., | |
48 | * 675 Mass Ave, Cambridge, MA 02139, USA. | |
49 | */ | |
50 | #include <linux/init.h> | |
51 | #include <linux/kernel.h> | |
52 | #include <linux/types.h> | |
53 | #include <linux/mc146818rtc.h> | |
54 | #include <linux/ioport.h> | |
55 | #include <linux/interrupt.h> | |
56 | #include <linux/pci.h> | |
57 | #include <linux/timex.h> | |
58 | #include <linux/bootmem.h> | |
59 | #include <linux/mv643xx.h> | |
fcdb27ad | 60 | #include <linux/pm.h> |
4f3a36a7 | 61 | #include <linux/bcd.h> |
fcdb27ad | 62 | |
1da177e4 LT |
63 | #include <asm/time.h> |
64 | #include <asm/page.h> | |
65 | #include <asm/bootinfo.h> | |
66 | #include <asm/io.h> | |
67 | #include <asm/irq.h> | |
68 | #include <asm/pci.h> | |
69 | #include <asm/processor.h> | |
1da177e4 LT |
70 | #include <asm/reboot.h> |
71 | #include <asm/mc146818rtc.h> | |
72 | #include <asm/tlbflush.h> | |
73 | #include "ocelot_3_fpga.h" | |
74 | ||
75 | /* Marvell Discovery Register Base */ | |
76 | unsigned long marvell_base = (signed)0xf4000000; | |
77 | ||
78 | /* CPU clock */ | |
79 | unsigned long cpu_clock; | |
80 | ||
81 | /* RTC/NVRAM */ | |
82 | unsigned char* rtc_base = (unsigned char*)(signed)0xfc800000; | |
83 | ||
84 | /* FPGA Base */ | |
85 | unsigned long ocelot_fpga_base = (signed)0xfc000000; | |
86 | ||
87 | /* Serial base */ | |
88 | unsigned long uart_base = (signed)0xfd000000; | |
89 | ||
90 | /* | |
91 | * Marvell Discovery SRAM. This is one place where Ethernet | |
92 | * Tx and Rx descriptors can be placed to improve performance | |
93 | */ | |
94 | extern unsigned long mv64340_sram_base; | |
95 | ||
96 | /* These functions are used for rebooting or halting the machine*/ | |
97 | extern void momenco_ocelot_restart(char *command); | |
98 | extern void momenco_ocelot_halt(void); | |
99 | extern void momenco_ocelot_power_off(void); | |
100 | ||
101 | void momenco_time_init(void); | |
102 | static char reset_reason; | |
103 | ||
104 | void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, | |
105 | unsigned long entryhi, unsigned long pagemask); | |
106 | ||
107 | static inline unsigned long ENTRYLO(unsigned long paddr) | |
108 | { | |
109 | return ((paddr & PAGE_MASK) | | |
110 | (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL | | |
111 | _CACHE_UNCACHED)) >> 6; | |
112 | } | |
113 | ||
114 | void __init bus_error_init(void) | |
115 | { | |
116 | /* nothing */ | |
117 | } | |
118 | ||
119 | /* | |
120 | * setup code for a handoff from a version 2 PMON 2000 PROM | |
121 | */ | |
122 | void setup_wired_tlb_entries(void) | |
123 | { | |
124 | write_c0_wired(0); | |
125 | local_flush_tlb_all(); | |
126 | ||
127 | /* marvell and extra space */ | |
128 | add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), (signed)0xf4000000, PM_64K); | |
129 | ||
130 | /* fpga, rtc, and uart */ | |
131 | add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), (signed)0xfc000000, PM_16M); | |
132 | } | |
133 | ||
1da177e4 LT |
134 | unsigned long m48t37y_get_time(void) |
135 | { | |
136 | unsigned int year, month, day, hour, min, sec; | |
53c2df2f | 137 | unsigned long flags; |
1da177e4 | 138 | |
53c2df2f | 139 | spin_lock_irqsave(&rtc_lock, flags); |
1da177e4 LT |
140 | /* stop the update */ |
141 | rtc_base[0x7ff8] = 0x40; | |
142 | ||
4f3a36a7 MM |
143 | year = BCD2BIN(rtc_base[0x7fff]); |
144 | year += BCD2BIN(rtc_base[0x7ff1]) * 100; | |
1da177e4 | 145 | |
4f3a36a7 | 146 | month = BCD2BIN(rtc_base[0x7ffe]); |
1da177e4 | 147 | |
4f3a36a7 | 148 | day = BCD2BIN(rtc_base[0x7ffd]); |
1da177e4 | 149 | |
4f3a36a7 MM |
150 | hour = BCD2BIN(rtc_base[0x7ffb]); |
151 | min = BCD2BIN(rtc_base[0x7ffa]); | |
152 | sec = BCD2BIN(rtc_base[0x7ff9]); | |
1da177e4 LT |
153 | |
154 | /* start the update */ | |
155 | rtc_base[0x7ff8] = 0x00; | |
53c2df2f | 156 | spin_unlock_irqrestore(&rtc_lock, flags); |
1da177e4 LT |
157 | |
158 | return mktime(year, month, day, hour, min, sec); | |
159 | } | |
160 | ||
161 | int m48t37y_set_time(unsigned long sec) | |
162 | { | |
163 | struct rtc_time tm; | |
53c2df2f | 164 | unsigned long flags; |
1da177e4 LT |
165 | |
166 | /* convert to a more useful format -- note months count from 0 */ | |
167 | to_tm(sec, &tm); | |
168 | tm.tm_mon += 1; | |
169 | ||
53c2df2f | 170 | spin_lock_irqsave(&rtc_lock, flags); |
1da177e4 LT |
171 | /* enable writing */ |
172 | rtc_base[0x7ff8] = 0x80; | |
173 | ||
174 | /* year */ | |
4f3a36a7 MM |
175 | rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100); |
176 | rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100); | |
1da177e4 LT |
177 | |
178 | /* month */ | |
4f3a36a7 | 179 | rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon); |
1da177e4 LT |
180 | |
181 | /* day */ | |
4f3a36a7 | 182 | rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday); |
1da177e4 LT |
183 | |
184 | /* hour/min/sec */ | |
4f3a36a7 MM |
185 | rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour); |
186 | rtc_base[0x7ffa] = BIN2BCD(tm.tm_min); | |
187 | rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec); | |
1da177e4 LT |
188 | |
189 | /* day of week -- not really used, but let's keep it up-to-date */ | |
4f3a36a7 | 190 | rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1); |
1da177e4 LT |
191 | |
192 | /* disable writing */ | |
193 | rtc_base[0x7ff8] = 0x00; | |
53c2df2f | 194 | spin_unlock_irqrestore(&rtc_lock, flags); |
1da177e4 LT |
195 | |
196 | return 0; | |
197 | } | |
198 | ||
54d0a216 | 199 | void __init plat_timer_setup(struct irqaction *irq) |
1da177e4 LT |
200 | { |
201 | setup_irq(7, irq); /* Timer interrupt, unmask status IM7 */ | |
202 | } | |
203 | ||
204 | void momenco_time_init(void) | |
205 | { | |
206 | setup_wired_tlb_entries(); | |
207 | ||
208 | /* | |
209 | * Ocelot-3 board has been built with both | |
210 | * the Rm7900 and the Rm7065C | |
211 | */ | |
212 | mips_hpt_frequency = cpu_clock / 2; | |
1da177e4 | 213 | |
d23ee8fe YY |
214 | rtc_mips_get_time = m48t37y_get_time; |
215 | rtc_mips_set_time = m48t37y_set_time; | |
1da177e4 LT |
216 | } |
217 | ||
218 | /* | |
219 | * PCI Support for Ocelot-3 | |
220 | */ | |
221 | ||
222 | /* Bus #0 IO and MEM space */ | |
223 | #define OCELOT_3_PCI_IO_0_START 0xe0000000 | |
224 | #define OCELOT_3_PCI_IO_0_SIZE 0x08000000 | |
225 | #define OCELOT_3_PCI_MEM_0_START 0xc0000000 | |
226 | #define OCELOT_3_PCI_MEM_0_SIZE 0x10000000 | |
227 | ||
228 | /* Bus #1 IO and MEM space */ | |
229 | #define OCELOT_3_PCI_IO_1_START 0xe8000000 | |
230 | #define OCELOT_3_PCI_IO_1_SIZE 0x08000000 | |
231 | #define OCELOT_3_PCI_MEM_1_START 0xd0000000 | |
232 | #define OCELOT_3_PCI_MEM_1_SIZE 0x10000000 | |
233 | ||
234 | static struct resource mv_pci_io_mem0_resource = { | |
235 | .name = "MV64340 PCI0 IO MEM", | |
236 | .start = OCELOT_3_PCI_IO_0_START, | |
237 | .end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE - 1, | |
238 | .flags = IORESOURCE_IO, | |
239 | }; | |
240 | ||
241 | static struct resource mv_pci_io_mem1_resource = { | |
242 | .name = "MV64340 PCI1 IO MEM", | |
243 | .start = OCELOT_3_PCI_IO_1_START, | |
244 | .end = OCELOT_3_PCI_IO_1_START + OCELOT_3_PCI_IO_1_SIZE - 1, | |
245 | .flags = IORESOURCE_IO, | |
246 | }; | |
247 | ||
248 | static struct resource mv_pci_mem0_resource = { | |
249 | .name = "MV64340 PCI0 MEM", | |
250 | .start = OCELOT_3_PCI_MEM_0_START, | |
251 | .end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE - 1, | |
252 | .flags = IORESOURCE_MEM, | |
253 | }; | |
254 | ||
255 | static struct resource mv_pci_mem1_resource = { | |
256 | .name = "MV64340 PCI1 MEM", | |
257 | .start = OCELOT_3_PCI_MEM_1_START, | |
258 | .end = OCELOT_3_PCI_MEM_1_START + OCELOT_3_PCI_MEM_1_SIZE - 1, | |
259 | .flags = IORESOURCE_MEM, | |
260 | }; | |
261 | ||
262 | static struct mv_pci_controller mv_bus0_controller = { | |
263 | .pcic = { | |
264 | .pci_ops = &mv_pci_ops, | |
265 | .mem_resource = &mv_pci_mem0_resource, | |
266 | .io_resource = &mv_pci_io_mem0_resource, | |
267 | }, | |
268 | .config_addr = MV64340_PCI_0_CONFIG_ADDR, | |
269 | .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG, | |
270 | }; | |
271 | ||
272 | static struct mv_pci_controller mv_bus1_controller = { | |
273 | .pcic = { | |
274 | .pci_ops = &mv_pci_ops, | |
275 | .mem_resource = &mv_pci_mem1_resource, | |
276 | .io_resource = &mv_pci_io_mem1_resource, | |
277 | }, | |
278 | .config_addr = MV64340_PCI_1_CONFIG_ADDR, | |
279 | .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG, | |
280 | }; | |
281 | ||
282 | static __init int __init ja_pci_init(void) | |
283 | { | |
284 | uint32_t enable; | |
285 | extern int pci_probe_only; | |
286 | ||
287 | /* PMON will assign PCI resources */ | |
288 | pci_probe_only = 1; | |
289 | ||
290 | enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE); | |
291 | /* | |
292 | * We require at least one enabled I/O or PCI memory window or we | |
293 | * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3. | |
294 | */ | |
295 | if (enable & (0x01 << 9) || enable & (0x01 << 10)) | |
296 | register_pci_controller(&mv_bus0_controller.pcic); | |
297 | ||
298 | if (enable & (0x01 << 14) || enable & (0x01 << 15)) | |
299 | register_pci_controller(&mv_bus1_controller.pcic); | |
300 | ||
301 | ioport_resource.end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE + | |
302 | OCELOT_3_PCI_IO_1_SIZE - 1; | |
303 | ||
304 | iomem_resource.end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE + | |
305 | OCELOT_3_PCI_MEM_1_SIZE - 1; | |
306 | ||
307 | set_io_port_base(OCELOT_3_PCI_IO_0_START); /* mips_io_port_base */ | |
308 | ||
309 | return 0; | |
310 | } | |
311 | ||
312 | arch_initcall(ja_pci_init); | |
313 | ||
2925aba4 | 314 | void __init plat_mem_setup(void) |
1da177e4 LT |
315 | { |
316 | unsigned int tmpword; | |
317 | ||
318 | board_time_init = momenco_time_init; | |
319 | ||
320 | _machine_restart = momenco_ocelot_restart; | |
321 | _machine_halt = momenco_ocelot_halt; | |
fcdb27ad | 322 | pm_power_off = momenco_ocelot_power_off; |
1da177e4 LT |
323 | |
324 | /* Wired TLB entries */ | |
325 | setup_wired_tlb_entries(); | |
326 | ||
327 | /* shut down ethernet ports, just to be sure our memory doesn't get | |
328 | * corrupted by random ethernet traffic. | |
329 | */ | |
c40b92e0 RB |
330 | MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8); |
331 | MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8); | |
332 | MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8); | |
333 | MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8); | |
1da177e4 | 334 | do {} |
c40b92e0 | 335 | while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff); |
1da177e4 | 336 | do {} |
c40b92e0 | 337 | while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff); |
1da177e4 | 338 | do {} |
c40b92e0 | 339 | while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff); |
1da177e4 | 340 | do {} |
c40b92e0 RB |
341 | while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff); |
342 | MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0), | |
343 | MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1); | |
344 | MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1), | |
345 | MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1); | |
1da177e4 LT |
346 | |
347 | /* Turn off the Bit-Error LED */ | |
348 | OCELOT_FPGA_WRITE(0x80, CLR); | |
349 | ||
350 | tmpword = OCELOT_FPGA_READ(BOARDREV); | |
351 | if (tmpword < 26) | |
352 | printk("Momenco Ocelot-3: Board Assembly Rev. %c\n", | |
353 | 'A'+tmpword); | |
354 | else | |
355 | printk("Momenco Ocelot-3: Board Assembly Revision #0x%x\n", | |
356 | tmpword); | |
357 | ||
358 | tmpword = OCELOT_FPGA_READ(FPGA_REV); | |
359 | printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15); | |
360 | tmpword = OCELOT_FPGA_READ(RESET_STATUS); | |
361 | printk("Reset reason: 0x%x\n", tmpword); | |
362 | switch (tmpword) { | |
363 | case 0x1: | |
364 | printk(" - Power-up reset\n"); | |
365 | break; | |
366 | case 0x2: | |
367 | printk(" - Push-button reset\n"); | |
368 | break; | |
369 | case 0x4: | |
370 | printk(" - cPCI bus reset\n"); | |
371 | break; | |
372 | case 0x8: | |
373 | printk(" - Watchdog reset\n"); | |
374 | break; | |
375 | case 0x10: | |
376 | printk(" - Software reset\n"); | |
377 | break; | |
378 | default: | |
379 | printk(" - Unknown reset cause\n"); | |
380 | } | |
381 | reset_reason = tmpword; | |
382 | OCELOT_FPGA_WRITE(0xff, RESET_STATUS); | |
383 | ||
384 | tmpword = OCELOT_FPGA_READ(CPCI_ID); | |
385 | printk("cPCI ID register: 0x%02x\n", tmpword); | |
386 | printk(" - Slot number: %d\n", tmpword & 0x1f); | |
387 | printk(" - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no"); | |
388 | printk(" - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no"); | |
389 | ||
390 | tmpword = OCELOT_FPGA_READ(BOARD_STATUS); | |
391 | printk("Board Status register: 0x%02x\n", tmpword); | |
392 | printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent"); | |
393 | printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent"); | |
394 | printk(" - L3 cache size: %d MB\n", (1<<((tmpword&12) >> 2))&~1); | |
395 | ||
396 | /* Support for 128 MB memory */ | |
397 | add_memory_region(0x0, 0x08000000, BOOT_MEM_RAM); | |
1da177e4 | 398 | } |