Because not all I3C drivers have the hot-join feature ready, and especially not all I3C devices support hot-join feature, exporting SETDASA method could be useful. With this function, the I3C controller could perform a DAA to I3C devices when users decide to turn these I3C devices off and on again during run-time. Tested: This change has been tested with turnning off an I3C device and turning on it again during run-time. The device driver calls SETDASA method to perform DAA to the device. And communication between I3C controller and device is set up again correctly.
Unified · Split
| @@ -50,6 +50,26 @@ int i3c_device_do_priv_xfers(struct i3c_device *dev, · 49 unmodified lines | |||
| 50 | } | 50 | } |
| 51 | EXPORT_SYMBOL_GPL(i3c_device_do_priv_xfers); | 51 | EXPORT_SYMBOL_GPL(i3c_device_do_priv_xfers); |
| 52 | 52 | ||
| 53 | /** | ||
| 54 | * i3c_device_do_setdasa() - do I3C dynamic address assignement with | ||
| 55 | * static address | ||
| 56 | * | ||
| 57 | * @dev: device with which the DAA should be done | ||
| 58 | * | ||
| 59 | * Return: 0 in case of success, a negative error core otherwise. | ||
| 60 | */ | ||
| 61 | int i3c_device_do_setdasa(struct i3c_device *dev) | ||
| 62 | { | ||
| 63 | int ret; | ||
| 64 | |||
| 65 | i3c_bus_normaluse_lock(dev->bus); | ||
| 66 | ret = i3c_dev_setdasa_locked(dev->desc); | ||
| 67 | i3c_bus_normaluse_unlock(dev->bus); | ||
| 68 | |||
| 69 | return ret; | ||
| 70 | } | ||
| 71 | EXPORT_SYMBOL_GPL(i3c_device_do_setdasa); | ||
| 72 | |||
| 53 | /** | 73 | /** |
| 54 | * i3c_device_get_info() - get I3C device information | 74 | * i3c_device_get_info() - get I3C device information |
| 55 | * | 75 | * |
| @@ -15,6 +15,7 @@ extern struct bus_type i3c_bus_type; · 14 unmodified lines | |||
| 15 | void i3c_bus_normaluse_lock(struct i3c_bus *bus); | 15 | void i3c_bus_normaluse_lock(struct i3c_bus *bus); |
| 16 | void i3c_bus_normaluse_unlock(struct i3c_bus *bus); | 16 | void i3c_bus_normaluse_unlock(struct i3c_bus *bus); |
| 17 | 17 | ||
| 18 | int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev); | ||
| 18 | int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev, | 19 | int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev, |
| 19 | struct i3c_priv_xfer *xfers, | 20 | struct i3c_priv_xfer *xfers, |
| 20 | int nxfers); | 21 | int nxfers); |
| @@ -2708,6 +2708,25 @@ int i3c_master_unregister(struct i3c_master_controller *master) · 2707 unmodified lines | |||
| 2708 | } | 2708 | } |
| 2709 | EXPORT_SYMBOL_GPL(i3c_master_unregister); | 2709 | EXPORT_SYMBOL_GPL(i3c_master_unregister); |
| 2710 | 2710 | ||
| 2711 | int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev) | ||
| 2712 | { | ||
| 2713 | struct i3c_master_controller *master; | ||
| 2714 | |||
| 2715 | if (!dev) | ||
| 2716 | return -ENOENT; | ||
| 2717 | |||
| 2718 | master = i3c_dev_get_master(dev); | ||
| 2719 | if (!master) | ||
| 2720 | return -EINVAL; | ||
| 2721 | |||
| 2722 | if (!dev->boardinfo || !dev->boardinfo->init_dyn_addr || | ||
| 2723 | !dev->boardinfo->static_addr) | ||
| 2724 | return -EINVAL; | ||
| 2725 | |||
| 2726 | return i3c_master_setdasa_locked(master, dev->info.static_addr, | ||
| 2727 | dev->boardinfo->init_dyn_addr); | ||
| 2728 | } | ||
| 2729 | |||
| 2711 | int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev, | 2730 | int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev, |
| 2712 | struct i3c_priv_xfer *xfers, | 2731 | struct i3c_priv_xfer *xfers, |
| 2713 | int nxfers) | 2732 | int nxfers) |
| @@ -294,6 +294,8 @@ int i3c_device_do_priv_xfers(struct i3c_device *dev, · 293 unmodified lines | |||
| 294 | struct i3c_priv_xfer *xfers, | 294 | struct i3c_priv_xfer *xfers, |
| 295 | int nxfers); | 295 | int nxfers); |
| 296 | 296 | ||
| 297 | int i3c_device_do_setdasa(struct i3c_device *dev); | ||
| 298 | |||
| 297 | void i3c_device_get_info(struct i3c_device *dev, struct i3c_device_info *info); | 299 | void i3c_device_get_info(struct i3c_device *dev, struct i3c_device_info *info); |
| 298 | 300 | ||
| 299 | struct i3c_ibi_payload { | 301 | struct i3c_ibi_payload { |