aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of/of_i2c.c
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2010-06-08 09:48:18 -0400
committerGrant Likely <grant.likely@secretlab.ca>2010-07-05 18:14:52 -0400
commit9fd049927ccba1c1d0343239b82f28c4e07fb95d (patch)
treee7d86e42e2643e1376c102f00c0e76d14cf65f86 /drivers/of/of_i2c.c
parent4f0ddcb020ef8afae65b4edb9aeb4a42ab74f4cf (diff)
of/i2c: Generalize OF support
This patch cleans up the i2c OF support code to make it selectable by all architectures and allow for automatic registration of i2c devices. Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/of/of_i2c.c')
-rw-r--r--drivers/of/of_i2c.c50
1 files changed, 29 insertions, 21 deletions
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
index ab6522c8e4fe..0a694debd226 100644
--- a/drivers/of/of_i2c.c
+++ b/drivers/of/of_i2c.c
@@ -14,57 +14,65 @@
14#include <linux/i2c.h> 14#include <linux/i2c.h>
15#include <linux/of.h> 15#include <linux/of.h>
16#include <linux/of_i2c.h> 16#include <linux/of_i2c.h>
17#include <linux/of_irq.h>
17#include <linux/module.h> 18#include <linux/module.h>
18 19
19void of_register_i2c_devices(struct i2c_adapter *adap, 20void of_i2c_register_devices(struct i2c_adapter *adap)
20 struct device_node *adap_node)
21{ 21{
22 void *result; 22 void *result;
23 struct device_node *node; 23 struct device_node *node;
24 24
25 for_each_child_of_node(adap_node, node) { 25 /* Only register child devices if the adapter has a node pointer set */
26 if (!adap->dev.of_node)
27 return;
28
29 dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
30
31 for_each_child_of_node(adap->dev.of_node, node) {
26 struct i2c_board_info info = {}; 32 struct i2c_board_info info = {};
27 struct dev_archdata dev_ad = {}; 33 struct dev_archdata dev_ad = {};
28 const __be32 *addr; 34 const __be32 *addr;
29 int len; 35 int len;
30 36
31 if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) 37 dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);
38
39 if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
40 dev_err(&adap->dev, "of_i2c: modalias failure on %s\n",
41 node->full_name);
32 continue; 42 continue;
43 }
33 44
34 addr = of_get_property(node, "reg", &len); 45 addr = of_get_property(node, "reg", &len);
35 if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) { 46 if (!addr || (len < sizeof(int))) {
36 printk(KERN_ERR 47 dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
37 "of-i2c: invalid i2c device entry\n"); 48 node->full_name);
38 continue; 49 continue;
39 } 50 }
40 51
41 info.irq = irq_of_parse_and_map(node, 0);
42
43 info.addr = be32_to_cpup(addr); 52 info.addr = be32_to_cpup(addr);
53 if (info.addr > (1 << 10) - 1) {
54 dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
55 info.addr, node->full_name);
56 continue;
57 }
44 58
45 info.of_node = node; 59 info.irq = irq_of_parse_and_map(node, 0);
60 info.of_node = of_node_get(node);
46 info.archdata = &dev_ad; 61 info.archdata = &dev_ad;
47 62
48 request_module("%s", info.type); 63 request_module("%s", info.type);
49 64
50 result = i2c_new_device(adap, &info); 65 result = i2c_new_device(adap, &info);
51 if (result == NULL) { 66 if (result == NULL) {
52 printk(KERN_ERR 67 dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
53 "of-i2c: Failed to load driver for %s\n", 68 node->full_name);
54 info.type); 69 of_node_put(node);
55 irq_dispose_mapping(info.irq); 70 irq_dispose_mapping(info.irq);
56 continue; 71 continue;
57 } 72 }
58
59 /*
60 * Get the node to not lose the dev_archdata->of_node.
61 * Currently there is no way to put it back, as well as no
62 * of_unregister_i2c_devices() call.
63 */
64 of_node_get(node);
65 } 73 }
66} 74}
67EXPORT_SYMBOL(of_register_i2c_devices); 75EXPORT_SYMBOL(of_i2c_register_devices);
68 76
69static int of_dev_node_match(struct device *dev, void *data) 77static int of_dev_node_match(struct device *dev, void *data)
70{ 78{