in master.c [1668:1795]
static int i3c_master_bus_init(struct i3c_master_controller *master)
{
enum i3c_addr_slot_status status;
struct i2c_dev_boardinfo *i2cboardinfo;
struct i3c_dev_boardinfo *i3cboardinfo;
struct i2c_dev_desc *i2cdev;
int ret;
/*
* First attach all devices with static definitions provided by the
* FW.
*/
list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
status = i3c_bus_get_addr_slot_status(&master->bus,
i2cboardinfo->base.addr);
if (status != I3C_ADDR_SLOT_FREE) {
ret = -EBUSY;
goto err_detach_devs;
}
i3c_bus_set_addr_slot_status(&master->bus,
i2cboardinfo->base.addr,
I3C_ADDR_SLOT_I2C_DEV);
i2cdev = i3c_master_alloc_i2c_dev(master, i2cboardinfo);
if (IS_ERR(i2cdev)) {
ret = PTR_ERR(i2cdev);
goto err_detach_devs;
}
ret = i3c_master_attach_i2c_dev(master, i2cdev);
if (ret) {
i3c_master_free_i2c_dev(i2cdev);
goto err_detach_devs;
}
}
/*
* Now execute the controller specific ->bus_init() routine, which
* might configure its internal logic to match the bus limitations.
*/
ret = master->ops->bus_init(master);
if (ret)
goto err_detach_devs;
/*
* The master device should have been instantiated in ->bus_init(),
* complain if this was not the case.
*/
if (!master->this) {
dev_err(&master->dev,
"master_set_info() was not called in ->bus_init()\n");
ret = -EINVAL;
goto err_bus_cleanup;
}
/*
* Reset all dynamic address that may have been assigned before
* (assigned by the bootloader for example).
*/
ret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
if (ret && ret != I3C_ERROR_M2)
goto err_bus_cleanup;
/* Disable all slave events before starting DAA. */
ret = i3c_master_disec_locked(master, I3C_BROADCAST_ADDR,
I3C_CCC_EVENT_SIR | I3C_CCC_EVENT_MR |
I3C_CCC_EVENT_HJ);
if (ret && ret != I3C_ERROR_M2)
goto err_bus_cleanup;
/*
* Reserve init_dyn_addr first, and then try to pre-assign dynamic
* address and retrieve device information if needed.
* In case pre-assign dynamic address fails, setting dynamic address to
* the requested init_dyn_addr is retried after DAA is done in
* i3c_master_add_i3c_dev_locked().
*/
list_for_each_entry(i3cboardinfo, &master->boardinfo.i3c, node) {
/*
* We don't reserve a dynamic address for devices that
* don't explicitly request one.
*/
if (!i3cboardinfo->init_dyn_addr)
continue;
ret = i3c_bus_get_addr_slot_status(&master->bus,
i3cboardinfo->init_dyn_addr);
if (ret != I3C_ADDR_SLOT_FREE) {
ret = -EBUSY;
goto err_rstdaa;
}
i3c_bus_set_addr_slot_status(&master->bus,
i3cboardinfo->init_dyn_addr,
I3C_ADDR_SLOT_I3C_DEV);
/*
* Only try to create/attach devices that have a static
* address. Other devices will be created/attached when
* DAA happens, and the requested dynamic address will
* be set using SETNEWDA once those devices become
* addressable.
*/
if (i3cboardinfo->static_addr)
i3c_master_early_i3c_dev_add(master, i3cboardinfo);
}
ret = i3c_master_do_daa(master);
if (ret)
goto err_rstdaa;
return 0;
err_rstdaa:
i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
err_bus_cleanup:
if (master->ops->bus_cleanup)
master->ops->bus_cleanup(master);
err_detach_devs:
i3c_master_detach_free_devs(master);
return ret;
}