diff options
Diffstat (limited to 'drivers/sbus/sbus.c')
-rw-r--r-- | drivers/sbus/sbus.c | 316 |
1 files changed, 0 insertions, 316 deletions
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c deleted file mode 100644 index 9c129248466c..000000000000 --- a/drivers/sbus/sbus.c +++ /dev/null | |||
@@ -1,316 +0,0 @@ | |||
1 | /* sbus.c: SBus support routines. | ||
2 | * | ||
3 | * Copyright (C) 1995, 2006 David S. Miller (davem@davemloft.net) | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/slab.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/device.h> | ||
10 | #include <linux/of_device.h> | ||
11 | |||
12 | #include <asm/system.h> | ||
13 | #include <asm/sbus.h> | ||
14 | #include <asm/dma.h> | ||
15 | #include <asm/oplib.h> | ||
16 | #include <asm/prom.h> | ||
17 | #include <asm/bpp.h> | ||
18 | #include <asm/irq.h> | ||
19 | |||
20 | static ssize_t | ||
21 | show_sbusobppath_attr(struct device * dev, struct device_attribute * attr, char * buf) | ||
22 | { | ||
23 | struct sbus_dev *sbus; | ||
24 | |||
25 | sbus = to_sbus_device(dev); | ||
26 | |||
27 | return snprintf (buf, PAGE_SIZE, "%s\n", sbus->ofdev.node->full_name); | ||
28 | } | ||
29 | |||
30 | static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_sbusobppath_attr, NULL); | ||
31 | |||
32 | struct sbus_bus *sbus_root; | ||
33 | |||
34 | static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev) | ||
35 | { | ||
36 | struct dev_archdata *sd; | ||
37 | unsigned long base; | ||
38 | const void *pval; | ||
39 | int len, err; | ||
40 | |||
41 | sdev->prom_node = dp->node; | ||
42 | strcpy(sdev->prom_name, dp->name); | ||
43 | |||
44 | pval = of_get_property(dp, "reg", &len); | ||
45 | sdev->num_registers = 0; | ||
46 | if (pval) { | ||
47 | memcpy(sdev->reg_addrs, pval, len); | ||
48 | |||
49 | sdev->num_registers = | ||
50 | len / sizeof(struct linux_prom_registers); | ||
51 | |||
52 | base = (unsigned long) sdev->reg_addrs[0].phys_addr; | ||
53 | |||
54 | /* Compute the slot number. */ | ||
55 | if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) | ||
56 | sdev->slot = sbus_dev_slot(base); | ||
57 | else | ||
58 | sdev->slot = sdev->reg_addrs[0].which_io; | ||
59 | } | ||
60 | |||
61 | pval = of_get_property(dp, "ranges", &len); | ||
62 | sdev->num_device_ranges = 0; | ||
63 | if (pval) { | ||
64 | memcpy(sdev->device_ranges, pval, len); | ||
65 | sdev->num_device_ranges = | ||
66 | len / sizeof(struct linux_prom_ranges); | ||
67 | } | ||
68 | |||
69 | sbus_fill_device_irq(sdev); | ||
70 | |||
71 | sd = &sdev->ofdev.dev.archdata; | ||
72 | sd->prom_node = dp; | ||
73 | sd->op = &sdev->ofdev; | ||
74 | |||
75 | sdev->ofdev.node = dp; | ||
76 | if (sdev->parent) | ||
77 | sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev; | ||
78 | else | ||
79 | sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev; | ||
80 | sdev->ofdev.dev.bus = &sbus_bus_type; | ||
81 | dev_set_name(&sdev->ofdev.dev, "sbus[%08x]", dp->node); | ||
82 | |||
83 | if (of_device_register(&sdev->ofdev) != 0) | ||
84 | printk(KERN_DEBUG "sbus: device registration error for %s!\n", | ||
85 | dp->path_component_name); | ||
86 | |||
87 | /* WE HAVE BEEN INVADED BY ALIENS! */ | ||
88 | err = sysfs_create_file(&sdev->ofdev.dev.kobj, &dev_attr_obppath.attr); | ||
89 | } | ||
90 | |||
91 | static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus) | ||
92 | { | ||
93 | const void *pval; | ||
94 | int len; | ||
95 | |||
96 | pval = of_get_property(dp, "ranges", &len); | ||
97 | sbus->num_sbus_ranges = 0; | ||
98 | if (pval) { | ||
99 | memcpy(sbus->sbus_ranges, pval, len); | ||
100 | sbus->num_sbus_ranges = | ||
101 | len / sizeof(struct linux_prom_ranges); | ||
102 | |||
103 | sbus_arch_bus_ranges_init(dp->parent, sbus); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges, | ||
108 | int num_ranges, | ||
109 | struct linux_prom_registers *regs, | ||
110 | int num_regs) | ||
111 | { | ||
112 | if (num_ranges) { | ||
113 | int regnum; | ||
114 | |||
115 | for (regnum = 0; regnum < num_regs; regnum++) { | ||
116 | int rngnum; | ||
117 | |||
118 | for (rngnum = 0; rngnum < num_ranges; rngnum++) { | ||
119 | if (regs[regnum].which_io == ranges[rngnum].ot_child_space) | ||
120 | break; | ||
121 | } | ||
122 | if (rngnum == num_ranges) { | ||
123 | /* We used to flag this as an error. Actually | ||
124 | * some devices do not report the regs as we expect. | ||
125 | * For example, see SUNW,pln device. In that case | ||
126 | * the reg property is in a format internal to that | ||
127 | * node, ie. it is not in the SBUS register space | ||
128 | * per se. -DaveM | ||
129 | */ | ||
130 | return; | ||
131 | } | ||
132 | regs[regnum].which_io = ranges[rngnum].ot_parent_space; | ||
133 | regs[regnum].phys_addr -= ranges[rngnum].ot_child_base; | ||
134 | regs[regnum].phys_addr += ranges[rngnum].ot_parent_base; | ||
135 | } | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static void __init __fixup_regs_sdev(struct sbus_dev *sdev) | ||
140 | { | ||
141 | if (sdev->num_registers != 0) { | ||
142 | struct sbus_dev *parent = sdev->parent; | ||
143 | int i; | ||
144 | |||
145 | while (parent != NULL) { | ||
146 | __apply_ranges_to_regs(parent->device_ranges, | ||
147 | parent->num_device_ranges, | ||
148 | sdev->reg_addrs, | ||
149 | sdev->num_registers); | ||
150 | |||
151 | parent = parent->parent; | ||
152 | } | ||
153 | |||
154 | __apply_ranges_to_regs(sdev->bus->sbus_ranges, | ||
155 | sdev->bus->num_sbus_ranges, | ||
156 | sdev->reg_addrs, | ||
157 | sdev->num_registers); | ||
158 | |||
159 | for (i = 0; i < sdev->num_registers; i++) { | ||
160 | struct resource *res = &sdev->resource[i]; | ||
161 | |||
162 | res->start = sdev->reg_addrs[i].phys_addr; | ||
163 | res->end = (res->start + | ||
164 | (unsigned long)sdev->reg_addrs[i].reg_size - 1UL); | ||
165 | res->flags = IORESOURCE_IO | | ||
166 | (sdev->reg_addrs[i].which_io & 0xff); | ||
167 | } | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static void __init sbus_fixup_all_regs(struct sbus_dev *first_sdev) | ||
172 | { | ||
173 | struct sbus_dev *sdev; | ||
174 | |||
175 | for (sdev = first_sdev; sdev; sdev = sdev->next) { | ||
176 | if (sdev->child) | ||
177 | sbus_fixup_all_regs(sdev->child); | ||
178 | __fixup_regs_sdev(sdev); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | /* We preserve the "probe order" of these bus and device lists to give | ||
183 | * the same ordering as the old code. | ||
184 | */ | ||
185 | static void __init sbus_insert(struct sbus_bus *sbus, struct sbus_bus **root) | ||
186 | { | ||
187 | while (*root) | ||
188 | root = &(*root)->next; | ||
189 | *root = sbus; | ||
190 | sbus->next = NULL; | ||
191 | } | ||
192 | |||
193 | static void __init sdev_insert(struct sbus_dev *sdev, struct sbus_dev **root) | ||
194 | { | ||
195 | while (*root) | ||
196 | root = &(*root)->next; | ||
197 | *root = sdev; | ||
198 | sdev->next = NULL; | ||
199 | } | ||
200 | |||
201 | static void __init walk_children(struct device_node *dp, struct sbus_dev *parent, struct sbus_bus *sbus) | ||
202 | { | ||
203 | dp = dp->child; | ||
204 | while (dp) { | ||
205 | struct sbus_dev *sdev; | ||
206 | |||
207 | sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); | ||
208 | if (sdev) { | ||
209 | sdev_insert(sdev, &parent->child); | ||
210 | |||
211 | sdev->bus = sbus; | ||
212 | sdev->parent = parent; | ||
213 | sdev->ofdev.dev.archdata.iommu = | ||
214 | sbus->ofdev.dev.archdata.iommu; | ||
215 | sdev->ofdev.dev.archdata.stc = | ||
216 | sbus->ofdev.dev.archdata.stc; | ||
217 | |||
218 | fill_sbus_device(dp, sdev); | ||
219 | |||
220 | walk_children(dp, sdev, sbus); | ||
221 | } | ||
222 | dp = dp->sibling; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | static void __init build_one_sbus(struct device_node *dp, int num_sbus) | ||
227 | { | ||
228 | struct sbus_bus *sbus; | ||
229 | unsigned int sbus_clock; | ||
230 | struct device_node *dev_dp; | ||
231 | |||
232 | sbus = kzalloc(sizeof(struct sbus_bus), GFP_ATOMIC); | ||
233 | if (!sbus) | ||
234 | return; | ||
235 | |||
236 | sbus_insert(sbus, &sbus_root); | ||
237 | sbus->prom_node = dp->node; | ||
238 | |||
239 | sbus_setup_iommu(sbus, dp); | ||
240 | |||
241 | printk("sbus%d: ", num_sbus); | ||
242 | |||
243 | sbus_clock = of_getintprop_default(dp, "clock-frequency", | ||
244 | (25*1000*1000)); | ||
245 | sbus->clock_freq = sbus_clock; | ||
246 | |||
247 | printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000), | ||
248 | (int) (((sbus_clock/1000)%1000 != 0) ? | ||
249 | (((sbus_clock/1000)%1000) + 1000) : 0)); | ||
250 | |||
251 | strcpy(sbus->prom_name, dp->name); | ||
252 | |||
253 | sbus_setup_arch_props(sbus, dp); | ||
254 | |||
255 | sbus_bus_ranges_init(dp, sbus); | ||
256 | |||
257 | sbus->ofdev.node = dp; | ||
258 | sbus->ofdev.dev.parent = NULL; | ||
259 | sbus->ofdev.dev.bus = &sbus_bus_type; | ||
260 | dev_set_name(&sbus->ofdev.dev, "sbus%d", num_sbus); | ||
261 | |||
262 | if (of_device_register(&sbus->ofdev) != 0) | ||
263 | printk(KERN_DEBUG "sbus: device registration error for %s!\n", | ||
264 | dev_name(&sbus->ofdev.dev)); | ||
265 | |||
266 | dev_dp = dp->child; | ||
267 | while (dev_dp) { | ||
268 | struct sbus_dev *sdev; | ||
269 | |||
270 | sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); | ||
271 | if (sdev) { | ||
272 | sdev_insert(sdev, &sbus->devices); | ||
273 | |||
274 | sdev->bus = sbus; | ||
275 | sdev->parent = NULL; | ||
276 | sdev->ofdev.dev.archdata.iommu = | ||
277 | sbus->ofdev.dev.archdata.iommu; | ||
278 | sdev->ofdev.dev.archdata.stc = | ||
279 | sbus->ofdev.dev.archdata.stc; | ||
280 | |||
281 | fill_sbus_device(dev_dp, sdev); | ||
282 | |||
283 | walk_children(dev_dp, sdev, sbus); | ||
284 | } | ||
285 | dev_dp = dev_dp->sibling; | ||
286 | } | ||
287 | |||
288 | sbus_fixup_all_regs(sbus->devices); | ||
289 | |||
290 | dvma_init(sbus); | ||
291 | } | ||
292 | |||
293 | static int __init sbus_init(void) | ||
294 | { | ||
295 | struct device_node *dp; | ||
296 | const char *sbus_name = "sbus"; | ||
297 | int num_sbus = 0; | ||
298 | |||
299 | if (sbus_arch_preinit()) | ||
300 | return 0; | ||
301 | |||
302 | if (sparc_cpu_model == sun4d) | ||
303 | sbus_name = "sbi"; | ||
304 | |||
305 | for_each_node_by_name(dp, sbus_name) { | ||
306 | build_one_sbus(dp, num_sbus); | ||
307 | num_sbus++; | ||
308 | |||
309 | } | ||
310 | |||
311 | sbus_arch_postinit(); | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | subsys_initcall(sbus_init); | ||