Commit 8fae097debdf8ac9b66d220ac258535ea09f3898
1 parent
d384ea691f
[SBUS]: Start cleaning up generic sbus support layer.
In particular, move the IRQ probing out to sparc32/sparc64 arch specific code where it belongs. Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 5 changed files with 87 additions and 125 deletions Side-by-side Diff
arch/sparc/kernel/ioport.c
... | ... | @@ -224,8 +224,52 @@ |
224 | 224 | |
225 | 225 | #ifdef CONFIG_SBUS |
226 | 226 | |
227 | -void sbus_set_sbus64(struct sbus_dev *sdev, int x) { | |
227 | +void sbus_set_sbus64(struct sbus_dev *sdev, int x) | |
228 | +{ | |
228 | 229 | printk("sbus_set_sbus64: unsupported\n"); |
230 | +} | |
231 | + | |
232 | +extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); | |
233 | +void __init sbus_fill_device_irq(struct sbus_dev *sdev) | |
234 | +{ | |
235 | + struct linux_prom_irqs irqs[PROMINTR_MAX]; | |
236 | + int len; | |
237 | + | |
238 | + len = prom_getproperty(sdev->prom_node, "intr", | |
239 | + (char *)irqs, sizeof(irqs)); | |
240 | + if (len != -1) { | |
241 | + sdev->num_irqs = len / 8; | |
242 | + if (sdev->num_irqs == 0) { | |
243 | + sdev->irqs[0] = 0; | |
244 | + } else if (sparc_cpu_model == sun4d) { | |
245 | + for (len = 0; len < sdev->num_irqs; len++) | |
246 | + sdev->irqs[len] = | |
247 | + sun4d_build_irq(sdev, irqs[len].pri); | |
248 | + } else { | |
249 | + for (len = 0; len < sdev->num_irqs; len++) | |
250 | + sdev->irqs[len] = irqs[len].pri; | |
251 | + } | |
252 | + } else { | |
253 | + int interrupts[PROMINTR_MAX]; | |
254 | + | |
255 | + /* No "intr" node found-- check for "interrupts" node. | |
256 | + * This node contains SBus interrupt levels, not IPLs | |
257 | + * as in "intr", and no vector values. We convert | |
258 | + * SBus interrupt levels to PILs (platform specific). | |
259 | + */ | |
260 | + len = prom_getproperty(sdev->prom_node, "interrupts", | |
261 | + (char *)interrupts, sizeof(interrupts)); | |
262 | + if (len == -1) { | |
263 | + sdev->irqs[0] = 0; | |
264 | + sdev->num_irqs = 0; | |
265 | + } else { | |
266 | + sdev->num_irqs = len / sizeof(int); | |
267 | + for (len = 0; len < sdev->num_irqs; len++) { | |
268 | + sdev->irqs[len] = | |
269 | + sbint_to_irq(sdev, interrupts[len]); | |
270 | + } | |
271 | + } | |
272 | + } | |
229 | 273 | } |
230 | 274 | |
231 | 275 | /* |
arch/sparc64/kernel/sbus.c
... | ... | @@ -1225,4 +1225,25 @@ |
1225 | 1225 | |
1226 | 1226 | sysio_register_error_handlers(sbus); |
1227 | 1227 | } |
1228 | + | |
1229 | +void sbus_fill_device_irq(struct sbus_dev *sdev) | |
1230 | +{ | |
1231 | + struct linux_prom_irqs irqs[PROMINTR_MAX]; | |
1232 | + int len; | |
1233 | + | |
1234 | + len = prom_getproperty(sdev->prom_node, "interrupts", | |
1235 | + (char *) irqs, sizeof(irqs)); | |
1236 | + if (len == -1 || len == 0) { | |
1237 | + sdev->irqs[0] = 0; | |
1238 | + sdev->num_irqs = 0; | |
1239 | + } else { | |
1240 | + unsigned int pri = irqs[0].pri; | |
1241 | + | |
1242 | + sdev->num_irqs = 1; | |
1243 | + if (pri < 0x20) | |
1244 | + pri += sdev->slot * 8; | |
1245 | + | |
1246 | + sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); | |
1247 | + } | |
1248 | +} |
drivers/sbus/sbus.c
1 | -/* $Id: sbus.c,v 1.100 2002/01/24 15:36:24 davem Exp $ | |
2 | - * sbus.c: SBus support routines. | |
1 | +/* sbus.c: SBus support routines. | |
3 | 2 | * |
4 | - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | |
3 | + * Copyright (C) 1995, 2006 David S. Miller (davem@davemloft.net) | |
5 | 4 | */ |
6 | 5 | |
7 | 6 | #include <linux/kernel.h> |
8 | 7 | |
9 | 8 | |
... | ... | @@ -17,29 +16,12 @@ |
17 | 16 | #include <asm/bpp.h> |
18 | 17 | #include <asm/irq.h> |
19 | 18 | |
20 | -struct sbus_bus *sbus_root = NULL; | |
19 | +struct sbus_bus *sbus_root; | |
21 | 20 | |
22 | -static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } }; | |
23 | -#ifdef CONFIG_SPARC32 | |
24 | -static int interrupts[PROMINTR_MAX] __initdata = { 0 }; | |
25 | -#endif | |
26 | - | |
27 | 21 | #ifdef CONFIG_PCI |
28 | 22 | extern int pcic_present(void); |
29 | 23 | #endif |
30 | 24 | |
31 | -/* Perhaps when I figure out more about the iommu we'll put a | |
32 | - * device registration routine here that probe_sbus() calls to | |
33 | - * setup the iommu for each Sbus. | |
34 | - */ | |
35 | - | |
36 | -/* We call this for each SBus device, and fill the structure based | |
37 | - * upon the prom device tree. We return the start of memory after | |
38 | - * the things we have allocated. | |
39 | - */ | |
40 | - | |
41 | -/* #define DEBUG_FILL */ | |
42 | - | |
43 | 25 | static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev) |
44 | 26 | { |
45 | 27 | unsigned long address, base; |
46 | 28 | |
47 | 29 | |
48 | 30 | |
49 | 31 | |
50 | 32 | |
... | ... | @@ -52,117 +34,30 @@ |
52 | 34 | len = prom_getproperty(prom_node, "reg", |
53 | 35 | (char *) sdev->reg_addrs, |
54 | 36 | sizeof(sdev->reg_addrs)); |
55 | - if (len == -1) { | |
56 | - sdev->num_registers = 0; | |
57 | - goto no_regs; | |
58 | - } | |
37 | + sdev->num_registers = 0; | |
38 | + if (len != -1) { | |
39 | + sdev->num_registers = | |
40 | + len / sizeof(struct linux_prom_registers); | |
41 | + sdev->ranges_applied = 0; | |
59 | 42 | |
60 | - if (len % sizeof(struct linux_prom_registers)) { | |
61 | - prom_printf("fill_sbus_device: proplen for regs of %s " | |
62 | - " was %d, need multiple of %d\n", | |
63 | - sdev->prom_name, len, | |
64 | - (int) sizeof(struct linux_prom_registers)); | |
65 | - prom_halt(); | |
66 | - } | |
67 | - if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) { | |
68 | - prom_printf("fill_sbus_device: Too many register properties " | |
69 | - "for device %s, len=%d\n", | |
70 | - sdev->prom_name, len); | |
71 | - prom_halt(); | |
72 | - } | |
73 | - sdev->num_registers = len / sizeof(struct linux_prom_registers); | |
74 | - sdev->ranges_applied = 0; | |
43 | + base = (unsigned long) sdev->reg_addrs[0].phys_addr; | |
75 | 44 | |
76 | - base = (unsigned long) sdev->reg_addrs[0].phys_addr; | |
77 | - | |
78 | - /* Compute the slot number. */ | |
79 | - if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) { | |
80 | - sdev->slot = sbus_dev_slot(base); | |
81 | - } else { | |
82 | - sdev->slot = sdev->reg_addrs[0].which_io; | |
45 | + /* Compute the slot number. */ | |
46 | + if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) | |
47 | + sdev->slot = sbus_dev_slot(base); | |
48 | + else | |
49 | + sdev->slot = sdev->reg_addrs[0].which_io; | |
83 | 50 | } |
84 | 51 | |
85 | -no_regs: | |
86 | 52 | len = prom_getproperty(prom_node, "ranges", |
87 | 53 | (char *)sdev->device_ranges, |
88 | 54 | sizeof(sdev->device_ranges)); |
89 | - if (len == -1) { | |
90 | - sdev->num_device_ranges = 0; | |
91 | - goto no_ranges; | |
92 | - } | |
93 | - if (len % sizeof(struct linux_prom_ranges)) { | |
94 | - prom_printf("fill_sbus_device: proplen for ranges of %s " | |
95 | - " was %d, need multiple of %d\n", | |
96 | - sdev->prom_name, len, | |
97 | - (int) sizeof(struct linux_prom_ranges)); | |
98 | - prom_halt(); | |
99 | - } | |
100 | - if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) { | |
101 | - prom_printf("fill_sbus_device: Too many range properties " | |
102 | - "for device %s, len=%d\n", | |
103 | - sdev->prom_name, len); | |
104 | - prom_halt(); | |
105 | - } | |
106 | - sdev->num_device_ranges = | |
107 | - len / sizeof(struct linux_prom_ranges); | |
55 | + sdev->num_device_ranges = 0; | |
56 | + if (len != -1) | |
57 | + sdev->num_device_ranges = | |
58 | + len / sizeof(struct linux_prom_ranges); | |
108 | 59 | |
109 | -no_ranges: | |
110 | - /* XXX Unfortunately, IRQ issues are very arch specific. | |
111 | - * XXX Pull this crud out into an arch specific area | |
112 | - * XXX at some point. -DaveM | |
113 | - */ | |
114 | -#ifdef CONFIG_SPARC64 | |
115 | - len = prom_getproperty(prom_node, "interrupts", | |
116 | - (char *) irqs, sizeof(irqs)); | |
117 | - if (len == -1 || len == 0) { | |
118 | - sdev->irqs[0] = 0; | |
119 | - sdev->num_irqs = 0; | |
120 | - } else { | |
121 | - unsigned int pri = irqs[0].pri; | |
122 | - | |
123 | - sdev->num_irqs = 1; | |
124 | - if (pri < 0x20) | |
125 | - pri += sdev->slot * 8; | |
126 | - | |
127 | - sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); | |
128 | - } | |
129 | -#endif /* CONFIG_SPARC64 */ | |
130 | - | |
131 | -#ifdef CONFIG_SPARC32 | |
132 | - len = prom_getproperty(prom_node, "intr", | |
133 | - (char *)irqs, sizeof(irqs)); | |
134 | - if (len != -1) { | |
135 | - sdev->num_irqs = len / 8; | |
136 | - if (sdev->num_irqs == 0) { | |
137 | - sdev->irqs[0] = 0; | |
138 | - } else if (sparc_cpu_model == sun4d) { | |
139 | - extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); | |
140 | - | |
141 | - for (len = 0; len < sdev->num_irqs; len++) | |
142 | - sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri); | |
143 | - } else { | |
144 | - for (len = 0; len < sdev->num_irqs; len++) | |
145 | - sdev->irqs[len] = irqs[len].pri; | |
146 | - } | |
147 | - } else { | |
148 | - /* No "intr" node found-- check for "interrupts" node. | |
149 | - * This node contains SBus interrupt levels, not IPLs | |
150 | - * as in "intr", and no vector values. We convert | |
151 | - * SBus interrupt levels to PILs (platform specific). | |
152 | - */ | |
153 | - len = prom_getproperty(prom_node, "interrupts", | |
154 | - (char *)interrupts, sizeof(interrupts)); | |
155 | - if (len == -1) { | |
156 | - sdev->irqs[0] = 0; | |
157 | - sdev->num_irqs = 0; | |
158 | - } else { | |
159 | - sdev->num_irqs = len / sizeof(int); | |
160 | - for (len = 0; len < sdev->num_irqs; len++) { | |
161 | - sdev->irqs[len] = sbint_to_irq(sdev, interrupts[len]); | |
162 | - } | |
163 | - } | |
164 | - } | |
165 | -#endif /* CONFIG_SPARC32 */ | |
60 | + sbus_fill_device_irq(sdev); | |
166 | 61 | } |
167 | 62 | |
168 | 63 | /* This routine gets called from whoever needs the sbus first, to scan |
include/asm-sparc/sbus.h
... | ... | @@ -102,6 +102,7 @@ |
102 | 102 | #define sbus_can_dma_64bit(sdev) (0) /* actually, sparc_cpu_model==sun4d */ |
103 | 103 | #define sbus_can_burst64(sdev) (0) /* actually, sparc_cpu_model==sun4d */ |
104 | 104 | extern void sbus_set_sbus64(struct sbus_dev *, int); |
105 | +extern void sbus_fill_device_irq(struct sbus_dev *); | |
105 | 106 | |
106 | 107 | /* These yield IOMMU mappings in consistent mode. */ |
107 | 108 | extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp); |
include/asm-sparc64/sbus.h
... | ... | @@ -95,6 +95,7 @@ |
95 | 95 | #define sbus_can_dma_64bit(sdev) (1) |
96 | 96 | #define sbus_can_burst64(sdev) (1) |
97 | 97 | extern void sbus_set_sbus64(struct sbus_dev *, int); |
98 | +extern void sbus_fill_device_irq(struct sbus_dev *); | |
98 | 99 | |
99 | 100 | /* These yield IOMMU mappings in consistent mode. */ |
100 | 101 | extern void *sbus_alloc_consistent(struct sbus_dev *, size_t, dma_addr_t *dma_addrp); |