diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-06-22 22:12:03 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-24 02:15:28 -0400 |
commit | 690c8fd31f1e35985d0f35772fde514da59ec9d1 (patch) | |
tree | 8a5a0036b3780a9eb315ea2201a2562570de1ebe /arch/sparc64/kernel/isa.c | |
parent | de8d28b16f5614aeb12bb69c8f9a38578b8d3ada (diff) |
[SPARC64]: Use in-kernel PROM tree for EBUS and ISA.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/isa.c')
-rw-r--r-- | arch/sparc64/kernel/isa.c | 144 |
1 files changed, 57 insertions, 87 deletions
diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index ae02c3820eab..8c8c5a491ad6 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c | |||
@@ -15,23 +15,19 @@ static void __init fatal_err(const char *reason) | |||
15 | static void __init report_dev(struct sparc_isa_device *isa_dev, int child) | 15 | static void __init report_dev(struct sparc_isa_device *isa_dev, int child) |
16 | { | 16 | { |
17 | if (child) | 17 | if (child) |
18 | printk(" (%s)", isa_dev->prom_name); | 18 | printk(" (%s)", isa_dev->prom_node->name); |
19 | else | 19 | else |
20 | printk(" [%s", isa_dev->prom_name); | 20 | printk(" [%s", isa_dev->prom_node->name); |
21 | } | 21 | } |
22 | 22 | ||
23 | static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev, | 23 | static struct linux_prom_registers * __init |
24 | struct linux_prom_registers *pregs, | 24 | isa_dev_get_resource(struct sparc_isa_device *isa_dev) |
25 | int pregs_size) | ||
26 | { | 25 | { |
26 | struct linux_prom_registers *pregs; | ||
27 | unsigned long base, len; | 27 | unsigned long base, len; |
28 | int prop_len; | 28 | int prop_len; |
29 | 29 | ||
30 | prop_len = prom_getproperty(isa_dev->prom_node, "reg", | 30 | pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len); |
31 | (char *) pregs, pregs_size); | ||
32 | |||
33 | if (prop_len <= 0) | ||
34 | return; | ||
35 | 31 | ||
36 | /* Only the first one is interesting. */ | 32 | /* Only the first one is interesting. */ |
37 | len = pregs[0].reg_size; | 33 | len = pregs[0].reg_size; |
@@ -42,10 +38,12 @@ static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev, | |||
42 | isa_dev->resource.start = base; | 38 | isa_dev->resource.start = base; |
43 | isa_dev->resource.end = (base + len - 1UL); | 39 | isa_dev->resource.end = (base + len - 1UL); |
44 | isa_dev->resource.flags = IORESOURCE_IO; | 40 | isa_dev->resource.flags = IORESOURCE_IO; |
45 | isa_dev->resource.name = isa_dev->prom_name; | 41 | isa_dev->resource.name = isa_dev->prom_node->name; |
46 | 42 | ||
47 | request_resource(&isa_dev->bus->parent->io_space, | 43 | request_resource(&isa_dev->bus->parent->io_space, |
48 | &isa_dev->resource); | 44 | &isa_dev->resource); |
45 | |||
46 | return pregs; | ||
49 | } | 47 | } |
50 | 48 | ||
51 | /* I can't believe they didn't put a real INO in the isa device | 49 | /* I can't believe they didn't put a real INO in the isa device |
@@ -98,8 +96,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev, | |||
98 | { | 96 | { |
99 | int irq_prop; | 97 | int irq_prop; |
100 | 98 | ||
101 | irq_prop = prom_getintdefault(isa_dev->prom_node, | 99 | irq_prop = of_getintprop_default(isa_dev->prom_node, |
102 | "interrupts", -1); | 100 | "interrupts", -1); |
103 | if (irq_prop <= 0) { | 101 | if (irq_prop <= 0) { |
104 | goto no_irq; | 102 | goto no_irq; |
105 | } else { | 103 | } else { |
@@ -141,16 +139,15 @@ no_irq: | |||
141 | 139 | ||
142 | static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) | 140 | static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) |
143 | { | 141 | { |
144 | int node = prom_getchild(parent_isa_dev->prom_node); | 142 | struct device_node *dp = parent_isa_dev->prom_node->child; |
145 | 143 | ||
146 | if (node == 0) | 144 | if (!dp) |
147 | return; | 145 | return; |
148 | 146 | ||
149 | printk(" ->"); | 147 | printk(" ->"); |
150 | while (node != 0) { | 148 | while (dp) { |
151 | struct linux_prom_registers regs[PROMREG_MAX]; | 149 | struct linux_prom_registers *regs; |
152 | struct sparc_isa_device *isa_dev; | 150 | struct sparc_isa_device *isa_dev; |
153 | int prop_len; | ||
154 | 151 | ||
155 | isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); | 152 | isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); |
156 | if (!isa_dev) { | 153 | if (!isa_dev) { |
@@ -165,40 +162,24 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) | |||
165 | parent_isa_dev->child = isa_dev; | 162 | parent_isa_dev->child = isa_dev; |
166 | 163 | ||
167 | isa_dev->bus = parent_isa_dev->bus; | 164 | isa_dev->bus = parent_isa_dev->bus; |
168 | isa_dev->prom_node = node; | 165 | isa_dev->prom_node = dp; |
169 | prop_len = prom_getproperty(node, "name", | ||
170 | (char *) isa_dev->prom_name, | ||
171 | sizeof(isa_dev->prom_name)); | ||
172 | if (prop_len <= 0) { | ||
173 | fatal_err("cannot get child isa_dev OBP node name"); | ||
174 | prom_halt(); | ||
175 | } | ||
176 | |||
177 | prop_len = prom_getproperty(node, "compatible", | ||
178 | (char *) isa_dev->compatible, | ||
179 | sizeof(isa_dev->compatible)); | ||
180 | 166 | ||
181 | /* Not having this is OK. */ | 167 | regs = isa_dev_get_resource(isa_dev); |
182 | if (prop_len <= 0) | ||
183 | isa_dev->compatible[0] = '\0'; | ||
184 | |||
185 | isa_dev_get_resource(isa_dev, regs, sizeof(regs)); | ||
186 | isa_dev_get_irq(isa_dev, regs); | 168 | isa_dev_get_irq(isa_dev, regs); |
187 | 169 | ||
188 | report_dev(isa_dev, 1); | 170 | report_dev(isa_dev, 1); |
189 | 171 | ||
190 | node = prom_getsibling(node); | 172 | dp = dp->sibling; |
191 | } | 173 | } |
192 | } | 174 | } |
193 | 175 | ||
194 | static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) | 176 | static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) |
195 | { | 177 | { |
196 | int node = prom_getchild(isa_br->prom_node); | 178 | struct device_node *dp = isa_br->prom_node->child; |
197 | 179 | ||
198 | while (node != 0) { | 180 | while (dp) { |
199 | struct linux_prom_registers regs[PROMREG_MAX]; | 181 | struct linux_prom_registers *regs; |
200 | struct sparc_isa_device *isa_dev; | 182 | struct sparc_isa_device *isa_dev; |
201 | int prop_len; | ||
202 | 183 | ||
203 | isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); | 184 | isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); |
204 | if (!isa_dev) { | 185 | if (!isa_dev) { |
@@ -222,24 +203,9 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) | |||
222 | } | 203 | } |
223 | 204 | ||
224 | isa_dev->bus = isa_br; | 205 | isa_dev->bus = isa_br; |
225 | isa_dev->prom_node = node; | 206 | isa_dev->prom_node = dp; |
226 | prop_len = prom_getproperty(node, "name", | ||
227 | (char *) isa_dev->prom_name, | ||
228 | sizeof(isa_dev->prom_name)); | ||
229 | if (prop_len <= 0) { | ||
230 | fatal_err("cannot get isa_dev OBP node name"); | ||
231 | prom_halt(); | ||
232 | } | ||
233 | |||
234 | prop_len = prom_getproperty(node, "compatible", | ||
235 | (char *) isa_dev->compatible, | ||
236 | sizeof(isa_dev->compatible)); | ||
237 | |||
238 | /* Not having this is OK. */ | ||
239 | if (prop_len <= 0) | ||
240 | isa_dev->compatible[0] = '\0'; | ||
241 | 207 | ||
242 | isa_dev_get_resource(isa_dev, regs, sizeof(regs)); | 208 | regs = isa_dev_get_resource(isa_dev); |
243 | isa_dev_get_irq(isa_dev, regs); | 209 | isa_dev_get_irq(isa_dev, regs); |
244 | 210 | ||
245 | report_dev(isa_dev, 0); | 211 | report_dev(isa_dev, 0); |
@@ -248,10 +214,40 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) | |||
248 | 214 | ||
249 | printk("]"); | 215 | printk("]"); |
250 | 216 | ||
251 | node = prom_getsibling(node); | 217 | dp = dp->sibling; |
252 | } | 218 | } |
253 | } | 219 | } |
254 | 220 | ||
221 | static void __init get_bridge_props(struct sparc_isa_bridge *isa_br) | ||
222 | { | ||
223 | struct device_node *dp = isa_br->prom_node; | ||
224 | void *pval; | ||
225 | int len; | ||
226 | |||
227 | pval = of_get_property(dp, "ranges", &len); | ||
228 | if (pval) { | ||
229 | memcpy(isa_br->isa_ranges, pval, len); | ||
230 | isa_br->num_isa_ranges = | ||
231 | len / sizeof(struct linux_prom_isa_ranges); | ||
232 | } else { | ||
233 | isa_br->num_isa_ranges = 0; | ||
234 | } | ||
235 | |||
236 | pval = of_get_property(dp, "interrupt-map", &len); | ||
237 | if (pval) { | ||
238 | memcpy(isa_br->isa_intmap, pval, len); | ||
239 | isa_br->num_isa_intmap = | ||
240 | (len / sizeof(struct linux_prom_isa_intmap)); | ||
241 | } else { | ||
242 | isa_br->num_isa_intmap = 0; | ||
243 | } | ||
244 | |||
245 | pval = of_get_property(dp, "interrupt-map-mask", &len); | ||
246 | if (pval) | ||
247 | memcpy(&isa_br->isa_intmask, pval, | ||
248 | sizeof(isa_br->isa_intmask)); | ||
249 | } | ||
250 | |||
255 | void __init isa_init(void) | 251 | void __init isa_init(void) |
256 | { | 252 | { |
257 | struct pci_dev *pdev; | 253 | struct pci_dev *pdev; |
@@ -266,7 +262,6 @@ void __init isa_init(void) | |||
266 | struct pcidev_cookie *pdev_cookie; | 262 | struct pcidev_cookie *pdev_cookie; |
267 | struct pci_pbm_info *pbm; | 263 | struct pci_pbm_info *pbm; |
268 | struct sparc_isa_bridge *isa_br; | 264 | struct sparc_isa_bridge *isa_br; |
269 | int prop_len; | ||
270 | 265 | ||
271 | pdev_cookie = pdev->sysdata; | 266 | pdev_cookie = pdev->sysdata; |
272 | if (!pdev_cookie) { | 267 | if (!pdev_cookie) { |
@@ -291,34 +286,9 @@ void __init isa_init(void) | |||
291 | isa_br->parent = pbm; | 286 | isa_br->parent = pbm; |
292 | isa_br->self = pdev; | 287 | isa_br->self = pdev; |
293 | isa_br->index = index++; | 288 | isa_br->index = index++; |
294 | isa_br->prom_node = pdev_cookie->prom_node->node; | 289 | isa_br->prom_node = pdev_cookie->prom_node; |
295 | strncpy(isa_br->prom_name, pdev_cookie->prom_node->name, | 290 | |
296 | sizeof(isa_br->prom_name)); | 291 | get_bridge_props(isa_br); |
297 | |||
298 | prop_len = prom_getproperty(isa_br->prom_node, | ||
299 | "ranges", | ||
300 | (char *) isa_br->isa_ranges, | ||
301 | sizeof(isa_br->isa_ranges)); | ||
302 | if (prop_len <= 0) | ||
303 | isa_br->num_isa_ranges = 0; | ||
304 | else | ||
305 | isa_br->num_isa_ranges = | ||
306 | (prop_len / sizeof(struct linux_prom_isa_ranges)); | ||
307 | |||
308 | prop_len = prom_getproperty(isa_br->prom_node, | ||
309 | "interrupt-map", | ||
310 | (char *) isa_br->isa_intmap, | ||
311 | sizeof(isa_br->isa_intmap)); | ||
312 | if (prop_len <= 0) | ||
313 | isa_br->num_isa_intmap = 0; | ||
314 | else | ||
315 | isa_br->num_isa_intmap = | ||
316 | (prop_len / sizeof(struct linux_prom_isa_intmap)); | ||
317 | |||
318 | prop_len = prom_getproperty(isa_br->prom_node, | ||
319 | "interrupt-map-mask", | ||
320 | (char *) &(isa_br->isa_intmask), | ||
321 | sizeof(isa_br->isa_intmask)); | ||
322 | 292 | ||
323 | printk("isa%d:", isa_br->index); | 293 | printk("isa%d:", isa_br->index); |
324 | 294 | ||