[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260113114529.1692213-1-aman.kumarpandey@nxp.com>
Date: Tue, 13 Jan 2026 13:45:25 +0200
From: Aman Kumar Pandey <aman.kumarpandey@....com>
To: linux-kernel@...r.kernel.org,
linux-i3c@...ts.infradead.org,
alexandre.belloni@...tlin.com,
krzk+dt@...nel.org,
robh@...nel.org,
conor+dt@...nel.org,
devicetree@...r.kernel.org,
broonie@...nel.org,
lee@...nel.org,
Frank.Li@....com,
lgirdwood@...il.com
Cc: vikash.bansal@....com,
priyanka.jain@....com,
shashank.rebbapragada@....com,
Aman Kumar Pandey <aman.kumarpandey@....com>
Subject: [PATCH v4 1/5] i3c: master: Expose the APIs to support I3C hub
Expose i3c_master_send_ccc_cmd(), i3c_master_supports_ccc_cmd(),
i3c_master_reattach_i3c_dev(), i3c_master_direct_attach_i3c_dev(),
and i3c_master_direct_detach_i3c_dev() to support I3C hub.
Signed-off-by: Aman Kumar Pandey <aman.kumarpandey@....com>
---
Changes in v4:
- Updated I3C master to handle hub support
---
---
drivers/i3c/master.c | 123 ++++++++++++++++++++++++++++++++++++-
include/linux/i3c/master.h | 11 ++++
2 files changed, 132 insertions(+), 2 deletions(-)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 7f606c871648..c92152ff795f 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1544,8 +1544,76 @@ static int i3c_master_attach_i3c_dev(struct i3c_master_controller *master,
return 0;
}
-static int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
- u8 old_dyn_addr)
+/**
+ * i3c_master_direct_attach_i3c_dev() - attach an I3C device to a master
+ * @master: I3C master controller to attach the device to
+ * @dev: I3C device descriptor representing the device
+ *
+ * This function attaches an I3C device to its master controller once the
+ * device has a valid address on the bus. Devices without
+ * an assigned address are ignored. The master device itself is never
+ * attached through this bus.
+ *
+ * Return: 0 on success, or a negative error code if the attach operation
+ * fails in the master controller driver.
+ */
+int i3c_master_direct_attach_i3c_dev(struct i3c_master_controller *master,
+ struct i3c_dev_desc *dev)
+{
+ int ret = 0;
+
+ /*
+ * We don't attach devices to the controller until they are
+ * addressable on the bus.
+ */
+
+ if (!dev->info.static_addr && !dev->info.dyn_addr)
+ return 0;
+
+ /* Do not attach the master device itself. */
+ if (master->this != dev && master->ops->attach_i3c_dev)
+ ret = master->ops->attach_i3c_dev(dev);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_master_direct_attach_i3c_dev);
+
+/**
+ * i3c_master_direct_detach_i3c_dev - Detach an I3C device from its master
+ * @dev: I3C device descriptor to be detached
+ *
+ * This function detaches an I3C device from its master controller.
+ * It ensures that the master itself is not detached. If the device is not
+ * the master and the master controller provides a detach operation,
+ * the detach callback is invoked to perform the actual removal.
+ */
+void i3c_master_direct_detach_i3c_dev(struct i3c_dev_desc *dev)
+{
+ struct i3c_master_controller *master = i3c_dev_get_master(dev);
+
+ /* Do not detach the master device itself. */
+ if (master->this != dev && master->ops->detach_i3c_dev)
+ master->ops->detach_i3c_dev(dev);
+}
+EXPORT_SYMBOL_GPL(i3c_master_direct_detach_i3c_dev);
+
+/**
+ * i3c_master_reattach_i3c_dev() - reattach an I3C device with a new address
+ * @dev: I3C device descriptor to reattach
+ * @old_dyn_addr: previous dynamic address of the device
+ *
+ * This function reattaches an existing I3C device to the bus when its dynamic
+ * address has changed. It updates the bus address slot status accordingly:
+ * - Marks the new dynamic address as occupied by an I3C device.
+ * - Frees the old dynamic address slot if applicable.
+ *
+ * This function must be called with the bus lock held in write mode.
+ *
+ * Return: 0 on success, or a negative error code if reattachment fails
+ * (e.g. -EBUSY if the new address slot is not free).
+ */
+int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
+ u8 old_dyn_addr)
{
struct i3c_master_controller *master = i3c_dev_get_master(dev);
int ret;
@@ -1569,6 +1637,7 @@ static int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
return 0;
}
+EXPORT_SYMBOL_GPL(i3c_master_reattach_i3c_dev);
static void i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev)
{
@@ -1692,6 +1761,56 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
}
}
+/**
+ * i3c_master_supports_ccc_cmd() - check CCC command support
+ * @master: I3C master controller
+ * @cmd: CCC command to verify
+ *
+ * This function verifies whether the given I3C master controller supports
+ * the specified Common Command Code (CCC).
+ *
+ * Return: 0 if the CCC command is supported and executed successfully,
+ * -EINVAL if arguments are invalid,
+ * -EOPNOTSUPP if the master does not support CCC commands,
+ * or another negative error code from the master's operation.
+ */
+int i3c_master_supports_ccc_cmd(struct i3c_master_controller *master,
+ const struct i3c_ccc_cmd *cmd)
+{
+ if (!cmd || !master)
+ return -EINVAL;
+
+ if (!master->ops->supports_ccc_cmd)
+ return -EOPNOTSUPP;
+
+ return master->ops->supports_ccc_cmd(master, cmd);
+}
+EXPORT_SYMBOL_GPL(i3c_master_supports_ccc_cmd);
+
+/**
+ * i3c_master_send_ccc_cmd() - send a CCC command
+ * @master: I3C master controller issuing the command
+ * @cmd: CCC command to be sent
+ *
+ * This function sends a Common Command Code (CCC) command to devices on the
+ * I3C bus. It acquires the bus maintenance lock, executes the command, and
+ * then releases the lock to ensure safe access to the bus.
+ *
+ * Return: 0 on success, or a negative error code on failure.
+ */
+int i3c_master_send_ccc_cmd(struct i3c_master_controller *master,
+ struct i3c_ccc_cmd *cmd)
+{
+ int ret;
+
+ i3c_bus_maintenance_lock(&master->bus);
+ ret = i3c_master_send_ccc_cmd_locked(master, cmd);
+ i3c_bus_maintenance_unlock(&master->bus);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_master_send_ccc_cmd);
+
/**
* i3c_master_do_daa() - do a DAA (Dynamic Address Assignment)
* @master: master doing the DAA
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index 58d01ed4cce7..b059da7777d7 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -602,6 +602,17 @@ void i3c_master_dma_unmap_single(struct i3c_dma *dma_xfer);
DEFINE_FREE(i3c_master_dma_unmap_single, void *,
if (_T) i3c_master_dma_unmap_single(_T))
+int i3c_master_send_ccc_cmd(struct i3c_master_controller *master,
+ struct i3c_ccc_cmd *cmd);
+
+int i3c_master_supports_ccc_cmd(struct i3c_master_controller *master,
+ const struct i3c_ccc_cmd *cmd);
+
+int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
+ u8 old_dyn_addr);
+int i3c_master_direct_attach_i3c_dev(struct i3c_master_controller *master,
+ struct i3c_dev_desc *dev);
+void i3c_master_direct_detach_i3c_dev(struct i3c_dev_desc *dev);
int i3c_master_set_info(struct i3c_master_controller *master,
const struct i3c_device_info *info);
--
2.25.1
Powered by blists - more mailing lists