Fix brcm63xx support. Now a kernel is booting, detecting the flash, and can probably...
[openwrt.git] / 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);