From 71c5ccb1efd2ae43b1241412f1357cd36aff25ec Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Thu, 16 Mar 2023 15:26:12 -0700 Subject: [PATCH] drivers: i3c: add reattach_i3c_device api Some I3C controllers have retaining registers which are used to contain the DA of the i3c device. This needs to be updated every time the DA is updated with SETNEWDA or SETDASA Signed-off-by: Ryan McClelland --- drivers/i3c/i3c_ccc.c | 3 ++- drivers/i3c/i3c_common.c | 16 +++--------- include/zephyr/drivers/i3c.h | 48 ++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/drivers/i3c/i3c_ccc.c b/drivers/i3c/i3c_ccc.c index da914a233b7..a19184ce053 100644 --- a/drivers/i3c/i3c_ccc.c +++ b/drivers/i3c/i3c_ccc.c @@ -130,7 +130,8 @@ int i3c_ccc_do_setdasa(const struct i3c_device_desc *target) * Note that the 7-bit address needs to start at bit 1 * (aka left-justified). So shift left by 1; */ - dyn_addr = target->static_addr << 1; + dyn_addr = (target->init_dynamic_addr ? + target->init_dynamic_addr : target->static_addr) << 1; ccc_tgt_payload.addr = target->static_addr; ccc_tgt_payload.rnw = 0; diff --git a/drivers/i3c/i3c_common.c b/drivers/i3c/i3c_common.c index fea6634bb28..7f00217440b 100644 --- a/drivers/i3c/i3c_common.c +++ b/drivers/i3c/i3c_common.c @@ -402,23 +402,13 @@ static int i3c_bus_setdasa(const struct device *dev, continue; } - /* - * If there is a desired dynamic address and it is - * not the same as the static address, wait till - * ENTDAA to do address assignment as this is - * no longer SETDASA. - */ - if ((desc->init_dynamic_addr != 0U) && - (desc->init_dynamic_addr != desc->static_addr)) { - *need_daa = true; - continue; - } - LOG_DBG("SETDASA for 0x%x", desc->static_addr); ret = i3c_ccc_do_setdasa(desc); if (ret == 0) { - desc->dynamic_addr = desc->static_addr; + desc->dynamic_addr = (desc->init_dynamic_addr ? desc->init_dynamic_addr + : desc->static_addr); + i3c_reattach_i3c_device(desc, desc->static_addr); } else { LOG_ERR("SETDASA error on address 0x%x (%d)", desc->static_addr, ret); diff --git a/include/zephyr/drivers/i3c.h b/include/zephyr/drivers/i3c.h index 3f6fb332fc3..57501de7979 100644 --- a/include/zephyr/drivers/i3c.h +++ b/include/zephyr/drivers/i3c.h @@ -487,6 +487,23 @@ __subsystem struct i3c_driver_api { */ int (*recover_bus)(const struct device *dev); + /** + * I3C Address Update + * + * Optional Controller only API. + * + * @see i3c_reattach_i3c_device + * + * @param dev Pointer to controller device driver instance. + * @param target Pointer to target device descriptor. + * @param old_dyn_addr Old dynamic address + * + * @return @see i3c_reattach_i3c_device + */ + int (*reattach_i3c_device)(const struct device *dev, + struct i3c_device_desc *target, + uint8_t old_dyn_addr); + /** * Perform Dynamic Address Assignment via ENTDAA. * @@ -1083,6 +1100,37 @@ static inline int i3c_recover_bus(const struct device *dev) return api->recover_bus(dev); } +/** + * @brief Reattach I3C device + * + * called after every time an I3C device has its address + * changed. It can be because the device has been powered + * down and has lost its address, or it can happen when a + * device had a static address and has been assigned a + * dynamic address with SETDASA or a dynamic address has + * been updated with SETNEWDA. + * This method is optional. + * + * @param target Pointer to the target device descriptor + * @param old_dyn_addr The old dynamic address of target device, 0 if + * there was no old dynamic address + * + * @retval 0 If successful. + * @retval -EINVAL If address is not available + */ +static inline int i3c_reattach_i3c_device(struct i3c_device_desc *target, + uint8_t old_dyn_addr) +{ + const struct i3c_driver_api *api = + (const struct i3c_driver_api *)target->bus->api; + + if (api->reattach_i3c_device == NULL) { + return -ENOSYS; + } + + return api->reattach_i3c_device(target->bus, target, old_dyn_addr); +} + /** * @brief Perform Dynamic Address Assignment on the I3C bus. *