i2c: Mark instantiated device nodes with OF_POPULATE
authorPantelis Antoniou <pantelis.antoniou@konsulko.com>
Thu, 15 Jan 2015 16:33:55 +0000 (18:33 +0200)
committerMark Brown <broonie@kernel.org>
Sat, 21 Feb 2015 03:14:08 +0000 (12:14 +0900)
Mark (and unmark) device nodes with the POPULATE flag as appropriate.
This is required to avoid multi probing when using I2C and device
overlays containing a mux.

Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
(cherry picked from commit d5285c36e6d27c1a411a3131c034641a5fa452cb)
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/i2c/i2c-core.c

index dac8cd5031e7131a6e866df7be4019b7a9b15278..92588d3bae45a24131c43ee4399bf135e22b70a9 100644 (file)
@@ -704,6 +704,8 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
  */
 void i2c_unregister_device(struct i2c_client *client)
 {
+       if (client->dev.of_node)
+               of_node_clear_flag(client->dev.of_node, OF_POPULATED);
        device_unregister(&client->dev);
 }
 EXPORT_SYMBOL_GPL(i2c_unregister_device);
@@ -1025,8 +1027,11 @@ static void internal_of_i2c_register_devices(struct i2c_adapter *adap)
 
        dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
 
-       for_each_available_child_of_node(adap->dev.of_node, node)
+       for_each_available_child_of_node(adap->dev.of_node, node) {
+               if (of_node_test_and_set_flag(node, OF_POPULATED))
+                       continue;
                of_i2c_register_device(adap, node);
+       }
 }
 
 static int of_dev_node_match(struct device *dev, void *data)
@@ -1552,6 +1557,11 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action,
                if (adap == NULL)
                        return NOTIFY_OK;       /* not for us */
 
+               if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) {
+                       put_device(&adap->dev);
+                       return NOTIFY_OK;
+               }
+
                client = of_i2c_register_device(adap, rd->dn);
                put_device(&adap->dev);
 
@@ -1562,6 +1572,10 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action,
                }
                break;
        case OF_RECONFIG_CHANGE_REMOVE:
+               /* already depopulated? */
+               if (!of_node_check_flag(rd->dn, OF_POPULATED))
+                       return NOTIFY_OK;
+
                /* find our device by node */
                client = of_find_i2c_device_by_node(rd->dn);
                if (client == NULL)