drm/nouveau: off by one in init_i2c_device_find()
[safe/jmp/linux-2.6] / drivers / of / of_i2c.c
index 24bbef7..ab6522c 100644 (file)
@@ -24,7 +24,8 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
 
        for_each_child_of_node(adap_node, node) {
                struct i2c_board_info info = {};
-               const u32 *addr;
+               struct dev_archdata dev_ad = {};
+               const __be32 *addr;
                int len;
 
                if (of_modalias_node(node, info.type, sizeof(info.type)) < 0)
@@ -39,7 +40,10 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
 
                info.irq = irq_of_parse_and_map(node, 0);
 
-               info.addr = *addr;
+               info.addr = be32_to_cpup(addr);
+
+               info.of_node = node;
+               info.archdata = &dev_ad;
 
                request_module("%s", info.type);
 
@@ -51,8 +55,34 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
                        irq_dispose_mapping(info.irq);
                        continue;
                }
+
+               /*
+                * Get the node to not lose the dev_archdata->of_node.
+                * Currently there is no way to put it back, as well as no
+                * of_unregister_i2c_devices() call.
+                */
+               of_node_get(node);
        }
 }
 EXPORT_SYMBOL(of_register_i2c_devices);
 
+static int of_dev_node_match(struct device *dev, void *data)
+{
+        return dev->of_node == data;
+}
+
+/* must call put_device() when done with returned i2c_client device */
+struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
+{
+       struct device *dev;
+
+       dev = bus_find_device(&i2c_bus_type, NULL, node,
+                                        of_dev_node_match);
+       if (!dev)
+               return NULL;
+
+       return to_i2c_client(dev);
+}
+EXPORT_SYMBOL(of_find_i2c_device_by_node);
+
 MODULE_LICENSE("GPL");