diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2010-06-08 09:48:18 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-07-05 18:14:52 -0400 |
commit | 9fd049927ccba1c1d0343239b82f28c4e07fb95d (patch) | |
tree | e7d86e42e2643e1376c102f00c0e76d14cf65f86 /drivers/of/of_i2c.c | |
parent | 4f0ddcb020ef8afae65b4edb9aeb4a42ab74f4cf (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.c | 50 |
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 | ||
19 | void of_register_i2c_devices(struct i2c_adapter *adap, | 20 | void 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 | } |
67 | EXPORT_SYMBOL(of_register_i2c_devices); | 75 | EXPORT_SYMBOL(of_i2c_register_devices); |
68 | 76 | ||
69 | static int of_dev_node_match(struct device *dev, void *data) | 77 | static int of_dev_node_match(struct device *dev, void *data) |
70 | { | 78 | { |