summaryrefslogtreecommitdiff
path: root/drivers/i3c
diff options
context:
space:
mode:
authorJack Chen <zenghuchen@google.com>2022-12-07 23:50:59 +0300
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2022-12-11 23:25:58 +0300
commit672825cd2823a0cee4687ce80fef5b702ff3caa3 (patch)
treeda9b5a85074db5b7b58c626c9fd8463604f4c03e /drivers/i3c
parent01744ce9f07f0b76b0b2d30adba2a7c104f1ff2a (diff)
downloadlinux-672825cd2823a0cee4687ce80fef5b702ff3caa3.tar.xz
i3c: export SETDASA method
Because not all I3C drivers have the hot-join feature ready, and especially not all I3C devices support hot-join feature, exporting SETDASA method could be useful. With this function, the I3C controller could perform a DAA to I3C devices when users decide to turn these I3C devices off and on again during run-time. Tested: This change has been tested with turnning off an I3C device and turning on it again during run-time. The device driver calls SETDASA method to perform DAA to the device. And communication between I3C controller and device is set up again correctly. Signed-off-by: Jack Chen <zenghuchen@google.com> Link: https://lore.kernel.org/r/20221207205059.3848851-1-zenghuchen@google.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Diffstat (limited to 'drivers/i3c')
-rw-r--r--drivers/i3c/device.c20
-rw-r--r--drivers/i3c/internals.h1
-rw-r--r--drivers/i3c/master.c19
3 files changed, 40 insertions, 0 deletions
diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c
index e92d3e9a52bd..9762630b917e 100644
--- a/drivers/i3c/device.c
+++ b/drivers/i3c/device.c
@@ -51,6 +51,26 @@ int i3c_device_do_priv_xfers(struct i3c_device *dev,
EXPORT_SYMBOL_GPL(i3c_device_do_priv_xfers);
/**
+ * i3c_device_do_setdasa() - do I3C dynamic address assignement with
+ * static address
+ *
+ * @dev: device with which the DAA should be done
+ *
+ * Return: 0 in case of success, a negative error core otherwise.
+ */
+int i3c_device_do_setdasa(struct i3c_device *dev)
+{
+ int ret;
+
+ i3c_bus_normaluse_lock(dev->bus);
+ ret = i3c_dev_setdasa_locked(dev->desc);
+ i3c_bus_normaluse_unlock(dev->bus);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_device_do_setdasa);
+
+/**
* i3c_device_get_info() - get I3C device information
*
* @dev: device we want information on
diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h
index 86b7b44cfca2..908a807badaf 100644
--- a/drivers/i3c/internals.h
+++ b/drivers/i3c/internals.h
@@ -15,6 +15,7 @@ extern struct bus_type i3c_bus_type;
void i3c_bus_normaluse_lock(struct i3c_bus *bus);
void i3c_bus_normaluse_unlock(struct i3c_bus *bus);
+int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev);
int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
struct i3c_priv_xfer *xfers,
int nxfers);
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 351c81a929a6..d7e6f6c99aea 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2708,6 +2708,25 @@ int i3c_master_unregister(struct i3c_master_controller *master)
}
EXPORT_SYMBOL_GPL(i3c_master_unregister);
+int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev)
+{
+ struct i3c_master_controller *master;
+
+ if (!dev)
+ return -ENOENT;
+
+ master = i3c_dev_get_master(dev);
+ if (!master)
+ return -EINVAL;
+
+ if (!dev->boardinfo || !dev->boardinfo->init_dyn_addr ||
+ !dev->boardinfo->static_addr)
+ return -EINVAL;
+
+ return i3c_master_setdasa_locked(master, dev->info.static_addr,
+ dev->boardinfo->init_dyn_addr);
+}
+
int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
struct i3c_priv_xfer *xfers,
int nxfers)