[PATCH 2/3] i3c: mipi-i3c-hci: Add optional System Suspend support

Adrian Hunter adrian.hunter at intel.com
Sun Jan 18 22:49:33 PST 2026


On 19/01/2026 08:31, David Nyström wrote:
> 
> 
> On Fri, 16 Jan 2026, Adrian Hunter wrote:
> 
>> Add system suspend callbacks.  Implement them by forcing runtime PM.
>> Consequently bail out if Runtime PM is not allowed.
>>
>> On resume from System Suspend (suspend to RAM), rerun Dynamic Address
>> Assignment to restore addresses for devices that may have lost power.
>>
>> On resume from System Hibernation (suspend to disk), use the new
>> i3c_master_restore_daa() helper which additionally handles the case where
>> devices are assigned different dynamic addresses after a hibernation boot.
> 
> Why do you make this distinction ?
> RSTDAA+DAA during boot is motivated by that uboot might have assigned addresses.
> Why would we need to behave differently in suspend and suspend-to-disk?

Because, in the case of suspend-to-disk, there is a complete
boot process in between.

> Its fair to assume that I3C devices might have been powered off in suspend too, right ?

Hibernation is quite different.  Briefly:

Entry
	ops->freeze
	create image
	ops->thaw
	write image
	ops->poweroff

Exit
	boot			<- address assignment not guaranteed to be the same as previous boot
	ops->freeze
	restore image
	ops->restore		<- deal with I3C devices that may have different addresses

> 
>> Signed-off-by: Adrian Hunter <adrian.hunter at intel.com>
>> ---
>> drivers/i3c/master/mipi-i3c-hci/core.c | 53 ++++++++++++++++++++++++++
>> 1 file changed, 53 insertions(+)
>>
>> diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
>> index 02c5a133e329..b972d8bc81e6 100644
>> --- a/drivers/i3c/master/mipi-i3c-hci/core.c
>> +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
>> @@ -769,6 +769,53 @@ static int i3c_hci_runtime_resume(struct device *dev)
>>     return 0;
>> }
>>
>> +static int i3c_hci_suspend(struct device *dev)
>> +{
>> +    struct i3c_hci *hci = dev_get_drvdata(dev);
>> +
>> +    if (!(hci->quirks & HCI_QUIRK_RPM_ALLOWED))
>> +        return 0;
>> +
>> +    return pm_runtime_force_suspend(dev);
>> +}
>> +
>> +static int i3c_hci_resume_common(struct device *dev, bool restore)
>> +{
>> +    struct i3c_hci *hci = dev_get_drvdata(dev);
>> +    int ret;
>> +
>> +    if (!(hci->quirks & HCI_QUIRK_RPM_ALLOWED))
>> +        return 0;
>> +
>> +    ret = pm_runtime_force_resume(dev);
>> +    if (ret)
>> +        return ret;
>> +
>> +    if (restore)
>> +        ret = i3c_master_restore_daa(&hci->master);
>> +    else
>> +        ret = i3c_master_do_daa(&hci->master);
>> +
>> +    if (ret)
>> +        dev_err(dev, "Dynamic Address Assignment failed on resume, error %d\n", ret);
>> +
>> +    /*
>> +     * I3C devices may have retained their dynamic address anyway. Do not
>> +     * fail the resume because of DAA error.
>> +     */
>> +    return 0;
>> +}
>> +
>> +static int i3c_hci_resume(struct device *dev)
>> +{
>> +    return i3c_hci_resume_common(dev, false);
>> +}
>> +
>> +static int i3c_hci_restore(struct device *dev)
>> +{
>> +    return i3c_hci_resume_common(dev, true);
>> +}
>> +
>> #define DEFAULT_AUTOSUSPEND_DELAY_MS 1000
>>
>> static void i3c_hci_rpm_enable(struct device *dev)
>> @@ -945,6 +992,12 @@ static const struct platform_device_id i3c_hci_driver_ids[] = {
>> MODULE_DEVICE_TABLE(platform, i3c_hci_driver_ids);
>>
>> static const struct dev_pm_ops i3c_hci_pm_ops = {
>> +    .suspend  = pm_sleep_ptr(i3c_hci_suspend),
>> +    .resume   = pm_sleep_ptr(i3c_hci_resume),
>> +    .freeze   = pm_sleep_ptr(i3c_hci_suspend),
>> +    .thaw     = pm_sleep_ptr(i3c_hci_resume),
>> +    .poweroff = pm_sleep_ptr(i3c_hci_suspend),
>> +    .restore  = pm_sleep_ptr(i3c_hci_restore),
>>     RUNTIME_PM_OPS(i3c_hci_runtime_suspend, i3c_hci_runtime_resume, NULL)
>> };
>>
>> -- 
>> 2.51.0
>>
>>
>> -- 
>> linux-i3c mailing list
>> linux-i3c at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-i3c
>>




More information about the linux-i3c mailing list