diff options
Diffstat (limited to 'drivers/i3c/master.c')
-rw-r--r-- | drivers/i3c/master.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index 04d6d54d2ab8..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; @@ -2830,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; |