in master.c [2462:2572]
int i3c_master_register(struct i3c_master_controller *master,
struct device *parent,
const struct i3c_master_controller_ops *ops,
bool secondary)
{
unsigned long i2c_scl_rate = I3C_BUS_I2C_FM_PLUS_SCL_RATE;
struct i3c_bus *i3cbus = i3c_master_get_bus(master);
enum i3c_bus_mode mode = I3C_BUS_MODE_PURE;
struct i2c_dev_boardinfo *i2cbi;
int ret;
/* We do not support secondary masters yet. */
if (secondary)
return -ENOTSUPP;
ret = i3c_master_check_ops(ops);
if (ret)
return ret;
master->dev.parent = parent;
master->dev.of_node = of_node_get(parent->of_node);
master->dev.bus = &i3c_bus_type;
master->dev.type = &i3c_masterdev_type;
master->dev.release = i3c_masterdev_release;
master->ops = ops;
master->secondary = secondary;
INIT_LIST_HEAD(&master->boardinfo.i2c);
INIT_LIST_HEAD(&master->boardinfo.i3c);
ret = i3c_bus_init(i3cbus);
if (ret)
return ret;
device_initialize(&master->dev);
dev_set_name(&master->dev, "i3c-%d", i3cbus->id);
ret = of_populate_i3c_bus(master);
if (ret)
goto err_put_dev;
list_for_each_entry(i2cbi, &master->boardinfo.i2c, node) {
switch (i2cbi->lvr & I3C_LVR_I2C_INDEX_MASK) {
case I3C_LVR_I2C_INDEX(0):
if (mode < I3C_BUS_MODE_MIXED_FAST)
mode = I3C_BUS_MODE_MIXED_FAST;
break;
case I3C_LVR_I2C_INDEX(1):
if (mode < I3C_BUS_MODE_MIXED_LIMITED)
mode = I3C_BUS_MODE_MIXED_LIMITED;
break;
case I3C_LVR_I2C_INDEX(2):
if (mode < I3C_BUS_MODE_MIXED_SLOW)
mode = I3C_BUS_MODE_MIXED_SLOW;
break;
default:
ret = -EINVAL;
goto err_put_dev;
}
if (i2cbi->lvr & I3C_LVR_I2C_FM_MODE)
i2c_scl_rate = I3C_BUS_I2C_FM_SCL_RATE;
}
ret = i3c_bus_set_mode(i3cbus, mode, i2c_scl_rate);
if (ret)
goto err_put_dev;
master->wq = alloc_workqueue("%s", 0, 0, dev_name(parent));
if (!master->wq) {
ret = -ENOMEM;
goto err_put_dev;
}
ret = i3c_master_bus_init(master);
if (ret)
goto err_put_dev;
ret = device_add(&master->dev);
if (ret)
goto err_cleanup_bus;
/*
* Expose our I3C bus as an I2C adapter so that I2C devices are exposed
* through the I2C subsystem.
*/
ret = i3c_master_i2c_adapter_init(master);
if (ret)
goto err_del_dev;
/*
* We're done initializing the bus and the controller, we can now
* register I3C devices discovered during the initial DAA.
*/
master->init_done = true;
i3c_bus_normaluse_lock(&master->bus);
i3c_master_register_new_i3c_devs(master);
i3c_bus_normaluse_unlock(&master->bus);
return 0;
err_del_dev:
device_del(&master->dev);
err_cleanup_bus:
i3c_master_bus_cleanup(master);
err_put_dev:
put_device(&master->dev);
return ret;
}