]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/sparc64/kernel/isa.c
[SPARC64]: Kill ebus/isa range and interrupt mapping struct members.
[linux-2.6-omap-h63xx.git] / arch / sparc64 / kernel / isa.c
1 #include <linux/kernel.h>
2 #include <linux/init.h>
3 #include <linux/pci.h>
4 #include <linux/slab.h>
5 #include <asm/oplib.h>
6 #include <asm/isa.h>
7
8 struct sparc_isa_bridge *isa_chain;
9
10 static void __init fatal_err(const char *reason)
11 {
12         prom_printf("ISA: fatal error, %s.\n", reason);
13 }
14
15 static void __init report_dev(struct sparc_isa_device *isa_dev, int child)
16 {
17         if (child)
18                 printk(" (%s)", isa_dev->prom_node->name);
19         else
20                 printk(" [%s", isa_dev->prom_node->name);
21 }
22
23 static struct linux_prom_registers * __init
24 isa_dev_get_resource(struct sparc_isa_device *isa_dev)
25 {
26         struct linux_prom_registers *pregs;
27         unsigned long base, len;
28         int prop_len;
29
30         pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len);
31
32         /* Only the first one is interesting. */
33         len = pregs[0].reg_size;
34         base = (((unsigned long)pregs[0].which_io << 32) |
35                 (unsigned long)pregs[0].phys_addr);
36         base += isa_dev->bus->parent->io_space.start;
37
38         isa_dev->resource.start = base;
39         isa_dev->resource.end   = (base + len - 1UL);
40         isa_dev->resource.flags = IORESOURCE_IO;
41         isa_dev->resource.name  = isa_dev->prom_node->name;
42
43         request_resource(&isa_dev->bus->parent->io_space,
44                          &isa_dev->resource);
45
46         return pregs;
47 }
48
49 /* I can't believe they didn't put a real INO in the isa device
50  * interrupts property.  The whole point of the OBP properties
51  * is to shield the kernel from IRQ routing details.
52  *
53  * The P1275 standard for ISA devices seems to also have been
54  * totally ignored.
55  *
56  * On later systems, an interrupt-map and interrupt-map-mask scheme
57  * akin to EBUS is used.
58  */
59 static struct {
60         int     obp_irq;
61         int     pci_ino;
62 } grover_irq_table[] = {
63         { 1, 0x00 },    /* dma, unknown ino at this point */
64         { 2, 0x27 },    /* floppy */
65         { 3, 0x22 },    /* parallel */
66         { 4, 0x2b },    /* serial */
67         { 5, 0x25 },    /* acpi power management */
68
69         { 0, 0x00 }     /* end of table */
70 };
71
72 static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev,
73                                              struct sparc_isa_bridge *isa_br,
74                                              int *interrupt,
75                                              struct linux_prom_registers *reg)
76 {
77         struct linux_prom_ebus_intmap *imap;
78         struct linux_prom_ebus_intmap *imask;
79         unsigned int hi, lo, irq;
80         int i, len, n_imap;
81
82         imap = of_get_property(isa_br->prom_node, "interrupt-map", &len);
83         if (!imap)
84                 return 0;
85         n_imap = len / sizeof(imap[0]);
86
87         imask = of_get_property(isa_br->prom_node, "interrupt-map-mask", NULL);
88         if (!imask)
89                 return 0;
90
91         hi = reg->which_io & imask->phys_hi;
92         lo = reg->phys_addr & imask->phys_lo;
93         irq = *interrupt & imask->interrupt;
94         for (i = 0; i < n_imap; i++) {
95                 if ((imap[i].phys_hi == hi) &&
96                     (imap[i].phys_lo == lo) &&
97                     (imap[i].interrupt == irq)) {
98                         *interrupt = imap[i].cinterrupt;
99                         return 0;
100                 }
101         }
102         return -1;
103 }
104
105 static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev,
106                                    struct linux_prom_registers *pregs)
107 {
108         int irq_prop;
109
110         irq_prop = of_getintprop_default(isa_dev->prom_node,
111                                          "interrupts", -1);
112         if (irq_prop <= 0) {
113                 goto no_irq;
114         } else {
115                 struct pci_controller_info *pcic;
116                 struct pci_pbm_info *pbm;
117                 int i;
118
119                 if (of_find_property(isa_dev->bus->prom_node,
120                                      "interrupt-map", NULL)) {
121                         if (!isa_dev_get_irq_using_imap(isa_dev,
122                                                         isa_dev->bus,
123                                                         &irq_prop,
124                                                         pregs))
125                                 goto route_irq;
126                 }
127
128                 for (i = 0; grover_irq_table[i].obp_irq != 0; i++) {
129                         if (grover_irq_table[i].obp_irq == irq_prop) {
130                                 int ino = grover_irq_table[i].pci_ino;
131
132                                 if (ino == 0)
133                                         goto no_irq;
134  
135                                 irq_prop = ino;
136                                 goto route_irq;
137                         }
138                 }
139                 goto no_irq;
140
141 route_irq:
142                 pbm = isa_dev->bus->parent;
143                 pcic = pbm->parent;
144                 isa_dev->irq = pcic->irq_build(pbm, NULL, irq_prop);
145                 return;
146         }
147
148 no_irq:
149         isa_dev->irq = PCI_IRQ_NONE;
150 }
151
152 static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
153 {
154         struct device_node *dp = parent_isa_dev->prom_node->child;
155
156         if (!dp)
157                 return;
158
159         printk(" ->");
160         while (dp) {
161                 struct linux_prom_registers *regs;
162                 struct sparc_isa_device *isa_dev;
163
164                 isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
165                 if (!isa_dev) {
166                         fatal_err("cannot allocate child isa_dev");
167                         prom_halt();
168                 }
169
170                 memset(isa_dev, 0, sizeof(*isa_dev));
171
172                 /* Link it in to parent. */
173                 isa_dev->next = parent_isa_dev->child;
174                 parent_isa_dev->child = isa_dev;
175
176                 isa_dev->bus = parent_isa_dev->bus;
177                 isa_dev->prom_node = dp;
178
179                 regs = isa_dev_get_resource(isa_dev);
180                 isa_dev_get_irq(isa_dev, regs);
181
182                 report_dev(isa_dev, 1);
183
184                 dp = dp->sibling;
185         }
186 }
187
188 static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
189 {
190         struct device_node *dp = isa_br->prom_node->child;
191
192         while (dp) {
193                 struct linux_prom_registers *regs;
194                 struct sparc_isa_device *isa_dev;
195
196                 isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
197                 if (!isa_dev) {
198                         fatal_err("cannot allocate isa_dev");
199                         prom_halt();
200                 }
201
202                 memset(isa_dev, 0, sizeof(*isa_dev));
203
204                 /* Link it in. */
205                 isa_dev->next = NULL;
206                 if (isa_br->devices == NULL) {
207                         isa_br->devices = isa_dev;
208                 } else {
209                         struct sparc_isa_device *tmp = isa_br->devices;
210
211                         while (tmp->next)
212                                 tmp = tmp->next;
213
214                         tmp->next = isa_dev;
215                 }
216
217                 isa_dev->bus = isa_br;
218                 isa_dev->prom_node = dp;
219
220                 regs = isa_dev_get_resource(isa_dev);
221                 isa_dev_get_irq(isa_dev, regs);
222
223                 report_dev(isa_dev, 0);
224
225                 isa_fill_children(isa_dev);
226
227                 printk("]");
228
229                 dp = dp->sibling;
230         }
231 }
232
233 void __init isa_init(void)
234 {
235         struct pci_dev *pdev;
236         unsigned short vendor, device;
237         int index = 0;
238
239         vendor = PCI_VENDOR_ID_AL;
240         device = PCI_DEVICE_ID_AL_M1533;
241
242         pdev = NULL;
243         while ((pdev = pci_get_device(vendor, device, pdev)) != NULL) {
244                 struct pcidev_cookie *pdev_cookie;
245                 struct pci_pbm_info *pbm;
246                 struct sparc_isa_bridge *isa_br;
247
248                 pdev_cookie = pdev->sysdata;
249                 if (!pdev_cookie) {
250                         printk("ISA: Warning, ISA bridge ignored due to "
251                                "lack of OBP data.\n");
252                         continue;
253                 }
254                 pbm = pdev_cookie->pbm;
255
256                 isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
257                 if (!isa_br) {
258                         fatal_err("cannot allocate sparc_isa_bridge");
259                         prom_halt();
260                 }
261
262                 memset(isa_br, 0, sizeof(*isa_br));
263
264                 /* Link it in. */
265                 isa_br->next = isa_chain;
266                 isa_chain = isa_br;
267
268                 isa_br->parent = pbm;
269                 isa_br->self = pdev;
270                 isa_br->index = index++;
271                 isa_br->prom_node = pdev_cookie->prom_node;
272
273                 printk("isa%d:", isa_br->index);
274
275                 isa_fill_devices(isa_br);
276
277                 printk("\n");
278         }
279 }