i3c: master: Add i3c_master_do_daa_ext() for post-hibernation address recovery

After system hibernation, I3C Dynamic Addresses may be reassigned at boot
and no longer match the values recorded before suspend. Introduce
i3c_master_do_daa_ext() to handle this situation.

The restore procedure is straightforward: issue a Reset Dynamic Address
Assignment (RSTDAA), then run the standard DAA sequence. The existing DAA
logic already supports detecting and updating devices whose dynamic
addresses differ from previously known values.

Refactor the DAA path by introducing a shared helper used by both the
normal i3c_master_do_daa() path and the new extended restore function,
and correct the kernel-doc in the process.

Export i3c_master_do_daa_ext() so that master drivers can invoke it from
their PM restore callbacks.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260123063325.8210-2-adrian.hunter@intel.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
Adrian Hunter
2026-01-23 08:33:23 +02:00
committed by Alexandre Belloni
parent b58eaa4761
commit c481ef12e7
2 changed files with 39 additions and 11 deletions

View File

@@ -1768,22 +1768,24 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
}
/**
* i3c_master_do_daa() - do a DAA (Dynamic Address Assignment)
* @master: master doing the DAA
* i3c_master_do_daa_ext() - Dynamic Address Assignment (extended version)
* @master: controller
* @rstdaa: whether to first perform Reset of Dynamic Addresses (RSTDAA)
*
* This function is instantiating an I3C device object and adding it to the
* I3C device list. All device information are automatically retrieved using
* standard CCC commands.
* Perform Dynamic Address Assignment with optional support for System
* Hibernation (@rstdaa is true).
*
* The I3C device object is returned in case the master wants to attach
* private data to it using i3c_dev_set_master_data().
*
* This function must be called with the bus lock held in write mode.
* After System Hibernation, Dynamic Addresses can have been reassigned at boot
* time to different values. A simple strategy is followed to handle that.
* Perform a Reset of Dynamic Addresses (RSTDAA) followed by the normal DAA
* procedure which has provision for reassigning addresses that differ from the
* previously recorded addresses.
*
* Return: a 0 in case of success, an negative error code otherwise.
*/
int i3c_master_do_daa(struct i3c_master_controller *master)
int i3c_master_do_daa_ext(struct i3c_master_controller *master, bool rstdaa)
{
int rstret = 0;
int ret;
ret = i3c_master_rpm_get(master);
@@ -1791,7 +1793,15 @@ int i3c_master_do_daa(struct i3c_master_controller *master)
return ret;
i3c_bus_maintenance_lock(&master->bus);
if (rstdaa) {
rstret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
if (rstret == I3C_ERROR_M2)
rstret = 0;
}
ret = master->ops->do_daa(master);
i3c_bus_maintenance_unlock(&master->bus);
if (ret)
@@ -1802,7 +1812,24 @@ int i3c_master_do_daa(struct i3c_master_controller *master)
i3c_bus_normaluse_unlock(&master->bus);
out:
i3c_master_rpm_put(master);
return ret;
return rstret ?: ret;
}
EXPORT_SYMBOL_GPL(i3c_master_do_daa_ext);
/**
* i3c_master_do_daa() - do a DAA (Dynamic Address Assignment)
* @master: master doing the DAA
*
* This function instantiates I3C device objects and adds them to the
* I3C device list. All device information is automatically retrieved using
* standard CCC commands.
*
* Return: a 0 in case of success, an negative error code otherwise.
*/
int i3c_master_do_daa(struct i3c_master_controller *master)
{
return i3c_master_do_daa_ext(master, false);
}
EXPORT_SYMBOL_GPL(i3c_master_do_daa);

View File

@@ -605,6 +605,7 @@ int i3c_master_get_free_addr(struct i3c_master_controller *master,
int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
u8 addr);
int i3c_master_do_daa(struct i3c_master_controller *master);
int i3c_master_do_daa_ext(struct i3c_master_controller *master, bool rstdaa);
struct i3c_dma *i3c_master_dma_map_single(struct device *dev, void *ptr,
size_t len, bool force_bounce,
enum dma_data_direction dir);