diff options
Diffstat (limited to 'arch/sparc64/kernel/isa.c')
-rw-r--r-- | arch/sparc64/kernel/isa.c | 183 |
1 files changed, 81 insertions, 102 deletions
diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index 30862abee611..6f16dee280a8 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 |
@@ -74,19 +72,30 @@ static struct { | |||
74 | static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev, | 72 | static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev, |
75 | struct sparc_isa_bridge *isa_br, | 73 | struct sparc_isa_bridge *isa_br, |
76 | int *interrupt, | 74 | int *interrupt, |
77 | struct linux_prom_registers *pregs) | 75 | struct linux_prom_registers *reg) |
78 | { | 76 | { |
77 | struct linux_prom_ebus_intmap *imap; | ||
78 | struct linux_prom_ebus_intmap *imask; | ||
79 | unsigned int hi, lo, irq; | 79 | unsigned int hi, lo, irq; |
80 | int i; | 80 | int i, len, n_imap; |
81 | 81 | ||
82 | hi = pregs->which_io & isa_br->isa_intmask.phys_hi; | 82 | imap = of_get_property(isa_br->prom_node, "interrupt-map", &len); |
83 | lo = pregs->phys_addr & isa_br->isa_intmask.phys_lo; | 83 | if (!imap) |
84 | irq = *interrupt & isa_br->isa_intmask.interrupt; | 84 | return 0; |
85 | for (i = 0; i < isa_br->num_isa_intmap; i++) { | 85 | n_imap = len / sizeof(imap[0]); |
86 | if ((isa_br->isa_intmap[i].phys_hi == hi) && | 86 | |
87 | (isa_br->isa_intmap[i].phys_lo == lo) && | 87 | imask = of_get_property(isa_br->prom_node, "interrupt-map-mask", NULL); |
88 | (isa_br->isa_intmap[i].interrupt == irq)) { | 88 | if (!imask) |
89 | *interrupt = isa_br->isa_intmap[i].cinterrupt; | 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; | ||
90 | return 0; | 99 | return 0; |
91 | } | 100 | } |
92 | } | 101 | } |
@@ -98,8 +107,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev, | |||
98 | { | 107 | { |
99 | int irq_prop; | 108 | int irq_prop; |
100 | 109 | ||
101 | irq_prop = prom_getintdefault(isa_dev->prom_node, | 110 | irq_prop = of_getintprop_default(isa_dev->prom_node, |
102 | "interrupts", -1); | 111 | "interrupts", -1); |
103 | if (irq_prop <= 0) { | 112 | if (irq_prop <= 0) { |
104 | goto no_irq; | 113 | goto no_irq; |
105 | } else { | 114 | } else { |
@@ -107,7 +116,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev, | |||
107 | struct pci_pbm_info *pbm; | 116 | struct pci_pbm_info *pbm; |
108 | int i; | 117 | int i; |
109 | 118 | ||
110 | if (isa_dev->bus->num_isa_intmap) { | 119 | if (of_find_property(isa_dev->bus->prom_node, |
120 | "interrupt-map", NULL)) { | ||
111 | if (!isa_dev_get_irq_using_imap(isa_dev, | 121 | if (!isa_dev_get_irq_using_imap(isa_dev, |
112 | isa_dev->bus, | 122 | isa_dev->bus, |
113 | &irq_prop, | 123 | &irq_prop, |
@@ -141,16 +151,15 @@ no_irq: | |||
141 | 151 | ||
142 | static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) | 152 | static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) |
143 | { | 153 | { |
144 | int node = prom_getchild(parent_isa_dev->prom_node); | 154 | struct device_node *dp = parent_isa_dev->prom_node->child; |
145 | 155 | ||
146 | if (node == 0) | 156 | if (!dp) |
147 | return; | 157 | return; |
148 | 158 | ||
149 | printk(" ->"); | 159 | printk(" ->"); |
150 | while (node != 0) { | 160 | while (dp) { |
151 | struct linux_prom_registers regs[PROMREG_MAX]; | 161 | struct linux_prom_registers *regs; |
152 | struct sparc_isa_device *isa_dev; | 162 | struct sparc_isa_device *isa_dev; |
153 | int prop_len; | ||
154 | 163 | ||
155 | isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); | 164 | isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); |
156 | if (!isa_dev) { | 165 | if (!isa_dev) { |
@@ -165,49 +174,46 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) | |||
165 | parent_isa_dev->child = isa_dev; | 174 | parent_isa_dev->child = isa_dev; |
166 | 175 | ||
167 | isa_dev->bus = parent_isa_dev->bus; | 176 | isa_dev->bus = parent_isa_dev->bus; |
168 | isa_dev->prom_node = node; | 177 | 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 | 178 | ||
177 | prop_len = prom_getproperty(node, "compatible", | 179 | regs = isa_dev_get_resource(isa_dev); |
178 | (char *) isa_dev->compatible, | ||
179 | sizeof(isa_dev->compatible)); | ||
180 | |||
181 | /* Not having this is OK. */ | ||
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); | 180 | isa_dev_get_irq(isa_dev, regs); |
187 | 181 | ||
188 | report_dev(isa_dev, 1); | 182 | report_dev(isa_dev, 1); |
189 | 183 | ||
190 | node = prom_getsibling(node); | 184 | dp = dp->sibling; |
191 | } | 185 | } |
192 | } | 186 | } |
193 | 187 | ||
194 | static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) | 188 | static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) |
195 | { | 189 | { |
196 | int node = prom_getchild(isa_br->prom_node); | 190 | struct device_node *dp = isa_br->prom_node->child; |
197 | 191 | ||
198 | while (node != 0) { | 192 | while (dp) { |
199 | struct linux_prom_registers regs[PROMREG_MAX]; | 193 | struct linux_prom_registers *regs; |
200 | struct sparc_isa_device *isa_dev; | 194 | struct sparc_isa_device *isa_dev; |
201 | int prop_len; | ||
202 | 195 | ||
203 | isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); | 196 | isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); |
204 | if (!isa_dev) { | 197 | if (!isa_dev) { |
205 | fatal_err("cannot allocate isa_dev"); | 198 | printk(KERN_DEBUG "ISA: cannot allocate isa_dev"); |
206 | prom_halt(); | 199 | return; |
207 | } | 200 | } |
208 | 201 | ||
209 | memset(isa_dev, 0, sizeof(*isa_dev)); | 202 | memset(isa_dev, 0, sizeof(*isa_dev)); |
210 | 203 | ||
204 | isa_dev->ofdev.node = dp; | ||
205 | isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; | ||
206 | isa_dev->ofdev.dev.bus = &isa_bus_type; | ||
207 | strcpy(isa_dev->ofdev.dev.bus_id, dp->path_component_name); | ||
208 | |||
209 | /* Register with core */ | ||
210 | if (of_device_register(&isa_dev->ofdev) != 0) { | ||
211 | printk(KERN_DEBUG "isa: device registration error for %s!\n", | ||
212 | isa_dev->ofdev.dev.bus_id); | ||
213 | kfree(isa_dev); | ||
214 | goto next_sibling; | ||
215 | } | ||
216 | |||
211 | /* Link it in. */ | 217 | /* Link it in. */ |
212 | isa_dev->next = NULL; | 218 | isa_dev->next = NULL; |
213 | if (isa_br->devices == NULL) { | 219 | if (isa_br->devices == NULL) { |
@@ -222,24 +228,9 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) | |||
222 | } | 228 | } |
223 | 229 | ||
224 | isa_dev->bus = isa_br; | 230 | isa_dev->bus = isa_br; |
225 | isa_dev->prom_node = node; | 231 | 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 | 232 | ||
238 | /* Not having this is OK. */ | 233 | regs = isa_dev_get_resource(isa_dev); |
239 | if (prop_len <= 0) | ||
240 | isa_dev->compatible[0] = '\0'; | ||
241 | |||
242 | isa_dev_get_resource(isa_dev, regs, sizeof(regs)); | ||
243 | isa_dev_get_irq(isa_dev, regs); | 234 | isa_dev_get_irq(isa_dev, regs); |
244 | 235 | ||
245 | report_dev(isa_dev, 0); | 236 | report_dev(isa_dev, 0); |
@@ -248,7 +239,8 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) | |||
248 | 239 | ||
249 | printk("]"); | 240 | printk("]"); |
250 | 241 | ||
251 | node = prom_getsibling(node); | 242 | next_sibling: |
243 | dp = dp->sibling; | ||
252 | } | 244 | } |
253 | } | 245 | } |
254 | 246 | ||
@@ -266,7 +258,7 @@ void __init isa_init(void) | |||
266 | struct pcidev_cookie *pdev_cookie; | 258 | struct pcidev_cookie *pdev_cookie; |
267 | struct pci_pbm_info *pbm; | 259 | struct pci_pbm_info *pbm; |
268 | struct sparc_isa_bridge *isa_br; | 260 | struct sparc_isa_bridge *isa_br; |
269 | int prop_len; | 261 | struct device_node *dp; |
270 | 262 | ||
271 | pdev_cookie = pdev->sysdata; | 263 | pdev_cookie = pdev->sysdata; |
272 | if (!pdev_cookie) { | 264 | if (!pdev_cookie) { |
@@ -275,15 +267,29 @@ void __init isa_init(void) | |||
275 | continue; | 267 | continue; |
276 | } | 268 | } |
277 | pbm = pdev_cookie->pbm; | 269 | pbm = pdev_cookie->pbm; |
270 | dp = pdev_cookie->prom_node; | ||
278 | 271 | ||
279 | isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL); | 272 | isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL); |
280 | if (!isa_br) { | 273 | if (!isa_br) { |
281 | fatal_err("cannot allocate sparc_isa_bridge"); | 274 | printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge"); |
282 | prom_halt(); | 275 | return; |
283 | } | 276 | } |
284 | 277 | ||
285 | memset(isa_br, 0, sizeof(*isa_br)); | 278 | memset(isa_br, 0, sizeof(*isa_br)); |
286 | 279 | ||
280 | isa_br->ofdev.node = dp; | ||
281 | isa_br->ofdev.dev.parent = &pdev->dev; | ||
282 | isa_br->ofdev.dev.bus = &isa_bus_type; | ||
283 | strcpy(isa_br->ofdev.dev.bus_id, dp->path_component_name); | ||
284 | |||
285 | /* Register with core */ | ||
286 | if (of_device_register(&isa_br->ofdev) != 0) { | ||
287 | printk(KERN_DEBUG "isa: device registration error for %s!\n", | ||
288 | isa_br->ofdev.dev.bus_id); | ||
289 | kfree(isa_br); | ||
290 | return; | ||
291 | } | ||
292 | |||
287 | /* Link it in. */ | 293 | /* Link it in. */ |
288 | isa_br->next = isa_chain; | 294 | isa_br->next = isa_chain; |
289 | isa_chain = isa_br; | 295 | isa_chain = isa_br; |
@@ -292,33 +298,6 @@ void __init isa_init(void) | |||
292 | isa_br->self = pdev; | 298 | isa_br->self = pdev; |
293 | isa_br->index = index++; | 299 | isa_br->index = index++; |
294 | isa_br->prom_node = pdev_cookie->prom_node; | 300 | isa_br->prom_node = pdev_cookie->prom_node; |
295 | strncpy(isa_br->prom_name, pdev_cookie->prom_name, | ||
296 | sizeof(isa_br->prom_name)); | ||
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 | 301 | ||
323 | printk("isa%d:", isa_br->index); | 302 | printk("isa%d:", isa_br->index); |
324 | 303 | ||