diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2006-06-18 11:39:46 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2006-06-19 12:39:26 -0400 |
commit | 35189fad3cb5f6e3ab66c8321928a851de0cd2b1 (patch) | |
tree | 70dcd11a08d964da9ee27bc716b2205f250b42dd /arch/mips/basler | |
parent | 355c471f2ff324c21f8a1fb8e2e242a0f2a4aa68 (diff) |
[MIPS] Support for the RM9000-based Basler eXcite smart camera platform.
Signed-off-by: Thomas Koeller <thomas.koeller@baslerweb.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/basler')
-rw-r--r-- | arch/mips/basler/excite/Makefile | 9 | ||||
-rw-r--r-- | arch/mips/basler/excite/excite_dbg_io.c | 122 | ||||
-rw-r--r-- | arch/mips/basler/excite/excite_device.c | 404 | ||||
-rw-r--r-- | arch/mips/basler/excite/excite_flashtest.c | 294 | ||||
-rw-r--r-- | arch/mips/basler/excite/excite_fpga.h | 80 | ||||
-rw-r--r-- | arch/mips/basler/excite/excite_iodev.c | 183 | ||||
-rw-r--r-- | arch/mips/basler/excite/excite_iodev.h | 10 | ||||
-rw-r--r-- | arch/mips/basler/excite/excite_irq.c | 129 | ||||
-rw-r--r-- | arch/mips/basler/excite/excite_procfs.c | 81 | ||||
-rw-r--r-- | arch/mips/basler/excite/excite_prom.c | 148 | ||||
-rw-r--r-- | arch/mips/basler/excite/excite_setup.c | 307 |
11 files changed, 1767 insertions, 0 deletions
diff --git a/arch/mips/basler/excite/Makefile b/arch/mips/basler/excite/Makefile new file mode 100644 index 000000000000..519142c2e4ef --- /dev/null +++ b/arch/mips/basler/excite/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | # | ||
2 | # Makefile for Basler eXcite | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_BASLER_EXCITE) += excite_irq.o excite_prom.o excite_setup.o \ | ||
6 | excite_device.o excite_procfs.o | ||
7 | |||
8 | obj-$(CONFIG_KGDB) += excite_dbg_io.o | ||
9 | obj-m += excite_iodev.o | ||
diff --git a/arch/mips/basler/excite/excite_dbg_io.c b/arch/mips/basler/excite/excite_dbg_io.c new file mode 100644 index 000000000000..83f6bddf578b --- /dev/null +++ b/arch/mips/basler/excite/excite_dbg_io.c | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 by Basler Vision Technologies AG | ||
3 | * Author: Thomas Koeller <thomas.koeller@baslerweb.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/linkage.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <asm/gdb-stub.h> | ||
25 | #include <asm/rm9k-ocd.h> | ||
26 | #include <excite.h> | ||
27 | |||
28 | #if defined(CONFIG_SERIAL_8250) && CONFIG_SERIAL_8250_NR_UARTS > 1 | ||
29 | #error Debug port used by serial driver | ||
30 | #endif | ||
31 | |||
32 | #define UART_CLK 25000000 | ||
33 | #define BASE_BAUD (UART_CLK / 16) | ||
34 | #define REGISTER_BASE_0 0x0208UL | ||
35 | #define REGISTER_BASE_1 0x0238UL | ||
36 | |||
37 | #define REGISTER_BASE_DBG REGISTER_BASE_1 | ||
38 | |||
39 | #define CPRR 0x0004 | ||
40 | #define UACFG 0x0200 | ||
41 | #define UAINTS 0x0204 | ||
42 | #define UARBR (REGISTER_BASE_DBG + 0x0000) | ||
43 | #define UATHR (REGISTER_BASE_DBG + 0x0004) | ||
44 | #define UADLL (REGISTER_BASE_DBG + 0x0008) | ||
45 | #define UAIER (REGISTER_BASE_DBG + 0x000c) | ||
46 | #define UADLH (REGISTER_BASE_DBG + 0x0010) | ||
47 | #define UAIIR (REGISTER_BASE_DBG + 0x0014) | ||
48 | #define UAFCR (REGISTER_BASE_DBG + 0x0018) | ||
49 | #define UALCR (REGISTER_BASE_DBG + 0x001c) | ||
50 | #define UAMCR (REGISTER_BASE_DBG + 0x0020) | ||
51 | #define UALSR (REGISTER_BASE_DBG + 0x0024) | ||
52 | #define UAMSR (REGISTER_BASE_DBG + 0x0028) | ||
53 | #define UASCR (REGISTER_BASE_DBG + 0x002c) | ||
54 | |||
55 | #define PARITY_NONE 0 | ||
56 | #define PARITY_ODD 0x08 | ||
57 | #define PARITY_EVEN 0x18 | ||
58 | #define PARITY_MARK 0x28 | ||
59 | #define PARITY_SPACE 0x38 | ||
60 | |||
61 | #define DATA_5BIT 0x0 | ||
62 | #define DATA_6BIT 0x1 | ||
63 | #define DATA_7BIT 0x2 | ||
64 | #define DATA_8BIT 0x3 | ||
65 | |||
66 | #define STOP_1BIT 0x0 | ||
67 | #define STOP_2BIT 0x4 | ||
68 | |||
69 | #define BAUD_DBG 57600 | ||
70 | #define PARITY_DBG PARITY_NONE | ||
71 | #define DATA_DBG DATA_8BIT | ||
72 | #define STOP_DBG STOP_1BIT | ||
73 | |||
74 | /* Initialize the serial port for KGDB debugging */ | ||
75 | void __init excite_kgdb_init(void) | ||
76 | { | ||
77 | const u32 divisor = BASE_BAUD / BAUD_DBG; | ||
78 | |||
79 | /* Take the UART out of reset */ | ||
80 | titan_writel(0x00ff1cff, CPRR); | ||
81 | titan_writel(0x00000000, UACFG); | ||
82 | titan_writel(0x00000002, UACFG); | ||
83 | |||
84 | titan_writel(0x0, UALCR); | ||
85 | titan_writel(0x0, UAIER); | ||
86 | |||
87 | /* Disable FIFOs */ | ||
88 | titan_writel(0x00, UAFCR); | ||
89 | |||
90 | titan_writel(0x80, UALCR); | ||
91 | titan_writel(divisor & 0xff, UADLL); | ||
92 | titan_writel((divisor & 0xff00) >> 8, UADLH); | ||
93 | titan_writel(0x0, UALCR); | ||
94 | |||
95 | titan_writel(DATA_DBG | PARITY_DBG | STOP_DBG, UALCR); | ||
96 | |||
97 | /* Enable receiver interrupt */ | ||
98 | titan_readl(UARBR); | ||
99 | titan_writel(0x1, UAIER); | ||
100 | } | ||
101 | |||
102 | int getDebugChar(void) | ||
103 | { | ||
104 | while (!(titan_readl(UALSR) & 0x1)); | ||
105 | return titan_readl(UARBR); | ||
106 | } | ||
107 | |||
108 | int putDebugChar(int data) | ||
109 | { | ||
110 | while (!(titan_readl(UALSR) & 0x20)); | ||
111 | titan_writel(data, UATHR); | ||
112 | return 1; | ||
113 | } | ||
114 | |||
115 | /* KGDB interrupt handler */ | ||
116 | asmlinkage void excite_kgdb_inthdl(struct pt_regs *regs) | ||
117 | { | ||
118 | if (unlikely( | ||
119 | ((titan_readl(UAIIR) & 0x7) == 4) | ||
120 | && ((titan_readl(UARBR) & 0xff) == 0x3))) | ||
121 | set_async_breakpoint(®s->cp0_epc); | ||
122 | } | ||
diff --git a/arch/mips/basler/excite/excite_device.c b/arch/mips/basler/excite/excite_device.c new file mode 100644 index 000000000000..34ec76716fa0 --- /dev/null +++ b/arch/mips/basler/excite/excite_device.c | |||
@@ -0,0 +1,404 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 by Basler Vision Technologies AG | ||
3 | * Author: Thomas Koeller <thomas.koeller@baslerweb.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/ioport.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/jiffies.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <asm/types.h> | ||
29 | #include <asm/rm9k-ocd.h> | ||
30 | |||
31 | #include <excite.h> | ||
32 | #include <rm9k_eth.h> | ||
33 | #include <rm9k_wdt.h> | ||
34 | #include <rm9k_xicap.h> | ||
35 | #include <excite_nandflash.h> | ||
36 | |||
37 | #include "excite_iodev.h" | ||
38 | |||
39 | #define RM9K_GE_UNIT 0 | ||
40 | #define XICAP_UNIT 0 | ||
41 | #define NAND_UNIT 0 | ||
42 | |||
43 | #define DLL_TIMEOUT 3 /* seconds */ | ||
44 | |||
45 | |||
46 | #define RINIT(__start__, __end__, __name__, __parent__) { \ | ||
47 | .name = __name__ "_0", \ | ||
48 | .start = (__start__), \ | ||
49 | .end = (__end__), \ | ||
50 | .flags = 0, \ | ||
51 | .parent = (__parent__) \ | ||
52 | } | ||
53 | |||
54 | #define RINIT_IRQ(__irq__, __name__) { \ | ||
55 | .name = __name__ "_0", \ | ||
56 | .start = (__irq__), \ | ||
57 | .end = (__irq__), \ | ||
58 | .flags = IORESOURCE_IRQ, \ | ||
59 | .parent = NULL \ | ||
60 | } | ||
61 | |||
62 | |||
63 | |||
64 | enum { | ||
65 | slice_xicap, | ||
66 | slice_eth | ||
67 | }; | ||
68 | |||
69 | |||
70 | |||
71 | static struct resource | ||
72 | excite_ctr_resource = { | ||
73 | .name = "GPI counters", | ||
74 | .start = 0, | ||
75 | .end = 5, | ||
76 | .flags = 0, | ||
77 | .parent = NULL, | ||
78 | .sibling = NULL, | ||
79 | .child = NULL | ||
80 | }, | ||
81 | excite_gpislice_resource = { | ||
82 | .name = "GPI slices", | ||
83 | .start = 0, | ||
84 | .end = 1, | ||
85 | .flags = 0, | ||
86 | .parent = NULL, | ||
87 | .sibling = NULL, | ||
88 | .child = NULL | ||
89 | }, | ||
90 | excite_mdio_channel_resource = { | ||
91 | .name = "MDIO channels", | ||
92 | .start = 0, | ||
93 | .end = 1, | ||
94 | .flags = 0, | ||
95 | .parent = NULL, | ||
96 | .sibling = NULL, | ||
97 | .child = NULL | ||
98 | }, | ||
99 | excite_fifomem_resource = { | ||
100 | .name = "FIFO memory", | ||
101 | .start = 0, | ||
102 | .end = 767, | ||
103 | .flags = 0, | ||
104 | .parent = NULL, | ||
105 | .sibling = NULL, | ||
106 | .child = NULL | ||
107 | }, | ||
108 | excite_scram_resource = { | ||
109 | .name = "Scratch RAM", | ||
110 | .start = EXCITE_PHYS_SCRAM, | ||
111 | .end = EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1, | ||
112 | .flags = IORESOURCE_MEM, | ||
113 | .parent = NULL, | ||
114 | .sibling = NULL, | ||
115 | .child = NULL | ||
116 | }, | ||
117 | excite_fpga_resource = { | ||
118 | .name = "System FPGA", | ||
119 | .start = EXCITE_PHYS_FPGA, | ||
120 | .end = EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1, | ||
121 | .flags = IORESOURCE_MEM, | ||
122 | .parent = NULL, | ||
123 | .sibling = NULL, | ||
124 | .child = NULL | ||
125 | }, | ||
126 | excite_nand_resource = { | ||
127 | .name = "NAND flash control", | ||
128 | .start = EXCITE_PHYS_NAND, | ||
129 | .end = EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1, | ||
130 | .flags = IORESOURCE_MEM, | ||
131 | .parent = NULL, | ||
132 | .sibling = NULL, | ||
133 | .child = NULL | ||
134 | }, | ||
135 | excite_titan_resource = { | ||
136 | .name = "TITAN registers", | ||
137 | .start = EXCITE_PHYS_TITAN, | ||
138 | .end = EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1, | ||
139 | .flags = IORESOURCE_MEM, | ||
140 | .parent = NULL, | ||
141 | .sibling = NULL, | ||
142 | .child = NULL | ||
143 | }; | ||
144 | |||
145 | |||
146 | |||
147 | static void adjust_resources(struct resource *res, unsigned int n) | ||
148 | { | ||
149 | struct resource *p; | ||
150 | const unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM | ||
151 | | IORESOURCE_IRQ | IORESOURCE_DMA; | ||
152 | |||
153 | for (p = res; p < res + n; p++) { | ||
154 | const struct resource * const parent = p->parent; | ||
155 | if (parent) { | ||
156 | p->start += parent->start; | ||
157 | p->end += parent->start; | ||
158 | p->flags = parent->flags & mask; | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | |||
164 | |||
165 | #if defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE) | ||
166 | static struct resource xicap_rsrc[] = { | ||
167 | RINIT(0x4840, 0x486f, XICAP_RESOURCE_FIFO_RX, &excite_titan_resource), | ||
168 | RINIT(0x4940, 0x494b, XICAP_RESOURCE_FIFO_TX, &excite_titan_resource), | ||
169 | RINIT(0x5040, 0x5127, XICAP_RESOURCE_XDMA, &excite_titan_resource), | ||
170 | RINIT(0x1000, 0x112f, XICAP_RESOURCE_PKTPROC, &excite_titan_resource), | ||
171 | RINIT(0x1100, 0x110f, XICAP_RESOURCE_PKT_STREAM, &excite_fpga_resource), | ||
172 | RINIT(0x0800, 0x0bff, XICAP_RESOURCE_DMADESC, &excite_scram_resource), | ||
173 | RINIT(slice_xicap, slice_xicap, XICAP_RESOURCE_GPI_SLICE, &excite_gpislice_resource), | ||
174 | RINIT(0x0100, 0x02ff, XICAP_RESOURCE_FIFO_BLK, &excite_fifomem_resource), | ||
175 | RINIT_IRQ(TITAN_IRQ, XICAP_RESOURCE_IRQ) | ||
176 | }; | ||
177 | |||
178 | static struct platform_device xicap_pdev = { | ||
179 | .name = XICAP_NAME, | ||
180 | .id = XICAP_UNIT, | ||
181 | .num_resources = ARRAY_SIZE(xicap_rsrc), | ||
182 | .resource = xicap_rsrc | ||
183 | }; | ||
184 | |||
185 | /* | ||
186 | * Create a platform device for the GPI port that receives the | ||
187 | * image data from the embedded camera. | ||
188 | */ | ||
189 | static int __init xicap_devinit(void) | ||
190 | { | ||
191 | unsigned long tend; | ||
192 | u32 reg; | ||
193 | int retval; | ||
194 | |||
195 | adjust_resources(xicap_rsrc, ARRAY_SIZE(xicap_rsrc)); | ||
196 | |||
197 | /* Power up the slice and configure it. */ | ||
198 | reg = titan_readl(CPTC1R); | ||
199 | reg &= ~(0x11100 << slice_xicap); | ||
200 | titan_writel(reg, CPTC1R); | ||
201 | |||
202 | /* Enable slice & DLL. */ | ||
203 | reg= titan_readl(CPRR); | ||
204 | reg &= ~(0x00030003 << (slice_xicap * 2)); | ||
205 | titan_writel(reg, CPRR); | ||
206 | |||
207 | /* Wait for DLLs to lock */ | ||
208 | tend = jiffies + DLL_TIMEOUT * HZ; | ||
209 | while (time_before(jiffies, tend)) { | ||
210 | if (!(~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4)))) | ||
211 | break; | ||
212 | yield(); | ||
213 | } | ||
214 | |||
215 | if (~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))) { | ||
216 | printk(KERN_ERR "%s: DLL not locked after %u seconds\n", | ||
217 | xicap_pdev.name, DLL_TIMEOUT); | ||
218 | retval = -ETIME; | ||
219 | } else { | ||
220 | /* Register platform device */ | ||
221 | retval = platform_device_register(&xicap_pdev); | ||
222 | } | ||
223 | |||
224 | return retval; | ||
225 | } | ||
226 | |||
227 | device_initcall(xicap_devinit); | ||
228 | #endif /* defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE) */ | ||
229 | |||
230 | |||
231 | |||
232 | #if defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE) | ||
233 | static struct resource wdt_rsrc[] = { | ||
234 | RINIT(0, 0, WDT_RESOURCE_COUNTER, &excite_ctr_resource), | ||
235 | RINIT(0x0084, 0x008f, WDT_RESOURCE_REGS, &excite_titan_resource), | ||
236 | RINIT_IRQ(TITAN_IRQ, WDT_RESOURCE_IRQ) | ||
237 | }; | ||
238 | |||
239 | static struct platform_device wdt_pdev = { | ||
240 | .name = WDT_NAME, | ||
241 | .id = -1, | ||
242 | .num_resources = ARRAY_SIZE(wdt_rsrc), | ||
243 | .resource = wdt_rsrc | ||
244 | }; | ||
245 | |||
246 | /* | ||
247 | * Create a platform device for the GPI port that receives the | ||
248 | * image data from the embedded camera. | ||
249 | */ | ||
250 | static int __init wdt_devinit(void) | ||
251 | { | ||
252 | adjust_resources(wdt_rsrc, ARRAY_SIZE(wdt_rsrc)); | ||
253 | return platform_device_register(&wdt_pdev); | ||
254 | } | ||
255 | |||
256 | device_initcall(wdt_devinit); | ||
257 | #endif /* defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE) */ | ||
258 | |||
259 | |||
260 | |||
261 | static struct resource excite_nandflash_rsrc[] = { | ||
262 | RINIT(0x2000, 0x201f, EXCITE_NANDFLASH_RESOURCE_REGS, &excite_nand_resource) | ||
263 | }; | ||
264 | |||
265 | static struct platform_device excite_nandflash_pdev = { | ||
266 | .name = "excite_nand", | ||
267 | .id = NAND_UNIT, | ||
268 | .num_resources = ARRAY_SIZE(excite_nandflash_rsrc), | ||
269 | .resource = excite_nandflash_rsrc | ||
270 | }; | ||
271 | |||
272 | /* | ||
273 | * Create a platform device for the access to the nand-flash | ||
274 | * port | ||
275 | */ | ||
276 | static int __init excite_nandflash_devinit(void) | ||
277 | { | ||
278 | adjust_resources(excite_nandflash_rsrc, ARRAY_SIZE(excite_nandflash_rsrc)); | ||
279 | |||
280 | /* nothing to be done here */ | ||
281 | |||
282 | /* Register platform device */ | ||
283 | return platform_device_register(&excite_nandflash_pdev); | ||
284 | } | ||
285 | |||
286 | device_initcall(excite_nandflash_devinit); | ||
287 | |||
288 | |||
289 | |||
290 | static struct resource iodev_rsrc[] = { | ||
291 | RINIT_IRQ(FPGA1_IRQ, IODEV_RESOURCE_IRQ) | ||
292 | }; | ||
293 | |||
294 | static struct platform_device io_pdev = { | ||
295 | .name = IODEV_NAME, | ||
296 | .id = -1, | ||
297 | .num_resources = ARRAY_SIZE(iodev_rsrc), | ||
298 | .resource = iodev_rsrc | ||
299 | }; | ||
300 | |||
301 | /* | ||
302 | * Create a platform device for the external I/O ports. | ||
303 | */ | ||
304 | static int __init io_devinit(void) | ||
305 | { | ||
306 | adjust_resources(iodev_rsrc, ARRAY_SIZE(iodev_rsrc)); | ||
307 | return platform_device_register(&io_pdev); | ||
308 | } | ||
309 | |||
310 | device_initcall(io_devinit); | ||
311 | |||
312 | |||
313 | |||
314 | |||
315 | #if defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE) | ||
316 | static struct resource rm9k_ge_rsrc[] = { | ||
317 | RINIT(0x2200, 0x27ff, RM9K_GE_RESOURCE_MAC, &excite_titan_resource), | ||
318 | RINIT(0x1800, 0x1fff, RM9K_GE_RESOURCE_MSTAT, &excite_titan_resource), | ||
319 | RINIT(0x2000, 0x212f, RM9K_GE_RESOURCE_PKTPROC, &excite_titan_resource), | ||
320 | RINIT(0x5140, 0x5227, RM9K_GE_RESOURCE_XDMA, &excite_titan_resource), | ||
321 | RINIT(0x4870, 0x489f, RM9K_GE_RESOURCE_FIFO_RX, &excite_titan_resource), | ||
322 | RINIT(0x494c, 0x4957, RM9K_GE_RESOURCE_FIFO_TX, &excite_titan_resource), | ||
323 | RINIT(0x0000, 0x007f, RM9K_GE_RESOURCE_FIFOMEM_RX, &excite_fifomem_resource), | ||
324 | RINIT(0x0080, 0x00ff, RM9K_GE_RESOURCE_FIFOMEM_TX, &excite_fifomem_resource), | ||
325 | RINIT(0x0180, 0x019f, RM9K_GE_RESOURCE_PHY, &excite_titan_resource), | ||
326 | RINIT(0x0000, 0x03ff, RM9K_GE_RESOURCE_DMADESC_RX, &excite_scram_resource), | ||
327 | RINIT(0x0400, 0x07ff, RM9K_GE_RESOURCE_DMADESC_TX, &excite_scram_resource), | ||
328 | RINIT(slice_eth, slice_eth, RM9K_GE_RESOURCE_GPI_SLICE, &excite_gpislice_resource), | ||
329 | RINIT(0, 0, RM9K_GE_RESOURCE_MDIO_CHANNEL, &excite_mdio_channel_resource), | ||
330 | RINIT_IRQ(TITAN_IRQ, RM9K_GE_RESOURCE_IRQ_MAIN), | ||
331 | RINIT_IRQ(PHY_IRQ, RM9K_GE_RESOURCE_IRQ_PHY) | ||
332 | }; | ||
333 | |||
334 | static struct platform_device rm9k_ge_pdev = { | ||
335 | .name = RM9K_GE_NAME, | ||
336 | .id = RM9K_GE_UNIT, | ||
337 | .num_resources = ARRAY_SIZE(rm9k_ge_rsrc), | ||
338 | .resource = rm9k_ge_rsrc | ||
339 | }; | ||
340 | |||
341 | |||
342 | |||
343 | /* | ||
344 | * Create a platform device for the Ethernet port. | ||
345 | */ | ||
346 | static int __init rm9k_ge_devinit(void) | ||
347 | { | ||
348 | u32 reg; | ||
349 | |||
350 | adjust_resources(rm9k_ge_rsrc, ARRAY_SIZE(rm9k_ge_rsrc)); | ||
351 | |||
352 | /* Power up the slice and configure it. */ | ||
353 | reg = titan_readl(CPTC1R); | ||
354 | reg &= ~(0x11000 << slice_eth); | ||
355 | reg |= 0x100 << slice_eth; | ||
356 | titan_writel(reg, CPTC1R); | ||
357 | |||
358 | /* Take the MAC out of reset, reset the DLLs. */ | ||
359 | reg = titan_readl(CPRR); | ||
360 | reg &= ~(0x00030000 << (slice_eth * 2)); | ||
361 | reg |= 0x3 << (slice_eth * 2); | ||
362 | titan_writel(reg, CPRR); | ||
363 | |||
364 | return platform_device_register(&rm9k_ge_pdev); | ||
365 | } | ||
366 | |||
367 | device_initcall(rm9k_ge_devinit); | ||
368 | #endif /* defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE) */ | ||
369 | |||
370 | |||
371 | |||
372 | static int __init excite_setup_devs(void) | ||
373 | { | ||
374 | int res; | ||
375 | u32 reg; | ||
376 | |||
377 | /* Enable xdma and fifo interrupts */ | ||
378 | reg = titan_readl(0x0050); | ||
379 | titan_writel(reg | 0x18000000, 0x0050); | ||
380 | |||
381 | res = request_resource(&iomem_resource, &excite_titan_resource); | ||
382 | if (res) | ||
383 | return res; | ||
384 | res = request_resource(&iomem_resource, &excite_scram_resource); | ||
385 | if (res) | ||
386 | return res; | ||
387 | res = request_resource(&iomem_resource, &excite_fpga_resource); | ||
388 | if (res) | ||
389 | return res; | ||
390 | res = request_resource(&iomem_resource, &excite_nand_resource); | ||
391 | if (res) | ||
392 | return res; | ||
393 | excite_fpga_resource.flags = excite_fpga_resource.parent->flags & | ||
394 | ( IORESOURCE_IO | IORESOURCE_MEM | ||
395 | | IORESOURCE_IRQ | IORESOURCE_DMA); | ||
396 | excite_nand_resource.flags = excite_nand_resource.parent->flags & | ||
397 | ( IORESOURCE_IO | IORESOURCE_MEM | ||
398 | | IORESOURCE_IRQ | IORESOURCE_DMA); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | arch_initcall(excite_setup_devs); | ||
404 | |||
diff --git a/arch/mips/basler/excite/excite_flashtest.c b/arch/mips/basler/excite/excite_flashtest.c new file mode 100644 index 000000000000..f0024a8e3294 --- /dev/null +++ b/arch/mips/basler/excite/excite_flashtest.c | |||
@@ -0,0 +1,294 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 by Basler Vision Technologies AG | ||
3 | * Author: Thies Moeller <thies.moeller@baslerweb.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/err.h> | ||
29 | #include <linux/kernel.h> | ||
30 | |||
31 | #include <excite.h> | ||
32 | |||
33 | #include <asm/io.h> | ||
34 | |||
35 | #include <linux/mtd/mtd.h> | ||
36 | #include <linux/mtd/nand.h> | ||
37 | #include <linux/mtd/nand_ecc.h> | ||
38 | #include <linux/mtd/partitions.h> | ||
39 | #include <asm/rm9k-ocd.h> // for ocd_write | ||
40 | #include <linux/workqueue.h> // for queue | ||
41 | |||
42 | #include "excite_nandflash.h" | ||
43 | #include "nandflash.h" | ||
44 | |||
45 | #define PFX "excite flashtest: " | ||
46 | typedef void __iomem *io_reg_t; | ||
47 | |||
48 | #define io_readb(__a__) __raw_readb((__a__)) | ||
49 | #define io_writeb(__v__, __a__) __raw_writeb((__v__), (__a__)) | ||
50 | |||
51 | |||
52 | |||
53 | static inline const struct resource *excite_nandflash_get_resource( | ||
54 | struct platform_device *d, unsigned long flags, const char *basename) | ||
55 | { | ||
56 | const char fmt[] = "%s_%u"; | ||
57 | char buf[80]; | ||
58 | |||
59 | if (unlikely(snprintf(buf, sizeof buf, fmt, basename, d->id) >= sizeof buf)) | ||
60 | return NULL; | ||
61 | |||
62 | return platform_get_resource_byname(d, flags, buf); | ||
63 | } | ||
64 | |||
65 | static inline io_reg_t | ||
66 | excite_nandflash_map_regs(struct platform_device *d, const char *basename) | ||
67 | { | ||
68 | void *result = NULL; | ||
69 | const struct resource *const r = | ||
70 | excite_nandflash_get_resource(d, IORESOURCE_MEM, basename); | ||
71 | if (r) | ||
72 | result = ioremap_nocache(r->start, r->end + 1 - r->start); | ||
73 | return result; | ||
74 | } | ||
75 | |||
76 | /* controller and mtd information */ | ||
77 | |||
78 | struct excite_nandflash_drvdata { | ||
79 | struct mtd_info board_mtd; | ||
80 | struct nand_chip board_chip; | ||
81 | io_reg_t regs; | ||
82 | }; | ||
83 | |||
84 | |||
85 | /* command and control functions */ | ||
86 | static void excite_nandflash_hwcontrol(struct mtd_info *mtd, int cmd) | ||
87 | { | ||
88 | struct nand_chip *this = mtd->priv; | ||
89 | io_reg_t regs = container_of(mtd,struct excite_nandflash_drvdata,board_mtd)->regs; | ||
90 | |||
91 | switch (cmd) { | ||
92 | /* Select the command latch */ | ||
93 | case NAND_CTL_SETCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_CMD; | ||
94 | break; | ||
95 | /* Deselect the command latch */ | ||
96 | case NAND_CTL_CLRCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_DATA; | ||
97 | break; | ||
98 | /* Select the address latch */ | ||
99 | case NAND_CTL_SETALE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_ADDR; | ||
100 | break; | ||
101 | /* Deselect the address latch */ | ||
102 | case NAND_CTL_CLRALE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_DATA; | ||
103 | break; | ||
104 | /* Select the chip -- not used */ | ||
105 | case NAND_CTL_SETNCE: | ||
106 | break; | ||
107 | /* Deselect the chip -- not used */ | ||
108 | case NAND_CTL_CLRNCE: | ||
109 | break; | ||
110 | } | ||
111 | |||
112 | this->IO_ADDR_R = this->IO_ADDR_W; | ||
113 | } | ||
114 | |||
115 | /* excite_nandflash_devready() | ||
116 | * | ||
117 | * returns 0 if the nand is busy, 1 if it is ready | ||
118 | */ | ||
119 | static int excite_nandflash_devready(struct mtd_info *mtd) | ||
120 | { | ||
121 | struct excite_nandflash_drvdata *drvdata = | ||
122 | container_of(mtd, struct excite_nandflash_drvdata, board_mtd); | ||
123 | |||
124 | return io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS); | ||
125 | } | ||
126 | |||
127 | /* device management functions */ | ||
128 | |||
129 | /* excite_nandflash_remove | ||
130 | * | ||
131 | * called by device layer to remove the driver | ||
132 | * the binding to the mtd and all allocated | ||
133 | * resources are released | ||
134 | */ | ||
135 | static int excite_nandflash_remove(struct device *dev) | ||
136 | { | ||
137 | struct excite_nandflash_drvdata *this = dev_get_drvdata(dev); | ||
138 | |||
139 | pr_info(PFX "remove"); | ||
140 | |||
141 | dev_set_drvdata(dev, NULL); | ||
142 | |||
143 | if (this == NULL) { | ||
144 | pr_debug(PFX "call remove without private data!!"); | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | |||
149 | /* free the common resources */ | ||
150 | if (this->regs != NULL) { | ||
151 | iounmap(this->regs); | ||
152 | this->regs = NULL; | ||
153 | } | ||
154 | |||
155 | kfree(this); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int elapsed; | ||
161 | |||
162 | void my_workqueue_handler(void *arg) | ||
163 | { | ||
164 | elapsed = 1; | ||
165 | } | ||
166 | |||
167 | DECLARE_WORK(sigElapsed, my_workqueue_handler, 0); | ||
168 | |||
169 | |||
170 | /* excite_nandflash_probe | ||
171 | * | ||
172 | * called by device layer when it finds a device matching | ||
173 | * one our driver can handled. This code checks to see if | ||
174 | * it can allocate all necessary resources then calls the | ||
175 | * nand layer to look for devices | ||
176 | */ | ||
177 | static int excite_nandflash_probe(struct device *dev) | ||
178 | { | ||
179 | struct platform_device *pdev = to_platform_device(dev); | ||
180 | |||
181 | struct excite_nandflash_drvdata *drvdata; /* private driver data */ | ||
182 | struct nand_chip *board_chip; /* private flash chip data */ | ||
183 | struct mtd_info *board_mtd; /* mtd info for this board */ | ||
184 | |||
185 | int err = 0; | ||
186 | int count = 0; | ||
187 | struct timeval tv,endtv; | ||
188 | unsigned int dt; | ||
189 | |||
190 | pr_info(PFX "probe dev: (%p)\n", dev); | ||
191 | |||
192 | pr_info(PFX "adjust LB timing\n"); | ||
193 | ocd_writel(0x00000330, LDP2); | ||
194 | |||
195 | drvdata = kmalloc(sizeof(*drvdata), GFP_KERNEL); | ||
196 | if (unlikely(!drvdata)) { | ||
197 | printk(KERN_ERR PFX "no memory for drvdata\n"); | ||
198 | err = -ENOMEM; | ||
199 | goto mem_error; | ||
200 | } | ||
201 | |||
202 | /* Initialize structures */ | ||
203 | memset(drvdata, 0, sizeof(*drvdata)); | ||
204 | |||
205 | /* bind private data into driver */ | ||
206 | dev_set_drvdata(dev, drvdata); | ||
207 | |||
208 | /* allocate and map the resource */ | ||
209 | drvdata->regs = | ||
210 | excite_nandflash_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS); | ||
211 | |||
212 | if (unlikely(!drvdata->regs)) { | ||
213 | printk(KERN_ERR PFX "cannot reserve register region\n"); | ||
214 | err = -ENXIO; | ||
215 | goto io_error; | ||
216 | } | ||
217 | |||
218 | /* initialise our chip */ | ||
219 | board_chip = &drvdata->board_chip; | ||
220 | |||
221 | board_chip->IO_ADDR_R = drvdata->regs + EXCITE_NANDFLASH_DATA; | ||
222 | board_chip->IO_ADDR_W = drvdata->regs + EXCITE_NANDFLASH_DATA; | ||
223 | |||
224 | board_chip->hwcontrol = excite_nandflash_hwcontrol; | ||
225 | board_chip->dev_ready = excite_nandflash_devready; | ||
226 | |||
227 | board_chip->chip_delay = 25; | ||
228 | #if 0 | ||
229 | /* TODO: speedup the initial scan */ | ||
230 | board_chip->options = NAND_USE_FLASH_BBT; | ||
231 | #endif | ||
232 | board_chip->eccmode = NAND_ECC_SOFT; | ||
233 | |||
234 | /* link chip to mtd */ | ||
235 | board_mtd = &drvdata->board_mtd; | ||
236 | board_mtd->priv = board_chip; | ||
237 | |||
238 | |||
239 | pr_info(PFX "FlashTest\n"); | ||
240 | elapsed = 0; | ||
241 | /* schedule_delayed_work(&sigElapsed, 1*HZ); | ||
242 | while (!elapsed) { | ||
243 | io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS); | ||
244 | count++; | ||
245 | } | ||
246 | pr_info(PFX "reads in 1 sec --> %d\n",count); | ||
247 | */ | ||
248 | do_gettimeofday(&tv); | ||
249 | for (count = 0 ; count < 1000000; count ++) { | ||
250 | io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS); | ||
251 | } | ||
252 | do_gettimeofday(&endtv); | ||
253 | dt = (endtv.tv_sec - tv.tv_sec) * 1000000 + endtv.tv_usec - tv.tv_usec; | ||
254 | pr_info(PFX "%8d us timeval\n",dt); | ||
255 | pr_info(PFX "EndFlashTest\n"); | ||
256 | |||
257 | /* return with error to unload everything | ||
258 | */ | ||
259 | io_error: | ||
260 | iounmap(drvdata->regs); | ||
261 | |||
262 | mem_error: | ||
263 | kfree(drvdata); | ||
264 | |||
265 | if (err == 0) | ||
266 | err = -EINVAL; | ||
267 | return err; | ||
268 | } | ||
269 | |||
270 | static struct device_driver excite_nandflash_driver = { | ||
271 | .name = "excite_nand", | ||
272 | .bus = &platform_bus_type, | ||
273 | .probe = excite_nandflash_probe, | ||
274 | .remove = excite_nandflash_remove, | ||
275 | }; | ||
276 | |||
277 | static int __init excite_nandflash_init(void) | ||
278 | { | ||
279 | pr_info(PFX "register Driver (Rev: $Revision:$)\n"); | ||
280 | return driver_register(&excite_nandflash_driver); | ||
281 | } | ||
282 | |||
283 | static void __exit excite_nandflash_exit(void) | ||
284 | { | ||
285 | driver_unregister(&excite_nandflash_driver); | ||
286 | pr_info(PFX "Driver unregistered"); | ||
287 | } | ||
288 | |||
289 | module_init(excite_nandflash_init); | ||
290 | module_exit(excite_nandflash_exit); | ||
291 | |||
292 | MODULE_AUTHOR("Thies Moeller <thies.moeller@baslerweb.com>"); | ||
293 | MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver"); | ||
294 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/mips/basler/excite/excite_fpga.h b/arch/mips/basler/excite/excite_fpga.h new file mode 100644 index 000000000000..38fcda703a0b --- /dev/null +++ b/arch/mips/basler/excite/excite_fpga.h | |||
@@ -0,0 +1,80 @@ | |||
1 | #ifndef EXCITE_FPGA_H_INCLUDED | ||
2 | #define EXCITE_FPGA_H_INCLUDED | ||
3 | |||
4 | |||
5 | /** | ||
6 | * Adress alignment of the individual FPGA bytes. | ||
7 | * The address arrangement of the individual bytes of the FPGA is two | ||
8 | * byte aligned at the embedded MK2 platform. | ||
9 | */ | ||
10 | #ifdef EXCITE_CCI_FPGA_MK2 | ||
11 | typedef unsigned char excite_cci_fpga_align_t __attribute__ ((aligned(2))); | ||
12 | #else | ||
13 | typedef unsigned char excite_cci_fpga_align_t; | ||
14 | #endif | ||
15 | |||
16 | |||
17 | /** | ||
18 | * Size of Dual Ported RAM. | ||
19 | */ | ||
20 | #define EXCITE_DPR_SIZE 263 | ||
21 | |||
22 | |||
23 | /** | ||
24 | * Size of Reserved Status Fields in Dual Ported RAM. | ||
25 | */ | ||
26 | #define EXCITE_DPR_STATUS_SIZE 7 | ||
27 | |||
28 | |||
29 | |||
30 | /** | ||
31 | * FPGA. | ||
32 | * Hardware register layout of the FPGA interface. The FPGA must accessed | ||
33 | * byte wise solely. | ||
34 | * @see EXCITE_CCI_DPR_MK2 | ||
35 | */ | ||
36 | typedef struct excite_fpga { | ||
37 | |||
38 | /** | ||
39 | * Dual Ported RAM. | ||
40 | */ | ||
41 | excite_cci_fpga_align_t dpr[EXCITE_DPR_SIZE]; | ||
42 | |||
43 | /** | ||
44 | * Status. | ||
45 | */ | ||
46 | excite_cci_fpga_align_t status[EXCITE_DPR_STATUS_SIZE]; | ||
47 | |||
48 | #ifdef EXCITE_CCI_FPGA_MK2 | ||
49 | /** | ||
50 | * RM9000 Interrupt. | ||
51 | * Write access initiates interrupt at the RM9000 (MIPS) processor of the eXcite. | ||
52 | */ | ||
53 | excite_cci_fpga_align_t rm9k_int; | ||
54 | #else | ||
55 | /** | ||
56 | * MK2 Interrupt. | ||
57 | * Write access initiates interrupt at the ARM processor of the MK2. | ||
58 | */ | ||
59 | excite_cci_fpga_align_t mk2_int; | ||
60 | |||
61 | excite_cci_fpga_align_t gap[0x1000-0x10f]; | ||
62 | |||
63 | /** | ||
64 | * IRQ Source/Acknowledge. | ||
65 | */ | ||
66 | excite_cci_fpga_align_t rm9k_irq_src; | ||
67 | |||
68 | /** | ||
69 | * IRQ Mask. | ||
70 | * Set bits enable the related interrupt. | ||
71 | */ | ||
72 | excite_cci_fpga_align_t rm9k_irq_mask; | ||
73 | #endif | ||
74 | |||
75 | |||
76 | } excite_fpga; | ||
77 | |||
78 | |||
79 | |||
80 | #endif /* ndef EXCITE_FPGA_H_INCLUDED */ | ||
diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c new file mode 100644 index 000000000000..91121e523043 --- /dev/null +++ b/arch/mips/basler/excite/excite_iodev.c | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 by Basler Vision Technologies AG | ||
3 | * Author: Thomas Koeller <thomas.koeller@baslerweb.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/compiler.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/wait.h> | ||
26 | #include <linux/poll.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/miscdevice.h> | ||
30 | |||
31 | #include "excite_iodev.h" | ||
32 | |||
33 | |||
34 | |||
35 | static const struct resource *iodev_get_resource(struct platform_device *, const char *, unsigned int); | ||
36 | static int __init iodev_probe(struct device *); | ||
37 | static int __exit iodev_remove(struct device *); | ||
38 | static int iodev_open(struct inode *, struct file *); | ||
39 | static int iodev_release(struct inode *, struct file *); | ||
40 | static ssize_t iodev_read(struct file *, char __user *, size_t s, loff_t *); | ||
41 | static unsigned int iodev_poll(struct file *, struct poll_table_struct *); | ||
42 | static irqreturn_t iodev_irqhdl(int, void *, struct pt_regs *); | ||
43 | |||
44 | |||
45 | |||
46 | static const char iodev_name[] = "iodev"; | ||
47 | static unsigned int iodev_irq; | ||
48 | static DECLARE_WAIT_QUEUE_HEAD(wq); | ||
49 | |||
50 | |||
51 | |||
52 | static struct file_operations fops = | ||
53 | { | ||
54 | .owner = THIS_MODULE, | ||
55 | .open = iodev_open, | ||
56 | .release = iodev_release, | ||
57 | .read = iodev_read, | ||
58 | .poll = iodev_poll | ||
59 | }; | ||
60 | |||
61 | static struct miscdevice miscdev = | ||
62 | { | ||
63 | .minor = MISC_DYNAMIC_MINOR, | ||
64 | .name = iodev_name, | ||
65 | .fops = &fops | ||
66 | }; | ||
67 | |||
68 | static struct device_driver iodev_driver = | ||
69 | { | ||
70 | .name = (char *) iodev_name, | ||
71 | .bus = &platform_bus_type, | ||
72 | .owner = THIS_MODULE, | ||
73 | .probe = iodev_probe, | ||
74 | .remove = __exit_p(iodev_remove) | ||
75 | }; | ||
76 | |||
77 | |||
78 | |||
79 | static const struct resource * | ||
80 | iodev_get_resource(struct platform_device *pdv, const char *name, | ||
81 | unsigned int type) | ||
82 | { | ||
83 | char buf[80]; | ||
84 | if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf) | ||
85 | return NULL; | ||
86 | return platform_get_resource_byname(pdv, type, buf); | ||
87 | } | ||
88 | |||
89 | |||
90 | |||
91 | /* No hotplugging on the platform bus - use __init */ | ||
92 | static int __init iodev_probe(struct device *dev) | ||
93 | { | ||
94 | struct platform_device * const pdv = to_platform_device(dev); | ||
95 | const struct resource * const ri = | ||
96 | iodev_get_resource(pdv, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ); | ||
97 | |||
98 | if (unlikely(!ri)) | ||
99 | return -ENXIO; | ||
100 | |||
101 | iodev_irq = ri->start; | ||
102 | return misc_register(&miscdev); | ||
103 | } | ||
104 | |||
105 | |||
106 | |||
107 | static int __exit iodev_remove(struct device *dev) | ||
108 | { | ||
109 | return misc_deregister(&miscdev); | ||
110 | } | ||
111 | |||
112 | |||
113 | |||
114 | static int iodev_open(struct inode *i, struct file *f) | ||
115 | { | ||
116 | return request_irq(iodev_irq, iodev_irqhdl, SA_INTERRUPT, | ||
117 | iodev_name, &miscdev); | ||
118 | } | ||
119 | |||
120 | |||
121 | |||
122 | static int iodev_release(struct inode *i, struct file *f) | ||
123 | { | ||
124 | free_irq(iodev_irq, &miscdev); | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | |||
129 | |||
130 | |||
131 | static ssize_t | ||
132 | iodev_read(struct file *f, char __user *d, size_t s, loff_t *o) | ||
133 | { | ||
134 | ssize_t ret; | ||
135 | DEFINE_WAIT(w); | ||
136 | |||
137 | prepare_to_wait(&wq, &w, TASK_INTERRUPTIBLE); | ||
138 | if (!signal_pending(current)) | ||
139 | schedule(); | ||
140 | ret = signal_pending(current) ? -ERESTARTSYS : 0; | ||
141 | finish_wait(&wq, &w); | ||
142 | return ret; | ||
143 | } | ||
144 | |||
145 | |||
146 | static unsigned int iodev_poll(struct file *f, struct poll_table_struct *p) | ||
147 | { | ||
148 | poll_wait(f, &wq, p); | ||
149 | return POLLOUT | POLLWRNORM; | ||
150 | } | ||
151 | |||
152 | |||
153 | |||
154 | |||
155 | static irqreturn_t iodev_irqhdl(int irq, void *ctxt, struct pt_regs *regs) | ||
156 | { | ||
157 | wake_up(&wq); | ||
158 | return IRQ_HANDLED; | ||
159 | } | ||
160 | |||
161 | |||
162 | |||
163 | static int __init iodev_init_module(void) | ||
164 | { | ||
165 | return driver_register(&iodev_driver); | ||
166 | } | ||
167 | |||
168 | |||
169 | |||
170 | static void __exit iodev_cleanup_module(void) | ||
171 | { | ||
172 | driver_unregister(&iodev_driver); | ||
173 | } | ||
174 | |||
175 | module_init(iodev_init_module); | ||
176 | module_exit(iodev_cleanup_module); | ||
177 | |||
178 | |||
179 | |||
180 | MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>"); | ||
181 | MODULE_DESCRIPTION("Basler eXcite i/o interrupt handler"); | ||
182 | MODULE_VERSION("0.0"); | ||
183 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/mips/basler/excite/excite_iodev.h b/arch/mips/basler/excite/excite_iodev.h new file mode 100644 index 000000000000..cbfbb5d2ee62 --- /dev/null +++ b/arch/mips/basler/excite/excite_iodev.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef __EXCITE_IODEV_H__ | ||
2 | #define __EXCITE_IODEV_H__ | ||
3 | |||
4 | /* Device name */ | ||
5 | #define IODEV_NAME "iodev" | ||
6 | |||
7 | /* Resource names */ | ||
8 | #define IODEV_RESOURCE_IRQ "excite_iodev_irq" | ||
9 | |||
10 | #endif /* __EXCITE_IODEV_H__ */ | ||
diff --git a/arch/mips/basler/excite/excite_irq.c b/arch/mips/basler/excite/excite_irq.c new file mode 100644 index 000000000000..511ad8730f54 --- /dev/null +++ b/arch/mips/basler/excite/excite_irq.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Copyright (C) by Basler Vision Technologies AG | ||
3 | * Author: Thomas Koeller <thomas.koeller@baslereb.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/errno.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/kernel_stat.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/signal.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/ioport.h> | ||
29 | #include <linux/timex.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/random.h> | ||
32 | #include <asm/bitops.h> | ||
33 | #include <asm/bootinfo.h> | ||
34 | #include <asm/io.h> | ||
35 | #include <asm/irq.h> | ||
36 | #include <asm/irq_cpu.h> | ||
37 | #include <asm/mipsregs.h> | ||
38 | #include <asm/system.h> | ||
39 | #include <asm/rm9k-ocd.h> | ||
40 | |||
41 | #include <excite.h> | ||
42 | |||
43 | extern asmlinkage void excite_handle_int(void); | ||
44 | |||
45 | /* | ||
46 | * Initialize the interrupt handler | ||
47 | */ | ||
48 | void __init arch_init_irq(void) | ||
49 | { | ||
50 | mips_cpu_irq_init(0); | ||
51 | rm7k_cpu_irq_init(8); | ||
52 | rm9k_cpu_irq_init(12); | ||
53 | |||
54 | #ifdef CONFIG_KGDB | ||
55 | excite_kgdb_init(); | ||
56 | #endif | ||
57 | } | ||
58 | |||
59 | asmlinkage void plat_irq_dispatch(struct pt_regs *regs) | ||
60 | { | ||
61 | const u32 | ||
62 | interrupts = read_c0_cause() >> 8, | ||
63 | mask = ((read_c0_status() >> 8) & 0x000000ff) | | ||
64 | (read_c0_intcontrol() & 0x0000ff00), | ||
65 | pending = interrupts & mask; | ||
66 | u32 msgintflags, msgintmask, msgint; | ||
67 | |||
68 | /* process timer interrupt */ | ||
69 | if (pending & (1 << TIMER_IRQ)) { | ||
70 | do_IRQ(TIMER_IRQ, regs); | ||
71 | return; | ||
72 | } | ||
73 | |||
74 | /* Process PCI interrupts */ | ||
75 | #if USB_IRQ < 10 | ||
76 | msgintflags = ocd_readl(INTP0Status0 + (USB_MSGINT / 0x20 * 0x10)); | ||
77 | msgintmask = ocd_readl(INTP0Mask0 + (USB_MSGINT / 0x20 * 0x10)); | ||
78 | msgint = msgintflags & msgintmask & (0x1 << (USB_MSGINT % 0x20)); | ||
79 | if ((pending & (1 << USB_IRQ)) && msgint) { | ||
80 | #else | ||
81 | if (pending & (1 << USB_IRQ)) { | ||
82 | #endif | ||
83 | do_IRQ(USB_IRQ, regs); | ||
84 | return; | ||
85 | } | ||
86 | |||
87 | /* Process TITAN interrupts */ | ||
88 | msgintflags = ocd_readl(INTP0Status0 + (TITAN_MSGINT / 0x20 * 0x10)); | ||
89 | msgintmask = ocd_readl(INTP0Mask0 + (TITAN_MSGINT / 0x20 * 0x10)); | ||
90 | msgint = msgintflags & msgintmask & (0x1 << (TITAN_MSGINT % 0x20)); | ||
91 | if ((pending & (1 << TITAN_IRQ)) && msgint) { | ||
92 | ocd_writel(msgint, INTP0Clear0 + (TITAN_MSGINT / 0x20 * 0x10)); | ||
93 | #if defined(CONFIG_KGDB) | ||
94 | excite_kgdb_inthdl(regs); | ||
95 | #endif | ||
96 | do_IRQ(TITAN_IRQ, regs); | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | /* Process FPGA line #0 interrupts */ | ||
101 | msgintflags = ocd_readl(INTP0Status0 + (FPGA0_MSGINT / 0x20 * 0x10)); | ||
102 | msgintmask = ocd_readl(INTP0Mask0 + (FPGA0_MSGINT / 0x20 * 0x10)); | ||
103 | msgint = msgintflags & msgintmask & (0x1 << (FPGA0_MSGINT % 0x20)); | ||
104 | if ((pending & (1 << FPGA0_IRQ)) && msgint) { | ||
105 | do_IRQ(FPGA0_IRQ, regs); | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | /* Process FPGA line #1 interrupts */ | ||
110 | msgintflags = ocd_readl(INTP0Status0 + (FPGA1_MSGINT / 0x20 * 0x10)); | ||
111 | msgintmask = ocd_readl(INTP0Mask0 + (FPGA1_MSGINT / 0x20 * 0x10)); | ||
112 | msgint = msgintflags & msgintmask & (0x1 << (FPGA1_MSGINT % 0x20)); | ||
113 | if ((pending & (1 << FPGA1_IRQ)) && msgint) { | ||
114 | do_IRQ(FPGA1_IRQ, regs); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | /* Process PHY interrupts */ | ||
119 | msgintflags = ocd_readl(INTP0Status0 + (PHY_MSGINT / 0x20 * 0x10)); | ||
120 | msgintmask = ocd_readl(INTP0Mask0 + (PHY_MSGINT / 0x20 * 0x10)); | ||
121 | msgint = msgintflags & msgintmask & (0x1 << (PHY_MSGINT % 0x20)); | ||
122 | if ((pending & (1 << PHY_IRQ)) && msgint) { | ||
123 | do_IRQ(PHY_IRQ, regs); | ||
124 | return; | ||
125 | } | ||
126 | |||
127 | /* Process spurious interrupts */ | ||
128 | spurious_interrupt(regs); | ||
129 | } | ||
diff --git a/arch/mips/basler/excite/excite_procfs.c b/arch/mips/basler/excite/excite_procfs.c new file mode 100644 index 000000000000..c62be0341fb8 --- /dev/null +++ b/arch/mips/basler/excite/excite_procfs.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2005 by Basler Vision Technologies AG | ||
3 | * Author: Thomas Koeller <thomas.koeller@baslerweb.com> | ||
4 | * | ||
5 | * Procfs support for Basler eXcite | ||
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 | |||
22 | #include <linux/config.h> | ||
23 | #include <linux/proc_fs.h> | ||
24 | #include <linux/stat.h> | ||
25 | #include <asm/page.h> | ||
26 | #include <asm/io.h> | ||
27 | #include <asm/system.h> | ||
28 | #include <asm/rm9k-ocd.h> | ||
29 | |||
30 | #include <excite.h> | ||
31 | |||
32 | static int excite_get_unit_id(char *buf, char **addr, off_t offs, int size) | ||
33 | { | ||
34 | const int len = snprintf(buf, PAGE_SIZE, "%06x", unit_id); | ||
35 | const int w = len - offs; | ||
36 | *addr = buf + offs; | ||
37 | return w < size ? w : size; | ||
38 | } | ||
39 | |||
40 | static int | ||
41 | excite_bootrom_read(char *page, char **start, off_t off, int count, | ||
42 | int *eof, void *data) | ||
43 | { | ||
44 | void __iomem * src; | ||
45 | |||
46 | if (off >= EXCITE_SIZE_BOOTROM) { | ||
47 | *eof = 1; | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | if ((off + count) > EXCITE_SIZE_BOOTROM) | ||
52 | count = EXCITE_SIZE_BOOTROM - off; | ||
53 | |||
54 | src = ioremap(EXCITE_PHYS_BOOTROM + off, count); | ||
55 | if (src) { | ||
56 | memcpy_fromio(page, src, count); | ||
57 | iounmap(src); | ||
58 | *start = page; | ||
59 | } else { | ||
60 | count = -ENOMEM; | ||
61 | } | ||
62 | |||
63 | return count; | ||
64 | } | ||
65 | |||
66 | void excite_procfs_init(void) | ||
67 | { | ||
68 | /* Create & populate /proc/excite */ | ||
69 | struct proc_dir_entry * const pdir = proc_mkdir("excite", &proc_root); | ||
70 | if (pdir) { | ||
71 | struct proc_dir_entry * e; | ||
72 | |||
73 | e = create_proc_info_entry("unit_id", S_IRUGO, pdir, | ||
74 | excite_get_unit_id); | ||
75 | if (e) e->size = 6; | ||
76 | |||
77 | e = create_proc_read_entry("bootrom", S_IRUGO, pdir, | ||
78 | excite_bootrom_read, NULL); | ||
79 | if (e) e->size = EXCITE_SIZE_BOOTROM; | ||
80 | } | ||
81 | } | ||
diff --git a/arch/mips/basler/excite/excite_prom.c b/arch/mips/basler/excite/excite_prom.c new file mode 100644 index 000000000000..84724b270753 --- /dev/null +++ b/arch/mips/basler/excite/excite_prom.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2005 by Thomas Koeller (thomas.koeller@baslerweb.com) | ||
3 | * Based on the PMC-Sierra Yosemite board support by Ralf Baechle and | ||
4 | * Manish Lachwani. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/config.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/smp.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <asm/io.h> | ||
29 | #include <asm/pgtable.h> | ||
30 | #include <asm/processor.h> | ||
31 | #include <asm/reboot.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/bootinfo.h> | ||
34 | #include <asm/string.h> | ||
35 | |||
36 | #include <excite.h> | ||
37 | |||
38 | /* This struct is used by Redboot to pass arguments to the kernel */ | ||
39 | typedef struct | ||
40 | { | ||
41 | char *name; | ||
42 | char *val; | ||
43 | } t_env_var; | ||
44 | |||
45 | struct parmblock { | ||
46 | t_env_var memsize; | ||
47 | t_env_var modetty0; | ||
48 | t_env_var ethaddr; | ||
49 | t_env_var env_end; | ||
50 | char *argv[2]; | ||
51 | char text[0]; | ||
52 | }; | ||
53 | |||
54 | static unsigned int prom_argc; | ||
55 | static const char ** prom_argv; | ||
56 | static const t_env_var * prom_env; | ||
57 | |||
58 | static void prom_halt(void) __attribute__((noreturn)); | ||
59 | static void prom_exit(void) __attribute__((noreturn)); | ||
60 | |||
61 | |||
62 | |||
63 | const char *get_system_type(void) | ||
64 | { | ||
65 | return "Basler eXcite"; | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Halt the system | ||
70 | */ | ||
71 | static void prom_halt(void) | ||
72 | { | ||
73 | printk(KERN_NOTICE "\n** System halted.\n"); | ||
74 | while (1) | ||
75 | asm volatile ( | ||
76 | "\t.set\tmips3\n" | ||
77 | "\twait\n" | ||
78 | "\t.set\tmips0\n" | ||
79 | ); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Reset the CPU and re-enter Redboot | ||
84 | */ | ||
85 | static void prom_exit(void) | ||
86 | { | ||
87 | unsigned int i; | ||
88 | volatile unsigned char * const flg = | ||
89 | (volatile unsigned char *) (EXCITE_ADDR_FPGA + EXCITE_FPGA_DPR); | ||
90 | |||
91 | /* Clear the watchdog reset flag, set the reboot flag */ | ||
92 | *flg &= ~0x01; | ||
93 | *flg |= 0x80; | ||
94 | |||
95 | for (i = 0; i < 10; i++) { | ||
96 | *(volatile unsigned char *) (EXCITE_ADDR_FPGA + EXCITE_FPGA_SYSCTL) = 0x02; | ||
97 | iob(); | ||
98 | mdelay(1000); | ||
99 | } | ||
100 | |||
101 | printk(KERN_NOTICE "Reset failed\n"); | ||
102 | prom_halt(); | ||
103 | } | ||
104 | |||
105 | static const char __init *prom_getenv(char *name) | ||
106 | { | ||
107 | const t_env_var * p; | ||
108 | for (p = prom_env; p->name != NULL; p++) | ||
109 | if(strcmp(name, p->name) == 0) | ||
110 | break; | ||
111 | return p->val; | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * Init routine which accepts the variables from Redboot | ||
116 | */ | ||
117 | void __init prom_init(void) | ||
118 | { | ||
119 | const struct parmblock * const pb = (struct parmblock *) fw_arg2; | ||
120 | |||
121 | prom_argc = fw_arg0; | ||
122 | prom_argv = (const char **) fw_arg1; | ||
123 | prom_env = &pb->memsize; | ||
124 | |||
125 | /* Callbacks for halt, restart */ | ||
126 | _machine_restart = (void (*)(char *)) prom_exit; | ||
127 | _machine_halt = prom_halt; | ||
128 | |||
129 | #ifdef CONFIG_32BIT | ||
130 | /* copy command line */ | ||
131 | strcpy(arcs_cmdline, prom_argv[1]); | ||
132 | memsize = simple_strtol(prom_getenv("memsize"), NULL, 16); | ||
133 | strcpy(modetty, prom_getenv("modetty0")); | ||
134 | #endif /* CONFIG_32BIT */ | ||
135 | |||
136 | #ifdef CONFIG_64BIT | ||
137 | # error 64 bit support not implemented | ||
138 | #endif /* CONFIG_64BIT */ | ||
139 | |||
140 | mips_machgroup = MACH_GROUP_TITAN; | ||
141 | mips_machtype = MACH_TITAN_EXCITE; | ||
142 | } | ||
143 | |||
144 | /* This is called from free_initmem(), so we need to provide it */ | ||
145 | void __init prom_free_prom_memory(void) | ||
146 | { | ||
147 | /* Nothing to do */ | ||
148 | } | ||
diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c new file mode 100644 index 000000000000..005b025605e6 --- /dev/null +++ b/arch/mips/basler/excite/excite_setup.c | |||
@@ -0,0 +1,307 @@ | |||
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 | |||
22 | #include <linux/config.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/string.h> | ||
27 | #include <linux/tty.h> | ||
28 | #include <linux/serial_core.h> | ||
29 | #include <linux/serial.h> | ||
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 */ | ||
67 | spinlock_t titan_lock = SPIN_LOCK_UNLOCKED; | ||
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 | |||
82 | static void excite_timer_setup(struct irqaction *irq) | ||
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; | ||
116 | up.iotype = UPIO_MEM32; | ||
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 | |||
257 | void __init plat_setup(void) | ||
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; | ||
266 | board_timer_setup = excite_timer_setup; | ||
267 | |||
268 | /* Set up the peripheral address map */ | ||
269 | *(boot_ocd_base + (LKB9 / sizeof (u32))) = 0; | ||
270 | *(boot_ocd_base + (LKB10 / sizeof (u32))) = 0; | ||
271 | *(boot_ocd_base + (LKB11 / sizeof (u32))) = 0; | ||
272 | *(boot_ocd_base + (LKB12 / sizeof (u32))) = 0; | ||
273 | wmb(); | ||
274 | *(boot_ocd_base + (LKB0 / sizeof (u32))) = EXCITE_PHYS_OCD >> 4; | ||
275 | wmb(); | ||
276 | |||
277 | ocd_writel((EXCITE_PHYS_TITAN >> 4) | 0x1UL, LKB5); | ||
278 | ocd_writel(((EXCITE_SIZE_TITAN >> 4) & 0x7fffff00) - 0x100, LKM5); | ||
279 | ocd_writel((EXCITE_PHYS_SCRAM >> 4) | 0x1UL, LKB13); | ||
280 | ocd_writel(((EXCITE_SIZE_SCRAM >> 4) & 0xffffff00) - 0x100, LKM13); | ||
281 | |||
282 | /* Local bus slot #0 */ | ||
283 | ocd_writel(0x00040510, LDP0); | ||
284 | ocd_writel((EXCITE_PHYS_BOOTROM >> 4) | 0x1UL, LKB9); | ||
285 | ocd_writel(((EXCITE_SIZE_BOOTROM >> 4) & 0x03ffff00) - 0x100, LKM9); | ||
286 | |||
287 | /* Local bus slot #2 */ | ||
288 | ocd_writel(0x00000330, LDP2); | ||
289 | ocd_writel((EXCITE_PHYS_FPGA >> 4) | 0x1, LKB11); | ||
290 | ocd_writel(((EXCITE_SIZE_FPGA >> 4) - 0x100) & 0x03ffff00, LKM11); | ||
291 | |||
292 | /* Local bus slot #3 */ | ||
293 | ocd_writel(0x00123413, LDP3); | ||
294 | ocd_writel((EXCITE_PHYS_NAND >> 4) | 0x1, LKB12); | ||
295 | ocd_writel(((EXCITE_SIZE_NAND >> 4) - 0x100) & 0x03ffff00, LKM12); | ||
296 | } | ||
297 | |||
298 | |||
299 | |||
300 | console_initcall(excite_init_console); | ||
301 | arch_initcall(excite_platform_init); | ||
302 | |||
303 | EXPORT_SYMBOL(titan_lock); | ||
304 | EXPORT_SYMBOL(titan_irqflags); | ||
305 | EXPORT_SYMBOL(titan_irq); | ||
306 | EXPORT_SYMBOL(ocd_base); | ||
307 | EXPORT_SYMBOL(titan_base); | ||