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:
parent
1f757bc67f
commit
2f02d6ca81
1 changed files with 37 additions and 3 deletions
|
@ -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
|
* 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
|
* as active duing ENTDAA, otherwise they get set as active here
|
||||||
*/
|
*/
|
||||||
if (!((i3c_device->static_addr == 0) ||
|
if (i3c_device->static_addr != 0) {
|
||||||
((i3c_device->init_dynamic_addr != 0) &&
|
|
||||||
(i3c_device->static_addr != i3c_device->init_dynamic_addr)))) {
|
|
||||||
sys_write32(sys_read32(config->base + DEVS_CTRL) |
|
sys_write32(sys_read32(config->base + DEVS_CTRL) |
|
||||||
DEVS_CTRL_DEV_ACTIVE(cdns_i3c_device_data->id),
|
DEVS_CTRL_DEV_ACTIVE(cdns_i3c_device_data->id),
|
||||||
config->base + DEVS_CTRL);
|
config->base + DEVS_CTRL);
|
||||||
|
@ -1582,6 +1580,40 @@ static int cdns_i3c_attach_device(const struct device *dev, struct i3c_device_de
|
||||||
return 0;
|
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)
|
static int cdns_i3c_i2c_attach_device(const struct device *dev, struct i3c_i2c_device_desc *desc)
|
||||||
{
|
{
|
||||||
struct cdns_i3c_data *data = dev->data;
|
struct cdns_i3c_data *data = dev->data;
|
||||||
|
@ -2416,6 +2448,8 @@ static struct i3c_driver_api api = {
|
||||||
.configure = cdns_i3c_configure,
|
.configure = cdns_i3c_configure,
|
||||||
.config_get = cdns_i3c_config_get,
|
.config_get = cdns_i3c_config_get,
|
||||||
|
|
||||||
|
.reattach_i3c_device = cdns_i3c_reattach_device,
|
||||||
|
|
||||||
.do_daa = cdns_i3c_do_daa,
|
.do_daa = cdns_i3c_do_daa,
|
||||||
.do_ccc = cdns_i3c_do_ccc,
|
.do_ccc = cdns_i3c_do_ccc,
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue