summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i3c/master.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 80dda0e85558..0eae19b3823d 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -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.
- *
- * The I3C device object is returned in case the master wants to attach
- * private data to it using i3c_dev_set_master_data().
+ * Perform Dynamic Address Assignment with optional support for System
+ * Hibernation (@rstdaa is true).
*
- * 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);