* [PATCH v7 0/4] firmware: ti_sci: Introduce BOARDCFG_MANAGED mode for Jacinto family
@ 2026-05-06 8:35 Thomas Richard (TI)
2026-05-06 8:35 ` [PATCH v7 1/4] firmware: ti_sci: add BOARDCFG_MANAGED mode support Thomas Richard (TI)
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Thomas Richard (TI) @ 2026-05-06 8:35 UTC (permalink / raw)
To: Nishanth Menon, Tero Kristo, Santosh Shilimkar, Michael Turquette,
Stephen Boyd
Cc: Gregory CLEMENT, richard.genoud, Udit Kumar, Abhash Kumar,
Thomas Petazzoni, linux-arm-kernel, linux-kernel, linux-clk,
Thomas Richard (TI), Dhruva Gole, Kendall Willis, Brian Masney
This is the 7th iteration of this series. I did some changes as suggested
by Nishanth. In ti_sci driver I added a lock around set_irq() and
free_irq() to keep hash list consistent in case of concurrent accesses, and
now ti_sci driver tries to restore all IRQs even in case of error.
On the clock side, get_parent() errors are now handled. If we fail to get
parent_id for a clock, set_parent() is not called anymore in
restore_context().
Other minor changes are listed in the changelog.
Best Regards,
Thomas
Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
---
Changes in v7:
- ti_sci: add a lock around set_irq() and free_irq() to keep hash list
consistent.
- ti_sci: in free_irq() add warning in case we are in a path that shall not
be run.
- ti_sci: free an IRQ if we failed to add it in the hash list.
- ti_sci: during resume in case of error, try to restore remaining IRQs and
logs all errors, then return the latest one.
- sci-clk: add Stephen's AB tag and Brian's RB tag.
- sci-clk: handle get_parent() error, in restore_context() do not call
set_parent() with parent_id=0 if get_parent() failed.
- Link to v6: https://lore.kernel.org/r/20260427-ti-sci-jacinto-s2r-restore-irq-v6-0-72c6468cb2ab@bootlin.com
Changes in v6:
- rebase on v7.1-rc1.
- add Kendall's RB tag.
- sci-clk: call set_parent() during restore_context() only for clocks which
have more than one parent.
- sci-clk: save also rate returned by recalc_rate().
- Link to v5: https://lore.kernel.org/r/20260407-ti-sci-jacinto-s2r-restore-irq-v5-0-97b28f2d93f9@bootlin.com
Changes in v5:
- rebase on v7.0-rc7.
- add Dhruva's RB tag.
- use kzalloc_obj() in ti_sci driver.
- Link to v4: https://lore.kernel.org/r/20260204-ti-sci-jacinto-s2r-restore-irq-v4-0-67820af39eac@bootlin.com
Changes in v4:
- rebase on linux-next next-20260202.
- fix BOARDCFG_MANAGED value.
- add MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST firmware capability.
- add MSG_FLAG_CAPS_LPM_CLK_CONTEXT_LOST firmware capability.
- Link to v3: https://lore.kernel.org/r/20251205-ti-sci-jacinto-s2r-restore-irq-v3-0-d06963974ad4@bootlin.com
Changes in v3:
- rebased on linux-next
- sci-clk: context_restore() operation restores also rate.
- Link to v2: https://lore.kernel.org/r/20251127-ti-sci-jacinto-s2r-restore-irq-v2-0-a487fa3ff221@bootlin.com
Changes in v2:
- ti_sci: use hlist to store IRQs.
- sci-clk: add context_restore operation
- ti_sci: restore clock parents during resume
- Link to v1: https://lore.kernel.org/r/20251017-ti-sci-jacinto-s2r-restore-irq-v1-0-34d4339d247a@bootlin.com
---
Thomas Richard (TI) (4):
firmware: ti_sci: add BOARDCFG_MANAGED mode support
firmware: ti_sci: add support for restoring IRQs during resume
clk: keystone: sci-clk: add restore_context() operation
firmware: ti_sci: add support for restoring clock context during resume
drivers/clk/keystone/sci-clk.c | 45 +++++++--
drivers/firmware/ti_sci.c | 212 ++++++++++++++++++++++++++++++++++++++---
drivers/firmware/ti_sci.h | 6 ++
3 files changed, 242 insertions(+), 21 deletions(-)
---
base-commit: a8afe52b5e5050c0c5825d7931a21b687a628d9a
change-id: 20251010-ti-sci-jacinto-s2r-restore-irq-428e008fd10c
Best regards,
--
Thomas Richard (TI) <thomas.richard@bootlin.com>
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v7 1/4] firmware: ti_sci: add BOARDCFG_MANAGED mode support 2026-05-06 8:35 [PATCH v7 0/4] firmware: ti_sci: Introduce BOARDCFG_MANAGED mode for Jacinto family Thomas Richard (TI) @ 2026-05-06 8:35 ` Thomas Richard (TI) 2026-05-06 14:06 ` Nishanth Menon 2026-05-06 8:35 ` [PATCH v7 2/4] firmware: ti_sci: add support for restoring IRQs during resume Thomas Richard (TI) ` (2 subsequent siblings) 3 siblings, 1 reply; 8+ messages in thread From: Thomas Richard (TI) @ 2026-05-06 8:35 UTC (permalink / raw) To: Nishanth Menon, Tero Kristo, Santosh Shilimkar, Michael Turquette, Stephen Boyd Cc: Gregory CLEMENT, richard.genoud, Udit Kumar, Abhash Kumar, Thomas Petazzoni, linux-arm-kernel, linux-kernel, linux-clk, Thomas Richard (TI), Dhruva Gole, Kendall Willis In BOARDCFG_MANAGED mode, the low power mode configuration is done statically for the DM via the boardcfg. Constraints are not supported, and prepare_sleep() is not needed. Reviewed-by: Dhruva Gole <d-gole@ti.com> Reviewed-by: Kendall Willis <k-willis@ti.com> Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com> --- drivers/firmware/ti_sci.c | 10 +++++++--- drivers/firmware/ti_sci.h | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index dd9911b1cc11..eaeaaae94142 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -3772,8 +3772,11 @@ static int ti_sci_prepare_system_suspend(struct ti_sci_info *info) return ti_sci_cmd_prepare_sleep(&info->handle, TISCI_MSG_VALUE_SLEEP_MODE_DM_MANAGED, 0, 0, 0); + } else if (info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED) { + /* Nothing to do in the BOARDCFG_MANAGED mode */ + return 0; } else { - /* DM Managed is not supported by the firmware. */ + /* DM Managed and BoardCfg Managed are not supported by the firmware. */ dev_err(info->dev, "Suspend to memory is not supported by the firmware\n"); return -EOPNOTSUPP; } @@ -4011,12 +4014,13 @@ static int ti_sci_probe(struct platform_device *pdev) } ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps); - dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s\n", + dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s%s\n", info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT ? " LPM-Abort" : "", - info->fw_caps & MSG_FLAG_CAPS_IO_ISOLATION ? " IO-Isolation" : "" + info->fw_caps & MSG_FLAG_CAPS_IO_ISOLATION ? " IO-Isolation" : "", + info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED ? " BoardConfig-Managed" : "" ); ti_sci_setup_ops(info); diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 4616127e33ff..d90de59e29eb 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -150,6 +150,7 @@ struct ti_sci_msg_req_reboot { * MSG_FLAG_CAPS_LPM_DM_MANAGED: LPM can be managed by DM * MSG_FLAG_CAPS_LPM_ABORT: Abort entry to LPM * MSG_FLAG_CAPS_IO_ISOLATION: IO Isolation support + * MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED: LPM config done statically for the DM via boardcfg * * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS * providing currently available SOC/firmware capabilities. SoC that don't @@ -162,6 +163,7 @@ struct ti_sci_msg_resp_query_fw_caps { #define MSG_FLAG_CAPS_LPM_DM_MANAGED TI_SCI_MSG_FLAG(5) #define MSG_FLAG_CAPS_LPM_ABORT TI_SCI_MSG_FLAG(9) #define MSG_FLAG_CAPS_IO_ISOLATION TI_SCI_MSG_FLAG(7) +#define MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED TI_SCI_MSG_FLAG(12) #define MSG_MASK_CAPS_LPM GENMASK_ULL(4, 1) u64 fw_caps; } __packed; -- 2.53.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v7 1/4] firmware: ti_sci: add BOARDCFG_MANAGED mode support 2026-05-06 8:35 ` [PATCH v7 1/4] firmware: ti_sci: add BOARDCFG_MANAGED mode support Thomas Richard (TI) @ 2026-05-06 14:06 ` Nishanth Menon 0 siblings, 0 replies; 8+ messages in thread From: Nishanth Menon @ 2026-05-06 14:06 UTC (permalink / raw) To: Thomas Richard (TI) Cc: Tero Kristo, Santosh Shilimkar, Michael Turquette, Stephen Boyd, Gregory CLEMENT, richard.genoud, Udit Kumar, Abhash Kumar, Thomas Petazzoni, linux-arm-kernel, linux-kernel, linux-clk, Dhruva Gole, Kendall Willis On 10:35-20260506, Thomas Richard (TI) wrote: > In BOARDCFG_MANAGED mode, the low power mode configuration is done > statically for the DM via the boardcfg. Constraints are not supported, and > prepare_sleep() is not needed. > minor nit: [..] > diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h > index 4616127e33ff..d90de59e29eb 100644 > --- a/drivers/firmware/ti_sci.h > +++ b/drivers/firmware/ti_sci.h > @@ -150,6 +150,7 @@ struct ti_sci_msg_req_reboot { > * MSG_FLAG_CAPS_LPM_DM_MANAGED: LPM can be managed by DM > * MSG_FLAG_CAPS_LPM_ABORT: Abort entry to LPM > * MSG_FLAG_CAPS_IO_ISOLATION: IO Isolation support > + * MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED: LPM config done statically for the DM via boardcfg will be good to keep this under 100 chars > * > * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS > * providing currently available SOC/firmware capabilities. SoC that don't > @@ -162,6 +163,7 @@ struct ti_sci_msg_resp_query_fw_caps { > #define MSG_FLAG_CAPS_LPM_DM_MANAGED TI_SCI_MSG_FLAG(5) > #define MSG_FLAG_CAPS_LPM_ABORT TI_SCI_MSG_FLAG(9) > #define MSG_FLAG_CAPS_IO_ISOLATION TI_SCI_MSG_FLAG(7) > +#define MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED TI_SCI_MSG_FLAG(12) > #define MSG_MASK_CAPS_LPM GENMASK_ULL(4, 1) > u64 fw_caps; > } __packed; > > -- > 2.53.0 > -- Regards, Nishanth Menon Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3 1A34 DDB5 849D 1736 249D https://ti.com/opensource ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v7 2/4] firmware: ti_sci: add support for restoring IRQs during resume 2026-05-06 8:35 [PATCH v7 0/4] firmware: ti_sci: Introduce BOARDCFG_MANAGED mode for Jacinto family Thomas Richard (TI) 2026-05-06 8:35 ` [PATCH v7 1/4] firmware: ti_sci: add BOARDCFG_MANAGED mode support Thomas Richard (TI) @ 2026-05-06 8:35 ` Thomas Richard (TI) 2026-05-06 14:15 ` Nishanth Menon 2026-05-06 8:35 ` [PATCH v7 3/4] clk: keystone: sci-clk: add restore_context() operation Thomas Richard (TI) 2026-05-06 8:35 ` [PATCH v7 4/4] firmware: ti_sci: add support for restoring clock context during resume Thomas Richard (TI) 3 siblings, 1 reply; 8+ messages in thread From: Thomas Richard (TI) @ 2026-05-06 8:35 UTC (permalink / raw) To: Nishanth Menon, Tero Kristo, Santosh Shilimkar, Michael Turquette, Stephen Boyd Cc: Gregory CLEMENT, richard.genoud, Udit Kumar, Abhash Kumar, Thomas Petazzoni, linux-arm-kernel, linux-kernel, linux-clk, Thomas Richard (TI), Dhruva Gole, Kendall Willis Some DM-Firmware are not able to restore the IRQ context after a suspend-resume. The IRQ_CONTEXT_LOST firmware capability has been introduced to identify this characteristic. In this case the responsibility is delegated to the ti_sci driver, which maintains an internal list of all requested IRQs. This list is updated on each set()/free() operation, and all IRQs are restored during the resume_noirq() phase. Reviewed-by: Dhruva Gole <d-gole@ti.com> Reviewed-by: Kendall Willis <k-willis@ti.com> Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com> --- drivers/firmware/ti_sci.c | 201 +++++++++++++++++++++++++++++++++++++++++++--- drivers/firmware/ti_sci.h | 2 + 2 files changed, 191 insertions(+), 12 deletions(-) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index eaeaaae94142..531ac3aa38b8 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -12,11 +12,13 @@ #include <linux/cpu.h> #include <linux/debugfs.h> #include <linux/export.h> +#include <linux/hashtable.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/mailbox_client.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/of.h> #include <linux/of_platform.h> #include <linux/platform_device.h> @@ -87,6 +89,16 @@ struct ti_sci_desc { int max_msg_size; }; +/** + * struct ti_sci_irq - Description of allocated irqs + * @node: Link to hash table + * @desc: Description of the irq + */ +struct ti_sci_irq { + struct hlist_node node; + struct ti_sci_msg_req_manage_irq desc; +}; + /** * struct ti_sci_info - Structure representing a TI SCI instance * @dev: Device pointer @@ -101,6 +113,8 @@ struct ti_sci_desc { * @chan_rx: Receive mailbox channel * @minfo: Message info * @node: list head + * @irqs: List of allocated irqs + * @irq_lock: Protection for irq hash list * @host_id: Host ID * @fw_caps: FW/SoC low power capabilities * @users: Number of users of this instance @@ -118,6 +132,8 @@ struct ti_sci_info { struct mbox_chan *chan_rx; struct ti_sci_xfers_info minfo; struct list_head node; + DECLARE_HASHTABLE(irqs, 8); + struct mutex irq_lock; u8 host_id; u64 fw_caps; /* protected by ti_sci_list_mutex */ @@ -2301,6 +2317,32 @@ static int ti_sci_manage_irq(const struct ti_sci_handle *handle, return ret; } +/** + * ti_sci_irq_hash() - Helper API to compute irq hash for the hash table. + * @irq: irq to hash + * + * Return: the computed hash value. + */ +static int ti_sci_irq_hash(struct ti_sci_msg_req_manage_irq *irq) +{ + return irq->src_id ^ irq->src_index; +} + +/** + * ti_sci_irq_equal() - Helper API to compare two irqs (generic headers are not + * compared) + * @irq_a: irq_a to compare + * @irq_b: irq_b to compare + * + * Return: true if the two irqs are equal, else false. + */ +static bool ti_sci_irq_equal(struct ti_sci_msg_req_manage_irq *irq_a, + struct ti_sci_msg_req_manage_irq *irq_b) +{ + return !memcmp(&irq_a->valid_params, &irq_b->valid_params, + sizeof(*irq_a) - sizeof(irq_a->hdr)); +} + /** * ti_sci_set_irq() - Helper api to configure the irq route between the * requested source and destination @@ -2324,15 +2366,60 @@ static int ti_sci_set_irq(const struct ti_sci_handle *handle, u32 valid_params, u16 dst_host_irq, u16 ia_id, u16 vint, u16 global_event, u8 vint_status_bit, u8 s_host) { + struct ti_sci_info *info = handle_to_ti_sci_info(handle); + struct ti_sci_msg_req_manage_irq *desc; + struct ti_sci_irq *irq; + int ret; + + /* + * Lock for set_irq() and free_irq() to keep the IRQ hash list + * consistent only if MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST is set. Else + * IRQ hash list is not used. + */ + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) + mutex_lock(&info->irq_lock); + pr_debug("%s: IRQ set with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", __func__, valid_params, src_id, src_index, dst_id, dst_host_irq, ia_id, vint, global_event, vint_status_bit); - return ti_sci_manage_irq(handle, valid_params, src_id, src_index, - dst_id, dst_host_irq, ia_id, vint, - global_event, vint_status_bit, s_host, - TI_SCI_MSG_SET_IRQ); + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index, + dst_id, dst_host_irq, ia_id, vint, + global_event, vint_status_bit, s_host, + TI_SCI_MSG_SET_IRQ); + + if (ret || !(info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST)) + goto end; + + irq = kzalloc_obj(*irq, GFP_KERNEL); + if (!irq) { + ti_sci_manage_irq(handle, valid_params, src_id, src_index, + dst_id, dst_host_irq, ia_id, vint, + global_event, vint_status_bit, s_host, + TI_SCI_MSG_FREE_IRQ); + ret = -ENOMEM; + goto end; + } + + desc = &irq->desc; + desc->valid_params = valid_params; + desc->src_id = src_id; + desc->src_index = src_index; + desc->dst_id = dst_id; + desc->dst_host_irq = dst_host_irq; + desc->ia_id = ia_id; + desc->vint = vint; + desc->global_event = global_event; + desc->vint_status_bit = vint_status_bit; + desc->secondary_host = s_host; + + hash_add(info->irqs, &irq->node, ti_sci_irq_hash(desc)); + +end: + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) + mutex_unlock(&info->irq_lock); + return ret; } /** @@ -2358,15 +2445,56 @@ static int ti_sci_free_irq(const struct ti_sci_handle *handle, u32 valid_params, u16 dst_host_irq, u16 ia_id, u16 vint, u16 global_event, u8 vint_status_bit, u8 s_host) { + struct ti_sci_info *info = handle_to_ti_sci_info(handle); + struct ti_sci_msg_req_manage_irq irq_desc; + struct device *dev = info->dev; + struct ti_sci_irq *this_irq; + struct hlist_node *tmp_node; + int ret; + + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) + mutex_lock(&info->irq_lock); + pr_debug("%s: IRQ release with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", __func__, valid_params, src_id, src_index, dst_id, dst_host_irq, ia_id, vint, global_event, vint_status_bit); - return ti_sci_manage_irq(handle, valid_params, src_id, src_index, - dst_id, dst_host_irq, ia_id, vint, - global_event, vint_status_bit, s_host, - TI_SCI_MSG_FREE_IRQ); + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index, + dst_id, dst_host_irq, ia_id, vint, + global_event, vint_status_bit, s_host, + TI_SCI_MSG_FREE_IRQ); + + if (ret || !(info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST)) + goto end; + + irq_desc.valid_params = valid_params; + irq_desc.src_id = src_id; + irq_desc.src_index = src_index; + irq_desc.dst_id = dst_id; + irq_desc.dst_host_irq = dst_host_irq; + irq_desc.ia_id = ia_id; + irq_desc.vint = vint; + irq_desc.global_event = global_event; + irq_desc.vint_status_bit = vint_status_bit; + irq_desc.secondary_host = s_host; + + hash_for_each_possible_safe(info->irqs, this_irq, tmp_node, node, + ti_sci_irq_hash(&irq_desc)) { + if (ti_sci_irq_equal(&irq_desc, &this_irq->desc)) { + hlist_del(&this_irq->node); + kfree(this_irq); + goto end; + } + } + + dev_warn(dev, "%s: should not be here, IRQ was not found in hash list\n", + __func__); + +end: + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) + mutex_unlock(&info->irq_lock); + return ret; } /** @@ -3847,7 +3975,10 @@ static int ti_sci_suspend_noirq(struct device *dev) static int ti_sci_resume_noirq(struct device *dev) { struct ti_sci_info *info = dev_get_drvdata(dev); - int ret = 0; + struct ti_sci_msg_req_manage_irq *irq_desc; + struct ti_sci_irq *irq; + struct hlist_node *tmp_node; + int ret = 0, err = 0, i; u32 source; u64 time; u8 pin; @@ -3859,13 +3990,50 @@ static int ti_sci_resume_noirq(struct device *dev) return ret; } + switch (pm_suspend_target_state) { + case PM_SUSPEND_MEM: + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) { + hash_for_each_safe(info->irqs, i, tmp_node, irq, node) { + irq_desc = &irq->desc; + ret = ti_sci_manage_irq(&info->handle, + irq_desc->valid_params, + irq_desc->src_id, + irq_desc->src_index, + irq_desc->dst_id, + irq_desc->dst_host_irq, + irq_desc->ia_id, + irq_desc->vint, + irq_desc->global_event, + irq_desc->vint_status_bit, + irq_desc->secondary_host, + TI_SCI_MSG_SET_IRQ); + if (ret) { + dev_err(dev, "failed to restore IRQ with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", + irq_desc->valid_params, + irq_desc->src_id, + irq_desc->src_index, + irq_desc->dst_id, + irq_desc->dst_host_irq, + irq_desc->ia_id, + irq_desc->vint, + irq_desc->global_event, + irq_desc->vint_status_bit); + err = ret; + } + } + } + break; + default: + break; + } + ret = ti_sci_msg_cmd_lpm_wake_reason(&info->handle, &source, &time, &pin, &mode); /* Do not fail to resume on error as the wake reason is not critical */ if (!ret) dev_info(dev, "ti_sci: wakeup source:0x%x, pin:0x%x, mode:0x%x\n", source, pin, mode); - return 0; + return err; } static void ti_sci_pm_complete(struct device *dev) @@ -4014,13 +4182,14 @@ static int ti_sci_probe(struct platform_device *pdev) } ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps); - dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s%s\n", + dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s%s%s\n", info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT ? " LPM-Abort" : "", info->fw_caps & MSG_FLAG_CAPS_IO_ISOLATION ? " IO-Isolation" : "", - info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED ? " BoardConfig-Managed" : "" + info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED ? " BoardConfig-Managed" : "", + info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST ? " IRQ-Context-Lost" : "" ); ti_sci_setup_ops(info); @@ -4053,6 +4222,14 @@ static int ti_sci_probe(struct platform_device *pdev) list_add_tail(&info->node, &ti_sci_list); mutex_unlock(&ti_sci_list_mutex); + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) { + ret = devm_mutex_init(dev, &info->irq_lock); + if (ret) + return ret; + + hash_init(info->irqs); + } + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); if (ret) { dev_err(dev, "platform_populate failed %pe\n", ERR_PTR(ret)); diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index d90de59e29eb..67f16e8c69a1 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -151,6 +151,7 @@ struct ti_sci_msg_req_reboot { * MSG_FLAG_CAPS_LPM_ABORT: Abort entry to LPM * MSG_FLAG_CAPS_IO_ISOLATION: IO Isolation support * MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED: LPM config done statically for the DM via boardcfg + * MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST: DM is not able to restore IRQ context * * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS * providing currently available SOC/firmware capabilities. SoC that don't @@ -164,6 +165,7 @@ struct ti_sci_msg_resp_query_fw_caps { #define MSG_FLAG_CAPS_LPM_ABORT TI_SCI_MSG_FLAG(9) #define MSG_FLAG_CAPS_IO_ISOLATION TI_SCI_MSG_FLAG(7) #define MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED TI_SCI_MSG_FLAG(12) +#define MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST TI_SCI_MSG_FLAG(14) #define MSG_MASK_CAPS_LPM GENMASK_ULL(4, 1) u64 fw_caps; } __packed; -- 2.53.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v7 2/4] firmware: ti_sci: add support for restoring IRQs during resume 2026-05-06 8:35 ` [PATCH v7 2/4] firmware: ti_sci: add support for restoring IRQs during resume Thomas Richard (TI) @ 2026-05-06 14:15 ` Nishanth Menon 2026-05-12 15:44 ` Thomas Richard 0 siblings, 1 reply; 8+ messages in thread From: Nishanth Menon @ 2026-05-06 14:15 UTC (permalink / raw) To: Thomas Richard (TI) Cc: Tero Kristo, Santosh Shilimkar, Michael Turquette, Stephen Boyd, Gregory CLEMENT, richard.genoud, Udit Kumar, Abhash Kumar, Thomas Petazzoni, linux-arm-kernel, linux-kernel, linux-clk, Dhruva Gole, Kendall Willis On 10:35-20260506, Thomas Richard (TI) wrote: > Some DM-Firmware are not able to restore the IRQ context after a > suspend-resume. The IRQ_CONTEXT_LOST firmware capability has been > introduced to identify this characteristic. In this case the > responsibility is delegated to the ti_sci driver, which maintains an > internal list of all requested IRQs. This list is updated on each > set()/free() operation, and all IRQs are restored during the resume_noirq() > phase. > > Reviewed-by: Dhruva Gole <d-gole@ti.com> > Reviewed-by: Kendall Willis <k-willis@ti.com> > Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com> > --- coccicheck reports two additional warnings at this patch: +drivers/firmware/ti_sci.c:2495:1-7: preceding lock on line 2454 +drivers/firmware/ti_sci.c:2420:1-7: preceding lock on line 2378 > drivers/firmware/ti_sci.c | 201 +++++++++++++++++++++++++++++++++++++++++++--- > drivers/firmware/ti_sci.h | 2 + > 2 files changed, 191 insertions(+), 12 deletions(-) > > diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c > index eaeaaae94142..531ac3aa38b8 100644 > --- a/drivers/firmware/ti_sci.c > +++ b/drivers/firmware/ti_sci.c > @@ -12,11 +12,13 @@ > #include <linux/cpu.h> > #include <linux/debugfs.h> > #include <linux/export.h> > +#include <linux/hashtable.h> > #include <linux/io.h> > #include <linux/iopoll.h> > #include <linux/kernel.h> > #include <linux/mailbox_client.h> > #include <linux/module.h> > +#include <linux/mutex.h> > #include <linux/of.h> > #include <linux/of_platform.h> > #include <linux/platform_device.h> > @@ -87,6 +89,16 @@ struct ti_sci_desc { > int max_msg_size; > }; > > +/** > + * struct ti_sci_irq - Description of allocated irqs > + * @node: Link to hash table > + * @desc: Description of the irq > + */ > +struct ti_sci_irq { > + struct hlist_node node; > + struct ti_sci_msg_req_manage_irq desc; > +}; > + > /** > * struct ti_sci_info - Structure representing a TI SCI instance > * @dev: Device pointer > @@ -101,6 +113,8 @@ struct ti_sci_desc { > * @chan_rx: Receive mailbox channel > * @minfo: Message info > * @node: list head > + * @irqs: List of allocated irqs > + * @irq_lock: Protection for irq hash list > * @host_id: Host ID > * @fw_caps: FW/SoC low power capabilities > * @users: Number of users of this instance > @@ -118,6 +132,8 @@ struct ti_sci_info { > struct mbox_chan *chan_rx; > struct ti_sci_xfers_info minfo; > struct list_head node; > + DECLARE_HASHTABLE(irqs, 8); > + struct mutex irq_lock; No action needed: checkpatch flags this as not documented, when it is clearly documented above. > u8 host_id; > u64 fw_caps; > /* protected by ti_sci_list_mutex */ > @@ -2301,6 +2317,32 @@ static int ti_sci_manage_irq(const struct ti_sci_handle *handle, > return ret; > } > > +/** > + * ti_sci_irq_hash() - Helper API to compute irq hash for the hash table. > + * @irq: irq to hash > + * > + * Return: the computed hash value. > + */ > +static int ti_sci_irq_hash(struct ti_sci_msg_req_manage_irq *irq) > +{ > + return irq->src_id ^ irq->src_index; > +} > + > +/** > + * ti_sci_irq_equal() - Helper API to compare two irqs (generic headers are not > + * compared) > + * @irq_a: irq_a to compare > + * @irq_b: irq_b to compare > + * > + * Return: true if the two irqs are equal, else false. > + */ > +static bool ti_sci_irq_equal(struct ti_sci_msg_req_manage_irq *irq_a, > + struct ti_sci_msg_req_manage_irq *irq_b) > +{ > + return !memcmp(&irq_a->valid_params, &irq_b->valid_params, > + sizeof(*irq_a) - sizeof(irq_a->hdr)); > +} > + > /** > * ti_sci_set_irq() - Helper api to configure the irq route between the > * requested source and destination > @@ -2324,15 +2366,60 @@ static int ti_sci_set_irq(const struct ti_sci_handle *handle, u32 valid_params, > u16 dst_host_irq, u16 ia_id, u16 vint, > u16 global_event, u8 vint_status_bit, u8 s_host) > { > + struct ti_sci_info *info = handle_to_ti_sci_info(handle); > + struct ti_sci_msg_req_manage_irq *desc; > + struct ti_sci_irq *irq; > + int ret; > + > + /* > + * Lock for set_irq() and free_irq() to keep the IRQ hash list > + * consistent only if MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST is set. Else > + * IRQ hash list is not used. > + */ > + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) > + mutex_lock(&info->irq_lock); > + > pr_debug("%s: IRQ set with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", > __func__, valid_params, src_id, src_index, > dst_id, dst_host_irq, ia_id, vint, global_event, > vint_status_bit); > > - return ti_sci_manage_irq(handle, valid_params, src_id, src_index, > - dst_id, dst_host_irq, ia_id, vint, > - global_event, vint_status_bit, s_host, > - TI_SCI_MSG_SET_IRQ); > + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index, > + dst_id, dst_host_irq, ia_id, vint, > + global_event, vint_status_bit, s_host, > + TI_SCI_MSG_SET_IRQ); > + > + if (ret || !(info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST)) > + goto end; > + > + irq = kzalloc_obj(*irq, GFP_KERNEL); > + if (!irq) { > + ti_sci_manage_irq(handle, valid_params, src_id, src_index, > + dst_id, dst_host_irq, ia_id, vint, > + global_event, vint_status_bit, s_host, > + TI_SCI_MSG_FREE_IRQ); > + ret = -ENOMEM; > + goto end; > + } > + > + desc = &irq->desc; > + desc->valid_params = valid_params; > + desc->src_id = src_id; > + desc->src_index = src_index; > + desc->dst_id = dst_id; > + desc->dst_host_irq = dst_host_irq; > + desc->ia_id = ia_id; > + desc->vint = vint; > + desc->global_event = global_event; > + desc->vint_status_bit = vint_status_bit; > + desc->secondary_host = s_host; > + > + hash_add(info->irqs, &irq->node, ti_sci_irq_hash(desc)); > + > +end: > + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) > + mutex_unlock(&info->irq_lock); > + return ret; > } > > /** > @@ -2358,15 +2445,56 @@ static int ti_sci_free_irq(const struct ti_sci_handle *handle, u32 valid_params, > u16 dst_host_irq, u16 ia_id, u16 vint, > u16 global_event, u8 vint_status_bit, u8 s_host) > { > + struct ti_sci_info *info = handle_to_ti_sci_info(handle); > + struct ti_sci_msg_req_manage_irq irq_desc; > + struct device *dev = info->dev; > + struct ti_sci_irq *this_irq; > + struct hlist_node *tmp_node; > + int ret; > + > + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) > + mutex_lock(&info->irq_lock); > + > pr_debug("%s: IRQ release with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", > __func__, valid_params, src_id, src_index, > dst_id, dst_host_irq, ia_id, vint, global_event, > vint_status_bit); > > - return ti_sci_manage_irq(handle, valid_params, src_id, src_index, > - dst_id, dst_host_irq, ia_id, vint, > - global_event, vint_status_bit, s_host, > - TI_SCI_MSG_FREE_IRQ); > + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index, > + dst_id, dst_host_irq, ia_id, vint, > + global_event, vint_status_bit, s_host, > + TI_SCI_MSG_FREE_IRQ); > + > + if (ret || !(info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST)) > + goto end; > + > + irq_desc.valid_params = valid_params; > + irq_desc.src_id = src_id; > + irq_desc.src_index = src_index; > + irq_desc.dst_id = dst_id; > + irq_desc.dst_host_irq = dst_host_irq; > + irq_desc.ia_id = ia_id; > + irq_desc.vint = vint; > + irq_desc.global_event = global_event; > + irq_desc.vint_status_bit = vint_status_bit; > + irq_desc.secondary_host = s_host; > + > + hash_for_each_possible_safe(info->irqs, this_irq, tmp_node, node, > + ti_sci_irq_hash(&irq_desc)) { > + if (ti_sci_irq_equal(&irq_desc, &this_irq->desc)) { > + hlist_del(&this_irq->node); > + kfree(this_irq); > + goto end; > + } > + } > + > + dev_warn(dev, "%s: should not be here, IRQ was not found in hash list\n", > + __func__); > + > +end: > + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) > + mutex_unlock(&info->irq_lock); > + return ret; > } > > /** > @@ -3847,7 +3975,10 @@ static int ti_sci_suspend_noirq(struct device *dev) > static int ti_sci_resume_noirq(struct device *dev) > { > struct ti_sci_info *info = dev_get_drvdata(dev); > - int ret = 0; > + struct ti_sci_msg_req_manage_irq *irq_desc; > + struct ti_sci_irq *irq; > + struct hlist_node *tmp_node; > + int ret = 0, err = 0, i; > u32 source; > u64 time; > u8 pin; > @@ -3859,13 +3990,50 @@ static int ti_sci_resume_noirq(struct device *dev) > return ret; > } > > + switch (pm_suspend_target_state) { > + case PM_SUSPEND_MEM: > + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) { > + hash_for_each_safe(info->irqs, i, tmp_node, irq, node) { > + irq_desc = &irq->desc; > + ret = ti_sci_manage_irq(&info->handle, > + irq_desc->valid_params, > + irq_desc->src_id, > + irq_desc->src_index, > + irq_desc->dst_id, > + irq_desc->dst_host_irq, > + irq_desc->ia_id, > + irq_desc->vint, > + irq_desc->global_event, > + irq_desc->vint_status_bit, > + irq_desc->secondary_host, > + TI_SCI_MSG_SET_IRQ); > + if (ret) { > + dev_err(dev, "failed to restore IRQ with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", space before via? overall this print is needed, but a bit umm.. we have similar ones already.. > + irq_desc->valid_params, > + irq_desc->src_id, > + irq_desc->src_index, > + irq_desc->dst_id, > + irq_desc->dst_host_irq, > + irq_desc->ia_id, > + irq_desc->vint, > + irq_desc->global_event, > + irq_desc->vint_status_bit); > + err = ret; > + } > + } > + } > + break; > + default: > + break; > + } > + > ret = ti_sci_msg_cmd_lpm_wake_reason(&info->handle, &source, &time, &pin, &mode); > /* Do not fail to resume on error as the wake reason is not critical */ > if (!ret) > dev_info(dev, "ti_sci: wakeup source:0x%x, pin:0x%x, mode:0x%x\n", > source, pin, mode); > > - return 0; > + return err; > } > > static void ti_sci_pm_complete(struct device *dev) > @@ -4014,13 +4182,14 @@ static int ti_sci_probe(struct platform_device *pdev) > } > > ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps); > - dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s%s\n", > + dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s%s%s\n", > info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "", > info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "", > info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "", > info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT ? " LPM-Abort" : "", > info->fw_caps & MSG_FLAG_CAPS_IO_ISOLATION ? " IO-Isolation" : "", > - info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED ? " BoardConfig-Managed" : "" > + info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED ? " BoardConfig-Managed" : "", > + info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST ? " IRQ-Context-Lost" : "" > ); > > ti_sci_setup_ops(info); > @@ -4053,6 +4222,14 @@ static int ti_sci_probe(struct platform_device *pdev) > list_add_tail(&info->node, &ti_sci_list); > mutex_unlock(&ti_sci_list_mutex); > > + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) { > + ret = devm_mutex_init(dev, &info->irq_lock); > + if (ret) > + return ret; If devm_mutex_init() fails, the function returns directly rather than going through the out: label. All other error paths after the mailbox channel allocations use goto out, which calls mbox_free_channel() for both channels. Since mbox_request_channel_byname() is not a devm allocation, those channels would not be freed by the devm cleanup path on probe failure. Does this leak info->chan_tx and info->chan_rx when devm_mutex_init() returns an error? > + > + hash_init(info->irqs); > + } > + > ret = of_platform_populate(dev->of_node, NULL, NULL, dev); > if (ret) { > dev_err(dev, "platform_populate failed %pe\n", ERR_PTR(ret)); > diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h > index d90de59e29eb..67f16e8c69a1 100644 > --- a/drivers/firmware/ti_sci.h > +++ b/drivers/firmware/ti_sci.h > @@ -151,6 +151,7 @@ struct ti_sci_msg_req_reboot { > * MSG_FLAG_CAPS_LPM_ABORT: Abort entry to LPM > * MSG_FLAG_CAPS_IO_ISOLATION: IO Isolation support > * MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED: LPM config done statically for the DM via boardcfg > + * MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST: DM is not able to restore IRQ context > * > * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS > * providing currently available SOC/firmware capabilities. SoC that don't > @@ -164,6 +165,7 @@ struct ti_sci_msg_resp_query_fw_caps { > #define MSG_FLAG_CAPS_LPM_ABORT TI_SCI_MSG_FLAG(9) > #define MSG_FLAG_CAPS_IO_ISOLATION TI_SCI_MSG_FLAG(7) > #define MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED TI_SCI_MSG_FLAG(12) > +#define MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST TI_SCI_MSG_FLAG(14) > #define MSG_MASK_CAPS_LPM GENMASK_ULL(4, 1) > u64 fw_caps; > } __packed; > > -- > 2.53.0 > -- Regards, Nishanth Menon Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3 1A34 DDB5 849D 1736 249D https://ti.com/opensource ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v7 2/4] firmware: ti_sci: add support for restoring IRQs during resume 2026-05-06 14:15 ` Nishanth Menon @ 2026-05-12 15:44 ` Thomas Richard 0 siblings, 0 replies; 8+ messages in thread From: Thomas Richard @ 2026-05-12 15:44 UTC (permalink / raw) To: Nishanth Menon Cc: Tero Kristo, Santosh Shilimkar, Michael Turquette, Stephen Boyd, Gregory CLEMENT, richard.genoud, Udit Kumar, Abhash Kumar, Thomas Petazzoni, linux-arm-kernel, linux-kernel, linux-clk, Dhruva Gole, Kendall Willis Hello Nishanth, On 5/6/26 4:15 PM, Nishanth Menon wrote: > On 10:35-20260506, Thomas Richard (TI) wrote: >> Some DM-Firmware are not able to restore the IRQ context after a >> suspend-resume. The IRQ_CONTEXT_LOST firmware capability has been >> introduced to identify this characteristic. In this case the >> responsibility is delegated to the ti_sci driver, which maintains an >> internal list of all requested IRQs. This list is updated on each >> set()/free() operation, and all IRQs are restored during the resume_noirq() >> phase. >> >> Reviewed-by: Dhruva Gole <d-gole@ti.com> >> Reviewed-by: Kendall Willis <k-willis@ti.com> >> Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com> >> --- > > coccicheck reports two additional warnings at this patch: > +drivers/firmware/ti_sci.c:2495:1-7: preceding lock on line 2454 > +drivers/firmware/ti_sci.c:2420:1-7: preceding lock on line 2378 I do not see the potential deadlock in set_irq() and free_irq(). I guess it is a false positive. > >> drivers/firmware/ti_sci.c | 201 +++++++++++++++++++++++++++++++++++++++++++--- >> drivers/firmware/ti_sci.h | 2 + >> 2 files changed, 191 insertions(+), 12 deletions(-) >> >> diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c >> index eaeaaae94142..531ac3aa38b8 100644 >> --- a/drivers/firmware/ti_sci.c >> +++ b/drivers/firmware/ti_sci.c >> @@ -12,11 +12,13 @@ >> #include <linux/cpu.h> >> #include <linux/debugfs.h> >> #include <linux/export.h> >> +#include <linux/hashtable.h> >> #include <linux/io.h> >> #include <linux/iopoll.h> >> #include <linux/kernel.h> >> #include <linux/mailbox_client.h> >> #include <linux/module.h> >> +#include <linux/mutex.h> >> #include <linux/of.h> >> #include <linux/of_platform.h> >> #include <linux/platform_device.h> >> @@ -87,6 +89,16 @@ struct ti_sci_desc { >> int max_msg_size; >> }; >> >> +/** >> + * struct ti_sci_irq - Description of allocated irqs >> + * @node: Link to hash table >> + * @desc: Description of the irq >> + */ >> +struct ti_sci_irq { >> + struct hlist_node node; >> + struct ti_sci_msg_req_manage_irq desc; >> +}; >> + >> /** >> * struct ti_sci_info - Structure representing a TI SCI instance >> * @dev: Device pointer >> @@ -101,6 +113,8 @@ struct ti_sci_desc { >> * @chan_rx: Receive mailbox channel >> * @minfo: Message info >> * @node: list head >> + * @irqs: List of allocated irqs >> + * @irq_lock: Protection for irq hash list >> * @host_id: Host ID >> * @fw_caps: FW/SoC low power capabilities >> * @users: Number of users of this instance >> @@ -118,6 +132,8 @@ struct ti_sci_info { >> struct mbox_chan *chan_rx; >> struct ti_sci_xfers_info minfo; >> struct list_head node; >> + DECLARE_HASHTABLE(irqs, 8); >> + struct mutex irq_lock; > > No action needed: checkpatch flags this as not documented, when it is > clearly documented above. > >> u8 host_id; >> u64 fw_caps; >> /* protected by ti_sci_list_mutex */ >> @@ -2301,6 +2317,32 @@ static int ti_sci_manage_irq(const struct ti_sci_handle *handle, >> return ret; >> } >> >> +/** >> + * ti_sci_irq_hash() - Helper API to compute irq hash for the hash table. >> + * @irq: irq to hash >> + * >> + * Return: the computed hash value. >> + */ >> +static int ti_sci_irq_hash(struct ti_sci_msg_req_manage_irq *irq) >> +{ >> + return irq->src_id ^ irq->src_index; >> +} >> + >> +/** >> + * ti_sci_irq_equal() - Helper API to compare two irqs (generic headers are not >> + * compared) >> + * @irq_a: irq_a to compare >> + * @irq_b: irq_b to compare >> + * >> + * Return: true if the two irqs are equal, else false. >> + */ >> +static bool ti_sci_irq_equal(struct ti_sci_msg_req_manage_irq *irq_a, >> + struct ti_sci_msg_req_manage_irq *irq_b) >> +{ >> + return !memcmp(&irq_a->valid_params, &irq_b->valid_params, >> + sizeof(*irq_a) - sizeof(irq_a->hdr)); >> +} >> + >> /** >> * ti_sci_set_irq() - Helper api to configure the irq route between the >> * requested source and destination >> @@ -2324,15 +2366,60 @@ static int ti_sci_set_irq(const struct ti_sci_handle *handle, u32 valid_params, >> u16 dst_host_irq, u16 ia_id, u16 vint, >> u16 global_event, u8 vint_status_bit, u8 s_host) >> { >> + struct ti_sci_info *info = handle_to_ti_sci_info(handle); >> + struct ti_sci_msg_req_manage_irq *desc; >> + struct ti_sci_irq *irq; >> + int ret; >> + >> + /* >> + * Lock for set_irq() and free_irq() to keep the IRQ hash list >> + * consistent only if MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST is set. Else >> + * IRQ hash list is not used. >> + */ >> + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) >> + mutex_lock(&info->irq_lock); >> + >> pr_debug("%s: IRQ set with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", >> __func__, valid_params, src_id, src_index, >> dst_id, dst_host_irq, ia_id, vint, global_event, >> vint_status_bit); >> >> - return ti_sci_manage_irq(handle, valid_params, src_id, src_index, >> - dst_id, dst_host_irq, ia_id, vint, >> - global_event, vint_status_bit, s_host, >> - TI_SCI_MSG_SET_IRQ); >> + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index, >> + dst_id, dst_host_irq, ia_id, vint, >> + global_event, vint_status_bit, s_host, >> + TI_SCI_MSG_SET_IRQ); >> + >> + if (ret || !(info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST)) >> + goto end; >> + >> + irq = kzalloc_obj(*irq, GFP_KERNEL); >> + if (!irq) { >> + ti_sci_manage_irq(handle, valid_params, src_id, src_index, >> + dst_id, dst_host_irq, ia_id, vint, >> + global_event, vint_status_bit, s_host, >> + TI_SCI_MSG_FREE_IRQ); >> + ret = -ENOMEM; >> + goto end; >> + } >> + >> + desc = &irq->desc; >> + desc->valid_params = valid_params; >> + desc->src_id = src_id; >> + desc->src_index = src_index; >> + desc->dst_id = dst_id; >> + desc->dst_host_irq = dst_host_irq; >> + desc->ia_id = ia_id; >> + desc->vint = vint; >> + desc->global_event = global_event; >> + desc->vint_status_bit = vint_status_bit; >> + desc->secondary_host = s_host; >> + >> + hash_add(info->irqs, &irq->node, ti_sci_irq_hash(desc)); >> + >> +end: >> + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) >> + mutex_unlock(&info->irq_lock); >> + return ret; >> } >> >> /** >> @@ -2358,15 +2445,56 @@ static int ti_sci_free_irq(const struct ti_sci_handle *handle, u32 valid_params, >> u16 dst_host_irq, u16 ia_id, u16 vint, >> u16 global_event, u8 vint_status_bit, u8 s_host) >> { >> + struct ti_sci_info *info = handle_to_ti_sci_info(handle); >> + struct ti_sci_msg_req_manage_irq irq_desc; >> + struct device *dev = info->dev; >> + struct ti_sci_irq *this_irq; >> + struct hlist_node *tmp_node; >> + int ret; >> + >> + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) >> + mutex_lock(&info->irq_lock); >> + >> pr_debug("%s: IRQ release with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", >> __func__, valid_params, src_id, src_index, >> dst_id, dst_host_irq, ia_id, vint, global_event, >> vint_status_bit); >> >> - return ti_sci_manage_irq(handle, valid_params, src_id, src_index, >> - dst_id, dst_host_irq, ia_id, vint, >> - global_event, vint_status_bit, s_host, >> - TI_SCI_MSG_FREE_IRQ); >> + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index, >> + dst_id, dst_host_irq, ia_id, vint, >> + global_event, vint_status_bit, s_host, >> + TI_SCI_MSG_FREE_IRQ); >> + >> + if (ret || !(info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST)) >> + goto end; >> + >> + irq_desc.valid_params = valid_params; >> + irq_desc.src_id = src_id; >> + irq_desc.src_index = src_index; >> + irq_desc.dst_id = dst_id; >> + irq_desc.dst_host_irq = dst_host_irq; >> + irq_desc.ia_id = ia_id; >> + irq_desc.vint = vint; >> + irq_desc.global_event = global_event; >> + irq_desc.vint_status_bit = vint_status_bit; >> + irq_desc.secondary_host = s_host; >> + >> + hash_for_each_possible_safe(info->irqs, this_irq, tmp_node, node, >> + ti_sci_irq_hash(&irq_desc)) { >> + if (ti_sci_irq_equal(&irq_desc, &this_irq->desc)) { >> + hlist_del(&this_irq->node); >> + kfree(this_irq); >> + goto end; >> + } >> + } >> + >> + dev_warn(dev, "%s: should not be here, IRQ was not found in hash list\n", >> + __func__); >> + >> +end: >> + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) >> + mutex_unlock(&info->irq_lock); >> + return ret; >> } >> >> /** >> @@ -3847,7 +3975,10 @@ static int ti_sci_suspend_noirq(struct device *dev) >> static int ti_sci_resume_noirq(struct device *dev) >> { >> struct ti_sci_info *info = dev_get_drvdata(dev); >> - int ret = 0; >> + struct ti_sci_msg_req_manage_irq *irq_desc; >> + struct ti_sci_irq *irq; >> + struct hlist_node *tmp_node; >> + int ret = 0, err = 0, i; >> u32 source; >> u64 time; >> u8 pin; >> @@ -3859,13 +3990,50 @@ static int ti_sci_resume_noirq(struct device *dev) >> return ret; >> } >> >> + switch (pm_suspend_target_state) { >> + case PM_SUSPEND_MEM: >> + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) { >> + hash_for_each_safe(info->irqs, i, tmp_node, irq, node) { >> + irq_desc = &irq->desc; >> + ret = ti_sci_manage_irq(&info->handle, >> + irq_desc->valid_params, >> + irq_desc->src_id, >> + irq_desc->src_index, >> + irq_desc->dst_id, >> + irq_desc->dst_host_irq, >> + irq_desc->ia_id, >> + irq_desc->vint, >> + irq_desc->global_event, >> + irq_desc->vint_status_bit, >> + irq_desc->secondary_host, >> + TI_SCI_MSG_SET_IRQ); >> + if (ret) { >> + dev_err(dev, "failed to restore IRQ with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", > > space before via? overall this print is needed, but a bit umm.. we have > similar ones already.. Yes I wanted to have consistent messages. Will fix the missing space. > >> + irq_desc->valid_params, >> + irq_desc->src_id, >> + irq_desc->src_index, >> + irq_desc->dst_id, >> + irq_desc->dst_host_irq, >> + irq_desc->ia_id, >> + irq_desc->vint, >> + irq_desc->global_event, >> + irq_desc->vint_status_bit); >> + err = ret; >> + } >> + } >> + } >> + break; >> + default: >> + break; >> + } >> + >> ret = ti_sci_msg_cmd_lpm_wake_reason(&info->handle, &source, &time, &pin, &mode); >> /* Do not fail to resume on error as the wake reason is not critical */ >> if (!ret) >> dev_info(dev, "ti_sci: wakeup source:0x%x, pin:0x%x, mode:0x%x\n", >> source, pin, mode); >> >> - return 0; >> + return err; >> } >> >> static void ti_sci_pm_complete(struct device *dev) >> @@ -4014,13 +4182,14 @@ static int ti_sci_probe(struct platform_device *pdev) >> } >> >> ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps); >> - dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s%s\n", >> + dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s%s%s\n", >> info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "", >> info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "", >> info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "", >> info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT ? " LPM-Abort" : "", >> info->fw_caps & MSG_FLAG_CAPS_IO_ISOLATION ? " IO-Isolation" : "", >> - info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED ? " BoardConfig-Managed" : "" >> + info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED ? " BoardConfig-Managed" : "", >> + info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST ? " IRQ-Context-Lost" : "" >> ); >> >> ti_sci_setup_ops(info); >> @@ -4053,6 +4222,14 @@ static int ti_sci_probe(struct platform_device *pdev) >> list_add_tail(&info->node, &ti_sci_list); >> mutex_unlock(&ti_sci_list_mutex); >> >> + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) { >> + ret = devm_mutex_init(dev, &info->irq_lock); >> + if (ret) >> + return ret; > > If devm_mutex_init() fails, the function returns directly rather than > going through the out: label. All other error paths after the mailbox > channel allocations use goto out, which calls mbox_free_channel() for > both channels. Since mbox_request_channel_byname() is not a devm > allocation, those channels would not be freed by the devm cleanup path > on probe failure. > > Does this leak info->chan_tx and info->chan_rx when devm_mutex_init() > returns an error? Indeed we should go to 'out'. Best Regards, Thomas ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v7 3/4] clk: keystone: sci-clk: add restore_context() operation 2026-05-06 8:35 [PATCH v7 0/4] firmware: ti_sci: Introduce BOARDCFG_MANAGED mode for Jacinto family Thomas Richard (TI) 2026-05-06 8:35 ` [PATCH v7 1/4] firmware: ti_sci: add BOARDCFG_MANAGED mode support Thomas Richard (TI) 2026-05-06 8:35 ` [PATCH v7 2/4] firmware: ti_sci: add support for restoring IRQs during resume Thomas Richard (TI) @ 2026-05-06 8:35 ` Thomas Richard (TI) 2026-05-06 8:35 ` [PATCH v7 4/4] firmware: ti_sci: add support for restoring clock context during resume Thomas Richard (TI) 3 siblings, 0 replies; 8+ messages in thread From: Thomas Richard (TI) @ 2026-05-06 8:35 UTC (permalink / raw) To: Nishanth Menon, Tero Kristo, Santosh Shilimkar, Michael Turquette, Stephen Boyd Cc: Gregory CLEMENT, richard.genoud, Udit Kumar, Abhash Kumar, Thomas Petazzoni, linux-arm-kernel, linux-kernel, linux-clk, Thomas Richard (TI), Dhruva Gole, Kendall Willis, Brian Masney Implement the restore_context() operation to restore the clock rate and the clock parent state. The clock rate is saved in sci_clk struct during set_rate() and recalc_rate() operations. The parent index is saved in sci_clk struct during set_parent() operation. During clock registration, the core retrieves each clock’s parent using get_parent() operation to ensure the internal clock tree reflects the actual hardware state, including any configurations made by the bootloader. So we also save the parent index in get_parent(). Reviewed-by: Dhruva Gole <d-gole@ti.com> Reviewed-by: Kendall Willis <k-willis@ti.com> Acked-by: Stephen Boyd <sboyd@kernel.org> Reviewed-by: Brian Masney <bmasney@redhat.com> Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com> --- drivers/clk/keystone/sci-clk.c | 45 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c index 9d5071223f4c..7c0f7b3e89e0 100644 --- a/drivers/clk/keystone/sci-clk.c +++ b/drivers/clk/keystone/sci-clk.c @@ -47,6 +47,8 @@ struct sci_clk_provider { * @node: Link for handling clocks probed via DT * @cached_req: Cached requested freq for determine rate calls * @cached_res: Cached result freq for determine rate calls + * @parent_id: Parent index for this clock + * @rate: Clock rate */ struct sci_clk { struct clk_hw hw; @@ -58,6 +60,8 @@ struct sci_clk { struct list_head node; unsigned long cached_req; unsigned long cached_res; + int parent_id; + unsigned long rate; }; #define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw) @@ -150,6 +154,8 @@ static unsigned long sci_clk_recalc_rate(struct clk_hw *hw, return 0; } + clk->rate = freq; + return freq; } @@ -210,10 +216,15 @@ static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct sci_clk *clk = to_sci_clk(hw); + int ret; - return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id, - clk->clk_id, rate / 10 * 9, rate, - rate / 10 * 11); + ret = clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id, + clk->clk_id, rate / 10 * 9, rate, + rate / 10 * 11); + if (!ret) + clk->rate = rate; + + return ret; } /** @@ -234,12 +245,13 @@ static u8 sci_clk_get_parent(struct clk_hw *hw) dev_err(clk->provider->dev, "get-parent failed for dev=%d, clk=%d, ret=%d\n", clk->dev_id, clk->clk_id, ret); + clk->parent_id = ret; return 0; } - parent_id = parent_id - clk->clk_id - 1; + clk->parent_id = parent_id - clk->clk_id - 1; - return (u8)parent_id; + return (u8)clk->parent_id; } /** @@ -252,12 +264,28 @@ static u8 sci_clk_get_parent(struct clk_hw *hw) static int sci_clk_set_parent(struct clk_hw *hw, u8 index) { struct sci_clk *clk = to_sci_clk(hw); + int ret; clk->cached_req = 0; - return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id, - clk->clk_id, - index + 1 + clk->clk_id); + ret = clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id, + clk->clk_id, + index + 1 + clk->clk_id); + if (!ret) + clk->parent_id = index; + + return ret; +} + +static void sci_clk_restore_context(struct clk_hw *hw) +{ + struct sci_clk *clk = to_sci_clk(hw); + + if (clk->num_parents > 1 && clk->parent_id >= 0) + sci_clk_set_parent(hw, (u8)clk->parent_id); + + if (clk->rate) + sci_clk_set_rate(hw, clk->rate, 0); } static const struct clk_ops sci_clk_ops = { @@ -269,6 +297,7 @@ static const struct clk_ops sci_clk_ops = { .set_rate = sci_clk_set_rate, .get_parent = sci_clk_get_parent, .set_parent = sci_clk_set_parent, + .restore_context = sci_clk_restore_context, }; /** -- 2.53.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v7 4/4] firmware: ti_sci: add support for restoring clock context during resume 2026-05-06 8:35 [PATCH v7 0/4] firmware: ti_sci: Introduce BOARDCFG_MANAGED mode for Jacinto family Thomas Richard (TI) ` (2 preceding siblings ...) 2026-05-06 8:35 ` [PATCH v7 3/4] clk: keystone: sci-clk: add restore_context() operation Thomas Richard (TI) @ 2026-05-06 8:35 ` Thomas Richard (TI) 3 siblings, 0 replies; 8+ messages in thread From: Thomas Richard (TI) @ 2026-05-06 8:35 UTC (permalink / raw) To: Nishanth Menon, Tero Kristo, Santosh Shilimkar, Michael Turquette, Stephen Boyd Cc: Gregory CLEMENT, richard.genoud, Udit Kumar, Abhash Kumar, Thomas Petazzoni, linux-arm-kernel, linux-kernel, linux-clk, Thomas Richard (TI), Dhruva Gole, Kendall Willis Some DM-Firmware are not able to restore the clock rates and the clock parents after a suspend-resume. The CLK_CONTEXT_LOST firmware capability has been introduced to identify this characteristic. In this case the responsibility is therefore delegated to the ti_sci driver, which uses clk_restore_context() to trigger the context_restore() operation for all registered clocks, including those managed by the sci-clk. The sci-clk driver implements the context_restore() operation to ensure rates and clock parents are correctly restored. Reviewed-by: Dhruva Gole <d-gole@ti.com> Reviewed-by: Kendall Willis <k-willis@ti.com> Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com> --- drivers/firmware/ti_sci.c | 9 +++++++-- drivers/firmware/ti_sci.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 531ac3aa38b8..1ee8f67d3f7e 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -9,6 +9,7 @@ #define pr_fmt(fmt) "%s: " fmt, __func__ #include <linux/bitmap.h> +#include <linux/clk.h> #include <linux/cpu.h> #include <linux/debugfs.h> #include <linux/export.h> @@ -4022,6 +4023,9 @@ static int ti_sci_resume_noirq(struct device *dev) } } } + + if (info->fw_caps & MSG_FLAG_CAPS_LPM_CLK_CONTEXT_LOST) + clk_restore_context(); break; default: break; @@ -4182,14 +4186,15 @@ static int ti_sci_probe(struct platform_device *pdev) } ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps); - dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s%s%s\n", + dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s%s%s%s\n", info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT ? " LPM-Abort" : "", info->fw_caps & MSG_FLAG_CAPS_IO_ISOLATION ? " IO-Isolation" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED ? " BoardConfig-Managed" : "", - info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST ? " IRQ-Context-Lost" : "" + info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST ? " IRQ-Context-Lost" : "", + info->fw_caps & MSG_FLAG_CAPS_LPM_CLK_CONTEXT_LOST ? " Clk-Context-Lost" : "" ); ti_sci_setup_ops(info); diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 67f16e8c69a1..2d75667a6723 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -152,6 +152,7 @@ struct ti_sci_msg_req_reboot { * MSG_FLAG_CAPS_IO_ISOLATION: IO Isolation support * MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED: LPM config done statically for the DM via boardcfg * MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST: DM is not able to restore IRQ context + * MSG_FLAG_CAPS_LPM_CLK_CONTEXT_LOST: DM is not able to restore Clock context * * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS * providing currently available SOC/firmware capabilities. SoC that don't @@ -166,6 +167,7 @@ struct ti_sci_msg_resp_query_fw_caps { #define MSG_FLAG_CAPS_IO_ISOLATION TI_SCI_MSG_FLAG(7) #define MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED TI_SCI_MSG_FLAG(12) #define MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST TI_SCI_MSG_FLAG(14) +#define MSG_FLAG_CAPS_LPM_CLK_CONTEXT_LOST TI_SCI_MSG_FLAG(15) #define MSG_MASK_CAPS_LPM GENMASK_ULL(4, 1) u64 fw_caps; } __packed; -- 2.53.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-05-12 15:44 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-06 8:35 [PATCH v7 0/4] firmware: ti_sci: Introduce BOARDCFG_MANAGED mode for Jacinto family Thomas Richard (TI) 2026-05-06 8:35 ` [PATCH v7 1/4] firmware: ti_sci: add BOARDCFG_MANAGED mode support Thomas Richard (TI) 2026-05-06 14:06 ` Nishanth Menon 2026-05-06 8:35 ` [PATCH v7 2/4] firmware: ti_sci: add support for restoring IRQs during resume Thomas Richard (TI) 2026-05-06 14:15 ` Nishanth Menon 2026-05-12 15:44 ` Thomas Richard 2026-05-06 8:35 ` [PATCH v7 3/4] clk: keystone: sci-clk: add restore_context() operation Thomas Richard (TI) 2026-05-06 8:35 ` [PATCH v7 4/4] firmware: ti_sci: add support for restoring clock context during resume Thomas Richard (TI)
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.