in master.c [894:964]
int i3c_master_defslvs_locked(struct i3c_master_controller *master)
{
struct i3c_ccc_defslvs *defslvs;
struct i3c_ccc_dev_desc *desc;
struct i3c_ccc_cmd_dest dest;
struct i3c_dev_desc *i3cdev;
struct i2c_dev_desc *i2cdev;
struct i3c_ccc_cmd cmd;
struct i3c_bus *bus;
bool send = false;
int ndevs = 0, ret;
if (!master)
return -EINVAL;
bus = i3c_master_get_bus(master);
i3c_bus_for_each_i3cdev(bus, i3cdev) {
ndevs++;
if (i3cdev == master->this)
continue;
if (I3C_BCR_DEVICE_ROLE(i3cdev->info.bcr) ==
I3C_BCR_I3C_MASTER)
send = true;
}
/* No other master on the bus, skip DEFSLVS. */
if (!send)
return 0;
i3c_bus_for_each_i2cdev(bus, i2cdev)
ndevs++;
defslvs = i3c_ccc_cmd_dest_init(&dest, I3C_BROADCAST_ADDR,
struct_size(defslvs, slaves,
ndevs - 1));
if (!defslvs)
return -ENOMEM;
defslvs->count = ndevs;
defslvs->master.bcr = master->this->info.bcr;
defslvs->master.dcr = master->this->info.dcr;
defslvs->master.dyn_addr = master->this->info.dyn_addr << 1;
defslvs->master.static_addr = I3C_BROADCAST_ADDR << 1;
desc = defslvs->slaves;
i3c_bus_for_each_i2cdev(bus, i2cdev) {
desc->lvr = i2cdev->lvr;
desc->static_addr = i2cdev->addr << 1;
desc++;
}
i3c_bus_for_each_i3cdev(bus, i3cdev) {
/* Skip the I3C dev representing this master. */
if (i3cdev == master->this)
continue;
desc->bcr = i3cdev->info.bcr;
desc->dcr = i3cdev->info.dcr;
desc->dyn_addr = i3cdev->info.dyn_addr << 1;
desc->static_addr = i3cdev->info.static_addr << 1;
desc++;
}
i3c_ccc_cmd_init(&cmd, false, I3C_CCC_DEFSLVS, &dest, 1);
ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
i3c_ccc_cmd_dest_cleanup(&dest);
return ret;
}