summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-imx.c10
-rw-r--r--drivers/i2c/i2c.c73
2 files changed, 66 insertions, 17 deletions
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 9fcfd5c6f7..c607bcba1a 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -545,6 +545,7 @@ static int __init i2c_fsl_probe(struct device_d *pdev)
i2c_fsl->adapter.master_xfer = i2c_fsl_xfer;
i2c_fsl->adapter.nr = pdev->id;
i2c_fsl->adapter.dev.parent = pdev;
+ i2c_fsl->adapter.dev.device_node = pdev->device_node;
i2c_fsl->base = dev_request_mem_region(pdev, 0);
i2c_fsl->dfsrr = -1;
@@ -572,8 +573,17 @@ fail:
return ret;
}
+static __maybe_unused struct of_device_id imx_i2c_dt_ids[] = {
+ {
+ .compatible = "fsl,imx21-i2c",
+ }, {
+ /* sentinel */
+ }
+};
+
static struct driver_d i2c_fsl_driver = {
.probe = i2c_fsl_probe,
.name = DRIVER_NAME,
+ .of_compatible = DRV_OF_COMPAT(imx_i2c_dt_ids),
};
device_platform_driver(i2c_fsl_driver);
diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c
index 4862df3c00..b63d94604d 100644
--- a/drivers/i2c/i2c.c
+++ b/drivers/i2c/i2c.c
@@ -254,33 +254,61 @@ struct i2c_client *i2c_new_device(struct i2c_adapter *adapter,
client->dev.platform_data = chip->platform_data;
client->dev.id = DEVICE_ID_DYNAMIC;
client->dev.bus = &i2c_bus;
+ client->dev.device_node = chip->of_node;
client->adapter = adapter;
client->addr = chip->addr;
client->dev.parent = &adapter->dev;
status = register_device(&client->dev);
-
-#if 0
- /* drivers may modify this initial i/o setup */
- status = master->setup(client);
- if (status < 0) {
- printf("can't setup %s, status %d\n",
- client->dev.name, status);
- goto fail;
+ if (status) {
+ free(client);
+ return NULL;
}
-#endif
return client;
-
-#if 0
- fail:
- free(proxy);
- return NULL;
-#endif
}
EXPORT_SYMBOL(i2c_new_device);
+void of_i2c_register_devices(struct i2c_adapter *adap)
+{
+ struct device_node *n;
+
+ /* Only register child devices if the adapter has a node pointer set */
+ if (!IS_ENABLED(CONFIG_OFDEVICE) || !adap->dev.device_node)
+ return;
+
+ device_node_for_nach_child(adap->dev.device_node, n) {
+ struct i2c_board_info info = {};
+ struct i2c_client *result;
+ const __be32 *addr;
+ int len;
+
+ of_modalias_node(n, info.type, I2C_NAME_SIZE);
+
+ info.of_node = n;
+
+ addr = of_get_property(n, "reg", &len);
+ if (!addr || (len < sizeof(int))) {
+ dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
+ n->full_name);
+ continue;
+ }
+
+ info.addr = be32_to_cpup(addr);
+ if (info.addr > (1 << 10) - 1) {
+ dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
+ info.addr, n->full_name);
+ continue;
+ }
+
+ result = i2c_new_device(adap, &info);
+ if (!result)
+ dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
+ n->full_name);
+ }
+}
+
/**
* i2c_new_dummy - return a new i2c device bound to a dummy driver
* @adapter: the adapter managing the device
@@ -396,8 +424,17 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adapter)
{
int ret;
- if (i2c_get_adapter(adapter->nr))
- return -EBUSY;
+ if (adapter->nr < 0) {
+ int nr;
+
+ for (nr = 0;; nr++)
+ if (!i2c_get_adapter(nr))
+ break;
+ adapter->nr = nr;
+ } else {
+ if (i2c_get_adapter(adapter->nr))
+ return -EBUSY;
+ }
adapter->dev.id = adapter->nr;
strcpy(adapter->dev.name, "i2c");
@@ -411,6 +448,8 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adapter)
/* populate children from any i2c device tables */
scan_boardinfo(adapter);
+ of_i2c_register_devices(adapter);
+
return 0;
}
EXPORT_SYMBOL(i2c_add_numbered_adapter);