Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * setup.c | |
3 | * | |
4 | * BRIEF MODULE DESCRIPTION | |
5 | * Momentum Computer Ocelot-3 board dependent boot routines | |
6 | * | |
7 | * Copyright (C) 1996, 1997, 01, 05 Ralf Baechle | |
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 RB |
60 | #include <linux/pm.h> |
61 | ||
1da177e4 LT |
62 | #include <asm/time.h> |
63 | #include <asm/page.h> | |
64 | #include <asm/bootinfo.h> | |
65 | #include <asm/io.h> | |
66 | #include <asm/irq.h> | |
67 | #include <asm/pci.h> | |
68 | #include <asm/processor.h> | |
69 | #include <asm/ptrace.h> | |
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 | ||
134 | #define CONV_BCD_TO_BIN(val) (((val) & 0xf) + (((val) >> 4) * 10)) | |
135 | #define CONV_BIN_TO_BCD(val) (((val) % 10) + (((val) / 10) << 4)) | |
136 | ||
137 | unsigned long m48t37y_get_time(void) | |
138 | { | |
139 | unsigned int year, month, day, hour, min, sec; | |
53c2df2f | 140 | unsigned long flags; |
1da177e4 | 141 | |
53c2df2f | 142 | spin_lock_irqsave(&rtc_lock, flags); |
1da177e4 LT |
143 | /* stop the update */ |
144 | rtc_base[0x7ff8] = 0x40; | |
145 | ||
146 | year = CONV_BCD_TO_BIN(rtc_base[0x7fff]); | |
147 | year += CONV_BCD_TO_BIN(rtc_base[0x7ff1]) * 100; | |
148 | ||
149 | month = CONV_BCD_TO_BIN(rtc_base[0x7ffe]); | |
150 | ||
151 | day = CONV_BCD_TO_BIN(rtc_base[0x7ffd]); | |
152 | ||
153 | hour = CONV_BCD_TO_BIN(rtc_base[0x7ffb]); | |
154 | min = CONV_BCD_TO_BIN(rtc_base[0x7ffa]); | |
155 | sec = CONV_BCD_TO_BIN(rtc_base[0x7ff9]); | |
156 | ||
157 | /* start the update */ | |
158 | rtc_base[0x7ff8] = 0x00; | |
53c2df2f | 159 | spin_unlock_irqrestore(&rtc_lock, flags); |
1da177e4 LT |
160 | |
161 | return mktime(year, month, day, hour, min, sec); | |
162 | } | |
163 | ||
164 | int m48t37y_set_time(unsigned long sec) | |
165 | { | |
166 | struct rtc_time tm; | |
53c2df2f | 167 | unsigned long flags; |
1da177e4 LT |
168 | |
169 | /* convert to a more useful format -- note months count from 0 */ | |
170 | to_tm(sec, &tm); | |
171 | tm.tm_mon += 1; | |
172 | ||
53c2df2f | 173 | spin_lock_irqsave(&rtc_lock, flags); |
1da177e4 LT |
174 | /* enable writing */ |
175 | rtc_base[0x7ff8] = 0x80; | |
176 | ||
177 | /* year */ | |
178 | rtc_base[0x7fff] = CONV_BIN_TO_BCD(tm.tm_year % 100); | |
179 | rtc_base[0x7ff1] = CONV_BIN_TO_BCD(tm.tm_year / 100); | |
180 | ||
181 | /* month */ | |
182 | rtc_base[0x7ffe] = CONV_BIN_TO_BCD(tm.tm_mon); | |
183 | ||
184 | /* day */ | |
185 | rtc_base[0x7ffd] = CONV_BIN_TO_BCD(tm.tm_mday); | |
186 | ||
187 | /* hour/min/sec */ | |
188 | rtc_base[0x7ffb] = CONV_BIN_TO_BCD(tm.tm_hour); | |
189 | rtc_base[0x7ffa] = CONV_BIN_TO_BCD(tm.tm_min); | |
190 | rtc_base[0x7ff9] = CONV_BIN_TO_BCD(tm.tm_sec); | |
191 | ||
192 | /* day of week -- not really used, but let's keep it up-to-date */ | |
193 | rtc_base[0x7ffc] = CONV_BIN_TO_BCD(tm.tm_wday + 1); | |
194 | ||
195 | /* disable writing */ | |
196 | rtc_base[0x7ff8] = 0x00; | |
53c2df2f | 197 | spin_unlock_irqrestore(&rtc_lock, flags); |
1da177e4 LT |
198 | |
199 | return 0; | |
200 | } | |
201 | ||
202 | void momenco_timer_setup(struct irqaction *irq) | |
203 | { | |
204 | setup_irq(7, irq); /* Timer interrupt, unmask status IM7 */ | |
205 | } | |
206 | ||
207 | void momenco_time_init(void) | |
208 | { | |
209 | setup_wired_tlb_entries(); | |
210 | ||
211 | /* | |
212 | * Ocelot-3 board has been built with both | |
213 | * the Rm7900 and the Rm7065C | |
214 | */ | |
215 | mips_hpt_frequency = cpu_clock / 2; | |
216 | board_timer_setup = momenco_timer_setup; | |
217 | ||
d23ee8fe YY |
218 | rtc_mips_get_time = m48t37y_get_time; |
219 | rtc_mips_set_time = m48t37y_set_time; | |
1da177e4 LT |
220 | } |
221 | ||
222 | /* | |
223 | * PCI Support for Ocelot-3 | |
224 | */ | |
225 | ||
226 | /* Bus #0 IO and MEM space */ | |
227 | #define OCELOT_3_PCI_IO_0_START 0xe0000000 | |
228 | #define OCELOT_3_PCI_IO_0_SIZE 0x08000000 | |
229 | #define OCELOT_3_PCI_MEM_0_START 0xc0000000 | |
230 | #define OCELOT_3_PCI_MEM_0_SIZE 0x10000000 | |
231 | ||
232 | /* Bus #1 IO and MEM space */ | |
233 | #define OCELOT_3_PCI_IO_1_START 0xe8000000 | |
234 | #define OCELOT_3_PCI_IO_1_SIZE 0x08000000 | |
235 | #define OCELOT_3_PCI_MEM_1_START 0xd0000000 | |
236 | #define OCELOT_3_PCI_MEM_1_SIZE 0x10000000 | |
237 | ||
238 | static struct resource mv_pci_io_mem0_resource = { | |
239 | .name = "MV64340 PCI0 IO MEM", | |
240 | .start = OCELOT_3_PCI_IO_0_START, | |
241 | .end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE - 1, | |
242 | .flags = IORESOURCE_IO, | |
243 | }; | |
244 | ||
245 | static struct resource mv_pci_io_mem1_resource = { | |
246 | .name = "MV64340 PCI1 IO MEM", | |
247 | .start = OCELOT_3_PCI_IO_1_START, | |
248 | .end = OCELOT_3_PCI_IO_1_START + OCELOT_3_PCI_IO_1_SIZE - 1, | |
249 | .flags = IORESOURCE_IO, | |
250 | }; | |
251 | ||
252 | static struct resource mv_pci_mem0_resource = { | |
253 | .name = "MV64340 PCI0 MEM", | |
254 | .start = OCELOT_3_PCI_MEM_0_START, | |
255 | .end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE - 1, | |
256 | .flags = IORESOURCE_MEM, | |
257 | }; | |
258 | ||
259 | static struct resource mv_pci_mem1_resource = { | |
260 | .name = "MV64340 PCI1 MEM", | |
261 | .start = OCELOT_3_PCI_MEM_1_START, | |
262 | .end = OCELOT_3_PCI_MEM_1_START + OCELOT_3_PCI_MEM_1_SIZE - 1, | |
263 | .flags = IORESOURCE_MEM, | |
264 | }; | |
265 | ||
266 | static struct mv_pci_controller mv_bus0_controller = { | |
267 | .pcic = { | |
268 | .pci_ops = &mv_pci_ops, | |
269 | .mem_resource = &mv_pci_mem0_resource, | |
270 | .io_resource = &mv_pci_io_mem0_resource, | |
271 | }, | |
272 | .config_addr = MV64340_PCI_0_CONFIG_ADDR, | |
273 | .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG, | |
274 | }; | |
275 | ||
276 | static struct mv_pci_controller mv_bus1_controller = { | |
277 | .pcic = { | |
278 | .pci_ops = &mv_pci_ops, | |
279 | .mem_resource = &mv_pci_mem1_resource, | |
280 | .io_resource = &mv_pci_io_mem1_resource, | |
281 | }, | |
282 | .config_addr = MV64340_PCI_1_CONFIG_ADDR, | |
283 | .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG, | |
284 | }; | |
285 | ||
286 | static __init int __init ja_pci_init(void) | |
287 | { | |
288 | uint32_t enable; | |
289 | extern int pci_probe_only; | |
290 | ||
291 | /* PMON will assign PCI resources */ | |
292 | pci_probe_only = 1; | |
293 | ||
294 | enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE); | |
295 | /* | |
296 | * We require at least one enabled I/O or PCI memory window or we | |
297 | * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3. | |
298 | */ | |
299 | if (enable & (0x01 << 9) || enable & (0x01 << 10)) | |
300 | register_pci_controller(&mv_bus0_controller.pcic); | |
301 | ||
302 | if (enable & (0x01 << 14) || enable & (0x01 << 15)) | |
303 | register_pci_controller(&mv_bus1_controller.pcic); | |
304 | ||
305 | ioport_resource.end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE + | |
306 | OCELOT_3_PCI_IO_1_SIZE - 1; | |
307 | ||
308 | iomem_resource.end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE + | |
309 | OCELOT_3_PCI_MEM_1_SIZE - 1; | |
310 | ||
311 | set_io_port_base(OCELOT_3_PCI_IO_0_START); /* mips_io_port_base */ | |
312 | ||
313 | return 0; | |
314 | } | |
315 | ||
316 | arch_initcall(ja_pci_init); | |
317 | ||
c83cfc9c | 318 | void __init plat_setup(void) |
1da177e4 LT |
319 | { |
320 | unsigned int tmpword; | |
321 | ||
322 | board_time_init = momenco_time_init; | |
323 | ||
324 | _machine_restart = momenco_ocelot_restart; | |
325 | _machine_halt = momenco_ocelot_halt; | |
fcdb27ad | 326 | pm_power_off = momenco_ocelot_power_off; |
1da177e4 LT |
327 | |
328 | /* Wired TLB entries */ | |
329 | setup_wired_tlb_entries(); | |
330 | ||
331 | /* shut down ethernet ports, just to be sure our memory doesn't get | |
332 | * corrupted by random ethernet traffic. | |
333 | */ | |
334 | MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8); | |
335 | MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8); | |
336 | MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8); | |
337 | MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8); | |
338 | do {} | |
339 | while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff); | |
340 | do {} | |
341 | while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff); | |
342 | do {} | |
343 | while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff); | |
344 | do {} | |
345 | while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff); | |
346 | MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0), | |
347 | MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1); | |
348 | MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1), | |
349 | MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1); | |
350 | ||
351 | /* Turn off the Bit-Error LED */ | |
352 | OCELOT_FPGA_WRITE(0x80, CLR); | |
353 | ||
354 | tmpword = OCELOT_FPGA_READ(BOARDREV); | |
355 | if (tmpword < 26) | |
356 | printk("Momenco Ocelot-3: Board Assembly Rev. %c\n", | |
357 | 'A'+tmpword); | |
358 | else | |
359 | printk("Momenco Ocelot-3: Board Assembly Revision #0x%x\n", | |
360 | tmpword); | |
361 | ||
362 | tmpword = OCELOT_FPGA_READ(FPGA_REV); | |
363 | printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15); | |
364 | tmpword = OCELOT_FPGA_READ(RESET_STATUS); | |
365 | printk("Reset reason: 0x%x\n", tmpword); | |
366 | switch (tmpword) { | |
367 | case 0x1: | |
368 | printk(" - Power-up reset\n"); | |
369 | break; | |
370 | case 0x2: | |
371 | printk(" - Push-button reset\n"); | |
372 | break; | |
373 | case 0x4: | |
374 | printk(" - cPCI bus reset\n"); | |
375 | break; | |
376 | case 0x8: | |
377 | printk(" - Watchdog reset\n"); | |
378 | break; | |
379 | case 0x10: | |
380 | printk(" - Software reset\n"); | |
381 | break; | |
382 | default: | |
383 | printk(" - Unknown reset cause\n"); | |
384 | } | |
385 | reset_reason = tmpword; | |
386 | OCELOT_FPGA_WRITE(0xff, RESET_STATUS); | |
387 | ||
388 | tmpword = OCELOT_FPGA_READ(CPCI_ID); | |
389 | printk("cPCI ID register: 0x%02x\n", tmpword); | |
390 | printk(" - Slot number: %d\n", tmpword & 0x1f); | |
391 | printk(" - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no"); | |
392 | printk(" - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no"); | |
393 | ||
394 | tmpword = OCELOT_FPGA_READ(BOARD_STATUS); | |
395 | printk("Board Status register: 0x%02x\n", tmpword); | |
396 | printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent"); | |
397 | printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent"); | |
398 | printk(" - L3 cache size: %d MB\n", (1<<((tmpword&12) >> 2))&~1); | |
399 | ||
400 | /* Support for 128 MB memory */ | |
401 | add_memory_region(0x0, 0x08000000, BOOT_MEM_RAM); | |
1da177e4 | 402 | } |