drivers: i3c: cdns: add reattach api implementation

This adds the reattach api necessary for writing the i3c retaining
registers within the cdns i3c when the dynamic address changes.

Signed-off-by: Ryan McClelland <ryanmcclelland@meta.com>
This commit is contained in:
Ryan McClelland 2022-12-09 00:28:40 -08:00 committed by Christopher Friedt
commit 2f02d6ca81

View file

@ -816,9 +816,7 @@ static void cdns_i3c_program_retaining_regs(const struct device *dev)
* it will be given the exact DA programmed in it's RR if the PID matches and marked
* as active duing ENTDAA, otherwise they get set as active here
*/
if (!((i3c_device->static_addr == 0) ||
((i3c_device->init_dynamic_addr != 0) &&
(i3c_device->static_addr != i3c_device->init_dynamic_addr)))) {
if (i3c_device->static_addr != 0) {
sys_write32(sys_read32(config->base + DEVS_CTRL) |
DEVS_CTRL_DEV_ACTIVE(cdns_i3c_device_data->id),
config->base + DEVS_CTRL);
@ -1582,6 +1580,40 @@ static int cdns_i3c_attach_device(const struct device *dev, struct i3c_device_de
return 0;
}
static int cdns_i3c_reattach_device(const struct device *dev, struct i3c_device_desc *desc,
uint8_t old_dyn_addr)
{
const struct cdns_i3c_config *config = dev->config;
struct cdns_i3c_data *data = dev->data;
struct cdns_i3c_i2c_dev_data *cdns_i3c_device_data = desc->controller_priv;
if (cdns_i3c_device_data == NULL) {
LOG_ERR("%s: %s: device not attached", dev->name, desc->dev->name);
return -EINVAL;
}
if (!i3c_addr_slots_is_free(&data->addr_slots, desc->dynamic_addr)) {
LOG_ERR("%s: %s: dynamic address 0x%02x is not free", dev->name, desc->dev->name,
desc->dynamic_addr);
return -EADDRNOTAVAIL;
}
k_mutex_lock(&data->bus_lock, K_FOREVER);
uint32_t rr0 = DEV_ID_RR0_IS_I3C | prepare_rr0_dev_address(desc->dynamic_addr);
if (old_dyn_addr) {
/* mark the old address as free */
i3c_addr_slots_mark_free(&data->addr_slots, old_dyn_addr);
}
sys_write32(rr0, config->base + DEV_ID_RR0(cdns_i3c_device_data->id));
i3c_addr_slots_mark_i3c(&data->addr_slots, desc->dynamic_addr);
k_mutex_unlock(&data->bus_lock);
return 0;
}
static int cdns_i3c_i2c_attach_device(const struct device *dev, struct i3c_i2c_device_desc *desc)
{
struct cdns_i3c_data *data = dev->data;
@ -2416,6 +2448,8 @@ static struct i3c_driver_api api = {
.configure = cdns_i3c_configure,
.config_get = cdns_i3c_config_get,
.reattach_i3c_device = cdns_i3c_reattach_device,
.do_daa = cdns_i3c_do_daa,
.do_ccc = cdns_i3c_do_ccc,