From 1f757bc67ffd9c8b2dffe89b6fe95c0568a9aafb Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Thu, 16 Mar 2023 15:26:45 -0700 Subject: [PATCH] drivers: i3c: add SETNEWDA ccc helper function This is a ccc helper function for setting a new dynamic addr for a Target. Signed-off-by: Ryan McClelland --- drivers/i3c/i3c_ccc.c | 32 ++++++++++++++++++++++++++++++++ include/zephyr/drivers/i3c/ccc.h | 16 ++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/drivers/i3c/i3c_ccc.c b/drivers/i3c/i3c_ccc.c index a19184ce053..b4690b583c8 100644 --- a/drivers/i3c/i3c_ccc.c +++ b/drivers/i3c/i3c_ccc.c @@ -146,6 +146,38 @@ int i3c_ccc_do_setdasa(const struct i3c_device_desc *target) return i3c_do_ccc(target->bus, &ccc_payload); } +int i3c_ccc_do_setnewda(const struct i3c_device_desc *target, struct i3c_ccc_address new_da) +{ + struct i3c_ccc_payload ccc_payload; + struct i3c_ccc_target_payload ccc_tgt_payload; + uint8_t new_dyn_addr; + + __ASSERT_NO_MSG(target != NULL); + __ASSERT_NO_MSG(target->bus != NULL); + + if (target->dynamic_addr == 0U) { + return -EINVAL; + } + + /* + * Note that the 7-bit address needs to start at bit 1 + * (aka left-justified). So shift left by 1; + */ + new_dyn_addr = new_da.addr << 1; + + ccc_tgt_payload.addr = target->dynamic_addr; + ccc_tgt_payload.rnw = 0; + ccc_tgt_payload.data = &new_dyn_addr; + ccc_tgt_payload.data_len = 1; + + memset(&ccc_payload, 0, sizeof(ccc_payload)); + ccc_payload.ccc.id = I3C_CCC_SETNEWDA; + ccc_payload.targets.payloads = &ccc_tgt_payload; + ccc_payload.targets.num_targets = 1; + + return i3c_do_ccc(target->bus, &ccc_payload); +} + int i3c_ccc_do_events_all_set(const struct device *controller, bool enable, struct i3c_ccc_events *events) { diff --git a/include/zephyr/drivers/i3c/ccc.h b/include/zephyr/drivers/i3c/ccc.h index 033e2038ad6..fcb0ac6e1e4 100644 --- a/include/zephyr/drivers/i3c/ccc.h +++ b/include/zephyr/drivers/i3c/ccc.h @@ -869,6 +869,22 @@ int i3c_ccc_do_rstdaa_all(const struct device *controller); */ int i3c_ccc_do_setdasa(const struct i3c_device_desc *target); +/** + * @brief Set New Dynamic Address for a target + * + * Helper function to do SETNEWDA(Set New Dynamic Address) for a particular target. + * + * Note this does not update @p target with the new dynamic address. + * + * @param[in] target Pointer to the target device descriptor where + * the device is configured with a static address. + * @param[in] new_da Pointer to the new_da struct. + * + * @return @see i3c_do_ccc + */ +int i3c_ccc_do_setnewda(const struct i3c_device_desc *target, + struct i3c_ccc_address new_da); + /** * @brief Broadcast ENEC/DISEC to enable/disable target events. *