Commit | Line | Data |
---|---|---|
35189fad RB |
1 | /* |
2 | * Copyright (C) 2004, 2005 by Basler Vision Technologies AG | |
3 | * Author: Thomas Koeller <thomas.koeller@baslerweb.com> | |
4 | * Based on the PMC-Sierra Yosemite board support by Ralf Baechle and | |
5 | * Manish Lachwani. | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 | */ | |
21 | ||
35189fad RB |
22 | #include <linux/types.h> |
23 | #include <linux/kernel.h> | |
24 | #include <linux/module.h> | |
25 | #include <linux/string.h> | |
26 | #include <linux/tty.h> | |
27 | #include <linux/serial_core.h> | |
28 | #include <linux/serial.h> | |
b187f180 | 29 | #include <linux/serial_8250.h> |
35189fad RB |
30 | #include <linux/ioport.h> |
31 | #include <linux/spinlock.h> | |
32 | #include <asm/bootinfo.h> | |
33 | #include <asm/mipsregs.h> | |
34 | #include <asm/pgtable-32.h> | |
35 | #include <asm/io.h> | |
36 | #include <asm/time.h> | |
37 | #include <asm/rm9k-ocd.h> | |
38 | ||
39 | #include <excite.h> | |
40 | ||
41 | #define TITAN_UART_CLK 25000000 | |
42 | ||
43 | #if 1 | |
44 | /* normal serial port assignment */ | |
45 | #define REGBASE_SER0 0x0208 | |
46 | #define REGBASE_SER1 0x0238 | |
47 | #define MASK_SER0 0x1 | |
48 | #define MASK_SER1 0x2 | |
49 | #else | |
50 | /* serial ports swapped */ | |
51 | #define REGBASE_SER0 0x0238 | |
52 | #define REGBASE_SER1 0x0208 | |
53 | #define MASK_SER0 0x2 | |
54 | #define MASK_SER1 0x1 | |
55 | #endif | |
56 | ||
57 | unsigned long memsize; | |
58 | char modetty[30]; | |
59 | unsigned int titan_irq = TITAN_IRQ; | |
60 | static void __iomem * ctl_regs; | |
61 | u32 unit_id; | |
62 | ||
63 | volatile void __iomem * const ocd_base = (void *) (EXCITE_ADDR_OCD); | |
64 | volatile void __iomem * const titan_base = (void *) (EXCITE_ADDR_TITAN); | |
65 | ||
66 | /* Protect access to shared GPI registers */ | |
820c229f | 67 | DEFINE_SPINLOCK(titan_lock); |
35189fad RB |
68 | int titan_irqflags; |
69 | ||
70 | ||
71 | static void excite_timer_init(void) | |
72 | { | |
73 | const u32 modebit5 = ocd_readl(0x00e4); | |
74 | unsigned int | |
75 | mult = ((modebit5 >> 11) & 0x1f) + 2, | |
76 | div = ((modebit5 >> 16) & 0x1f) + 2; | |
77 | ||
78 | if (div == 33) div = 1; | |
79 | mips_hpt_frequency = EXCITE_CPU_EXT_CLOCK * mult / div / 2; | |
80 | } | |
81 | ||
54d0a216 | 82 | void __init plat_timer_setup(struct irqaction *irq) |
35189fad RB |
83 | { |
84 | /* The eXcite platform uses the alternate timer interrupt */ | |
85 | set_c0_intcontrol(0x80); | |
86 | setup_irq(TIMER_IRQ, irq); | |
87 | } | |
88 | ||
89 | static int __init excite_init_console(void) | |
90 | { | |
91 | #if defined(CONFIG_SERIAL_8250) | |
92 | static __initdata char serr[] = | |
93 | KERN_ERR "Serial port #%u setup failed\n"; | |
94 | struct uart_port up; | |
95 | ||
96 | /* Take the DUART out of reset */ | |
97 | titan_writel(0x00ff1cff, CPRR); | |
98 | ||
99 | #if defined(CONFIG_KGDB) || (CONFIG_SERIAL_8250_NR_UARTS > 1) | |
100 | /* Enable both ports */ | |
101 | titan_writel(MASK_SER0 | MASK_SER1, UACFG); | |
102 | #else | |
103 | /* Enable port #0 only */ | |
104 | titan_writel(MASK_SER0, UACFG); | |
105 | #endif /* defined(CONFIG_KGDB) */ | |
106 | ||
107 | /* | |
108 | * Set up serial port #0. Do not use autodetection; the result is | |
109 | * not what we want. | |
110 | */ | |
111 | memset(&up, 0, sizeof(up)); | |
112 | up.membase = (char *) titan_addr(REGBASE_SER0); | |
113 | up.irq = TITAN_IRQ; | |
114 | up.uartclk = TITAN_UART_CLK; | |
115 | up.regshift = 0; | |
cbc84135 | 116 | up.iotype = UPIO_RM9000; |
35189fad RB |
117 | up.type = PORT_RM9000; |
118 | up.flags = UPF_SHARE_IRQ; | |
119 | up.line = 0; | |
120 | if (early_serial_setup(&up)) | |
121 | printk(serr, up.line); | |
122 | ||
123 | #if CONFIG_SERIAL_8250_NR_UARTS > 1 | |
124 | /* And now for port #1. */ | |
125 | up.membase = (char *) titan_addr(REGBASE_SER1); | |
126 | up.line = 1; | |
127 | if (early_serial_setup(&up)) | |
128 | printk(serr, up.line); | |
129 | #endif /* CONFIG_SERIAL_8250_NR_UARTS > 1 */ | |
130 | #else | |
131 | /* Leave the DUART in reset */ | |
132 | titan_writel(0x00ff3cff, CPRR); | |
133 | #endif /* defined(CONFIG_SERIAL_8250) */ | |
134 | ||
135 | return 0; | |
136 | } | |
137 | ||
138 | static int __init excite_platform_init(void) | |
139 | { | |
140 | unsigned int i; | |
141 | unsigned char buf[3]; | |
142 | u8 reg; | |
143 | void __iomem * dpr; | |
144 | ||
145 | /* BIU buffer allocations */ | |
146 | ocd_writel(8, CPURSLMT); /* CPU */ | |
147 | titan_writel(4, CPGRWL); /* GPI / Ethernet */ | |
148 | ||
149 | /* Map control registers located in FPGA */ | |
150 | ctl_regs = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_SYSCTL, 16); | |
151 | if (!ctl_regs) | |
152 | panic("eXcite: failed to map platform control registers\n"); | |
153 | memcpy_fromio(buf, ctl_regs + 2, ARRAY_SIZE(buf)); | |
154 | unit_id = buf[0] | (buf[1] << 8) | (buf[2] << 16); | |
155 | ||
156 | /* Clear the reboot flag */ | |
157 | dpr = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_DPR, 1); | |
158 | reg = __raw_readb(dpr); | |
159 | __raw_writeb(reg & 0x7f, dpr); | |
160 | iounmap(dpr); | |
161 | ||
162 | /* Interrupt controller setup */ | |
163 | for (i = INTP0Status0; i < INTP0Status0 + 0x80; i += 0x10) { | |
164 | ocd_writel(0x00000000, i + 0x04); | |
165 | ocd_writel(0xffffffff, i + 0x0c); | |
166 | } | |
167 | ocd_writel(0x2, NMICONFIG); | |
168 | ||
169 | ocd_writel(0x1 << (TITAN_MSGINT % 0x20), | |
170 | INTP0Mask0 + (0x10 * (TITAN_MSGINT / 0x20))); | |
171 | ocd_writel((0x1 << (FPGA0_MSGINT % 0x20)) | |
172 | | ocd_readl(INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20))), | |
173 | INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20))); | |
174 | ocd_writel((0x1 << (FPGA1_MSGINT % 0x20)) | |
175 | | ocd_readl(INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20))), | |
176 | INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20))); | |
177 | ocd_writel((0x1 << (PHY_MSGINT % 0x20)) | |
178 | | ocd_readl(INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20))), | |
179 | INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20))); | |
180 | #if USB_IRQ < 10 | |
181 | ocd_writel((0x1 << (USB_MSGINT % 0x20)) | |
182 | | ocd_readl(INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20))), | |
183 | INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20))); | |
184 | #endif | |
185 | /* Enable the packet FIFO, XDMA and XDMA arbiter */ | |
186 | titan_writel(0x00ff18ff, CPRR); | |
187 | ||
188 | /* | |
189 | * Set up the PADMUX. Power down all ethernet slices, | |
190 | * they will be powered up and configured at device startup. | |
191 | */ | |
192 | titan_writel(0x00878206, CPTC1R); | |
193 | titan_writel(0x00001100, CPTC0R); /* latch PADMUX, enable WCIMODE */ | |
194 | ||
195 | /* Reset and enable the FIFO block */ | |
196 | titan_writel(0x00000001, SDRXFCIE); | |
197 | titan_writel(0x00000001, SDTXFCIE); | |
198 | titan_writel(0x00000100, SDRXFCIE); | |
199 | titan_writel(0x00000000, SDTXFCIE); | |
200 | ||
201 | /* | |
202 | * Initialize the common interrupt shared by all components of | |
203 | * the GPI/Ethernet subsystem. | |
204 | */ | |
205 | titan_writel((EXCITE_PHYS_OCD >> 12), CPCFG0); | |
206 | titan_writel(TITAN_MSGINT, CPCFG1); | |
207 | ||
208 | /* | |
209 | * XDMA configuration. | |
210 | * In order for the XDMA to be sharable among multiple drivers, | |
211 | * the setup must be done here in the platform. The reason is that | |
212 | * this setup can only be done while the XDMA is in reset. If this | |
213 | * were done in a driver, it would interrupt all other drivers | |
214 | * using the XDMA. | |
215 | */ | |
216 | titan_writel(0x80021dff, GXCFG); /* XDMA reset */ | |
217 | titan_writel(0x00000000, CPXCISRA); | |
218 | titan_writel(0x00000000, CPXCISRB); /* clear pending interrupts */ | |
219 | #if defined (CONFIG_HIGHMEM) | |
220 | # error change for HIGHMEM support! | |
221 | #else | |
222 | titan_writel(0x00000000, GXDMADRPFX); /* buffer address prefix */ | |
223 | #endif | |
224 | titan_writel(0, GXDMA_DESCADR); | |
225 | ||
226 | for (i = 0x5040; i <= 0x5300; i += 0x0040) | |
227 | titan_writel(0x80080000, i); /* reset channel */ | |
228 | ||
229 | titan_writel((0x1 << 29) /* no sparse tx descr. */ | |
230 | | (0x1 << 28) /* no sparse rx descr. */ | |
231 | | (0x1 << 23) | (0x1 << 24) /* descriptor coherency */ | |
232 | | (0x1 << 21) | (0x1 << 22) /* data coherency */ | |
233 | | (0x1 << 17) | |
234 | | 0x1dff, | |
235 | GXCFG); | |
236 | ||
237 | #if defined(CONFIG_SMP) | |
238 | # error No SMP support | |
239 | #else | |
240 | /* All interrupts go to core #0 only. */ | |
241 | titan_writel(0x1f007fff, CPDST0A); | |
242 | titan_writel(0x00000000, CPDST0B); | |
243 | titan_writel(0x0000ff3f, CPDST1A); | |
244 | titan_writel(0x00000000, CPDST1B); | |
245 | titan_writel(0x00ffffff, CPXDSTA); | |
246 | titan_writel(0x00000000, CPXDSTB); | |
247 | #endif | |
248 | ||
249 | /* Enable DUART interrupts, disable everything else. */ | |
250 | titan_writel(0x04000000, CPGIG0ER); | |
251 | titan_writel(0x000000c0, CPGIG1ER); | |
252 | ||
253 | excite_procfs_init(); | |
254 | return 0; | |
255 | } | |
256 | ||
ec52d7bf | 257 | void __init plat_mem_setup(void) |
35189fad RB |
258 | { |
259 | volatile u32 * const boot_ocd_base = (u32 *) 0xbf7fc000; | |
260 | ||
261 | /* Announce RAM to system */ | |
262 | add_memory_region(0x00000000, memsize, BOOT_MEM_RAM); | |
263 | ||
264 | /* Set up timer initialization hooks */ | |
265 | board_time_init = excite_timer_init; | |
35189fad RB |
266 | |
267 | /* Set up the peripheral address map */ | |
268 | *(boot_ocd_base + (LKB9 / sizeof (u32))) = 0; | |
269 | *(boot_ocd_base + (LKB10 / sizeof (u32))) = 0; | |
270 | *(boot_ocd_base + (LKB11 / sizeof (u32))) = 0; | |
271 | *(boot_ocd_base + (LKB12 / sizeof (u32))) = 0; | |
272 | wmb(); | |
273 | *(boot_ocd_base + (LKB0 / sizeof (u32))) = EXCITE_PHYS_OCD >> 4; | |
274 | wmb(); | |
275 | ||
276 | ocd_writel((EXCITE_PHYS_TITAN >> 4) | 0x1UL, LKB5); | |
277 | ocd_writel(((EXCITE_SIZE_TITAN >> 4) & 0x7fffff00) - 0x100, LKM5); | |
278 | ocd_writel((EXCITE_PHYS_SCRAM >> 4) | 0x1UL, LKB13); | |
279 | ocd_writel(((EXCITE_SIZE_SCRAM >> 4) & 0xffffff00) - 0x100, LKM13); | |
280 | ||
281 | /* Local bus slot #0 */ | |
282 | ocd_writel(0x00040510, LDP0); | |
283 | ocd_writel((EXCITE_PHYS_BOOTROM >> 4) | 0x1UL, LKB9); | |
284 | ocd_writel(((EXCITE_SIZE_BOOTROM >> 4) & 0x03ffff00) - 0x100, LKM9); | |
285 | ||
286 | /* Local bus slot #2 */ | |
287 | ocd_writel(0x00000330, LDP2); | |
288 | ocd_writel((EXCITE_PHYS_FPGA >> 4) | 0x1, LKB11); | |
289 | ocd_writel(((EXCITE_SIZE_FPGA >> 4) - 0x100) & 0x03ffff00, LKM11); | |
290 | ||
291 | /* Local bus slot #3 */ | |
292 | ocd_writel(0x00123413, LDP3); | |
293 | ocd_writel((EXCITE_PHYS_NAND >> 4) | 0x1, LKB12); | |
294 | ocd_writel(((EXCITE_SIZE_NAND >> 4) - 0x100) & 0x03ffff00, LKM12); | |
295 | } | |
296 | ||
297 | ||
298 | ||
299 | console_initcall(excite_init_console); | |
300 | arch_initcall(excite_platform_init); | |
301 | ||
302 | EXPORT_SYMBOL(titan_lock); | |
303 | EXPORT_SYMBOL(titan_irqflags); | |
304 | EXPORT_SYMBOL(titan_irq); | |
305 | EXPORT_SYMBOL(ocd_base); | |
306 | EXPORT_SYMBOL(titan_base); |