in master/i3c-master-cdns.c [1132:1190]
static int cdns_i3c_master_do_daa(struct i3c_master_controller *m)
{
struct cdns_i3c_master *master = to_cdns_i3c_master(m);
unsigned long olddevs, newdevs;
int ret, slot;
u8 addrs[MAX_DEVS] = { };
u8 last_addr = 0;
olddevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK;
olddevs |= BIT(0);
/* Prepare RR slots before launching DAA. */
for_each_clear_bit(slot, &olddevs, master->maxdevs + 1) {
ret = i3c_master_get_free_addr(m, last_addr + 1);
if (ret < 0)
return -ENOSPC;
last_addr = ret;
addrs[slot] = last_addr;
writel(prepare_rr0_dev_address(last_addr) | DEV_ID_RR0_IS_I3C,
master->regs + DEV_ID_RR0(slot));
writel(0, master->regs + DEV_ID_RR1(slot));
writel(0, master->regs + DEV_ID_RR2(slot));
}
ret = i3c_master_entdaa_locked(&master->base);
if (ret && ret != I3C_ERROR_M2)
return ret;
newdevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK;
newdevs &= ~olddevs;
/*
* Clear all retaining registers filled during DAA. We already
* have the addressed assigned to them in the addrs array.
*/
for_each_set_bit(slot, &newdevs, master->maxdevs + 1)
i3c_master_add_i3c_dev_locked(m, addrs[slot]);
/*
* Clear slots that ended up not being used. Can be caused by I3C
* device creation failure or when the I3C device was already known
* by the system but with a different address (in this case the device
* already has a slot and does not need a new one).
*/
writel(readl(master->regs + DEVS_CTRL) |
master->free_rr_slots << DEVS_CTRL_DEV_CLR_SHIFT,
master->regs + DEVS_CTRL);
i3c_master_defslvs_locked(&master->base);
cdns_i3c_master_upd_i3c_scl_lim(master);
/* Unmask Hot-Join and Mastership request interrupts. */
i3c_master_enec_locked(m, I3C_BROADCAST_ADDR,
I3C_CCC_EVENT_HJ | I3C_CCC_EVENT_MR);
return 0;
}