aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/isa.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/isa.c')
-rw-r--r--arch/sparc64/kernel/isa.c183
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)
15static void __init report_dev(struct sparc_isa_device *isa_dev, int child) 15static 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
23static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev, 23static struct linux_prom_registers * __init
24 struct linux_prom_registers *pregs, 24isa_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 {
74static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev, 72static 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
142static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) 152static 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
194static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) 188static 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