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 <ryanmcclelland@meta.com>
This commit is contained in:
parent
281871ca4d
commit
71c5ccb1ef
3 changed files with 53 additions and 14 deletions
|
@ -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
|
* Note that the 7-bit address needs to start at bit 1
|
||||||
* (aka left-justified). So shift left by 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.addr = target->static_addr;
|
||||||
ccc_tgt_payload.rnw = 0;
|
ccc_tgt_payload.rnw = 0;
|
||||||
|
|
|
@ -402,23 +402,13 @@ static int i3c_bus_setdasa(const struct device *dev,
|
||||||
continue;
|
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);
|
LOG_DBG("SETDASA for 0x%x", desc->static_addr);
|
||||||
|
|
||||||
ret = i3c_ccc_do_setdasa(desc);
|
ret = i3c_ccc_do_setdasa(desc);
|
||||||
if (ret == 0) {
|
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 {
|
} else {
|
||||||
LOG_ERR("SETDASA error on address 0x%x (%d)",
|
LOG_ERR("SETDASA error on address 0x%x (%d)",
|
||||||
desc->static_addr, ret);
|
desc->static_addr, ret);
|
||||||
|
|
|
@ -487,6 +487,23 @@ __subsystem struct i3c_driver_api {
|
||||||
*/
|
*/
|
||||||
int (*recover_bus)(const struct device *dev);
|
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.
|
* 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);
|
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.
|
* @brief Perform Dynamic Address Assignment on the I3C bus.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue