diff options
Diffstat (limited to 'drivers/i3c/master.c')
-rw-r--r-- | drivers/i3c/master.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index 54e4c34b4a22..08aeb69a7800 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -21,6 +21,7 @@ static DEFINE_IDR(i3c_bus_idr); static DEFINE_MUTEX(i3c_core_lock); +static int __i3c_first_dynamic_bus_num; /** * i3c_bus_maintenance_lock - Lock the bus for a maintenance operation @@ -419,9 +420,9 @@ static void i3c_bus_cleanup(struct i3c_bus *i3cbus) mutex_unlock(&i3c_core_lock); } -static int i3c_bus_init(struct i3c_bus *i3cbus) +static int i3c_bus_init(struct i3c_bus *i3cbus, struct device_node *np) { - int ret; + int ret, start, end, id = -1; init_rwsem(&i3cbus->lock); INIT_LIST_HEAD(&i3cbus->devs.i2c); @@ -429,8 +430,19 @@ static int i3c_bus_init(struct i3c_bus *i3cbus) i3c_bus_init_addrslots(i3cbus); i3cbus->mode = I3C_BUS_MODE_PURE; + if (np) + id = of_alias_get_id(np, "i3c"); + mutex_lock(&i3c_core_lock); - ret = idr_alloc(&i3c_bus_idr, i3cbus, 0, 0, GFP_KERNEL); + if (id >= 0) { + start = id; + end = start + 1; + } else { + start = __i3c_first_dynamic_bus_num; + end = 0; + } + + ret = idr_alloc(&i3c_bus_idr, i3cbus, start, end, GFP_KERNEL); mutex_unlock(&i3c_core_lock); if (ret < 0) @@ -2606,7 +2618,7 @@ int i3c_master_register(struct i3c_master_controller *master, INIT_LIST_HEAD(&master->boardinfo.i2c); INIT_LIST_HEAD(&master->boardinfo.i3c); - ret = i3c_bus_init(i3cbus); + ret = i3c_bus_init(i3cbus, master->dev.of_node); if (ret) return ret; @@ -2695,17 +2707,13 @@ EXPORT_SYMBOL_GPL(i3c_master_register); * @master: master used to send frames on the bus * * Basically undo everything done in i3c_master_register(). - * - * Return: 0 in case of success, a negative error code otherwise. */ -int i3c_master_unregister(struct i3c_master_controller *master) +void i3c_master_unregister(struct i3c_master_controller *master) { i3c_master_i2c_adapter_cleanup(master); i3c_master_unregister_i3c_devs(master); i3c_master_bus_cleanup(master); device_unregister(&master->dev); - - return 0; } EXPORT_SYMBOL_GPL(i3c_master_unregister); @@ -2834,8 +2842,16 @@ void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev) static int __init i3c_init(void) { - int res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier); + int res; + + res = of_alias_get_highest_id("i3c"); + if (res >= 0) { + mutex_lock(&i3c_core_lock); + __i3c_first_dynamic_bus_num = res + 1; + mutex_unlock(&i3c_core_lock); + } + res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier); if (res) return res; |