Commit 576c352e89e57cfa6c9f493e549d10d86f60a0cf
Committed by
David S. Miller
1 parent
fd53143116
[SBUS]: Rewrite and plug into of_device framework.
I severely apologize, I was still learning how to program in C when I wrote this stuff 10 years ago... Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 5 changed files with 293 additions and 327 deletions Side-by-side Diff
arch/sparc/kernel/ioport.c
... | ... | @@ -39,6 +39,8 @@ |
39 | 39 | #include <asm/io.h> |
40 | 40 | #include <asm/vaddrs.h> |
41 | 41 | #include <asm/oplib.h> |
42 | +#include <asm/prom.h> | |
43 | +#include <asm/sbus.h> | |
42 | 44 | #include <asm/page.h> |
43 | 45 | #include <asm/pgalloc.h> |
44 | 46 | #include <asm/dma.h> |
... | ... | @@ -457,6 +459,89 @@ |
457 | 459 | void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) |
458 | 460 | { |
459 | 461 | printk("sbus_dma_sync_sg_for_device: not implemented yet\n"); |
462 | +} | |
463 | + | |
464 | +/* Support code for sbus_init(). */ | |
465 | +/* | |
466 | + * XXX This functions appears to be a distorted version of | |
467 | + * prom_sbus_ranges_init(), with all sun4d stuff cut away. | |
468 | + * Ask DaveM what is going on here, how is sun4d supposed to work... XXX | |
469 | + */ | |
470 | +/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */ | |
471 | +void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) | |
472 | +{ | |
473 | + int parent_node = pn->node; | |
474 | + | |
475 | + if (sparc_cpu_model == sun4d) { | |
476 | + struct linux_prom_ranges iounit_ranges[PROMREG_MAX]; | |
477 | + int num_iounit_ranges, len; | |
478 | + | |
479 | + len = prom_getproperty(parent_node, "ranges", | |
480 | + (char *) iounit_ranges, | |
481 | + sizeof (iounit_ranges)); | |
482 | + if (len != -1) { | |
483 | + num_iounit_ranges = | |
484 | + (len / sizeof(struct linux_prom_ranges)); | |
485 | + prom_adjust_ranges(sbus->sbus_ranges, | |
486 | + sbus->num_sbus_ranges, | |
487 | + iounit_ranges, num_iounit_ranges); | |
488 | + } | |
489 | + } | |
490 | +} | |
491 | + | |
492 | +void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) | |
493 | +{ | |
494 | + struct device_node *parent = dp->parent; | |
495 | + | |
496 | + if (sparc_cpu_model != sun4d && | |
497 | + parent != NULL && | |
498 | + !strcmp(parent->name, "iommu")) { | |
499 | + extern void iommu_init(int iommu_node, struct sbus_bus *sbus); | |
500 | + | |
501 | + iommu_init(parent->node, sbus); | |
502 | + } | |
503 | + | |
504 | + if (sparc_cpu_model == sun4d) { | |
505 | + extern void iounit_init(int sbi_node, int iounit_node, | |
506 | + struct sbus_bus *sbus); | |
507 | + | |
508 | + iounit_init(dp->node, parent->node, sbus); | |
509 | + } | |
510 | +} | |
511 | + | |
512 | +void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) | |
513 | +{ | |
514 | + if (sparc_cpu_model == sun4d) { | |
515 | + struct device_node *parent = dp->parent; | |
516 | + | |
517 | + sbus->devid = of_getintprop_default(parent, "device-id", 0); | |
518 | + sbus->board = of_getintprop_default(parent, "board#", 0); | |
519 | + } | |
520 | +} | |
521 | + | |
522 | +int __init sbus_arch_preinit(void) | |
523 | +{ | |
524 | + extern void register_proc_sparc_ioport(void); | |
525 | + | |
526 | + register_proc_sparc_ioport(); | |
527 | + | |
528 | +#ifdef CONFIG_SUN4 | |
529 | + { | |
530 | + extern void sun4_dvma_init(void); | |
531 | + sun4_dvma_init(); | |
532 | + } | |
533 | + return 1; | |
534 | +#else | |
535 | + return 0; | |
536 | +#endif | |
537 | +} | |
538 | + | |
539 | +void __init sbus_arch_postinit(void) | |
540 | +{ | |
541 | + if (sparc_cpu_model == sun4d) { | |
542 | + extern void sun4d_init_sbi_irq(void); | |
543 | + sun4d_init_sbi_irq(); | |
544 | + } | |
460 | 545 | } |
461 | 546 | #endif /* CONFIG_SBUS */ |
462 | 547 |
arch/sparc64/kernel/sbus.c
... | ... | @@ -1099,7 +1099,7 @@ |
1099 | 1099 | } |
1100 | 1100 | |
1101 | 1101 | /* Boot time initialization. */ |
1102 | -void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |
1102 | +static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |
1103 | 1103 | { |
1104 | 1104 | struct linux_prom64_registers *pr; |
1105 | 1105 | struct device_node *dp; |
... | ... | @@ -1246,5 +1246,34 @@ |
1246 | 1246 | |
1247 | 1247 | sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); |
1248 | 1248 | } |
1249 | +} | |
1250 | + | |
1251 | +void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) | |
1252 | +{ | |
1253 | +} | |
1254 | + | |
1255 | +void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) | |
1256 | +{ | |
1257 | + sbus_iommu_init(dp->node, sbus); | |
1258 | +} | |
1259 | + | |
1260 | +void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) | |
1261 | +{ | |
1262 | +} | |
1263 | + | |
1264 | +int __init sbus_arch_preinit(void) | |
1265 | +{ | |
1266 | + return 0; | |
1267 | +} | |
1268 | + | |
1269 | +void __init sbus_arch_postinit(void) | |
1270 | +{ | |
1271 | + extern void firetruck_init(void); | |
1272 | + extern void auxio_probe(void); | |
1273 | + extern void clock_probe(void); | |
1274 | + | |
1275 | + firetruck_init(); | |
1276 | + auxio_probe(); | |
1277 | + clock_probe(); | |
1249 | 1278 | } |
drivers/sbus/sbus.c
... | ... | @@ -13,32 +13,29 @@ |
13 | 13 | #include <asm/sbus.h> |
14 | 14 | #include <asm/dma.h> |
15 | 15 | #include <asm/oplib.h> |
16 | +#include <asm/prom.h> | |
17 | +#include <asm/of_device.h> | |
16 | 18 | #include <asm/bpp.h> |
17 | 19 | #include <asm/irq.h> |
18 | 20 | |
19 | 21 | struct sbus_bus *sbus_root; |
20 | 22 | |
21 | -#ifdef CONFIG_PCI | |
22 | -extern int pcic_present(void); | |
23 | -#endif | |
24 | - | |
25 | -static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev) | |
23 | +static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev) | |
26 | 24 | { |
27 | - unsigned long address, base; | |
25 | + unsigned long base; | |
26 | + void *pval; | |
28 | 27 | int len; |
29 | 28 | |
30 | - sdev->prom_node = prom_node; | |
31 | - prom_getstring(prom_node, "name", | |
32 | - sdev->prom_name, sizeof(sdev->prom_name)); | |
33 | - address = prom_getint(prom_node, "address"); | |
34 | - len = prom_getproperty(prom_node, "reg", | |
35 | - (char *) sdev->reg_addrs, | |
36 | - sizeof(sdev->reg_addrs)); | |
29 | + sdev->prom_node = dp->node; | |
30 | + strcpy(sdev->prom_name, dp->name); | |
31 | + | |
32 | + pval = of_get_property(dp, "reg", &len); | |
37 | 33 | sdev->num_registers = 0; |
38 | - if (len != -1) { | |
34 | + if (pval) { | |
35 | + memcpy(sdev->reg_addrs, pval, len); | |
36 | + | |
39 | 37 | sdev->num_registers = |
40 | 38 | len / sizeof(struct linux_prom_registers); |
41 | - sdev->ranges_applied = 0; | |
42 | 39 | |
43 | 40 | base = (unsigned long) sdev->reg_addrs[0].phys_addr; |
44 | 41 | |
45 | 42 | |
46 | 43 | |
47 | 44 | |
48 | 45 | |
49 | 46 | |
50 | 47 | |
51 | 48 | |
52 | 49 | |
53 | 50 | |
54 | 51 | |
... | ... | @@ -49,97 +46,43 @@ |
49 | 46 | sdev->slot = sdev->reg_addrs[0].which_io; |
50 | 47 | } |
51 | 48 | |
52 | - len = prom_getproperty(prom_node, "ranges", | |
53 | - (char *)sdev->device_ranges, | |
54 | - sizeof(sdev->device_ranges)); | |
49 | + pval = of_get_property(dp, "ranges", &len); | |
55 | 50 | sdev->num_device_ranges = 0; |
56 | - if (len != -1) | |
51 | + if (pval) { | |
52 | + memcpy(sdev->device_ranges, pval, len); | |
57 | 53 | sdev->num_device_ranges = |
58 | 54 | len / sizeof(struct linux_prom_ranges); |
55 | + } | |
59 | 56 | |
60 | 57 | sbus_fill_device_irq(sdev); |
61 | -} | |
62 | 58 | |
63 | -/* This routine gets called from whoever needs the sbus first, to scan | |
64 | - * the SBus device tree. Currently it just prints out the devices | |
65 | - * found on the bus and builds trees of SBUS structs and attached | |
66 | - * devices. | |
67 | - */ | |
59 | + sdev->ofdev.node = dp; | |
60 | + if (sdev->parent) | |
61 | + sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev; | |
62 | + else | |
63 | + sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev; | |
64 | + sdev->ofdev.dev.bus = &sbus_bus_type; | |
65 | + strcpy(sdev->ofdev.dev.bus_id, dp->path_component_name); | |
68 | 66 | |
69 | -extern void iommu_init(int iommu_node, struct sbus_bus *sbus); | |
70 | -extern void iounit_init(int sbi_node, int iounit_node, struct sbus_bus *sbus); | |
71 | -void sun4_init(void); | |
72 | -#ifdef CONFIG_SUN_AUXIO | |
73 | -extern void auxio_probe(void); | |
74 | -#endif | |
75 | - | |
76 | -static void __init sbus_do_child_siblings(int start_node, | |
77 | - struct sbus_dev *child, | |
78 | - struct sbus_dev *parent, | |
79 | - struct sbus_bus *sbus) | |
80 | -{ | |
81 | - struct sbus_dev *this_dev = child; | |
82 | - int this_node = start_node; | |
83 | - | |
84 | - /* Child already filled in, just need to traverse siblings. */ | |
85 | - child->child = NULL; | |
86 | - child->parent = parent; | |
87 | - while((this_node = prom_getsibling(this_node)) != 0) { | |
88 | - this_dev->next = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); | |
89 | - this_dev = this_dev->next; | |
90 | - this_dev->next = NULL; | |
91 | - this_dev->parent = parent; | |
92 | - | |
93 | - this_dev->bus = sbus; | |
94 | - fill_sbus_device(this_node, this_dev); | |
95 | - | |
96 | - if(prom_getchild(this_node)) { | |
97 | - this_dev->child = kmalloc(sizeof(struct sbus_dev), | |
98 | - GFP_ATOMIC); | |
99 | - this_dev->child->bus = sbus; | |
100 | - this_dev->child->next = NULL; | |
101 | - fill_sbus_device(prom_getchild(this_node), this_dev->child); | |
102 | - sbus_do_child_siblings(prom_getchild(this_node), | |
103 | - this_dev->child, this_dev, sbus); | |
104 | - } else { | |
105 | - this_dev->child = NULL; | |
106 | - } | |
107 | - } | |
67 | + if (of_device_register(&sdev->ofdev) != 0) | |
68 | + printk(KERN_DEBUG "sbus: device registration error for %s!\n", | |
69 | + sdev->ofdev.dev.bus_id); | |
108 | 70 | } |
109 | 71 | |
110 | -/* | |
111 | - * XXX This functions appears to be a distorted version of | |
112 | - * prom_sbus_ranges_init(), with all sun4d stuff cut away. | |
113 | - * Ask DaveM what is going on here, how is sun4d supposed to work... XXX | |
114 | - */ | |
115 | -/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */ | |
116 | - | |
117 | -static void __init sbus_bus_ranges_init(int parent_node, struct sbus_bus *sbus) | |
72 | +static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus) | |
118 | 73 | { |
74 | + void *pval; | |
119 | 75 | int len; |
120 | 76 | |
121 | - len = prom_getproperty(sbus->prom_node, "ranges", | |
122 | - (char *) sbus->sbus_ranges, | |
123 | - sizeof(sbus->sbus_ranges)); | |
124 | - if (len == -1 || len == 0) { | |
125 | - sbus->num_sbus_ranges = 0; | |
126 | - return; | |
127 | - } | |
128 | - sbus->num_sbus_ranges = len / sizeof(struct linux_prom_ranges); | |
129 | -#ifdef CONFIG_SPARC32 | |
130 | - if (sparc_cpu_model == sun4d) { | |
131 | - struct linux_prom_ranges iounit_ranges[PROMREG_MAX]; | |
132 | - int num_iounit_ranges; | |
77 | + pval = of_get_property(dp, "ranges", &len); | |
78 | + sbus->num_sbus_ranges = 0; | |
79 | + if (pval) { | |
80 | + memcpy(sbus->sbus_ranges, pval, len); | |
81 | + sbus->num_sbus_ranges = | |
82 | + len / sizeof(struct linux_prom_ranges); | |
133 | 83 | |
134 | - len = prom_getproperty(parent_node, "ranges", | |
135 | - (char *) iounit_ranges, | |
136 | - sizeof (iounit_ranges)); | |
137 | - if (len != -1) { | |
138 | - num_iounit_ranges = (len/sizeof(struct linux_prom_ranges)); | |
139 | - prom_adjust_ranges (sbus->sbus_ranges, sbus->num_sbus_ranges, iounit_ranges, num_iounit_ranges); | |
140 | - } | |
84 | + sbus_arch_bus_ranges_init(dp->parent, sbus); | |
141 | 85 | } |
142 | -#endif | |
143 | 86 | } |
144 | 87 | |
145 | 88 | static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges, |
146 | 89 | |
147 | 90 | |
148 | 91 | |
149 | 92 | |
150 | 93 | |
151 | 94 | |
152 | 95 | |
153 | 96 | |
154 | 97 | |
155 | 98 | |
156 | 99 | |
157 | 100 | |
158 | 101 | |
159 | 102 | |
160 | 103 | |
161 | 104 | |
162 | 105 | |
163 | 106 | |
164 | 107 | |
165 | 108 | |
166 | 109 | |
167 | 110 | |
168 | 111 | |
169 | 112 | |
170 | 113 | |
171 | 114 | |
172 | 115 | |
173 | 116 | |
174 | 117 | |
... | ... | @@ -217,241 +160,127 @@ |
217 | 160 | } |
218 | 161 | } |
219 | 162 | |
220 | -extern void register_proc_sparc_ioport(void); | |
221 | -extern void firetruck_init(void); | |
163 | +/* We preserve the "probe order" of these bus and device lists to give | |
164 | + * the same ordering as the old code. | |
165 | + */ | |
166 | +static void __init sbus_insert(struct sbus_bus *sbus, struct sbus_bus **root) | |
167 | +{ | |
168 | + while (*root) | |
169 | + root = &(*root)->next; | |
170 | + *root = sbus; | |
171 | + sbus->next = NULL; | |
172 | +} | |
222 | 173 | |
223 | -#ifdef CONFIG_SUN4 | |
224 | -extern void sun4_dvma_init(void); | |
225 | -#endif | |
174 | +static void __init sdev_insert(struct sbus_dev *sdev, struct sbus_dev **root) | |
175 | +{ | |
176 | + while (*root) | |
177 | + root = &(*root)->next; | |
178 | + *root = sdev; | |
179 | + sdev->next = NULL; | |
180 | +} | |
226 | 181 | |
227 | -static int __init sbus_init(void) | |
182 | +static void __init walk_children(struct device_node *dp, struct sbus_dev *parent, struct sbus_bus *sbus) | |
228 | 183 | { |
229 | - int nd, this_sbus, sbus_devs, topnd, iommund; | |
230 | - unsigned int sbus_clock; | |
231 | - struct sbus_bus *sbus; | |
232 | - struct sbus_dev *this_dev; | |
233 | - int num_sbus = 0; /* How many did we find? */ | |
184 | + dp = dp->child; | |
185 | + while (dp) { | |
186 | + struct sbus_dev *sdev; | |
234 | 187 | |
235 | -#ifdef CONFIG_SPARC32 | |
236 | - register_proc_sparc_ioport(); | |
237 | -#endif | |
188 | + sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); | |
189 | + if (sdev) { | |
190 | + sdev_insert(sdev, &parent->child); | |
238 | 191 | |
239 | -#ifdef CONFIG_SUN4 | |
240 | - sun4_dvma_init(); | |
241 | - return 0; | |
242 | -#endif | |
192 | + sdev->bus = sbus; | |
193 | + sdev->parent = parent; | |
243 | 194 | |
244 | - topnd = prom_getchild(prom_root_node); | |
245 | - | |
246 | - /* Finding the first sbus is a special case... */ | |
247 | - iommund = 0; | |
248 | - if(sparc_cpu_model == sun4u) { | |
249 | - nd = prom_searchsiblings(topnd, "sbus"); | |
250 | - if(nd == 0) { | |
251 | -#ifdef CONFIG_PCI | |
252 | - if (!pcic_present()) { | |
253 | - prom_printf("Neither SBUS nor PCI found.\n"); | |
254 | - prom_halt(); | |
255 | - } else { | |
256 | -#ifdef CONFIG_SPARC64 | |
257 | - firetruck_init(); | |
258 | -#endif | |
259 | - } | |
260 | - return 0; | |
261 | -#else | |
262 | - prom_printf("YEEE, UltraSparc sbus not found\n"); | |
263 | - prom_halt(); | |
264 | -#endif | |
195 | + fill_sbus_device(dp, sdev); | |
196 | + | |
197 | + walk_children(dp, sdev, sbus); | |
265 | 198 | } |
266 | - } else if(sparc_cpu_model == sun4d) { | |
267 | - if((iommund = prom_searchsiblings(topnd, "io-unit")) == 0 || | |
268 | - (nd = prom_getchild(iommund)) == 0 || | |
269 | - (nd = prom_searchsiblings(nd, "sbi")) == 0) { | |
270 | - panic("sbi not found"); | |
271 | - } | |
272 | - } else if((nd = prom_searchsiblings(topnd, "sbus")) == 0) { | |
273 | - if((iommund = prom_searchsiblings(topnd, "iommu")) == 0 || | |
274 | - (nd = prom_getchild(iommund)) == 0 || | |
275 | - (nd = prom_searchsiblings(nd, "sbus")) == 0) { | |
276 | -#ifdef CONFIG_PCI | |
277 | - if (!pcic_present()) { | |
278 | - prom_printf("Neither SBUS nor PCI found.\n"); | |
279 | - prom_halt(); | |
280 | - } | |
281 | - return 0; | |
282 | -#else | |
283 | - /* No reason to run further - the data access trap will occur. */ | |
284 | - panic("sbus not found"); | |
285 | -#endif | |
286 | - } | |
199 | + dp = dp->sibling; | |
287 | 200 | } |
201 | +} | |
288 | 202 | |
289 | - /* Ok, we've found the first one, allocate first SBus struct | |
290 | - * and place in chain. | |
291 | - */ | |
292 | - sbus = sbus_root = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC); | |
293 | - sbus->next = NULL; | |
294 | - sbus->prom_node = nd; | |
295 | - this_sbus = nd; | |
203 | +static void __init build_one_sbus(struct device_node *dp, int num_sbus) | |
204 | +{ | |
205 | + struct sbus_bus *sbus; | |
206 | + unsigned int sbus_clock; | |
207 | + struct device_node *dev_dp; | |
296 | 208 | |
297 | - if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d) | |
298 | - iommu_init(iommund, sbus); | |
209 | + sbus = kzalloc(sizeof(struct sbus_bus), GFP_ATOMIC); | |
210 | + if (!sbus) | |
211 | + return; | |
299 | 212 | |
300 | - /* Loop until we find no more SBUS's */ | |
301 | - while(this_sbus) { | |
302 | -#ifdef CONFIG_SPARC64 | |
303 | - /* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */ | |
304 | - if(sparc_cpu_model == sun4u) { | |
305 | - extern void sbus_iommu_init(int prom_node, struct sbus_bus *sbus); | |
213 | + sbus_insert(sbus, &sbus_root); | |
214 | + sbus->prom_node = dp->node; | |
306 | 215 | |
307 | - sbus_iommu_init(this_sbus, sbus); | |
308 | - } | |
309 | -#endif /* CONFIG_SPARC64 */ | |
216 | + sbus_setup_iommu(sbus, dp); | |
310 | 217 | |
311 | -#ifdef CONFIG_SPARC32 | |
312 | - if (sparc_cpu_model == sun4d) | |
313 | - iounit_init(this_sbus, iommund, sbus); | |
314 | -#endif /* CONFIG_SPARC32 */ | |
315 | - printk("sbus%d: ", num_sbus); | |
316 | - sbus_clock = prom_getint(this_sbus, "clock-frequency"); | |
317 | - if(sbus_clock == -1) | |
318 | - sbus_clock = (25*1000*1000); | |
319 | - printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000), | |
320 | - (int) (((sbus_clock/1000)%1000 != 0) ? | |
321 | - (((sbus_clock/1000)%1000) + 1000) : 0)); | |
218 | + printk("sbus%d: ", num_sbus); | |
322 | 219 | |
323 | - prom_getstring(this_sbus, "name", | |
324 | - sbus->prom_name, sizeof(sbus->prom_name)); | |
325 | - sbus->clock_freq = sbus_clock; | |
326 | -#ifdef CONFIG_SPARC32 | |
327 | - if (sparc_cpu_model == sun4d) { | |
328 | - sbus->devid = prom_getint(iommund, "device-id"); | |
329 | - sbus->board = prom_getint(iommund, "board#"); | |
330 | - } | |
331 | -#endif | |
332 | - | |
333 | - sbus_bus_ranges_init(iommund, sbus); | |
220 | + sbus_clock = of_getintprop_default(dp, "clock-frequency", | |
221 | + (25*1000*1000)); | |
222 | + sbus->clock_freq = sbus_clock; | |
334 | 223 | |
335 | - sbus_devs = prom_getchild(this_sbus); | |
336 | - if (!sbus_devs) { | |
337 | - sbus->devices = NULL; | |
338 | - goto next_bus; | |
339 | - } | |
224 | + printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000), | |
225 | + (int) (((sbus_clock/1000)%1000 != 0) ? | |
226 | + (((sbus_clock/1000)%1000) + 1000) : 0)); | |
340 | 227 | |
341 | - sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); | |
228 | + strcpy(sbus->prom_name, dp->name); | |
342 | 229 | |
343 | - this_dev = sbus->devices; | |
344 | - this_dev->next = NULL; | |
230 | + sbus_setup_arch_props(sbus, dp); | |
345 | 231 | |
346 | - this_dev->bus = sbus; | |
347 | - this_dev->parent = NULL; | |
348 | - fill_sbus_device(sbus_devs, this_dev); | |
232 | + sbus_bus_ranges_init(dp, sbus); | |
349 | 233 | |
350 | - /* Should we traverse for children? */ | |
351 | - if(prom_getchild(sbus_devs)) { | |
352 | - /* Allocate device node */ | |
353 | - this_dev->child = kmalloc(sizeof(struct sbus_dev), | |
354 | - GFP_ATOMIC); | |
355 | - /* Fill it */ | |
356 | - this_dev->child->bus = sbus; | |
357 | - this_dev->child->next = NULL; | |
358 | - fill_sbus_device(prom_getchild(sbus_devs), | |
359 | - this_dev->child); | |
360 | - sbus_do_child_siblings(prom_getchild(sbus_devs), | |
361 | - this_dev->child, | |
362 | - this_dev, | |
363 | - sbus); | |
364 | - } else { | |
365 | - this_dev->child = NULL; | |
366 | - } | |
234 | + sbus->ofdev.node = dp; | |
235 | + sbus->ofdev.dev.parent = NULL; | |
236 | + sbus->ofdev.dev.bus = &sbus_bus_type; | |
237 | + strcpy(sbus->ofdev.dev.bus_id, dp->path_component_name); | |
367 | 238 | |
368 | - while((sbus_devs = prom_getsibling(sbus_devs)) != 0) { | |
369 | - /* Allocate device node */ | |
370 | - this_dev->next = kmalloc(sizeof(struct sbus_dev), | |
371 | - GFP_ATOMIC); | |
372 | - this_dev = this_dev->next; | |
373 | - this_dev->next = NULL; | |
239 | + if (of_device_register(&sbus->ofdev) != 0) | |
240 | + printk(KERN_DEBUG "sbus: device registration error for %s!\n", | |
241 | + sbus->ofdev.dev.bus_id); | |
374 | 242 | |
375 | - /* Fill it */ | |
376 | - this_dev->bus = sbus; | |
377 | - this_dev->parent = NULL; | |
378 | - fill_sbus_device(sbus_devs, this_dev); | |
243 | + dev_dp = dp->child; | |
244 | + while (dev_dp) { | |
245 | + struct sbus_dev *sdev; | |
379 | 246 | |
380 | - /* Is there a child node hanging off of us? */ | |
381 | - if(prom_getchild(sbus_devs)) { | |
382 | - /* Get new device struct */ | |
383 | - this_dev->child = kmalloc(sizeof(struct sbus_dev), | |
384 | - GFP_ATOMIC); | |
385 | - /* Fill it */ | |
386 | - this_dev->child->bus = sbus; | |
387 | - this_dev->child->next = NULL; | |
388 | - fill_sbus_device(prom_getchild(sbus_devs), | |
389 | - this_dev->child); | |
390 | - sbus_do_child_siblings(prom_getchild(sbus_devs), | |
391 | - this_dev->child, | |
392 | - this_dev, | |
393 | - sbus); | |
394 | - } else { | |
395 | - this_dev->child = NULL; | |
396 | - } | |
247 | + sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); | |
248 | + if (sdev) { | |
249 | + sdev_insert(sdev, &sbus->devices); | |
250 | + | |
251 | + sdev->bus = sbus; | |
252 | + sdev->parent = NULL; | |
253 | + fill_sbus_device(dev_dp, sdev); | |
254 | + | |
255 | + walk_children(dev_dp, sdev, sbus); | |
397 | 256 | } |
257 | + dev_dp = dev_dp->sibling; | |
258 | + } | |
398 | 259 | |
399 | - /* Walk all devices and apply parent ranges. */ | |
400 | - sbus_fixup_all_regs(sbus->devices); | |
260 | + sbus_fixup_all_regs(sbus->devices); | |
401 | 261 | |
402 | - dvma_init(sbus); | |
403 | - next_bus: | |
262 | + dvma_init(sbus); | |
263 | +} | |
264 | + | |
265 | +static int __init sbus_init(void) | |
266 | +{ | |
267 | + struct device_node *dp; | |
268 | + const char *sbus_name = "sbus"; | |
269 | + int num_sbus = 0; | |
270 | + | |
271 | + if (sbus_arch_preinit()) | |
272 | + return 0; | |
273 | + | |
274 | + if (sparc_cpu_model == sun4d) | |
275 | + sbus_name = "sbi"; | |
276 | + | |
277 | + for_each_node_by_name(dp, sbus_name) { | |
278 | + build_one_sbus(dp, num_sbus); | |
404 | 279 | num_sbus++; |
405 | - if(sparc_cpu_model == sun4u) { | |
406 | - this_sbus = prom_getsibling(this_sbus); | |
407 | - if(!this_sbus) | |
408 | - break; | |
409 | - this_sbus = prom_searchsiblings(this_sbus, "sbus"); | |
410 | - } else if(sparc_cpu_model == sun4d) { | |
411 | - iommund = prom_getsibling(iommund); | |
412 | - if(!iommund) | |
413 | - break; | |
414 | - iommund = prom_searchsiblings(iommund, "io-unit"); | |
415 | - if(!iommund) | |
416 | - break; | |
417 | - this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi"); | |
418 | - } else { | |
419 | - this_sbus = prom_getsibling(this_sbus); | |
420 | - if(!this_sbus) | |
421 | - break; | |
422 | - this_sbus = prom_searchsiblings(this_sbus, "sbus"); | |
423 | - } | |
424 | - if(this_sbus) { | |
425 | - sbus->next = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC); | |
426 | - sbus = sbus->next; | |
427 | - sbus->next = NULL; | |
428 | - sbus->prom_node = this_sbus; | |
429 | - } else { | |
430 | - break; | |
431 | - } | |
432 | - } /* while(this_sbus) */ | |
433 | 280 | |
434 | - if (sparc_cpu_model == sun4d) { | |
435 | - extern void sun4d_init_sbi_irq(void); | |
436 | - sun4d_init_sbi_irq(); | |
437 | 281 | } |
438 | - | |
439 | -#ifdef CONFIG_SPARC64 | |
440 | - if (sparc_cpu_model == sun4u) { | |
441 | - firetruck_init(); | |
442 | - } | |
443 | -#endif | |
444 | -#ifdef CONFIG_SUN_AUXIO | |
445 | - if (sparc_cpu_model == sun4u) | |
446 | - auxio_probe (); | |
447 | -#endif | |
448 | -#ifdef CONFIG_SPARC64 | |
449 | - if (sparc_cpu_model == sun4u) { | |
450 | - extern void clock_probe(void); | |
451 | 282 | |
452 | - clock_probe(); | |
453 | - } | |
454 | -#endif | |
283 | + sbus_arch_postinit(); | |
455 | 284 | |
456 | 285 | return 0; |
457 | 286 | } |
include/asm-sparc/sbus.h
... | ... | @@ -11,7 +11,8 @@ |
11 | 11 | #include <linux/ioport.h> |
12 | 12 | |
13 | 13 | #include <asm/oplib.h> |
14 | -/* #include <asm/iommu.h> */ /* Unused since we use opaque iommu (|io-unit) */ | |
14 | +#include <asm/prom.h> | |
15 | +#include <asm/of_device.h> | |
15 | 16 | #include <asm/scatterlist.h> |
16 | 17 | |
17 | 18 | /* We scan which devices are on the SBus using the PROM node device |
18 | 19 | |
... | ... | @@ -42,18 +43,19 @@ |
42 | 43 | |
43 | 44 | /* Linux SBUS device tables */ |
44 | 45 | struct sbus_dev { |
45 | - struct sbus_bus *bus; /* Back ptr to sbus */ | |
46 | - struct sbus_dev *next; /* next device on this SBus or null */ | |
47 | - struct sbus_dev *child; /* For ledma and espdma on sun4m */ | |
48 | - struct sbus_dev *parent; /* Parent device if not toplevel */ | |
49 | - int prom_node; /* PROM device tree node for this device */ | |
50 | - char prom_name[64]; /* PROM device name */ | |
46 | + struct of_device ofdev; | |
47 | + struct sbus_bus *bus; | |
48 | + struct sbus_dev *next; | |
49 | + struct sbus_dev *child; | |
50 | + struct sbus_dev *parent; | |
51 | + int prom_node; | |
52 | + char prom_name[64]; | |
51 | 53 | int slot; |
52 | 54 | |
53 | 55 | struct resource resource[PROMREG_MAX]; |
54 | 56 | |
55 | 57 | struct linux_prom_registers reg_addrs[PROMREG_MAX]; |
56 | - int num_registers, ranges_applied; | |
58 | + int num_registers; | |
57 | 59 | |
58 | 60 | struct linux_prom_ranges device_ranges[PROMREG_MAX]; |
59 | 61 | int num_device_ranges; |
60 | 62 | |
... | ... | @@ -61,9 +63,11 @@ |
61 | 63 | unsigned int irqs[4]; |
62 | 64 | int num_irqs; |
63 | 65 | }; |
66 | +#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev) | |
64 | 67 | |
65 | 68 | /* This struct describes the SBus(s) found on this machine. */ |
66 | 69 | struct sbus_bus { |
70 | + struct of_device ofdev; | |
67 | 71 | void *iommu; /* Opaque IOMMU cookie */ |
68 | 72 | struct sbus_dev *devices; /* Link to devices on this SBus */ |
69 | 73 | struct sbus_bus *next; /* next SBus, if more than one SBus */ |
... | ... | @@ -77,6 +81,7 @@ |
77 | 81 | int devid; |
78 | 82 | int board; |
79 | 83 | }; |
84 | +#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) | |
80 | 85 | |
81 | 86 | extern struct sbus_bus *sbus_root; |
82 | 87 | |
... | ... | @@ -139,6 +144,12 @@ |
139 | 144 | */ |
140 | 145 | BTFIXUPDEF_CALL(unsigned int, sbint_to_irq, struct sbus_dev *sdev, unsigned int) |
141 | 146 | #define sbint_to_irq(sdev, sbint) BTFIXUP_CALL(sbint_to_irq)(sdev, sbint) |
147 | + | |
148 | +extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); | |
149 | +extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); | |
150 | +extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *); | |
151 | +extern int sbus_arch_preinit(void); | |
152 | +extern void sbus_arch_postinit(void); | |
142 | 153 | |
143 | 154 | #endif /* !(_SPARC_SBUS_H) */ |
include/asm-sparc64/sbus.h
... | ... | @@ -11,6 +11,8 @@ |
11 | 11 | #include <linux/ioport.h> |
12 | 12 | |
13 | 13 | #include <asm/oplib.h> |
14 | +#include <asm/prom.h> | |
15 | +#include <asm/of_device.h> | |
14 | 16 | #include <asm/iommu.h> |
15 | 17 | #include <asm/scatterlist.h> |
16 | 18 | |
17 | 19 | |
... | ... | @@ -42,18 +44,19 @@ |
42 | 44 | |
43 | 45 | /* Linux SBUS device tables */ |
44 | 46 | struct sbus_dev { |
45 | - struct sbus_bus *bus; /* Our toplevel parent SBUS */ | |
46 | - struct sbus_dev *next; /* Chain of siblings */ | |
47 | - struct sbus_dev *child; /* Chain of children */ | |
48 | - struct sbus_dev *parent;/* Parent device if not toplevel*/ | |
49 | - int prom_node; /* OBP node of this device */ | |
50 | - char prom_name[64]; /* OBP device name property */ | |
51 | - int slot; /* SBUS slot number */ | |
47 | + struct of_device ofdev; | |
48 | + struct sbus_bus *bus; | |
49 | + struct sbus_dev *next; | |
50 | + struct sbus_dev *child; | |
51 | + struct sbus_dev *parent; | |
52 | + int prom_node; | |
53 | + char prom_name[64]; | |
54 | + int slot; | |
52 | 55 | |
53 | 56 | struct resource resource[PROMREG_MAX]; |
54 | 57 | |
55 | 58 | struct linux_prom_registers reg_addrs[PROMREG_MAX]; |
56 | - int num_registers, ranges_applied; | |
59 | + int num_registers; | |
57 | 60 | |
58 | 61 | struct linux_prom_ranges device_ranges[PROMREG_MAX]; |
59 | 62 | int num_device_ranges; |
60 | 63 | |
... | ... | @@ -61,9 +64,11 @@ |
61 | 64 | unsigned int irqs[4]; |
62 | 65 | int num_irqs; |
63 | 66 | }; |
67 | +#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev) | |
64 | 68 | |
65 | 69 | /* This struct describes the SBus(s) found on this machine. */ |
66 | 70 | struct sbus_bus { |
71 | + struct of_device ofdev; | |
67 | 72 | void *iommu; /* Opaque IOMMU cookie */ |
68 | 73 | struct sbus_dev *devices; /* Tree of SBUS devices */ |
69 | 74 | struct sbus_bus *next; /* Next SBUS in system */ |
... | ... | @@ -77,6 +82,7 @@ |
77 | 82 | int portid; |
78 | 83 | void *starfire_cookie; |
79 | 84 | }; |
85 | +#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) | |
80 | 86 | |
81 | 87 | extern struct sbus_bus *sbus_root; |
82 | 88 | |
... | ... | @@ -119,6 +125,12 @@ |
119 | 125 | extern void sbus_dma_sync_sg_for_cpu(struct sbus_dev *, struct scatterlist *, int, int); |
120 | 126 | #define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu |
121 | 127 | extern void sbus_dma_sync_sg_for_device(struct sbus_dev *, struct scatterlist *, int, int); |
128 | + | |
129 | +extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); | |
130 | +extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); | |
131 | +extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *); | |
132 | +extern int sbus_arch_preinit(void); | |
133 | +extern void sbus_arch_postinit(void); | |
122 | 134 | |
123 | 135 | #endif /* !(_SPARC64_SBUS_H) */ |