diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/xsysace.c | 98 | ||||
-rw-r--r-- | drivers/of/address.c | 18 | ||||
-rw-r--r-- | drivers/of/base.c | 65 | ||||
-rw-r--r-- | drivers/of/platform.c | 196 | ||||
-rw-r--r-- | drivers/tty/serial/of_serial.c | 43 |
5 files changed, 313 insertions, 107 deletions
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 6c7fd7db6dff..fb1975d82a73 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c | |||
@@ -1155,12 +1155,19 @@ static int __devinit ace_probe(struct platform_device *dev) | |||
1155 | { | 1155 | { |
1156 | resource_size_t physaddr = 0; | 1156 | resource_size_t physaddr = 0; |
1157 | int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */ | 1157 | int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */ |
1158 | int id = dev->id; | 1158 | u32 id = dev->id; |
1159 | int irq = NO_IRQ; | 1159 | int irq = NO_IRQ; |
1160 | int i; | 1160 | int i; |
1161 | 1161 | ||
1162 | dev_dbg(&dev->dev, "ace_probe(%p)\n", dev); | 1162 | dev_dbg(&dev->dev, "ace_probe(%p)\n", dev); |
1163 | 1163 | ||
1164 | /* device id and bus width */ | ||
1165 | of_property_read_u32(dev->dev.of_node, "port-number", &id); | ||
1166 | if (id < 0) | ||
1167 | id = 0; | ||
1168 | if (of_find_property(dev->dev.of_node, "8-bit", NULL)) | ||
1169 | bus_width = ACE_BUS_WIDTH_8; | ||
1170 | |||
1164 | for (i = 0; i < dev->num_resources; i++) { | 1171 | for (i = 0; i < dev->num_resources; i++) { |
1165 | if (dev->resource[i].flags & IORESOURCE_MEM) | 1172 | if (dev->resource[i].flags & IORESOURCE_MEM) |
1166 | physaddr = dev->resource[i].start; | 1173 | physaddr = dev->resource[i].start; |
@@ -1181,57 +1188,7 @@ static int __devexit ace_remove(struct platform_device *dev) | |||
1181 | return 0; | 1188 | return 0; |
1182 | } | 1189 | } |
1183 | 1190 | ||
1184 | static struct platform_driver ace_platform_driver = { | ||
1185 | .probe = ace_probe, | ||
1186 | .remove = __devexit_p(ace_remove), | ||
1187 | .driver = { | ||
1188 | .owner = THIS_MODULE, | ||
1189 | .name = "xsysace", | ||
1190 | }, | ||
1191 | }; | ||
1192 | |||
1193 | /* --------------------------------------------------------------------- | ||
1194 | * OF_Platform Bus Support | ||
1195 | */ | ||
1196 | |||
1197 | #if defined(CONFIG_OF) | 1191 | #if defined(CONFIG_OF) |
1198 | static int __devinit ace_of_probe(struct platform_device *op) | ||
1199 | { | ||
1200 | struct resource res; | ||
1201 | resource_size_t physaddr; | ||
1202 | const u32 *id; | ||
1203 | int irq, bus_width, rc; | ||
1204 | |||
1205 | /* device id */ | ||
1206 | id = of_get_property(op->dev.of_node, "port-number", NULL); | ||
1207 | |||
1208 | /* physaddr */ | ||
1209 | rc = of_address_to_resource(op->dev.of_node, 0, &res); | ||
1210 | if (rc) { | ||
1211 | dev_err(&op->dev, "invalid address\n"); | ||
1212 | return rc; | ||
1213 | } | ||
1214 | physaddr = res.start; | ||
1215 | |||
1216 | /* irq */ | ||
1217 | irq = irq_of_parse_and_map(op->dev.of_node, 0); | ||
1218 | |||
1219 | /* bus width */ | ||
1220 | bus_width = ACE_BUS_WIDTH_16; | ||
1221 | if (of_find_property(op->dev.of_node, "8-bit", NULL)) | ||
1222 | bus_width = ACE_BUS_WIDTH_8; | ||
1223 | |||
1224 | /* Call the bus-independent setup code */ | ||
1225 | return ace_alloc(&op->dev, id ? be32_to_cpup(id) : 0, | ||
1226 | physaddr, irq, bus_width); | ||
1227 | } | ||
1228 | |||
1229 | static int __devexit ace_of_remove(struct platform_device *op) | ||
1230 | { | ||
1231 | ace_free(&op->dev); | ||
1232 | return 0; | ||
1233 | } | ||
1234 | |||
1235 | /* Match table for of_platform binding */ | 1192 | /* Match table for of_platform binding */ |
1236 | static const struct of_device_id ace_of_match[] __devinitconst = { | 1193 | static const struct of_device_id ace_of_match[] __devinitconst = { |
1237 | { .compatible = "xlnx,opb-sysace-1.00.b", }, | 1194 | { .compatible = "xlnx,opb-sysace-1.00.b", }, |
@@ -1241,34 +1198,20 @@ static const struct of_device_id ace_of_match[] __devinitconst = { | |||
1241 | {}, | 1198 | {}, |
1242 | }; | 1199 | }; |
1243 | MODULE_DEVICE_TABLE(of, ace_of_match); | 1200 | MODULE_DEVICE_TABLE(of, ace_of_match); |
1201 | #else /* CONFIG_OF */ | ||
1202 | #define ace_of_match NULL | ||
1203 | #endif /* CONFIG_OF */ | ||
1244 | 1204 | ||
1245 | static struct platform_driver ace_of_driver = { | 1205 | static struct platform_driver ace_platform_driver = { |
1246 | .probe = ace_of_probe, | 1206 | .probe = ace_probe, |
1247 | .remove = __devexit_p(ace_of_remove), | 1207 | .remove = __devexit_p(ace_remove), |
1248 | .driver = { | 1208 | .driver = { |
1249 | .name = "xsysace", | ||
1250 | .owner = THIS_MODULE, | 1209 | .owner = THIS_MODULE, |
1210 | .name = "xsysace", | ||
1251 | .of_match_table = ace_of_match, | 1211 | .of_match_table = ace_of_match, |
1252 | }, | 1212 | }, |
1253 | }; | 1213 | }; |
1254 | 1214 | ||
1255 | /* Registration helpers to keep the number of #ifdefs to a minimum */ | ||
1256 | static inline int __init ace_of_register(void) | ||
1257 | { | ||
1258 | pr_debug("xsysace: registering OF binding\n"); | ||
1259 | return platform_driver_register(&ace_of_driver); | ||
1260 | } | ||
1261 | |||
1262 | static inline void __exit ace_of_unregister(void) | ||
1263 | { | ||
1264 | platform_driver_unregister(&ace_of_driver); | ||
1265 | } | ||
1266 | #else /* CONFIG_OF */ | ||
1267 | /* CONFIG_OF not enabled; do nothing helpers */ | ||
1268 | static inline int __init ace_of_register(void) { return 0; } | ||
1269 | static inline void __exit ace_of_unregister(void) { } | ||
1270 | #endif /* CONFIG_OF */ | ||
1271 | |||
1272 | /* --------------------------------------------------------------------- | 1215 | /* --------------------------------------------------------------------- |
1273 | * Module init/exit routines | 1216 | * Module init/exit routines |
1274 | */ | 1217 | */ |
@@ -1282,11 +1225,6 @@ static int __init ace_init(void) | |||
1282 | goto err_blk; | 1225 | goto err_blk; |
1283 | } | 1226 | } |
1284 | 1227 | ||
1285 | rc = ace_of_register(); | ||
1286 | if (rc) | ||
1287 | goto err_of; | ||
1288 | |||
1289 | pr_debug("xsysace: registering platform binding\n"); | ||
1290 | rc = platform_driver_register(&ace_platform_driver); | 1228 | rc = platform_driver_register(&ace_platform_driver); |
1291 | if (rc) | 1229 | if (rc) |
1292 | goto err_plat; | 1230 | goto err_plat; |
@@ -1295,21 +1233,17 @@ static int __init ace_init(void) | |||
1295 | return 0; | 1233 | return 0; |
1296 | 1234 | ||
1297 | err_plat: | 1235 | err_plat: |
1298 | ace_of_unregister(); | ||
1299 | err_of: | ||
1300 | unregister_blkdev(ace_major, "xsysace"); | 1236 | unregister_blkdev(ace_major, "xsysace"); |
1301 | err_blk: | 1237 | err_blk: |
1302 | printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc); | 1238 | printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc); |
1303 | return rc; | 1239 | return rc; |
1304 | } | 1240 | } |
1241 | module_init(ace_init); | ||
1305 | 1242 | ||
1306 | static void __exit ace_exit(void) | 1243 | static void __exit ace_exit(void) |
1307 | { | 1244 | { |
1308 | pr_debug("Unregistering Xilinx SystemACE driver\n"); | 1245 | pr_debug("Unregistering Xilinx SystemACE driver\n"); |
1309 | platform_driver_unregister(&ace_platform_driver); | 1246 | platform_driver_unregister(&ace_platform_driver); |
1310 | ace_of_unregister(); | ||
1311 | unregister_blkdev(ace_major, "xsysace"); | 1247 | unregister_blkdev(ace_major, "xsysace"); |
1312 | } | 1248 | } |
1313 | |||
1314 | module_init(ace_init); | ||
1315 | module_exit(ace_exit); | 1249 | module_exit(ace_exit); |
diff --git a/drivers/of/address.c b/drivers/of/address.c index b4559c58c095..da1f4b9605df 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c | |||
@@ -577,6 +577,24 @@ int of_address_to_resource(struct device_node *dev, int index, | |||
577 | } | 577 | } |
578 | EXPORT_SYMBOL_GPL(of_address_to_resource); | 578 | EXPORT_SYMBOL_GPL(of_address_to_resource); |
579 | 579 | ||
580 | struct device_node *of_find_matching_node_by_address(struct device_node *from, | ||
581 | const struct of_device_id *matches, | ||
582 | u64 base_address) | ||
583 | { | ||
584 | struct device_node *dn = of_find_matching_node(from, matches); | ||
585 | struct resource res; | ||
586 | |||
587 | while (dn) { | ||
588 | if (of_address_to_resource(dn, 0, &res)) | ||
589 | continue; | ||
590 | if (res.start == base_address) | ||
591 | return dn; | ||
592 | dn = of_find_matching_node(dn, matches); | ||
593 | } | ||
594 | |||
595 | return NULL; | ||
596 | } | ||
597 | |||
580 | 598 | ||
581 | /** | 599 | /** |
582 | * of_iomap - Maps the memory mapped IO for a given device_node | 600 | * of_iomap - Maps the memory mapped IO for a given device_node |
diff --git a/drivers/of/base.c b/drivers/of/base.c index 632ebae7f17a..02ed36719def 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -596,6 +596,71 @@ struct device_node *of_find_node_by_phandle(phandle handle) | |||
596 | EXPORT_SYMBOL(of_find_node_by_phandle); | 596 | EXPORT_SYMBOL(of_find_node_by_phandle); |
597 | 597 | ||
598 | /** | 598 | /** |
599 | * of_property_read_u32_array - Find and read an array of 32 bit integers | ||
600 | * from a property. | ||
601 | * | ||
602 | * @np: device node from which the property value is to be read. | ||
603 | * @propname: name of the property to be searched. | ||
604 | * @out_value: pointer to return value, modified only if return value is 0. | ||
605 | * | ||
606 | * Search for a property in a device node and read 32-bit value(s) from | ||
607 | * it. Returns 0 on success, -EINVAL if the property does not exist, | ||
608 | * -ENODATA if property does not have a value, and -EOVERFLOW if the | ||
609 | * property data isn't large enough. | ||
610 | * | ||
611 | * The out_value is modified only if a valid u32 value can be decoded. | ||
612 | */ | ||
613 | int of_property_read_u32_array(const struct device_node *np, char *propname, | ||
614 | u32 *out_values, size_t sz) | ||
615 | { | ||
616 | struct property *prop = of_find_property(np, propname, NULL); | ||
617 | const __be32 *val; | ||
618 | |||
619 | if (!prop) | ||
620 | return -EINVAL; | ||
621 | if (!prop->value) | ||
622 | return -ENODATA; | ||
623 | if ((sz * sizeof(*out_values)) > prop->length) | ||
624 | return -EOVERFLOW; | ||
625 | |||
626 | val = prop->value; | ||
627 | while (sz--) | ||
628 | *out_values++ = be32_to_cpup(val++); | ||
629 | return 0; | ||
630 | } | ||
631 | EXPORT_SYMBOL_GPL(of_property_read_u32_array); | ||
632 | |||
633 | /** | ||
634 | * of_property_read_string - Find and read a string from a property | ||
635 | * @np: device node from which the property value is to be read. | ||
636 | * @propname: name of the property to be searched. | ||
637 | * @out_string: pointer to null terminated return string, modified only if | ||
638 | * return value is 0. | ||
639 | * | ||
640 | * Search for a property in a device tree node and retrieve a null | ||
641 | * terminated string value (pointer to data, not a copy). Returns 0 on | ||
642 | * success, -EINVAL if the property does not exist, -ENODATA if property | ||
643 | * does not have a value, and -EILSEQ if the string is not null-terminated | ||
644 | * within the length of the property data. | ||
645 | * | ||
646 | * The out_string pointer is modified only if a valid string can be decoded. | ||
647 | */ | ||
648 | int of_property_read_string(struct device_node *np, char *propname, | ||
649 | const char **out_string) | ||
650 | { | ||
651 | struct property *prop = of_find_property(np, propname, NULL); | ||
652 | if (!prop) | ||
653 | return -EINVAL; | ||
654 | if (!prop->value) | ||
655 | return -ENODATA; | ||
656 | if (strnlen(prop->value, prop->length) >= prop->length) | ||
657 | return -EILSEQ; | ||
658 | *out_string = prop->value; | ||
659 | return 0; | ||
660 | } | ||
661 | EXPORT_SYMBOL_GPL(of_property_read_string); | ||
662 | |||
663 | /** | ||
599 | * of_parse_phandle - Resolve a phandle property to a device_node pointer | 664 | * of_parse_phandle - Resolve a phandle property to a device_node pointer |
600 | * @np: Pointer to device node holding phandle property | 665 | * @np: Pointer to device node holding phandle property |
601 | * @phandle_name: Name of property holding a phandle value | 666 | * @phandle_name: Name of property holding a phandle value |
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 63d3cb73bdb9..e75af391e286 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -13,6 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/amba/bus.h> | ||
16 | #include <linux/device.h> | 17 | #include <linux/device.h> |
17 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
@@ -22,6 +23,14 @@ | |||
22 | #include <linux/of_platform.h> | 23 | #include <linux/of_platform.h> |
23 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
24 | 25 | ||
26 | const struct of_device_id of_default_bus_match_table[] = { | ||
27 | { .compatible = "simple-bus", }, | ||
28 | #ifdef CONFIG_ARM_AMBA | ||
29 | { .compatible = "arm,amba-bus", }, | ||
30 | #endif /* CONFIG_ARM_AMBA */ | ||
31 | {} /* Empty terminated list */ | ||
32 | }; | ||
33 | |||
25 | static int of_dev_node_match(struct device *dev, void *data) | 34 | static int of_dev_node_match(struct device *dev, void *data) |
26 | { | 35 | { |
27 | return dev->of_node == data; | 36 | return dev->of_node == data; |
@@ -168,17 +177,20 @@ struct platform_device *of_device_alloc(struct device_node *np, | |||
168 | EXPORT_SYMBOL(of_device_alloc); | 177 | EXPORT_SYMBOL(of_device_alloc); |
169 | 178 | ||
170 | /** | 179 | /** |
171 | * of_platform_device_create - Alloc, initialize and register an of_device | 180 | * of_platform_device_create_pdata - Alloc, initialize and register an of_device |
172 | * @np: pointer to node to create device for | 181 | * @np: pointer to node to create device for |
173 | * @bus_id: name to assign device | 182 | * @bus_id: name to assign device |
183 | * @platform_data: pointer to populate platform_data pointer with | ||
174 | * @parent: Linux device model parent device. | 184 | * @parent: Linux device model parent device. |
175 | * | 185 | * |
176 | * Returns pointer to created platform device, or NULL if a device was not | 186 | * Returns pointer to created platform device, or NULL if a device was not |
177 | * registered. Unavailable devices will not get registered. | 187 | * registered. Unavailable devices will not get registered. |
178 | */ | 188 | */ |
179 | struct platform_device *of_platform_device_create(struct device_node *np, | 189 | struct platform_device *of_platform_device_create_pdata( |
180 | const char *bus_id, | 190 | struct device_node *np, |
181 | struct device *parent) | 191 | const char *bus_id, |
192 | void *platform_data, | ||
193 | struct device *parent) | ||
182 | { | 194 | { |
183 | struct platform_device *dev; | 195 | struct platform_device *dev; |
184 | 196 | ||
@@ -194,6 +206,7 @@ struct platform_device *of_platform_device_create(struct device_node *np, | |||
194 | #endif | 206 | #endif |
195 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | 207 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); |
196 | dev->dev.bus = &platform_bus_type; | 208 | dev->dev.bus = &platform_bus_type; |
209 | dev->dev.platform_data = platform_data; | ||
197 | 210 | ||
198 | /* We do not fill the DMA ops for platform devices by default. | 211 | /* We do not fill the DMA ops for platform devices by default. |
199 | * This is currently the responsibility of the platform code | 212 | * This is currently the responsibility of the platform code |
@@ -207,8 +220,111 @@ struct platform_device *of_platform_device_create(struct device_node *np, | |||
207 | 220 | ||
208 | return dev; | 221 | return dev; |
209 | } | 222 | } |
223 | |||
224 | /** | ||
225 | * of_platform_device_create - Alloc, initialize and register an of_device | ||
226 | * @np: pointer to node to create device for | ||
227 | * @bus_id: name to assign device | ||
228 | * @parent: Linux device model parent device. | ||
229 | * | ||
230 | * Returns pointer to created platform device, or NULL if a device was not | ||
231 | * registered. Unavailable devices will not get registered. | ||
232 | */ | ||
233 | struct platform_device *of_platform_device_create(struct device_node *np, | ||
234 | const char *bus_id, | ||
235 | struct device *parent) | ||
236 | { | ||
237 | return of_platform_device_create_pdata(np, bus_id, NULL, parent); | ||
238 | } | ||
210 | EXPORT_SYMBOL(of_platform_device_create); | 239 | EXPORT_SYMBOL(of_platform_device_create); |
211 | 240 | ||
241 | #ifdef CONFIG_ARM_AMBA | ||
242 | static struct amba_device *of_amba_device_create(struct device_node *node, | ||
243 | const char *bus_id, | ||
244 | void *platform_data, | ||
245 | struct device *parent) | ||
246 | { | ||
247 | struct amba_device *dev; | ||
248 | const void *prop; | ||
249 | int i, ret; | ||
250 | |||
251 | pr_debug("Creating amba device %s\n", node->full_name); | ||
252 | |||
253 | if (!of_device_is_available(node)) | ||
254 | return NULL; | ||
255 | |||
256 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
257 | if (!dev) | ||
258 | return NULL; | ||
259 | |||
260 | /* setup generic device info */ | ||
261 | dev->dev.coherent_dma_mask = ~0; | ||
262 | dev->dev.of_node = of_node_get(node); | ||
263 | dev->dev.parent = parent; | ||
264 | dev->dev.platform_data = platform_data; | ||
265 | if (bus_id) | ||
266 | dev_set_name(&dev->dev, "%s", bus_id); | ||
267 | else | ||
268 | of_device_make_bus_id(&dev->dev); | ||
269 | |||
270 | /* setup amba-specific device info */ | ||
271 | dev->dma_mask = ~0; | ||
272 | |||
273 | /* Allow the HW Peripheral ID to be overridden */ | ||
274 | prop = of_get_property(node, "arm,primecell-periphid", NULL); | ||
275 | if (prop) | ||
276 | dev->periphid = of_read_ulong(prop, 1); | ||
277 | |||
278 | /* Decode the IRQs and address ranges */ | ||
279 | for (i = 0; i < AMBA_NR_IRQS; i++) | ||
280 | dev->irq[i] = irq_of_parse_and_map(node, i); | ||
281 | |||
282 | ret = of_address_to_resource(node, 0, &dev->res); | ||
283 | if (ret) | ||
284 | goto err_free; | ||
285 | |||
286 | ret = amba_device_register(dev, &iomem_resource); | ||
287 | if (ret) | ||
288 | goto err_free; | ||
289 | |||
290 | return dev; | ||
291 | |||
292 | err_free: | ||
293 | kfree(dev); | ||
294 | return NULL; | ||
295 | } | ||
296 | #else /* CONFIG_ARM_AMBA */ | ||
297 | static struct amba_device *of_amba_device_create(struct device_node *node, | ||
298 | const char *bus_id, | ||
299 | void *platform_data, | ||
300 | struct device *parent) | ||
301 | { | ||
302 | return NULL; | ||
303 | } | ||
304 | #endif /* CONFIG_ARM_AMBA */ | ||
305 | |||
306 | /** | ||
307 | * of_devname_lookup() - Given a device node, lookup the preferred Linux name | ||
308 | */ | ||
309 | static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *lookup, | ||
310 | struct device_node *np) | ||
311 | { | ||
312 | struct resource res; | ||
313 | if (lookup) { | ||
314 | for(; lookup->name != NULL; lookup++) { | ||
315 | if (!of_device_is_compatible(np, lookup->compatible)) | ||
316 | continue; | ||
317 | if (of_address_to_resource(np, 0, &res)) | ||
318 | continue; | ||
319 | if (res.start != lookup->phys_addr) | ||
320 | continue; | ||
321 | pr_debug("%s: devname=%s\n", np->full_name, lookup->name); | ||
322 | return lookup; | ||
323 | } | ||
324 | } | ||
325 | return NULL; | ||
326 | } | ||
327 | |||
212 | /** | 328 | /** |
213 | * of_platform_bus_create() - Create a device for a node and its children. | 329 | * of_platform_bus_create() - Create a device for a node and its children. |
214 | * @bus: device node of the bus to instantiate | 330 | * @bus: device node of the bus to instantiate |
@@ -221,19 +337,41 @@ EXPORT_SYMBOL(of_platform_device_create); | |||
221 | */ | 337 | */ |
222 | static int of_platform_bus_create(struct device_node *bus, | 338 | static int of_platform_bus_create(struct device_node *bus, |
223 | const struct of_device_id *matches, | 339 | const struct of_device_id *matches, |
224 | struct device *parent) | 340 | const struct of_dev_auxdata *lookup, |
341 | struct device *parent, bool strict) | ||
225 | { | 342 | { |
343 | const struct of_dev_auxdata *auxdata; | ||
226 | struct device_node *child; | 344 | struct device_node *child; |
227 | struct platform_device *dev; | 345 | struct platform_device *dev; |
346 | const char *bus_id = NULL; | ||
347 | void *platform_data = NULL; | ||
228 | int rc = 0; | 348 | int rc = 0; |
229 | 349 | ||
230 | dev = of_platform_device_create(bus, NULL, parent); | 350 | /* Make sure it has a compatible property */ |
351 | if (strict && (!of_get_property(bus, "compatible", NULL))) { | ||
352 | pr_debug("%s() - skipping %s, no compatible prop\n", | ||
353 | __func__, bus->full_name); | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | auxdata = of_dev_lookup(lookup, bus); | ||
358 | if (auxdata) { | ||
359 | bus_id = auxdata->name; | ||
360 | platform_data = auxdata->platform_data; | ||
361 | } | ||
362 | |||
363 | if (of_device_is_compatible(bus, "arm,primecell")) { | ||
364 | of_amba_device_create(bus, bus_id, platform_data, parent); | ||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent); | ||
231 | if (!dev || !of_match_node(matches, bus)) | 369 | if (!dev || !of_match_node(matches, bus)) |
232 | return 0; | 370 | return 0; |
233 | 371 | ||
234 | for_each_child_of_node(bus, child) { | 372 | for_each_child_of_node(bus, child) { |
235 | pr_debug(" create child: %s\n", child->full_name); | 373 | pr_debug(" create child: %s\n", child->full_name); |
236 | rc = of_platform_bus_create(child, matches, &dev->dev); | 374 | rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict); |
237 | if (rc) { | 375 | if (rc) { |
238 | of_node_put(child); | 376 | of_node_put(child); |
239 | break; | 377 | break; |
@@ -267,11 +405,11 @@ int of_platform_bus_probe(struct device_node *root, | |||
267 | 405 | ||
268 | /* Do a self check of bus type, if there's a match, create children */ | 406 | /* Do a self check of bus type, if there's a match, create children */ |
269 | if (of_match_node(matches, root)) { | 407 | if (of_match_node(matches, root)) { |
270 | rc = of_platform_bus_create(root, matches, parent); | 408 | rc = of_platform_bus_create(root, matches, NULL, parent, false); |
271 | } else for_each_child_of_node(root, child) { | 409 | } else for_each_child_of_node(root, child) { |
272 | if (!of_match_node(matches, child)) | 410 | if (!of_match_node(matches, child)) |
273 | continue; | 411 | continue; |
274 | rc = of_platform_bus_create(child, matches, parent); | 412 | rc = of_platform_bus_create(child, matches, NULL, parent, false); |
275 | if (rc) | 413 | if (rc) |
276 | break; | 414 | break; |
277 | } | 415 | } |
@@ -280,4 +418,44 @@ int of_platform_bus_probe(struct device_node *root, | |||
280 | return rc; | 418 | return rc; |
281 | } | 419 | } |
282 | EXPORT_SYMBOL(of_platform_bus_probe); | 420 | EXPORT_SYMBOL(of_platform_bus_probe); |
421 | |||
422 | /** | ||
423 | * of_platform_populate() - Populate platform_devices from device tree data | ||
424 | * @root: parent of the first level to probe or NULL for the root of the tree | ||
425 | * @matches: match table, NULL to use the default | ||
426 | * @parent: parent to hook devices from, NULL for toplevel | ||
427 | * | ||
428 | * Similar to of_platform_bus_probe(), this function walks the device tree | ||
429 | * and creates devices from nodes. It differs in that it follows the modern | ||
430 | * convention of requiring all device nodes to have a 'compatible' property, | ||
431 | * and it is suitable for creating devices which are children of the root | ||
432 | * node (of_platform_bus_probe will only create children of the root which | ||
433 | * are selected by the @matches argument). | ||
434 | * | ||
435 | * New board support should be using this function instead of | ||
436 | * of_platform_bus_probe(). | ||
437 | * | ||
438 | * Returns 0 on success, < 0 on failure. | ||
439 | */ | ||
440 | int of_platform_populate(struct device_node *root, | ||
441 | const struct of_device_id *matches, | ||
442 | const struct of_dev_auxdata *lookup, | ||
443 | struct device *parent) | ||
444 | { | ||
445 | struct device_node *child; | ||
446 | int rc = 0; | ||
447 | |||
448 | root = root ? of_node_get(root) : of_find_node_by_path("/"); | ||
449 | if (!root) | ||
450 | return -EINVAL; | ||
451 | |||
452 | for_each_child_of_node(root, child) { | ||
453 | rc = of_platform_bus_create(child, matches, lookup, parent, true); | ||
454 | if (rc) | ||
455 | break; | ||
456 | } | ||
457 | |||
458 | of_node_put(root); | ||
459 | return rc; | ||
460 | } | ||
283 | #endif /* !CONFIG_SPARC */ | 461 | #endif /* !CONFIG_SPARC */ |
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index c911b2419abb..e58cece6f443 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c | |||
@@ -32,17 +32,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev, | |||
32 | { | 32 | { |
33 | struct resource resource; | 33 | struct resource resource; |
34 | struct device_node *np = ofdev->dev.of_node; | 34 | struct device_node *np = ofdev->dev.of_node; |
35 | const __be32 *clk, *spd; | 35 | u32 clk, spd, prop; |
36 | const __be32 *prop; | 36 | int ret; |
37 | int ret, prop_size; | ||
38 | 37 | ||
39 | memset(port, 0, sizeof *port); | 38 | memset(port, 0, sizeof *port); |
40 | spd = of_get_property(np, "current-speed", NULL); | 39 | if (of_property_read_u32(np, "clock-frequency", &clk)) { |
41 | clk = of_get_property(np, "clock-frequency", NULL); | ||
42 | if (!clk) { | ||
43 | dev_warn(&ofdev->dev, "no clock-frequency property set\n"); | 40 | dev_warn(&ofdev->dev, "no clock-frequency property set\n"); |
44 | return -ENODEV; | 41 | return -ENODEV; |
45 | } | 42 | } |
43 | /* If current-speed was set, then try not to change it. */ | ||
44 | if (of_property_read_u32(np, "current-speed", &spd) == 0) | ||
45 | port->custom_divisor = clk / (16 * spd); | ||
46 | 46 | ||
47 | ret = of_address_to_resource(np, 0, &resource); | 47 | ret = of_address_to_resource(np, 0, &resource); |
48 | if (ret) { | 48 | if (ret) { |
@@ -54,25 +54,35 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev, | |||
54 | port->mapbase = resource.start; | 54 | port->mapbase = resource.start; |
55 | 55 | ||
56 | /* Check for shifted address mapping */ | 56 | /* Check for shifted address mapping */ |
57 | prop = of_get_property(np, "reg-offset", &prop_size); | 57 | if (of_property_read_u32(np, "reg-offset", &prop) == 0) |
58 | if (prop && (prop_size == sizeof(u32))) | 58 | port->mapbase += prop; |
59 | port->mapbase += be32_to_cpup(prop); | ||
60 | 59 | ||
61 | /* Check for registers offset within the devices address range */ | 60 | /* Check for registers offset within the devices address range */ |
62 | prop = of_get_property(np, "reg-shift", &prop_size); | 61 | if (of_property_read_u32(np, "reg-shift", &prop) == 0) |
63 | if (prop && (prop_size == sizeof(u32))) | 62 | port->regshift = prop; |
64 | port->regshift = be32_to_cpup(prop); | ||
65 | 63 | ||
66 | port->irq = irq_of_parse_and_map(np, 0); | 64 | port->irq = irq_of_parse_and_map(np, 0); |
67 | port->iotype = UPIO_MEM; | 65 | port->iotype = UPIO_MEM; |
66 | if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { | ||
67 | switch (prop) { | ||
68 | case 1: | ||
69 | port->iotype = UPIO_MEM; | ||
70 | break; | ||
71 | case 4: | ||
72 | port->iotype = UPIO_MEM32; | ||
73 | break; | ||
74 | default: | ||
75 | dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n", | ||
76 | prop); | ||
77 | return -EINVAL; | ||
78 | } | ||
79 | } | ||
80 | |||
68 | port->type = type; | 81 | port->type = type; |
69 | port->uartclk = be32_to_cpup(clk); | 82 | port->uartclk = clk; |
70 | port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | 83 | port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
71 | | UPF_FIXED_PORT | UPF_FIXED_TYPE; | 84 | | UPF_FIXED_PORT | UPF_FIXED_TYPE; |
72 | port->dev = &ofdev->dev; | 85 | port->dev = &ofdev->dev; |
73 | /* If current-speed was set, then try not to change it. */ | ||
74 | if (spd) | ||
75 | port->custom_divisor = be32_to_cpup(clk) / (16 * (be32_to_cpup(spd))); | ||
76 | 86 | ||
77 | return 0; | 87 | return 0; |
78 | } | 88 | } |
@@ -171,6 +181,7 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = { | |||
171 | { .compatible = "ns16550", .data = (void *)PORT_16550, }, | 181 | { .compatible = "ns16550", .data = (void *)PORT_16550, }, |
172 | { .compatible = "ns16750", .data = (void *)PORT_16750, }, | 182 | { .compatible = "ns16750", .data = (void *)PORT_16750, }, |
173 | { .compatible = "ns16850", .data = (void *)PORT_16850, }, | 183 | { .compatible = "ns16850", .data = (void *)PORT_16850, }, |
184 | { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, | ||
174 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL | 185 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL |
175 | { .compatible = "ibm,qpace-nwp-serial", | 186 | { .compatible = "ibm,qpace-nwp-serial", |
176 | .data = (void *)PORT_NWPSERIAL, }, | 187 | .data = (void *)PORT_NWPSERIAL, }, |