Fix brcm63xx support. Now a kernel is booting, detecting the flash, and can probably...
[openwrt/staging/dedeckeh.git] / openwrt / target / linux / brcm63xx-2.6 / patches / 002-pci_bcm96348.patch
1 diff -Naurp linux-2.6.16.7-generic-patched/arch/mips/pci/Makefile linux-2.6.16.7-patched/arch/mips/pci/Makefile
2 --- linux-2.6.16.7-generic-patched/arch/mips/pci/Makefile 2006-04-17 23:53:25.000000000 +0200
3 +++ linux-2.6.16.7-patched/arch/mips/pci/Makefile 2006-07-05 15:21:58.000000000 +0200
4 @@ -18,6 +18,7 @@ obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o
5 obj-$(CONFIG_MIPS_TX3927) += ops-tx3927.o
6 obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o
7 obj-$(CONFIG_NEC_CMBVR4133) += fixup-vr4133.o
8 +obj-$(CONFIG_BCM_PCI) += fixup-bcm96348.o pci-bcm96348.o ops-bcm96348.o
9
10 #
11 # These are still pretty much in the old state, watch, go blind.
12 diff -Naurp linux-2.6.16.7-generic-patched/arch/mips/pci/fixup-bcm96348.c linux-2.6.16.7-patched/arch/mips/pci/fixup-bcm96348.c
13 --- linux-2.6.16.7-generic-patched/arch/mips/pci/fixup-bcm96348.c 1970-01-01 01:00:00.000000000 +0100
14 +++ linux-2.6.16.7-patched/arch/mips/pci/fixup-bcm96348.c 2006-07-05 15:21:58.000000000 +0200
15 @@ -0,0 +1,85 @@
16 +/*
17 +<:copyright-gpl
18 + Copyright 2002 Broadcom Corp. All Rights Reserved.
19 +
20 + This program is free software; you can distribute it and/or modify it
21 + under the terms of the GNU General Public License (Version 2) as
22 + published by the Free Software Foundation.
23 +
24 + This program is distributed in the hope it will be useful, but WITHOUT
25 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26 + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 + for more details.
28 +
29 + You should have received a copy of the GNU General Public License along
30 + with this program; if not, write to the Free Software Foundation, Inc.,
31 + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
32 +:>
33 +*/
34 +#include <linux/init.h>
35 +#include <linux/types.h>
36 +#include <linux/pci.h>
37 +
38 +#include <bcmpci.h>
39 +#include <bcm_intr.h>
40 +#include <bcm_map_part.h>
41 +
42 +static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE);
43 +
44 +static char irq_tab_bcm96348[] __initdata = {
45 + [0] = INTERRUPT_ID_MPI,
46 + [1] = INTERRUPT_ID_MPI,
47 +#if defined(CONFIG_USB)
48 + [USB_HOST_SLOT] = INTERRUPT_ID_USBH
49 +#endif
50 +};
51 +
52 +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
53 +{
54 + return irq_tab_bcm96348[slot];
55 +}
56 +
57 +static void bcm96348_fixup(struct pci_dev *dev)
58 +{
59 + uint32 memaddr;
60 + uint32 size;
61 +
62 + memaddr = pci_resource_start(dev, 0);
63 + size = pci_resource_len(dev, 0);
64 +
65 + switch (PCI_SLOT(dev->devfn)) {
66 + case 0:
67 + // UBUS to PCI address range
68 + // Memory Window 1. Mask determines which bits are decoded.
69 + mpi->l2pmrange1 = ~(size-1);
70 + // UBUS to PCI Memory base address. This is akin to the ChipSelect base
71 + // register.
72 + mpi->l2pmbase1 = memaddr & BCM_PCI_ADDR_MASK;
73 + // UBUS to PCI Remap Address. Replaces the masked address bits in the
74 + // range register with this setting.
75 + // Also, enable direct I/O and direct Memory accesses
76 + mpi->l2pmremap1 = (memaddr | MEM_WINDOW_EN);
77 + break;
78 +
79 + case 1:
80 + // Memory Window 2
81 + mpi->l2pmrange2 = ~(size-1);
82 + // UBUS to PCI Memory base address.
83 + mpi->l2pmbase2 = memaddr & BCM_PCI_ADDR_MASK;
84 + // UBUS to PCI Remap Address
85 + mpi->l2pmremap2 = (memaddr | MEM_WINDOW_EN);
86 + break;
87 +
88 +#if defined(CONFIG_USB)
89 + case USB_HOST_SLOT:
90 + dev->resource[0].start = USB_HOST_BASE;
91 + dev->resource[0].end = USB_HOST_BASE+USB_BAR0_MEM_SIZE-1;
92 + break;
93 +#endif
94 + }
95 +}
96 +
97 +struct pci_fixup pcibios_fixups[] = {
98 + { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, bcm96348_fixup },
99 + {0}
100 +};
101 diff -Naurp linux-2.6.16.7-generic-patched/arch/mips/pci/ops-bcm96348.c linux-2.6.16.7-patched/arch/mips/pci/ops-bcm96348.c
102 --- linux-2.6.16.7-generic-patched/arch/mips/pci/ops-bcm96348.c 1970-01-01 01:00:00.000000000 +0100
103 +++ linux-2.6.16.7-patched/arch/mips/pci/ops-bcm96348.c 2006-07-05 15:21:58.000000000 +0200
104 @@ -0,0 +1,276 @@
105 +/*
106 +<:copyright-gpl
107 + Copyright 2002 Broadcom Corp. All Rights Reserved.
108 +
109 + This program is free software; you can distribute it and/or modify it
110 + under the terms of the GNU General Public License (Version 2) as
111 + published by the Free Software Foundation.
112 +
113 + This program is distributed in the hope it will be useful, but WITHOUT
114 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
115 + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
116 + for more details.
117 +
118 + You should have received a copy of the GNU General Public License along
119 + with this program; if not, write to the Free Software Foundation, Inc.,
120 + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
121 +:>
122 +*/
123 +#include <linux/types.h>
124 +#include <linux/pci.h>
125 +#include <linux/kernel.h>
126 +#include <linux/init.h>
127 +#include <asm/addrspace.h>
128 +
129 +#include <bcm_intr.h>
130 +#include <bcm_map_part.h>
131 +#include <bcmpci.h>
132 +
133 +#include <linux/delay.h>
134 +
135 +#if defined(CONFIG_USB)
136 +#if 0
137 +#define DPRINT(x...) printk(x)
138 +#else
139 +#define DPRINT(x...)
140 +#endif
141 +
142 +static int
143 +pci63xx_int_read(unsigned int devfn, int where, u32 * value, int size);
144 +static int
145 +pci63xx_int_write(unsigned int devfn, int where, u32 * value, int size);
146 +
147 +static bool usb_mem_size_rd = FALSE;
148 +static uint32 usb_mem_base = 0;
149 +static uint32 usb_cfg_space_cmd_reg = 0;
150 +#endif
151 +static bool pci_mem_size_rd = FALSE;
152 +
153 +static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE);
154 +
155 +static void mpi_SetupPciConfigAccess(uint32 addr)
156 +{
157 + mpi->l2pcfgctl = (DIR_CFG_SEL | DIR_CFG_USEREG | addr) & ~CONFIG_TYPE;
158 +}
159 +
160 +static void mpi_ClearPciConfigAccess(void)
161 +{
162 + mpi->l2pcfgctl = 0x00000000;
163 +}
164 +
165 +#if defined(CONFIG_USB)
166 +/* --------------------------------------------------------------------------
167 + Name: pci63xx_int_write
168 +Abstract: PCI Config write on internal device(s)
169 + -------------------------------------------------------------------------- */
170 +static int
171 +pci63xx_int_write(unsigned int devfn, int where, u32 * value, int size)
172 +{
173 + if (PCI_SLOT(devfn) != USB_HOST_SLOT) {
174 + return PCIBIOS_SUCCESSFUL;
175 + }
176 +
177 + switch (size) {
178 + case 1:
179 + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %02X\n",
180 + PCI_SLOT(devfn), where, size, *value);
181 + break;
182 + case 2:
183 + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %04X\n",
184 + PCI_SLOT(devfn), where, size, *value);
185 + switch (where) {
186 + case PCI_COMMAND:
187 + usb_cfg_space_cmd_reg = *value;
188 + break;
189 + default:
190 + break;
191 + }
192 + break;
193 + case 4:
194 + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %08lX\n",
195 + PCI_SLOT(devfn), where, size, *value);
196 + switch (where) {
197 + case PCI_BASE_ADDRESS_0:
198 + if (*value == 0xffffffff) {
199 + usb_mem_size_rd = TRUE;
200 + } else {
201 + usb_mem_base = *value;
202 + }
203 + break;
204 + default:
205 + break;
206 + }
207 + break;
208 + default:
209 + break;
210 + }
211 +
212 + return PCIBIOS_SUCCESSFUL;
213 +}
214 +
215 +/* --------------------------------------------------------------------------
216 + Name: pci63xx_int_read
217 +Abstract: PCI Config read on internal device(s)
218 + -------------------------------------------------------------------------- */
219 +static int
220 +pci63xx_int_read(unsigned int devfn, int where, u32 * value, int size)
221 +{
222 + uint32 retValue = 0xFFFFFFFF;
223 +
224 + if (PCI_SLOT(devfn) != USB_HOST_SLOT) {
225 + return PCIBIOS_SUCCESSFUL;
226 + }
227 +
228 + // For now, this is specific to the USB Host controller. We can
229 + // make it more general if we have to...
230 + // Emulate PCI Config accesses
231 + switch (where) {
232 + case PCI_VENDOR_ID:
233 + case PCI_DEVICE_ID:
234 + retValue = PCI_VENDOR_ID_BROADCOM | 0x63000000;
235 + break;
236 + case PCI_COMMAND:
237 + case PCI_STATUS:
238 + retValue = (0x0006 << 16) | usb_cfg_space_cmd_reg;
239 + break;
240 + case PCI_CLASS_REVISION:
241 + case PCI_CLASS_DEVICE:
242 + retValue = (PCI_CLASS_SERIAL_USB << 16) | (0x10 << 8) | 0x01;
243 + break;
244 + case PCI_BASE_ADDRESS_0:
245 + if (usb_mem_size_rd) {
246 + retValue = USB_BAR0_MEM_SIZE;
247 + } else {
248 + if (usb_mem_base != 0)
249 + retValue = usb_mem_base;
250 + else
251 + retValue = USB_HOST_BASE;
252 + }
253 + usb_mem_size_rd = FALSE;
254 + break;
255 + case PCI_CACHE_LINE_SIZE:
256 + case PCI_LATENCY_TIMER:
257 + retValue = 0;
258 + break;
259 + case PCI_HEADER_TYPE:
260 + retValue = PCI_HEADER_TYPE_NORMAL;
261 + break;
262 + case PCI_SUBSYSTEM_VENDOR_ID:
263 + retValue = PCI_VENDOR_ID_BROADCOM;
264 + break;
265 + case PCI_SUBSYSTEM_ID:
266 + retValue = 0x6300;
267 + break;
268 + case PCI_INTERRUPT_LINE:
269 + retValue = INTERRUPT_ID_USBH;
270 + break;
271 + default:
272 + break;
273 + }
274 +
275 + switch (size) {
276 + case 1:
277 + *value = (retValue >> ((where & 3) << 3)) & 0xff;
278 + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %02X\n",
279 + PCI_SLOT(devfn), where, size, *value);
280 + break;
281 + case 2:
282 + *value = (retValue >> ((where & 3) << 3)) & 0xffff;
283 + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %04X\n",
284 + PCI_SLOT(devfn), where, size, *value);
285 + break;
286 + case 4:
287 + *value = retValue;
288 + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %08lX\n",
289 + PCI_SLOT(devfn), where, size, *value);
290 + break;
291 + default:
292 + break;
293 + }
294 +
295 + return PCIBIOS_SUCCESSFUL;
296 +}
297 +#endif
298 +
299 +static int bcm96348_pcibios_read(struct pci_bus *bus, unsigned int devfn,
300 + int where, int size, u32 * val)
301 +{
302 + volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1);
303 + uint32 data;
304 +
305 +#if defined(CONFIG_USB)
306 + if (PCI_SLOT(devfn) == USB_HOST_SLOT)
307 + return pci63xx_int_read(devfn, where, val, size);
308 +#endif
309 +
310 + mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where));
311 + data = *(uint32 *)ioBase;
312 + switch(size) {
313 + case 1:
314 + *val = (data >> ((where & 3) << 3)) & 0xff;
315 + break;
316 + case 2:
317 + *val = (data >> ((where & 3) << 3)) & 0xffff;
318 + break;
319 + case 4:
320 + *val = data;
321 + /* Special case for reading PCI device range */
322 + if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) {
323 + if (pci_mem_size_rd) {
324 + /* bcm6348 PCI memory window minimum size is 64K */
325 + *val &= PCI_SIZE_64K;
326 + }
327 + }
328 + break;
329 + default:
330 + break;
331 + }
332 + pci_mem_size_rd = FALSE;
333 + mpi_ClearPciConfigAccess();
334 +
335 + return PCIBIOS_SUCCESSFUL;
336 +}
337 +
338 +static int bcm96348_pcibios_write(struct pci_bus *bus, unsigned int devfn,
339 + int where, int size, u32 val)
340 +{
341 + volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1);
342 + uint32 data;
343 +
344 +#if defined(CONFIG_USB)
345 + if (PCI_SLOT(devfn) == USB_HOST_SLOT)
346 + return pci63xx_int_write(devfn, where, &val, size);
347 +#endif
348 + mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where));
349 + data = *(uint32 *)ioBase;
350 + switch(size) {
351 + case 1:
352 + data = (data & ~(0xff << ((where & 3) << 3))) |
353 + (val << ((where & 3) << 3));
354 + break;
355 + case 2:
356 + data = (data & ~(0xffff << ((where & 3) << 3))) |
357 + (val << ((where & 3) << 3));
358 + break;
359 + case 4:
360 + data = val;
361 + /* Special case for reading PCI device range */
362 + if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) {
363 + if (val == 0xffffffff)
364 + pci_mem_size_rd = TRUE;
365 + }
366 + break;
367 + default:
368 + break;
369 + }
370 + *(uint32 *)ioBase = data;
371 + udelay(500);
372 + mpi_ClearPciConfigAccess();
373 +
374 + return PCIBIOS_SUCCESSFUL;
375 +}
376 +
377 +struct pci_ops bcm96348_pci_ops = {
378 + .read = bcm96348_pcibios_read,
379 + .write = bcm96348_pcibios_write
380 +};
381 diff -Naurp linux-2.6.16.7-generic-patched/arch/mips/pci/pci-bcm96348.c linux-2.6.16.7-patched/arch/mips/pci/pci-bcm96348.c
382 --- linux-2.6.16.7-generic-patched/arch/mips/pci/pci-bcm96348.c 1970-01-01 01:00:00.000000000 +0100
383 +++ linux-2.6.16.7-patched/arch/mips/pci/pci-bcm96348.c 2006-07-05 15:21:58.000000000 +0200
384 @@ -0,0 +1,54 @@
385 +/*
386 +<:copyright-gpl
387 + Copyright 2002 Broadcom Corp. All Rights Reserved.
388 +
389 + This program is free software; you can distribute it and/or modify it
390 + under the terms of the GNU General Public License (Version 2) as
391 + published by the Free Software Foundation.
392 +
393 + This program is distributed in the hope it will be useful, but WITHOUT
394 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
395 + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
396 + for more details.
397 +
398 + You should have received a copy of the GNU General Public License along
399 + with this program; if not, write to the Free Software Foundation, Inc.,
400 + 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
401 +:>
402 +*/
403 +#include <linux/types.h>
404 +#include <linux/pci.h>
405 +#include <linux/kernel.h>
406 +#include <linux/init.h>
407 +
408 +#include <asm/pci_channel.h>
409 +#include <bcmpci.h>
410 +
411 +static struct resource bcm_pci_io_resource = {
412 + .name = "bcm96348 pci IO space",
413 + .start = BCM_PCI_IO_BASE,
414 + .end = BCM_PCI_IO_BASE + BCM_PCI_IO_SIZE_64KB - 1,
415 + .flags = IORESOURCE_IO
416 +};
417 +
418 +static struct resource bcm_pci_mem_resource = {
419 + .name = "bcm96348 pci memory space",
420 + .start = BCM_PCI_MEM_BASE,
421 + .end = BCM_PCI_MEM_BASE + BCM_PCI_MEM_SIZE_16MB - 1,
422 + .flags = IORESOURCE_MEM
423 +};
424 +
425 +extern struct pci_ops bcm96348_pci_ops;
426 +
427 +struct pci_controller bcm96348_controller = {
428 + .pci_ops = &bcm96348_pci_ops,
429 + .io_resource = &bcm_pci_io_resource,
430 + .mem_resource = &bcm_pci_mem_resource,
431 +};
432 +
433 +static void bcm96348_pci_init(void)
434 +{
435 + register_pci_controller(&bcm96348_controller);
436 +}
437 +
438 +arch_initcall(bcm96348_pci_init);