summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/i2c-core-of.c48
-rw-r--r--include/linux/i2c.h10
2 files changed, 41 insertions, 17 deletions
diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c
index 9fb38e99a6c6..6cb7ad608bcd 100644
--- a/drivers/i2c/i2c-core-of.c
+++ b/drivers/i2c/i2c-core-of.c
@@ -22,46 +22,60 @@
#include "i2c-core.h"
-static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
- struct device_node *node)
+int of_i2c_get_board_info(struct device *dev, struct device_node *node,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
- struct i2c_board_info info = {};
u32 addr;
int ret;
- dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);
+ memset(info, 0, sizeof(*info));
- if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
- dev_err(&adap->dev, "of_i2c: modalias failure on %pOF\n",
- node);
- return ERR_PTR(-EINVAL);
+ if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) {
+ dev_err(dev, "of_i2c: modalias failure on %pOF\n", node);
+ return -EINVAL;
}
ret = of_property_read_u32(node, "reg", &addr);
if (ret) {
- dev_err(&adap->dev, "of_i2c: invalid reg on %pOF\n", node);
- return ERR_PTR(ret);
+ dev_err(dev, "of_i2c: invalid reg on %pOF\n", node);
+ return ret;
}
if (addr & I2C_TEN_BIT_ADDRESS) {
addr &= ~I2C_TEN_BIT_ADDRESS;
- info.flags |= I2C_CLIENT_TEN;
+ info->flags |= I2C_CLIENT_TEN;
}
if (addr & I2C_OWN_SLAVE_ADDRESS) {
addr &= ~I2C_OWN_SLAVE_ADDRESS;
- info.flags |= I2C_CLIENT_SLAVE;
+ info->flags |= I2C_CLIENT_SLAVE;
}
- info.addr = addr;
- info.of_node = node;
+ info->addr = addr;
+ info->of_node = node;
if (of_property_read_bool(node, "host-notify"))
- info.flags |= I2C_CLIENT_HOST_NOTIFY;
+ info->flags |= I2C_CLIENT_HOST_NOTIFY;
if (of_get_property(node, "wakeup-source", NULL))
- info.flags |= I2C_CLIENT_WAKE;
+ info->flags |= I2C_CLIENT_WAKE;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_i2c_get_board_info);
+
+static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
+ struct device_node *node)
+{
+ struct i2c_client *client;
+ struct i2c_board_info info;
+ int ret;
+
+ dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);
+
+ ret = of_i2c_get_board_info(&adap->dev, node, &info);
+ if (ret)
+ return ERR_PTR(ret);
client = i2c_new_device(adap, &info);
if (!client) {
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index aeb655772ef8..254cd34eeae2 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -901,6 +901,9 @@ extern const struct of_device_id
*i2c_of_match_device(const struct of_device_id *matches,
struct i2c_client *client);
+int of_i2c_get_board_info(struct device *dev, struct device_node *node,
+ struct i2c_board_info *info);
+
#else
static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
@@ -925,6 +928,13 @@ static inline const struct of_device_id
return NULL;
}
+static inline int of_i2c_get_board_info(struct device *dev,
+ struct device_node *node,
+ struct i2c_board_info *info)
+{
+ return -ENOTSUPP;
+}
+
#endif /* CONFIG_OF */
#if IS_ENABLED(CONFIG_ACPI)