http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / kernel / linux / arch / arm / mach-iop3xx / iq80310-pci.c
1 /*
2  * arch/arm/mach-iop3xx/iq80310-pci.c
3  *
4  * PCI support for the Intel IQ80310 reference board
5  *
6  * Matt Porter <mporter@mvista.com>
7  *
8  * Copyright (C) 2001 MontaVista Software, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  */
14 #include <linux/kernel.h>
15 #include <linux/pci.h>
16 #include <linux/init.h>
17
18 #include <asm/hardware.h>
19 #include <asm/irq.h>
20 #include <asm/mach/pci.h>
21 #include <asm/mach-types.h>
22
23 /*
24  * The following macro is used to lookup irqs in a standard table
25  * format for those systems that do not already have PCI
26  * interrupts properly routed.  We assume 1 <= pin <= 4
27  */
28 #define PCI_IRQ_TABLE_LOOKUP(minid,maxid)       \
29 ({ int _ctl_ = -1;                              \
30    unsigned int _idsel = idsel - minid;         \
31    if (_idsel <= maxid)                         \
32       _ctl_ = pci_irq_table[_idsel][pin-1];     \
33    _ctl_; })
34
35 #define INTA    IRQ_IQ80310_INTA
36 #define INTB    IRQ_IQ80310_INTB
37 #define INTC    IRQ_IQ80310_INTC
38 #define INTD    IRQ_IQ80310_INTD
39
40 #define INTE    IRQ_IQ80310_I82559
41
42 typedef u8 irq_table[4];
43
44 /*
45  * IRQ tables for primary bus.
46  *
47  * On a Rev D.1 and older board, INT A-C are not routed, so we
48  * just fake it as INTA and than we take care of handling it
49  * correctly in the IRQ demux routine.
50  */
51 static irq_table pci_pri_d_irq_table[] = {
52 /* Pin:    A     B     C     D */
53         { INTA, INTD, INTA, INTA }, /*  PCI Slot J3 */
54         { INTD, INTA, INTA, INTA }, /*  PCI Slot J4 */
55 };
56
57 static irq_table pci_pri_f_irq_table[] = {
58 /* Pin:    A     B     C     D */
59         { INTC, INTD, INTA, INTB }, /*  PCI Slot J3 */
60         { INTD, INTA, INTB, INTC }, /*  PCI Slot J4 */
61 };
62
63 static int __init
64 iq80310_pri_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
65 {
66         irq_table *pci_irq_table;
67
68         BUG_ON(pin < 1 || pin > 4);
69
70         if (!system_rev) {
71                 pci_irq_table = pci_pri_d_irq_table;
72         } else {
73                 pci_irq_table = pci_pri_f_irq_table;
74         }
75
76         return PCI_IRQ_TABLE_LOOKUP(2, 3);
77 }
78
79 /*
80  * IRQ tables for secondary bus.
81  *
82  * On a Rev D.1 and older board, INT A-C are not routed, so we
83  * just fake it as INTA and than we take care of handling it
84  * correctly in the IRQ demux routine.
85  */
86 static irq_table pci_sec_d_irq_table[] = {
87 /* Pin:    A     B     C     D */
88         { INTA, INTA, INTA, INTD }, /*  PCI Slot J1 */
89         { INTA, INTA, INTD, INTA }, /*  PCI Slot J5 */
90         { INTE, INTE, INTE, INTE }, /*  P2P Bridge */
91 };
92
93 static irq_table pci_sec_f_irq_table[] = {
94 /* Pin:    A     B     C     D */
95         { INTA, INTB, INTC, INTD }, /* PCI Slot J1 */
96         { INTB, INTC, INTD, INTA }, /* PCI Slot J5 */
97         { INTE, INTE, INTE, INTE }, /* P2P Bridge */
98 };
99
100 static int __init
101 iq80310_sec_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
102 {
103         irq_table *pci_irq_table;
104
105         BUG_ON(pin < 1 || pin > 4);
106
107         if (!system_rev) {
108                 pci_irq_table = pci_sec_d_irq_table;
109         } else {
110                 pci_irq_table = pci_sec_f_irq_table;
111         }
112
113         return PCI_IRQ_TABLE_LOOKUP(0, 2);
114 }
115
116 static int iq80310_pri_host;
117
118 static int iq80310_setup(int nr, struct pci_sys_data *sys)
119 {
120         switch (nr) {
121         case 0:
122                 if (!iq80310_pri_host)
123                         return 0;
124
125                 sys->map_irq = iq80310_pri_map_irq;
126                 break;
127
128         case 1:
129                 sys->map_irq = iq80310_sec_map_irq;
130                 break;
131
132         default:
133                 return 0;
134         }
135
136         return iop310_setup(nr, sys);
137 }
138
139 static void iq80310_preinit(void)
140 {
141         iq80310_pri_host = *(volatile u32 *)IQ80310_BACKPLANE & 1;
142
143         printk(KERN_INFO "PCI: IQ80310 is a%s\n",
144                 iq80310_pri_host ? " system controller" : "n agent");
145
146         iop310_init();
147 }
148
149 static struct hw_pci iq80310_pci __initdata = {
150         .swizzle        = pci_std_swizzle,
151         .nr_controllers = 2,
152         .setup          = iq80310_setup,
153         .scan           = iop310_scan_bus,
154         .preinit        = iq80310_preinit,
155 };
156
157 static int __init iq80310_pci_init(void)
158 {
159         if (machine_is_iq80310())
160                 pci_common_init(&iq80310_pci);
161         return 0;
162 }
163
164 subsys_initcall(iq80310_pci_init);