* Re: [PATCH v6 15/19] drm/connector: Add new atomic_create_state callback
From: Luca Ceresoli @ 2026-06-19 16:24 UTC (permalink / raw)
To: Maxime Ripard, Maarten Lankhorst, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Shuah Khan, Dmitry Baryshkov,
Jyri Sarha, Tomi Valkeinen, Andrzej Hajda, Neil Armstrong,
Robert Foss, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Simon Ser, Harry Wentland, Melissa Wen, Sebastian Wick, Alex Hung,
Jani Nikula, Rodrigo Vivi, Joonas Lahtinen, Tvrtko Ursulin,
Chen-Yu Tsai, Samuel Holland, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance
Cc: dri-devel, linux-doc, linux-kernel, Daniel Stone, intel-gfx,
intel-xe, linux-arm-kernel, linux-sunxi, Laurent Pinchart
In-Reply-To: <20260526-drm-mode-config-init-v6-15-852346394200@kernel.org>
Hello Maxime, Dmitry, all,
On Tue May 26, 2026 at 6:46 PM CEST, Maxime Ripard wrote:
> Commit 47b5ac7daa46 ("drm/atomic: Add new atomic_create_state callback
> to drm_private_obj") introduced a new pattern for allocating drm object
> states.
>
> Instead of relying on the reset() callback, it created a new
> atomic_create_state hook. This is helpful because reset is a bit
> overloaded: it's used to create the initial software state, reset it,
> but also reset the hardware.
>
> It can also be used either at probe time, to create the initial state
> and possibly reset the hardware to an expected default, but also during
> suspend/resume.
>
> Both these cases come with different expectations too: during the
> initialization, we want to initialize all states, but during
> suspend/resume, drm_private_states for example are expected to be kept
> around.
>
> reset() also isn't fallible, which makes it harder to handle
> initialization errors properly. This is only really relevant for some
> drivers though, since all the helpers for reset only create a new
> state, and don't touch the hardware at all.
>
> It was thus decided to create a new hook that would allocate and
> initialize a pristine state without any side effect:
> atomic_create_state to untangle a bit some of it, and to separate the
> initialization with the actual reset one might need during a
> suspend/resume.
>
> Continue the transition to the new pattern with connectors.
>
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
> Signed-off-by: Maxime Ripard <mripard@kernel.org>
As I'm rebasing another series on current drm-misc-next, which now includes
this patch, I ran into troubles and I'm not sure what is the right thing to
do. I hope you can help me clarify this. See below for my question.
FTR the series I'm rebasing is "drm bridge hotplug", but the question is
not specific to that series.
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -616,11 +616,19 @@ int drmm_connector_hdmi_init(struct drm_device *dev,
>
> /*
> * drm_connector_attach_max_bpc_property() requires the
> * connector to have a state.
> */
> - if (connector->funcs->reset)
> + if (connector->funcs->atomic_create_state) {
> + struct drm_connector_state *state;
> +
> + state = connector->funcs->atomic_create_state(connector);
> + if (IS_ERR(state))
> + return PTR_ERR(state);
> +
> + connector->state = state;
> + } else if (connector->funcs->reset)
> connector->funcs->reset(connector);
Here a state is added to connector->state, and that's fine.
However non-HDMI connectors don't get a state created by default.
I was hit by this with the drm_bridge_connector which it can add either an
HDMI or a non-HDMI connector [0]. In the former case it calls
drmm_connector_hdmi_init(), which creates the state (in the hunk quoted
above). In the latter case, as I experienced at runtime and confirmed by
code inspection, it does not create a state: no one calls
connector->funcs->atomic_create_state.
I suspect this is related to patch 19/19 which converted the
drm_bridge_connector from drm_atomic_helper_connector_reset() to
drm_atomic_helper_connector_create_state(), and only the former sets
'connector->state = conn_state'.
Generally speaking, looks like a state is created only for HDMI
connectors.
The hardware I have uses the drm_bridge_connector in the non-HDMI case, so
the state is not created and this results in a NULL pointer deref later on,
in my case it's in in drm_atomic_connector_get_property().
Am I missing anything obvious?
For now I've come up with a quick workaround, adding (roughly after
connector init at [1]):
if (!connector->state)
connector->state = drm_bridge_connector_create_state(connector);
I'm not sure which would be the best solution. Maybe taking the whole
atomic_create_state/reset state creation calls [2] from
drmm_connector_hdmi_init() and hoist them up into
drmm_connector_init(), so all connectors benefit?
Let me know what you think.
[0] https://gitlab.freedesktop.org/drm/misc/kernel/-/blob/7a921d111810652672e02c392b35fdcefa4d5030/drivers/gpu/drm/display/drm_bridge_connector.c#L995-1029
[1] https://gitlab.freedesktop.org/drm/misc/kernel/-/blob/7a921d111810652672e02c392b35fdcefa4d5030/drivers/gpu/drm/display/drm_bridge_connector.c#L1030
[2] https://gitlab.freedesktop.org/drm/misc/kernel/-/blob/7a921d111810652672e02c392b35fdcefa4d5030/drivers/gpu/drm/drm_connector.c#L617-631
Kind regards,
Luca
--
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH] arm64: static_call: include asm/insns.h
From: Will Deacon @ 2026-06-19 16:36 UTC (permalink / raw)
To: Peter Zijlstra, Josh Poimboeuf, Jason Baron, Alice Ryhl,
Catalin Marinas, Ard Biesheuvel, Arnd Bergmann
Cc: kernel-team, Will Deacon, Arnd Bergmann, Steven Rostedt,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260611132149.40873-1-arnd@kernel.org>
On Thu, 11 Jun 2026 15:21:44 +0200, Arnd Bergmann wrote:
> I came a cross a missing declaration in a randconfig build:
>
> arch/arm64/kernel/static_call.c:16:5: error: call to undeclared function 'aarch64_insn_adrp_get_offset'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
> 16 | aarch64_insn_adrp_get_offset(le32_to_cpup(tramp + 4)) +
> | ^
>
> Include the header that contains this definition explicitly,
> rather than relying on it to come indirectly through another
> header.
>
> [...]
Applied to arm64 (for-next/core), thanks!
[1/1] arm64: static_call: include asm/insns.h
https://git.kernel.org/arm64/c/998d4d789d2d
Cheers,
--
Will
https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev
^ permalink raw reply
* Re: [PATCH v2] arm64/hw_breakpoint: reject unaligned watchpoints that would truncate BAS
From: Will Deacon @ 2026-06-19 16:36 UTC (permalink / raw)
To: Mark Rutland, Catalin Marinas, Pratyush Anand, Breno Leitao
Cc: kernel-team, Will Deacon, linux-arm-kernel, linux-perf-users,
linux-kernel, clm, leo.bras, kernel-team
In-Reply-To: <20260609-arm64_bas-v2-1-9f34dbbded88@debian.org>
On Tue, 09 Jun 2026 06:15:53 -0700, Breno Leitao wrote:
> hw_breakpoint_arch_parse() positions the BAS bit pattern in
> hw->ctrl.len with
>
> offset = hw->address & alignment_mask; /* 0..7 */
> hw->ctrl.len <<= offset;
>
> ctrl.len is an 8-bit bitfield (struct arch_hw_breakpoint_ctrl::len is
> u32 :8), so the shift silently drops any bits past bit 7. For
> non-compat AArch64 watchpoints the offset is unbounded relative to
> ctrl.len: a perf_event_open(PERF_TYPE_BREAKPOINT) caller asking for
> HW_BREAKPOINT_W with bp_addr=page+1 and bp_len=HW_BREAKPOINT_LEN_8
> ends up with 0xff << 1 = 0x1fe, stored as 0xfe. The kernel programs
> WCR.BAS=0xfe and the hardware watches bytes [1..7] instead of the
> requested [1..8] -- the eighth byte is silently dropped. The
> syscall still returns success, leaving userspace to discover the
> gap by empirical probing.
>
> [...]
Applied to arm64 (for-next/core), thanks!
[1/1] arm64/hw_breakpoint: reject unaligned watchpoints that would truncate BAS
https://git.kernel.org/arm64/c/4cc70f75853b
Cheers,
--
Will
https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev
^ permalink raw reply
* [PATCH] remoteproc: xlnx: refactor start & stop ops
From: Tanmay Shah @ 2026-06-19 16:38 UTC (permalink / raw)
To: michal.simek, andersson, mathieu.poirier
Cc: linux-arm-kernel, linux-kernel, linux-remoteproc, Tanmay Shah
Current _start and _stop ops are implemented using various APIs from the
platform management firmware driver. Instead provide respective RPU
start and stop API in the firmware driver and move the logic to interact
with the PM firmware in the firmware driver. The remoteproc driver doesn't
need to know actual logic, but only the final result i.e. RPU start/stop
was success or not. This refactor keeps the remoteproc driver simple and
moves firmware interaction logic to the firmware driver.
Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
---
drivers/firmware/xilinx/zynqmp.c | 93 +++++++++++++++++++++++++
drivers/remoteproc/xlnx_r5_remoteproc.c | 68 ++----------------
include/linux/firmware/xlnx-zynqmp.h | 12 ++++
3 files changed, 110 insertions(+), 63 deletions(-)
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index af838b2dc327..f9a3a95b0638 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -1513,6 +1513,99 @@ int zynqmp_pm_request_wake(const u32 node,
}
EXPORT_SYMBOL_GPL(zynqmp_pm_request_wake);
+/**
+ * zynqmp_pm_start_rpu - Boot Real-time Processing Unit (Cortex-R) on SoC
+ *
+ * @node: power-domains id of the core
+ * @bootaddr: Boot address of elf
+ *
+ * Return: status, either success or error+reason
+ */
+int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr)
+{
+ enum rpu_boot_mem bootmem;
+ int ret;
+
+ /*
+ * The exception vector pointers (EVP) refer to the base-address of
+ * exception vectors (for reset, IRQ, FIQ, etc). The reset-vector
+ * starts at the base-address and subsequent vectors are on 4-byte
+ * boundaries.
+ *
+ * Exception vectors can start either from 0x0000_0000 (LOVEC) or
+ * from 0xFFFF_0000 (HIVEC) which is mapped in the OCM (On-Chip Memory)
+ *
+ * Usually firmware will put Exception vectors at LOVEC.
+ *
+ * It is not recommend that you change the exception vector.
+ * Changing the EVP to HIVEC will result in increased interrupt latency
+ * and jitter. Also, if the OCM is secured and the Cortex-R5F processor
+ * is non-secured, then the Cortex-R5F processor cannot access the
+ * HIVEC exception vectors in the OCM.
+ */
+ bootmem = (bootaddr >= 0xFFFC0000) ?
+ PM_RPU_BOOTMEM_HIVEC : PM_RPU_BOOTMEM_LOVEC;
+
+ pr_debug("RPU boot addr 0x%llx from %s.", bootaddr,
+ bootmem == PM_RPU_BOOTMEM_HIVEC ? "OCM" : "TCM");
+
+ /* Request node before starting RPU core if new version of API is supported */
+ if (zynqmp_pm_feature(PM_REQUEST_NODE) > PM_API_VERSION_1) {
+ ret = zynqmp_pm_request_node(node,
+ ZYNQMP_PM_CAPABILITY_ACCESS, 0,
+ ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+ if (ret < 0) {
+ pr_err("failed to request 0x%x", node);
+ return ret;
+ }
+ }
+
+ ret = zynqmp_pm_request_wake(node, true,
+ bootmem, ZYNQMP_PM_REQUEST_ACK_NO);
+ if (ret)
+ pr_err("failed to start RPU = 0x%x\n", node);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(zynqmp_pm_start_rpu);
+
+/**
+ * zynqmp_pm_stop_rpu - Stop Real-time Processing Unit (Cortex-R) on SoC
+ *
+ * @node: power-domains id of the core
+ *
+ * Return: status, either success or error+reason
+ */
+int zynqmp_pm_stop_rpu(const u32 node)
+{
+ int ret;
+
+ /* Use release node API to stop core if new version of API is supported */
+ if (zynqmp_pm_feature(PM_RELEASE_NODE) > PM_API_VERSION_1) {
+ ret = zynqmp_pm_release_node(node);
+ if (ret)
+ pr_err("failed to stop remoteproc RPU %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * Check expected version of EEMI call before calling it. This avoids
+ * any error or warning prints from firmware as it is expected that fw
+ * doesn't support it.
+ */
+ if (zynqmp_pm_feature(PM_FORCE_POWERDOWN) != PM_API_VERSION_1) {
+ pr_debug("EEMI interface %d ver 1 not supported\n",
+ PM_FORCE_POWERDOWN);
+ return -EOPNOTSUPP;
+ }
+
+ /* maintain force pwr down for backward compatibility */
+ ret = zynqmp_pm_force_pwrdwn(node, ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+ if (ret)
+ pr_err("core force power down failed\n");
+ return ret;
+}
+EXPORT_SYMBOL_GPL(zynqmp_pm_stop_rpu);
+
/**
* zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
* @node: Node ID of the slave
diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
index 3349d1877751..dcd8a93f031c 100644
--- a/drivers/remoteproc/xlnx_r5_remoteproc.c
+++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
@@ -364,49 +364,12 @@ static void zynqmp_r5_rproc_kick(struct rproc *rproc, int vqid)
static int zynqmp_r5_rproc_start(struct rproc *rproc)
{
struct zynqmp_r5_core *r5_core = rproc->priv;
- enum rpu_boot_mem bootmem;
int ret;
- /*
- * The exception vector pointers (EVP) refer to the base-address of
- * exception vectors (for reset, IRQ, FIQ, etc). The reset-vector
- * starts at the base-address and subsequent vectors are on 4-byte
- * boundaries.
- *
- * Exception vectors can start either from 0x0000_0000 (LOVEC) or
- * from 0xFFFF_0000 (HIVEC) which is mapped in the OCM (On-Chip Memory)
- *
- * Usually firmware will put Exception vectors at LOVEC.
- *
- * It is not recommend that you change the exception vector.
- * Changing the EVP to HIVEC will result in increased interrupt latency
- * and jitter. Also, if the OCM is secured and the Cortex-R5F processor
- * is non-secured, then the Cortex-R5F processor cannot access the
- * HIVEC exception vectors in the OCM.
- */
- bootmem = (rproc->bootaddr >= 0xFFFC0000) ?
- PM_RPU_BOOTMEM_HIVEC : PM_RPU_BOOTMEM_LOVEC;
-
- dev_dbg(r5_core->dev, "RPU boot addr 0x%llx from %s.", rproc->bootaddr,
- bootmem == PM_RPU_BOOTMEM_HIVEC ? "OCM" : "TCM");
-
- /* Request node before starting RPU core if new version of API is supported */
- if (zynqmp_pm_feature(PM_REQUEST_NODE) > 1) {
- ret = zynqmp_pm_request_node(r5_core->pm_domain_id,
- ZYNQMP_PM_CAPABILITY_ACCESS, 0,
- ZYNQMP_PM_REQUEST_ACK_BLOCKING);
- if (ret < 0) {
- dev_err(r5_core->dev, "failed to request 0x%x",
- r5_core->pm_domain_id);
- return ret;
- }
- }
-
- ret = zynqmp_pm_request_wake(r5_core->pm_domain_id, 1,
- bootmem, ZYNQMP_PM_REQUEST_ACK_NO);
+ ret = zynqmp_pm_start_rpu(r5_core->pm_domain_id, rproc->bootaddr);
if (ret)
- dev_err(r5_core->dev,
- "failed to start RPU = 0x%x\n", r5_core->pm_domain_id);
+ dev_err(&rproc->dev, "failed to start RPU\n");
+
return ret;
}
@@ -423,30 +386,9 @@ static int zynqmp_r5_rproc_stop(struct rproc *rproc)
struct zynqmp_r5_core *r5_core = rproc->priv;
int ret;
- /* Use release node API to stop core if new version of API is supported */
- if (zynqmp_pm_feature(PM_RELEASE_NODE) > 1) {
- ret = zynqmp_pm_release_node(r5_core->pm_domain_id);
- if (ret)
- dev_err(r5_core->dev, "failed to stop remoteproc RPU %d\n", ret);
- return ret;
- }
-
- /*
- * Check expected version of EEMI call before calling it. This avoids
- * any error or warning prints from firmware as it is expected that fw
- * doesn't support it.
- */
- if (zynqmp_pm_feature(PM_FORCE_POWERDOWN) != 1) {
- dev_dbg(r5_core->dev, "EEMI interface %d ver 1 not supported\n",
- PM_FORCE_POWERDOWN);
- return -EOPNOTSUPP;
- }
-
- /* maintain force pwr down for backward compatibility */
- ret = zynqmp_pm_force_pwrdwn(r5_core->pm_domain_id,
- ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+ ret = zynqmp_pm_stop_rpu(r5_core->pm_domain_id);
if (ret)
- dev_err(r5_core->dev, "core force power down failed\n");
+ dev_err(&rproc->dev, "failed to stop RPU\n");
return ret;
}
diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h
index 7e27b0f7bf7e..347df66ee176 100644
--- a/include/linux/firmware/xlnx-zynqmp.h
+++ b/include/linux/firmware/xlnx-zynqmp.h
@@ -644,6 +644,8 @@ int zynqmp_pm_get_node_status(const u32 node, u32 *const status,
u32 *const requirements, u32 *const usage);
int zynqmp_pm_get_rpu_node_status(const u32 node, u32 *const status,
u32 *const requirements, u32 *const usage);
+int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr);
+int zynqmp_pm_stop_rpu(const u32 node);
int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value);
int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
u32 value);
@@ -960,6 +962,16 @@ static inline int zynqmp_pm_get_rpu_node_status(const u32 node, u32 *const statu
return -ENODEV;
}
+static inline int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr)
+{
+ return -ENODEV;
+}
+
+static inline int zynqmp_pm_stop_rpu(const u32 node)
+{
+ return -ENODEV;
+}
+
static inline int zynqmp_pm_set_sd_config(u32 node,
enum pm_sd_config_type config,
u32 value)
base-commit: 721396afea31eac476d88f5db10ba111ba4b8382
--
2.34.1
^ permalink raw reply related
* [PATCH] arm64: mm: Defer read-only remap of data/bss linear alias
From: Ard Biesheuvel @ 2026-06-19 16:39 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, catalin.marinas, will, Ard Biesheuvel, Fuad Tabba
From: Ard Biesheuvel <ardb@kernel.org>
Fuad reports that in some cases, the KVM init code may apply relocations
to variables that reside in .data, and does so via the linear map. This
means that remapping .data read-only beforehand is a bad idea, and
results in an early boot crash.
These variables in .data are only present when CONFIG_NVHE_EL2_DEBUG or
CONFIG_NVHE_EL2_TRACING are enabled, which is why it was not spotted in
testing.
So move the remap to mark_rodata_ro(), which is a reasonable place to
put this, and ensures that it happens much later during the boot. It
also means that rodata=off is now taken into account, and so the linear
alias will remain writable in that case.
Cc: Fuad Tabba <fuad.tabba@linux.dev>
Fixes: f2ba877402e5 ("arm64: mm: Map the kernel data/bss read-only in the linear map")
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/arm64/mm/mmu.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 9f354971b7e4..1f7eca86b5c1 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1198,11 +1198,6 @@ static void __init map_mem(void)
__map_memblock(start, end, pgprot_tagged(PAGE_KERNEL),
flags);
}
-
- /* Map the kernel data/bss read-only in the linear map */
- __map_memblock(init_end, kernel_end, PAGE_KERNEL_RO, flags);
- flush_tlb_kernel_range((unsigned long)lm_alias(__init_end),
- (unsigned long)lm_alias(__bss_stop));
}
void mark_rodata_ro(void)
@@ -1221,6 +1216,12 @@ void mark_rodata_ro(void)
update_mapping_prot(__pa_symbol(_text), (unsigned long)_text,
(unsigned long)_stext - (unsigned long)_text,
PAGE_KERNEL_RO);
+
+ /* Map the kernel data/bss read-only in the linear map */
+ update_mapping_prot(__pa_symbol(__init_end),
+ (unsigned long)lm_alias(__init_end),
+ (unsigned long)__bss_stop - (unsigned long)__init_end,
+ PAGE_KERNEL_RO);
}
static void __init declare_vma(struct vm_struct *vma,
--
2.55.0.rc0.738.g0c8ab3ebcc-goog
^ permalink raw reply related
* Re: [PATCH v2 8/8] KVM: arm64: Implement lazy vCPU state sync for non-protected guests
From: Fuad Tabba @ 2026-06-19 16:41 UTC (permalink / raw)
To: Vincent Donnefort
Cc: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel,
linux-kernel, Catalin Marinas, Will Deacon, Joey Gouly,
Steffen Eiden, Suzuki K Poulose, Zenghui Yu, Quentin Perret,
Sebastian Ene, Hyunwoo Kim
In-Reply-To: <ajVAV5ct0xdLn1KX@google.com>
On Fri, 19 Jun 2026 at 14:13, Vincent Donnefort <vdonnefort@google.com> wrote:
>
> On Fri, Jun 19, 2026 at 08:07:19AM +0100, Fuad Tabba wrote:
> > pKVM copies a non-protected guest's register context between the host
> > and the hypervisor on every world switch, even when the host never
> > inspects it. Defer the copy: on entry, flush the host context into the
> > hyp vCPU only when the host marked it dirty (PKVM_HOST_STATE_DIRTY); on
> > exit, leave it in the hyp vCPU and copy it back only when the host needs
> > it, via a __pkvm_vcpu_sync_state hypercall on trap handling or at vcpu
> > put. A protected guest's context is copied as before, since lazy sync
> > only helps where the host is trusted to see the guest's registers.
> >
> > PC and PSTATE are the exception: they are copied back on every exit so
> > the kvm_exit tracepoint reports the guest's real exit PC, and the run
> > loop's vcpu_mode_is_bad_32bit() and SError-masking checks evaluate the
> > guest's current PSTATE rather than the value left by the previous sync.
> >
> > handle_exit_early() can also inject an SError, which writes the guest
> > context (ESR_EL1) outside the trap-handling path. For a non-protected
> > guest it therefore syncs the context from the hyp vCPU and marks it
> > dirty, as handle_trap_exceptions() does, so the injection reaches the
> > hyp vCPU on re-entry rather than being dropped.
> >
> > Signed-off-by: Fuad Tabba <tabba@google.com>
> > ---
> > arch/arm64/include/asm/kvm_asm.h | 1 +
> > arch/arm64/include/asm/kvm_host.h | 2 +
> > arch/arm64/kvm/arm.c | 7 +++
> > arch/arm64/kvm/handle_exit.c | 30 +++++++++++
> > arch/arm64/kvm/hyp/nvhe/hyp-main.c | 86 ++++++++++++++++++++++++++++--
> > 5 files changed, 121 insertions(+), 5 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
> > index 043495f7fc78..6e1135b3ded4 100644
> > --- a/arch/arm64/include/asm/kvm_asm.h
> > +++ b/arch/arm64/include/asm/kvm_asm.h
> > @@ -113,6 +113,7 @@ enum __kvm_host_smccc_func {
> > __KVM_HOST_SMCCC_FUNC___pkvm_finalize_teardown_vm,
> > __KVM_HOST_SMCCC_FUNC___pkvm_vcpu_load,
> > __KVM_HOST_SMCCC_FUNC___pkvm_vcpu_put,
> > + __KVM_HOST_SMCCC_FUNC___pkvm_vcpu_sync_state,
> > __KVM_HOST_SMCCC_FUNC___pkvm_tlb_flush_vmid,
> >
> > MARKER(__KVM_HOST_SMCCC_FUNC_MAX)
> > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > index 2faa60df847d..caa39ee5125f 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -1068,6 +1068,8 @@ struct kvm_vcpu_arch {
> > #define INCREMENT_PC __vcpu_single_flag(iflags, BIT(1))
> > /* Target EL/MODE (not a single flag, but let's abuse the macro) */
> > #define EXCEPT_MASK __vcpu_single_flag(iflags, GENMASK(3, 1))
> > +/* Host-set: the hyp flushes the non-protected vCPU state in on entry */
> > +#define PKVM_HOST_STATE_DIRTY __vcpu_single_flag(iflags, BIT(4))
> >
> > /* Helpers to encode exceptions with minimum fuss */
> > #define __EXCEPT_MASK_VAL unpack_vcpu_flag(EXCEPT_MASK)
> > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> > index 3732ee9eb0d4..4e89558d8027 100644
> > --- a/arch/arm64/kvm/arm.c
> > +++ b/arch/arm64/kvm/arm.c
> > @@ -733,6 +733,10 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
> > if (is_protected_kvm_enabled()) {
> > kvm_call_hyp(__vgic_v3_save_aprs, &vcpu->arch.vgic_cpu.vgic_v3);
> > kvm_call_hyp_nvhe(__pkvm_vcpu_put);
> > +
> > + /* __pkvm_vcpu_put implies a sync of the state */
> > + if (!kvm_vm_is_protected(vcpu->kvm))
> > + vcpu_set_flag(vcpu, PKVM_HOST_STATE_DIRTY);
> > }
> >
> > kvm_vcpu_put_debug(vcpu);
> > @@ -964,6 +968,9 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
> > return ret;
> >
> > if (is_protected_kvm_enabled()) {
> > + /* Start with the vcpu in a dirty state */
> > + if (!kvm_vm_is_protected(vcpu->kvm))
> > + vcpu_set_flag(vcpu, PKVM_HOST_STATE_DIRTY);
> > ret = pkvm_create_hyp_vm(kvm);
> > if (ret)
> > return ret;
> > diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> > index 54aedf93c78b..8963621bcdd1 100644
> > --- a/arch/arm64/kvm/handle_exit.c
> > +++ b/arch/arm64/kvm/handle_exit.c
> > @@ -422,6 +422,20 @@ static int handle_trap_exceptions(struct kvm_vcpu *vcpu)
> > {
> > int handled;
> >
> > + /*
> > + * If we run a non-protected VM when protection is enabled
> > + * system-wide, resync the state from the hypervisor and mark
> > + * it as dirty on the host side if it wasn't dirty already
> > + * (which could happen if preemption has taken place).
> > + */
> > + if (is_protected_kvm_enabled() && !kvm_vm_is_protected(vcpu->kvm)) {
> > + guard(preempt)();
> > + if (!(vcpu_get_flag(vcpu, PKVM_HOST_STATE_DIRTY))) {
> > + kvm_call_hyp_nvhe(__pkvm_vcpu_sync_state);
> > + vcpu_set_flag(vcpu, PKVM_HOST_STATE_DIRTY);
> > + }
> > + }
> > +
>
> Could we remove this update here and let handle_exit_early() do the sync
> regardless of the SError injection? One of the main point of handle_exit_early()
> is to do things under !prempt().
Agreed on the move: handle_exit_early() is already preempt-off, so the
guard() goes away. Not on every exit though. handle_exit_early() runs
on every exit, and sync_hyp_vcpu() only copies PC/PSTATE/fault back
for a non-protected guest; the GPRs and sysregs cross solely via
__pkvm_vcpu_sync_state. Syncing unconditionally would pull the full
context back on plain IRQ exits, which is the copy this patch avoids.
So I will gate it on trap-or-SError and drop the
handle_trap_exceptions() block.
>
>
> > /*
> > * See ARM ARM B1.14.1: "Hyp traps on instructions
> > * that fail their condition code check"
> > @@ -489,6 +503,22 @@ int handle_exit(struct kvm_vcpu *vcpu, int exception_index)
> > /* For exit types that need handling before we can be preempted */
> > void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index)
> > {
> > + bool inject_serror = ARM_SERROR_PENDING(exception_index) ||
> > + ARM_EXCEPTION_CODE(exception_index) == ARM_EXCEPTION_EL1_SERROR;
> > +
> > + /*
> > + * An SError injected below writes the host ctxt; for a non-protected
> > + * guest, sync from the hyp vCPU and keep it dirty so it isn't dropped.
> > + */
> > + if (is_protected_kvm_enabled()) {
>
> Should we test !kvm_vm_is_protected(vcpu->kvm) here, as the
> PKVM_HOST_STATE_DIRTY is only updated for p-guests everywhere else?
Yes. The flag is only ever set for non-protected guests, so clearing it
for a protected one is a no-op, but gating it matches the invariant.
Both fold into one block in handle_exit_early():
if (is_protected_kvm_enabled() && !kvm_vm_is_protected(vcpu->kvm)) {
if (inject_serror ||
ARM_EXCEPTION_CODE(exception_index) == ARM_EXCEPTION_TRAP) {
kvm_call_hyp_nvhe(__pkvm_vcpu_sync_state);
vcpu_set_flag(vcpu, PKVM_HOST_STATE_DIRTY);
} else {
vcpu_clear_flag(vcpu, PKVM_HOST_STATE_DIRTY);
}
}
I will fold this into the next respin.
Thanks for the reviews!
/fuad
>
> > + vcpu_clear_flag(vcpu, PKVM_HOST_STATE_DIRTY);
> > +
> > + if (inject_serror && !kvm_vm_is_protected(vcpu->kvm)) {
> > + kvm_call_hyp_nvhe(__pkvm_vcpu_sync_state);
> > + vcpu_set_flag(vcpu, PKVM_HOST_STATE_DIRTY);
> > + }
> > + }
> > +
> > if (ARM_SERROR_PENDING(exception_index)) {
> > if (this_cpu_has_cap(ARM64_HAS_RAS_EXTN)) {
> > u64 disr = kvm_vcpu_get_disr(vcpu);
>
> [...]
^ permalink raw reply
* Re: [PATCH v3] drm/bridge: imx93-mipi-dsi: Fix mode validation
From: Luca Ceresoli @ 2026-06-19 16:49 UTC (permalink / raw)
To: Liu Ying, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Luca Ceresoli
Cc: Dmitry Baryshkov, dri-devel, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <20260515-imx93-mipi-dsi-fix-mode-validation-v3-1-91f7d22b2fe4@nxp.com>
Hello Liu,
On Fri May 15, 2026 at 8:54 AM CEST, Liu Ying wrote:
> i.MX93 MIPI DPHY PLL has limitation for matching with some pixel clock
> rates, e.g., the best DPHY PLL frequency is 445.333333MHz for a typical
> 1920x1080p@60Hz CEA/DMT display mode with a pixel clock rate running
> at 148.5MHz with 4 data lanes + RGB888 pixel in MIPI DSI sync pulse mode,
> while the expected PLL frequency is (148.5 * 24) / 4 / 2 MHz = 445.5MHz.
> Fortunately, VESA Display Monitor Timing Standard allows +/-0.5% pixel
> clock rate deviation for timings. So, for those display modes read
> from EDID through a bridge with DRM_BRIDGE_OP_DETECT and DRM_BRIDGE_OP_EDID
> operation bit masks set, pixel clock rate could be adjusted to match
> with the PLL frequency(for the above example, the pixel clock rate is
> adjusted to be 148.444444MHz with about -0.03% deviation from the 148.5MHz
> nominal rate so that the adjusted rate matches with the 445.333333MHz PLL
> frequency).
>
> Instead of checking the last bridge's operation bit masks against
> DRM_BRIDGE_OP_DETECT and DRM_BRIDGE_OP_EDID to determine if allowing
> +/-0.5% pixel clock rate deviation, check any bridge after this bridge,
> because the last bridge is usually a display connector bridge without
> any operation bit mask when the clock rate deviation is allowed.
>
> Fixes: ce62f8ea7e3f ("drm/bridge: imx: Add i.MX93 MIPI DSI support")
> Fixes: 5849eff7f067 ("drm/bridge: imx93-mipi-dsi: use drm_bridge_chain_get_last_bridge()")
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Signed-off-by: Liu Ying <victor.liu@nxp.com>
I'm perhaps not the most qualified to review this change, but let me try.
> --- a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
> +++ b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
> @@ -489,25 +489,43 @@ static int imx93_dsi_get_phy_configure_opts(struct imx93_dsi *dsi,
> return 0;
> }
>
> +static inline struct drm_bridge *
> +imx93_dsi_get_next_bridge_in_chain(struct drm_bridge *bridge)
> +{
> + struct drm_bridge *next = drm_bridge_get_next_bridge(bridge);
> +
> + drm_bridge_put(bridge);
> +
> + return next;
> +}
> +
> static enum drm_mode_status
> imx93_dsi_validate_mode(struct imx93_dsi *dsi, const struct drm_display_mode *mode)
> {
> struct drm_bridge *dmd_bridge = dw_mipi_dsi_get_bridge(dsi->dmd);
> - struct drm_bridge *last_bridge __free(drm_bridge_put) =
> - drm_bridge_chain_get_last_bridge(dmd_bridge->encoder);
> + struct drm_bridge *bridge;
>
> - if ((last_bridge->ops & DRM_BRIDGE_OP_DETECT) &&
> - (last_bridge->ops & DRM_BRIDGE_OP_EDID)) {
> - unsigned long pixel_clock_rate = mode->clock * 1000;
> - unsigned long rounded_rate;
> + for (bridge = drm_bridge_get_next_bridge(dmd_bridge);
> + bridge;
> + bridge = imx93_dsi_get_next_bridge_in_chain(bridge)) {
> + if ((bridge->ops & DRM_BRIDGE_OP_DETECT) &&
> + (bridge->ops & DRM_BRIDGE_OP_EDID)) {
> + unsigned long pixel_clock_rate = mode->clock * 1000;
> + unsigned long rounded_rate;
>
> - /* Allow +/-0.5% pixel clock rate deviation */
> - rounded_rate = clk_round_rate(dsi->clk_pixel, pixel_clock_rate);
> - if (rounded_rate < pixel_clock_rate * 995 / 1000 ||
> - rounded_rate > pixel_clock_rate * 1005 / 1000) {
> - dev_dbg(dsi->dev, "failed to round clock for mode " DRM_MODE_FMT "\n",
> - DRM_MODE_ARG(mode));
> - return MODE_NOCLOCK;
> + /* Allow +/-0.5% pixel clock rate deviation */
> + rounded_rate = clk_round_rate(dsi->clk_pixel, pixel_clock_rate);
> + if (rounded_rate < pixel_clock_rate * 995 / 1000 ||
> + rounded_rate > pixel_clock_rate * 1005 / 1000) {
> + dev_dbg(dsi->dev,
> + "failed to round clock for mode " DRM_MODE_FMT "\n",
> + DRM_MODE_ARG(mode));
> + drm_bridge_put(bridge);
> + return MODE_NOCLOCK;
> + }
> +
> + drm_bridge_put(bridge);
> + break;
> }
> }
Is this logic specific to the imx93 MIPI DSI host only? Or should it be
made generic for all dw-hdmi users, or even every DSI host?
Also, iterating over the bridge chain is not very clean. I'm working on
bridge hotplug (not upstream yet) and bad things would happen if a bridge
were hot-unplugged during this loop. If the core did this sort of algorithm
it would be able to be more robust.
Finally, out of my utter ignorance on the subject, is the VESA +/-0.5%
margin generic enough that this driver can always rely on it?
Luca
--
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* [PATCH v2] mfd: mt6397-irq: Fix PM notifier and IRQ domain teardown
From: Yuho Choi @ 2026-06-19 16:56 UTC (permalink / raw)
To: Lee Jones, Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-kernel, linux-arm-kernel, linux-mediatek, Yuho Choi
mt6397_irq_init() registers a PM notifier and creates an irq_domain. Both
objects point back to the devm-managed mt6397_chip.
The notifier was not unregistered on probe failure or unbind, so a later PM
transition could dereference freed chip state. The irq_domain had the
opposite lifetime problem: it could be removed while the devm-managed
parent IRQ was still active, but it was leaked on successful unbind.
Manage both lifetimes with devm actions. Register the domain cleanup before
requesting the parent IRQ, so devres frees the parent IRQ before removing
child mappings and the irq_domain. This keeps the domain alive while the
parent IRQ handler can still run.
Also serialize PM notifier mask writes with irqlock. While suspend is in
progress, keep wake_mask programmed in hardware even if a concurrent IRQ
sync updates irq_masks_cur in software.
Fixes: a4872e80ce7d ("mfd: mt6397: Extract IRQ related code from core driver")
Fixes: 4e2e7cfec13a ("mfd: mt6397: Modify suspend/resume behavior")
Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
---
Changes in v2:
- Use devm actions for PM notifier and irq_domain cleanup.
- Remove direct irq_domain_remove() calls from failure paths.
- Serialize PM notifier mask writes with irqlock.
---
drivers/mfd/mt6397-core.c | 4 +-
drivers/mfd/mt6397-irq.c | 85 +++++++++++++++++++++++----------
include/linux/mfd/mt6397/core.h | 1 +
3 files changed, 63 insertions(+), 27 deletions(-)
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 1bdacda9a933..ff1e393202ee 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -389,10 +389,8 @@ static int mt6397_probe(struct platform_device *pdev)
ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
pmic_core->cells, pmic_core->cell_size,
NULL, 0, pmic->irq_domain);
- if (ret) {
- irq_domain_remove(pmic->irq_domain);
+ if (ret)
dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
- }
return ret;
}
diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c
index 5d2e5459f744..4be74d8325cd 100644
--- a/drivers/mfd/mt6397-irq.c
+++ b/drivers/mfd/mt6397-irq.c
@@ -25,17 +25,23 @@ static void mt6397_irq_lock(struct irq_data *data)
mutex_lock(&mt6397->irqlock);
}
+static void mt6397_irq_write_masks(struct mt6397_chip *mt6397,
+ const u16 *masks)
+{
+ regmap_write(mt6397->regmap, mt6397->int_con[0], masks[0]);
+ regmap_write(mt6397->regmap, mt6397->int_con[1], masks[1]);
+ if (mt6397->int_con[2])
+ regmap_write(mt6397->regmap, mt6397->int_con[2], masks[2]);
+}
+
static void mt6397_irq_sync_unlock(struct irq_data *data)
{
struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
+ const u16 *masks;
- regmap_write(mt6397->regmap, mt6397->int_con[0],
- mt6397->irq_masks_cur[0]);
- regmap_write(mt6397->regmap, mt6397->int_con[1],
- mt6397->irq_masks_cur[1]);
- if (mt6397->int_con[2])
- regmap_write(mt6397->regmap, mt6397->int_con[2],
- mt6397->irq_masks_cur[2]);
+ masks = mt6397->irq_suspended ? mt6397->wake_mask :
+ mt6397->irq_masks_cur;
+ mt6397_irq_write_masks(mt6397, masks);
mutex_unlock(&mt6397->irqlock);
}
@@ -141,24 +147,20 @@ static int mt6397_irq_pm_notifier(struct notifier_block *notifier,
switch (pm_event) {
case PM_SUSPEND_PREPARE:
- regmap_write(chip->regmap,
- chip->int_con[0], chip->wake_mask[0]);
- regmap_write(chip->regmap,
- chip->int_con[1], chip->wake_mask[1]);
- if (chip->int_con[2])
- regmap_write(chip->regmap,
- chip->int_con[2], chip->wake_mask[2]);
+ mutex_lock(&chip->irqlock);
+ chip->irq_suspended = true;
+ mt6397_irq_write_masks(chip, chip->wake_mask);
+ mutex_unlock(&chip->irqlock);
+
enable_irq_wake(chip->irq);
break;
case PM_POST_SUSPEND:
- regmap_write(chip->regmap,
- chip->int_con[0], chip->irq_masks_cur[0]);
- regmap_write(chip->regmap,
- chip->int_con[1], chip->irq_masks_cur[1]);
- if (chip->int_con[2])
- regmap_write(chip->regmap,
- chip->int_con[2], chip->irq_masks_cur[2]);
+ mutex_lock(&chip->irqlock);
+ chip->irq_suspended = false;
+ mt6397_irq_write_masks(chip, chip->irq_masks_cur);
+ mutex_unlock(&chip->irqlock);
+
disable_irq_wake(chip->irq);
break;
@@ -169,6 +171,29 @@ static int mt6397_irq_pm_notifier(struct notifier_block *notifier,
return NOTIFY_DONE;
}
+static void mt6397_irq_pm_notifier_unregister(void *data)
+{
+ struct mt6397_chip *chip = data;
+
+ unregister_pm_notifier(&chip->pm_nb);
+}
+
+static void mt6397_irq_domain_remove(void *data)
+{
+ struct mt6397_chip *chip = data;
+ unsigned int hwirq;
+ unsigned int virq;
+
+ for (hwirq = 0; hwirq < MT6397_IRQ_NR; hwirq++) {
+ virq = irq_find_mapping(chip->irq_domain, hwirq);
+ if (virq)
+ irq_dispose_mapping(virq);
+ }
+
+ irq_domain_remove(chip->irq_domain);
+ chip->irq_domain = NULL;
+}
+
int mt6397_irq_init(struct mt6397_chip *chip)
{
int ret;
@@ -223,16 +248,28 @@ int mt6397_irq_init(struct mt6397_chip *chip)
return -ENOMEM;
}
+ ret = devm_add_action_or_reset(chip->dev, mt6397_irq_domain_remove,
+ chip);
+ if (ret)
+ return ret;
+
ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL,
mt6397_irq_thread, IRQF_ONESHOT,
"mt6397-pmic", chip);
if (ret) {
dev_err(chip->dev, "failed to register irq=%d; err: %d\n",
chip->irq, ret);
- irq_domain_remove(chip->irq_domain);
return ret;
}
- register_pm_notifier(&chip->pm_nb);
- return 0;
+ ret = register_pm_notifier(&chip->pm_nb);
+ if (ret) {
+ dev_err(chip->dev, "failed to register PM notifier: %d\n", ret);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(chip->dev,
+ mt6397_irq_pm_notifier_unregister, chip);
+
+ return ret;
}
diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h
index 340fc72e22aa..f9c2cbd17c5c 100644
--- a/include/linux/mfd/mt6397/core.h
+++ b/include/linux/mfd/mt6397/core.h
@@ -66,6 +66,7 @@ struct mt6397_chip {
int irq;
struct irq_domain *irq_domain;
struct mutex irqlock;
+ bool irq_suspended;
u16 wake_mask[3];
u16 irq_masks_cur[3];
u16 irq_masks_cache[3];
--
2.43.0
^ permalink raw reply related
* [PATCH v3 0/2] regulator: Rework i2c_device_id initialisation
From: Uwe Kleine-König (The Capable Hub) @ 2026-06-19 17:17 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown
Cc: Laurent Pinchart, Woodrow Douglass, linux-kernel,
Michael Hennerich, Support Opensource, Ivaylo Ivanov,
Claudiu Beznea, Saravanan Sekar, Matthias Brugger,
AngeloGioacchino Del Regno, Jagan Teki, Icenowy Zheng,
linux-arm-kernel, linux-mediatek
Hello,
v2 is available at https://lore.kernel.org/lkml/cover.1779184320.git.u.kleine-koenig@baylibre.com .
The only change is that I rebased to next-20260619 and dropped the
adaptions to the of_regulator_match arrays that Laurent pointed out to
not belong into this patch set.
Best regards
Uwe
Uwe Kleine-König (The Capable Hub) (2):
regulator: Drop unused i2c driver data
regulator: Use named initializers for arrays of i2c_device_data
drivers/regulator/88pg86x.c | 4 ++--
drivers/regulator/ad5398.c | 4 ++--
drivers/regulator/da9121-regulator.c | 20 ++++++++++----------
drivers/regulator/da9210-regulator.c | 4 ++--
drivers/regulator/da9211-regulator.c | 18 +++++++++---------
drivers/regulator/fan53880.c | 4 ++--
drivers/regulator/isl9305.c | 4 ++--
drivers/regulator/lp3971.c | 2 +-
drivers/regulator/lp3972.c | 2 +-
drivers/regulator/lp872x.c | 4 ++--
drivers/regulator/lp8755.c | 4 ++--
drivers/regulator/ltc3589.c | 6 +++---
drivers/regulator/ltc3676.c | 2 +-
drivers/regulator/max1586.c | 2 +-
drivers/regulator/max20086-regulator.c | 8 ++++----
drivers/regulator/max20411-regulator.c | 2 +-
drivers/regulator/max77503-regulator.c | 2 +-
drivers/regulator/max77675-regulator.c | 2 +-
drivers/regulator/max77826-regulator.c | 2 +-
drivers/regulator/max77838-regulator.c | 2 +-
drivers/regulator/max77857-regulator.c | 8 ++++----
drivers/regulator/max8649.c | 2 +-
drivers/regulator/max8893.c | 2 +-
drivers/regulator/max8952.c | 2 +-
drivers/regulator/mcp16502.c | 2 +-
drivers/regulator/mp5416.c | 6 +++---
drivers/regulator/mp8859.c | 4 ++--
drivers/regulator/mp886x.c | 6 +++---
drivers/regulator/mpq7920.c | 4 ++--
drivers/regulator/mt6311-regulator.c | 4 ++--
drivers/regulator/pf530x-regulator.c | 8 ++++----
drivers/regulator/pf8x00-regulator.c | 8 ++++----
drivers/regulator/pv88060-regulator.c | 4 ++--
drivers/regulator/pv88080-regulator.c | 8 ++++----
drivers/regulator/pv88090-regulator.c | 4 ++--
drivers/regulator/slg51000-regulator.c | 4 ++--
drivers/regulator/sy8106a-regulator.c | 2 +-
drivers/regulator/sy8824x.c | 8 ++++----
drivers/regulator/sy8827n.c | 4 ++--
drivers/regulator/tps6286x-regulator.c | 10 +++++-----
drivers/regulator/tps6287x-regulator.c | 10 +++++-----
41 files changed, 104 insertions(+), 104 deletions(-)
base-commit: 3ce97bd3c4f18608335e709c24d6a40e7036cab8
--
2.47.3
^ permalink raw reply
* [PATCH v3 2/2] regulator: Use named initializers for arrays of i2c_device_data
From: Uwe Kleine-König (The Capable Hub) @ 2026-06-19 17:17 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown
Cc: Michael Hennerich, Support Opensource, Laurent Pinchart,
Ivaylo Ivanov, Claudiu Beznea, Saravanan Sekar, Matthias Brugger,
AngeloGioacchino Del Regno, Woodrow Douglass, Jagan Teki,
Icenowy Zheng, linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1781888370.git.u.kleine-koenig@baylibre.com>
While being less compact, using named initializers allows to more easily
see which members of the structs are assigned which value without having
to lookup the declaration of the struct. And it's also more robust
against changes to the struct definition.
The mentioned robustness is relevant for a planned change to struct
i2c_device_id that replaces .driver_data by an anonymous union.
While touching all these arrays, unify usage of whitespace and commas.
This patch doesn't modify the compiled arrays, only their representation
in source form benefits. The former was confirmed with x86 and arm64
builds.
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
---
drivers/regulator/88pg86x.c | 4 ++--
drivers/regulator/ad5398.c | 4 ++--
drivers/regulator/da9121-regulator.c | 20 ++++++++++----------
drivers/regulator/da9210-regulator.c | 4 ++--
drivers/regulator/da9211-regulator.c | 18 +++++++++---------
drivers/regulator/fan53880.c | 4 ++--
drivers/regulator/isl9305.c | 4 ++--
drivers/regulator/lp3971.c | 2 +-
drivers/regulator/lp3972.c | 2 +-
drivers/regulator/lp872x.c | 4 ++--
drivers/regulator/lp8755.c | 4 ++--
drivers/regulator/ltc3589.c | 6 +++---
drivers/regulator/ltc3676.c | 2 +-
drivers/regulator/max1586.c | 2 +-
drivers/regulator/max20086-regulator.c | 8 ++++----
drivers/regulator/max20411-regulator.c | 2 +-
drivers/regulator/max77503-regulator.c | 2 +-
drivers/regulator/max77675-regulator.c | 2 +-
drivers/regulator/max77826-regulator.c | 2 +-
drivers/regulator/max77838-regulator.c | 2 +-
drivers/regulator/max77857-regulator.c | 8 ++++----
drivers/regulator/max8649.c | 2 +-
drivers/regulator/max8893.c | 2 +-
drivers/regulator/max8952.c | 2 +-
drivers/regulator/mcp16502.c | 2 +-
drivers/regulator/mp5416.c | 6 +++---
drivers/regulator/mp8859.c | 4 ++--
drivers/regulator/mp886x.c | 6 +++---
drivers/regulator/mpq7920.c | 4 ++--
drivers/regulator/mt6311-regulator.c | 4 ++--
drivers/regulator/pf530x-regulator.c | 6 +++---
drivers/regulator/pf8x00-regulator.c | 8 ++++----
drivers/regulator/pv88060-regulator.c | 4 ++--
drivers/regulator/pv88080-regulator.c | 8 ++++----
drivers/regulator/pv88090-regulator.c | 4 ++--
drivers/regulator/slg51000-regulator.c | 4 ++--
drivers/regulator/sy8106a-regulator.c | 2 +-
drivers/regulator/sy8824x.c | 8 ++++----
drivers/regulator/sy8827n.c | 4 ++--
drivers/regulator/tps6286x-regulator.c | 10 +++++-----
drivers/regulator/tps6287x-regulator.c | 10 +++++-----
41 files changed, 103 insertions(+), 103 deletions(-)
diff --git a/drivers/regulator/88pg86x.c b/drivers/regulator/88pg86x.c
index e6598e74ec94..8c25a1db412f 100644
--- a/drivers/regulator/88pg86x.c
+++ b/drivers/regulator/88pg86x.c
@@ -92,8 +92,8 @@ static const struct of_device_id __maybe_unused pg86x_dt_ids[] = {
MODULE_DEVICE_TABLE(of, pg86x_dt_ids);
static const struct i2c_device_id pg86x_i2c_id[] = {
- { "88pg867", },
- { "88pg868", },
+ { .name = "88pg867" },
+ { .name = "88pg868" },
{ }
};
MODULE_DEVICE_TABLE(i2c, pg86x_i2c_id);
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index eb2a666a45cb..0123ca8157a8 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -207,8 +207,8 @@ struct ad5398_current_data_format {
static const struct ad5398_current_data_format df_10_4_120 = {10, 4, 0, 120000};
static const struct i2c_device_id ad5398_id[] = {
- { "ad5398", (kernel_ulong_t)&df_10_4_120 },
- { "ad5821", (kernel_ulong_t)&df_10_4_120 },
+ { .name = "ad5398", .driver_data = (kernel_ulong_t)&df_10_4_120 },
+ { .name = "ad5821", .driver_data = (kernel_ulong_t)&df_10_4_120 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ad5398_id);
diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c
index 2b150bb4d471..8155f0974f7d 100644
--- a/drivers/regulator/da9121-regulator.c
+++ b/drivers/regulator/da9121-regulator.c
@@ -1195,16 +1195,16 @@ static void da9121_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id da9121_i2c_id[] = {
- {"da9121", DA9121_TYPE_DA9121_DA9130},
- {"da9130", DA9121_TYPE_DA9121_DA9130},
- {"da9217", DA9121_TYPE_DA9217},
- {"da9122", DA9121_TYPE_DA9122_DA9131},
- {"da9131", DA9121_TYPE_DA9122_DA9131},
- {"da9220", DA9121_TYPE_DA9220_DA9132},
- {"da9132", DA9121_TYPE_DA9220_DA9132},
- {"da9141", DA9121_TYPE_DA9141},
- {"da9142", DA9121_TYPE_DA9142},
- {},
+ { .name = "da9121", .driver_data = DA9121_TYPE_DA9121_DA9130 },
+ { .name = "da9130", .driver_data = DA9121_TYPE_DA9121_DA9130 },
+ { .name = "da9217", .driver_data = DA9121_TYPE_DA9217 },
+ { .name = "da9122", .driver_data = DA9121_TYPE_DA9122_DA9131 },
+ { .name = "da9131", .driver_data = DA9121_TYPE_DA9122_DA9131 },
+ { .name = "da9220", .driver_data = DA9121_TYPE_DA9220_DA9132 },
+ { .name = "da9132", .driver_data = DA9121_TYPE_DA9220_DA9132 },
+ { .name = "da9141", .driver_data = DA9121_TYPE_DA9141 },
+ { .name = "da9142", .driver_data = DA9121_TYPE_DA9142 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, da9121_i2c_id);
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
index 39ade0dba40f..9154e32bd745 100644
--- a/drivers/regulator/da9210-regulator.c
+++ b/drivers/regulator/da9210-regulator.c
@@ -202,8 +202,8 @@ static int da9210_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id da9210_i2c_id[] = {
- { "da9210" },
- {}
+ { .name = "da9210" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, da9210_i2c_id);
diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c
index d4f14d7ea8cf..9cf713755636 100644
--- a/drivers/regulator/da9211-regulator.c
+++ b/drivers/regulator/da9211-regulator.c
@@ -522,15 +522,15 @@ static int da9211_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id da9211_i2c_id[] = {
- {"da9211", DA9211},
- {"da9212", DA9212},
- {"da9213", DA9213},
- {"da9223", DA9223},
- {"da9214", DA9214},
- {"da9224", DA9224},
- {"da9215", DA9215},
- {"da9225", DA9225},
- {},
+ { .name = "da9211", .driver_data = DA9211 },
+ { .name = "da9212", .driver_data = DA9212 },
+ { .name = "da9213", .driver_data = DA9213 },
+ { .name = "da9223", .driver_data = DA9223 },
+ { .name = "da9214", .driver_data = DA9214 },
+ { .name = "da9224", .driver_data = DA9224 },
+ { .name = "da9215", .driver_data = DA9215 },
+ { .name = "da9225", .driver_data = DA9225 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, da9211_i2c_id);
diff --git a/drivers/regulator/fan53880.c b/drivers/regulator/fan53880.c
index 6cb5656845f9..79ba705ec324 100644
--- a/drivers/regulator/fan53880.c
+++ b/drivers/regulator/fan53880.c
@@ -164,8 +164,8 @@ static const struct of_device_id fan53880_dt_ids[] = {
MODULE_DEVICE_TABLE(of, fan53880_dt_ids);
static const struct i2c_device_id fan53880_i2c_id[] = {
- { "fan53880", },
- {}
+ { .name = "fan53880" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, fan53880_i2c_id);
diff --git a/drivers/regulator/isl9305.c b/drivers/regulator/isl9305.c
index 5a234f25e6bb..ec6bd6bb9721 100644
--- a/drivers/regulator/isl9305.c
+++ b/drivers/regulator/isl9305.c
@@ -186,8 +186,8 @@ MODULE_DEVICE_TABLE(of, isl9305_dt_ids);
#endif
static const struct i2c_device_id isl9305_i2c_id[] = {
- { "isl9305", },
- { "isl9305h", },
+ { .name = "isl9305" },
+ { .name = "isl9305h" },
{ }
};
MODULE_DEVICE_TABLE(i2c, isl9305_i2c_id);
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index d4dab86fe385..6f830ae1bb61 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -439,7 +439,7 @@ static int lp3971_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id lp3971_i2c_id[] = {
- { "lp3971" },
+ { .name = "lp3971" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id);
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
index 1b918fb72134..235c640ba57f 100644
--- a/drivers/regulator/lp3972.c
+++ b/drivers/regulator/lp3972.c
@@ -537,7 +537,7 @@ static int lp3972_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id lp3972_i2c_id[] = {
- { "lp3972" },
+ { .name = "lp3972" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lp3972_i2c_id);
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 942f37082cb1..5b2faddd8110 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -935,8 +935,8 @@ static const struct of_device_id lp872x_dt_ids[] __maybe_unused = {
MODULE_DEVICE_TABLE(of, lp872x_dt_ids);
static const struct i2c_device_id lp872x_ids[] = {
- {"lp8720", LP8720},
- {"lp8725", LP8725},
+ { .name = "lp8720", .driver_data = LP8720 },
+ { .name = "lp8725", .driver_data = LP8725 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lp872x_ids);
diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c
index 5509bee49bda..632320ba1800 100644
--- a/drivers/regulator/lp8755.c
+++ b/drivers/regulator/lp8755.c
@@ -430,8 +430,8 @@ static void lp8755_remove(struct i2c_client *client)
}
static const struct i2c_device_id lp8755_id[] = {
- { LP8755_NAME },
- {}
+ { .name = LP8755_NAME },
+ { }
};
MODULE_DEVICE_TABLE(i2c, lp8755_id);
diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c
index 3f70c2225dba..8bae5d8aeaf4 100644
--- a/drivers/regulator/ltc3589.c
+++ b/drivers/regulator/ltc3589.c
@@ -445,9 +445,9 @@ static const struct ltc3589_info ltc3589_12_info = {
};
static const struct i2c_device_id ltc3589_i2c_id[] = {
- { "ltc3589", (kernel_ulong_t)<c3589_info },
- { "ltc3589-1", (kernel_ulong_t)<c3589_12_info },
- { "ltc3589-2", (kernel_ulong_t)<c3589_12_info },
+ { .name = "ltc3589", .driver_data = (kernel_ulong_t)<c3589_info },
+ { .name = "ltc3589-1", .driver_data = (kernel_ulong_t)<c3589_12_info },
+ { .name = "ltc3589-2", .driver_data = (kernel_ulong_t)<c3589_12_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltc3589_i2c_id);
diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c
index 73d511eb1c1d..597d20a200d7 100644
--- a/drivers/regulator/ltc3676.c
+++ b/drivers/regulator/ltc3676.c
@@ -357,7 +357,7 @@ static int ltc3676_regulator_probe(struct i2c_client *client)
}
static const struct i2c_device_id ltc3676_i2c_id[] = {
- { "ltc3676" },
+ { .name = "ltc3676" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltc3676_i2c_id);
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index 4242fbb7b147..e5cbc09c2d39 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -276,7 +276,7 @@ static int max1586_pmic_probe(struct i2c_client *client)
}
static const struct i2c_device_id max1586_id[] = {
- { "max1586" },
+ { .name = "max1586" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max1586_id);
diff --git a/drivers/regulator/max20086-regulator.c b/drivers/regulator/max20086-regulator.c
index fcdd2d0317a5..92594b2915f3 100644
--- a/drivers/regulator/max20086-regulator.c
+++ b/drivers/regulator/max20086-regulator.c
@@ -301,10 +301,10 @@ static const struct max20086_chip_info max20089_chip_info = {
};
static const struct i2c_device_id max20086_i2c_id[] = {
- { "max20086", (kernel_ulong_t)&max20086_chip_info },
- { "max20087", (kernel_ulong_t)&max20087_chip_info },
- { "max20088", (kernel_ulong_t)&max20088_chip_info },
- { "max20089", (kernel_ulong_t)&max20089_chip_info },
+ { .name = "max20086", .driver_data = (kernel_ulong_t)&max20086_chip_info },
+ { .name = "max20087", .driver_data = (kernel_ulong_t)&max20087_chip_info },
+ { .name = "max20088", .driver_data = (kernel_ulong_t)&max20088_chip_info },
+ { .name = "max20089", .driver_data = (kernel_ulong_t)&max20089_chip_info },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, max20086_i2c_id);
diff --git a/drivers/regulator/max20411-regulator.c b/drivers/regulator/max20411-regulator.c
index 6c0ebb970e90..ac7a9aa014aa 100644
--- a/drivers/regulator/max20411-regulator.c
+++ b/drivers/regulator/max20411-regulator.c
@@ -145,7 +145,7 @@ static const struct of_device_id of_max20411_match_tbl[] = {
MODULE_DEVICE_TABLE(of, of_max20411_match_tbl);
static const struct i2c_device_id max20411_id[] = {
- { "max20411" },
+ { .name = "max20411" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max20411_id);
diff --git a/drivers/regulator/max77503-regulator.c b/drivers/regulator/max77503-regulator.c
index c7c94e868fc1..1cae846f96d0 100644
--- a/drivers/regulator/max77503-regulator.c
+++ b/drivers/regulator/max77503-regulator.c
@@ -107,7 +107,7 @@ static const struct of_device_id of_max77503_match_tbl[] = {
MODULE_DEVICE_TABLE(of, of_max77503_match_tbl);
static const struct i2c_device_id max77503_regulator_id[] = {
- {"max77503"},
+ { .name = "max77503" },
{ }
};
diff --git a/drivers/regulator/max77675-regulator.c b/drivers/regulator/max77675-regulator.c
index 57350526afd7..ebea08ddf4b8 100644
--- a/drivers/regulator/max77675-regulator.c
+++ b/drivers/regulator/max77675-regulator.c
@@ -1029,7 +1029,7 @@ static int max77675_regulator_probe(struct i2c_client *client)
}
static const struct i2c_device_id max77675_i2c_id[] = {
- { "max77675" },
+ { .name = "max77675" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max77675_i2c_id);
diff --git a/drivers/regulator/max77826-regulator.c b/drivers/regulator/max77826-regulator.c
index 310bc8ee7af8..8b60a9fcab44 100644
--- a/drivers/regulator/max77826-regulator.c
+++ b/drivers/regulator/max77826-regulator.c
@@ -278,7 +278,7 @@ static const struct of_device_id __maybe_unused max77826_of_match[] = {
MODULE_DEVICE_TABLE(of, max77826_of_match);
static const struct i2c_device_id max77826_id[] = {
- { "max77826-regulator" },
+ { .name = "max77826-regulator" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, max77826_id);
diff --git a/drivers/regulator/max77838-regulator.c b/drivers/regulator/max77838-regulator.c
index 9faddbfd25fd..765756fdcf6e 100644
--- a/drivers/regulator/max77838-regulator.c
+++ b/drivers/regulator/max77838-regulator.c
@@ -200,7 +200,7 @@ static const struct of_device_id __maybe_unused max77838_of_match[] = {
MODULE_DEVICE_TABLE(of, max77838_of_match);
static const struct i2c_device_id max77838_id[] = {
- { "max77838-regulator" },
+ { .name = "max77838-regulator" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, max77838_id);
diff --git a/drivers/regulator/max77857-regulator.c b/drivers/regulator/max77857-regulator.c
index 1216cc3a6f72..f1410f845653 100644
--- a/drivers/regulator/max77857-regulator.c
+++ b/drivers/regulator/max77857-regulator.c
@@ -428,10 +428,10 @@ static int max77857_probe(struct i2c_client *client)
}
static const struct i2c_device_id max77857_id[] = {
- { "max77831", ID_MAX77831 },
- { "max77857", ID_MAX77857 },
- { "max77859", ID_MAX77859 },
- { "max77859a", ID_MAX77859A },
+ { .name = "max77831", .driver_data = ID_MAX77831 },
+ { .name = "max77857", .driver_data = ID_MAX77857 },
+ { .name = "max77859", .driver_data = ID_MAX77859 },
+ { .name = "max77859a", .driver_data = ID_MAX77859A },
{ }
};
MODULE_DEVICE_TABLE(i2c, max77857_id);
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index f57c588bcf28..2d17405242e7 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -240,7 +240,7 @@ static int max8649_regulator_probe(struct i2c_client *client)
}
static const struct i2c_device_id max8649_id[] = {
- { "max8649" },
+ { .name = "max8649" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max8649_id);
diff --git a/drivers/regulator/max8893.c b/drivers/regulator/max8893.c
index 5a90633d8536..7a0e44a16d49 100644
--- a/drivers/regulator/max8893.c
+++ b/drivers/regulator/max8893.c
@@ -162,7 +162,7 @@ MODULE_DEVICE_TABLE(of, max8893_dt_match);
#endif
static const struct i2c_device_id max8893_ids[] = {
- { "max8893" },
+ { .name = "max8893" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max8893_ids);
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index 1f94315bfb02..f8b91a5701f3 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -307,7 +307,7 @@ static int max8952_pmic_probe(struct i2c_client *client)
}
static const struct i2c_device_id max8952_ids[] = {
- { "max8952" },
+ { .name = "max8952" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max8952_ids);
diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c
index b34ae0bbba6f..89fd79d446f7 100644
--- a/drivers/regulator/mcp16502.c
+++ b/drivers/regulator/mcp16502.c
@@ -578,7 +578,7 @@ static const struct dev_pm_ops mcp16502_pm_ops = {
};
#endif
static const struct i2c_device_id mcp16502_i2c_id[] = {
- { "mcp16502" },
+ { .name = "mcp16502" },
{ }
};
MODULE_DEVICE_TABLE(i2c, mcp16502_i2c_id);
diff --git a/drivers/regulator/mp5416.c b/drivers/regulator/mp5416.c
index e6794190cb68..2948635b1b9f 100644
--- a/drivers/regulator/mp5416.c
+++ b/drivers/regulator/mp5416.c
@@ -228,9 +228,9 @@ static const struct of_device_id mp5416_of_match[] = {
MODULE_DEVICE_TABLE(of, mp5416_of_match);
static const struct i2c_device_id mp5416_id[] = {
- { "mp5416", (kernel_ulong_t)&mp5416_regulators_desc },
- { "mp5496", (kernel_ulong_t)&mp5496_regulators_desc },
- {}
+ { .name = "mp5416", .driver_data = (kernel_ulong_t)&mp5416_regulators_desc },
+ { .name = "mp5496", .driver_data = (kernel_ulong_t)&mp5496_regulators_desc },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mp5416_id);
diff --git a/drivers/regulator/mp8859.c b/drivers/regulator/mp8859.c
index ab105ffd6a2e..9a708e826d93 100644
--- a/drivers/regulator/mp8859.c
+++ b/drivers/regulator/mp8859.c
@@ -386,8 +386,8 @@ static const struct of_device_id mp8859_dt_id[] __maybe_unused = {
MODULE_DEVICE_TABLE(of, mp8859_dt_id);
static const struct i2c_device_id mp8859_i2c_id[] = {
- { "mp8859", },
- { },
+ { .name = "mp8859" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mp8859_i2c_id);
diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c
index 9ad16b04c913..e0b62bc02a1e 100644
--- a/drivers/regulator/mp886x.c
+++ b/drivers/regulator/mp886x.c
@@ -348,9 +348,9 @@ static const struct of_device_id mp886x_dt_ids[] = {
MODULE_DEVICE_TABLE(of, mp886x_dt_ids);
static const struct i2c_device_id mp886x_id[] = {
- { "mp8867", (kernel_ulong_t)&mp8867_ci },
- { "mp8869", (kernel_ulong_t)&mp8869_ci },
- { },
+ { .name = "mp8867", .driver_data = (kernel_ulong_t)&mp8867_ci },
+ { .name = "mp8869", .driver_data = (kernel_ulong_t)&mp8869_ci },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mp886x_id);
diff --git a/drivers/regulator/mpq7920.c b/drivers/regulator/mpq7920.c
index a670e09891e7..0cbc17deb1d1 100644
--- a/drivers/regulator/mpq7920.c
+++ b/drivers/regulator/mpq7920.c
@@ -309,8 +309,8 @@ static const struct of_device_id mpq7920_of_match[] = {
MODULE_DEVICE_TABLE(of, mpq7920_of_match);
static const struct i2c_device_id mpq7920_id[] = {
- { "mpq7920", },
- { },
+ { .name = "mpq7920" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mpq7920_id);
diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c
index 2ebc1c0b5e6f..1d457d1fdf23 100644
--- a/drivers/regulator/mt6311-regulator.c
+++ b/drivers/regulator/mt6311-regulator.c
@@ -133,8 +133,8 @@ static int mt6311_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id mt6311_i2c_id[] = {
- { "mt6311" },
- {}
+ { .name = "mt6311" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mt6311_i2c_id);
diff --git a/drivers/regulator/pf530x-regulator.c b/drivers/regulator/pf530x-regulator.c
index ef3d5bb784cd..8ad1cbbd7a8c 100644
--- a/drivers/regulator/pf530x-regulator.c
+++ b/drivers/regulator/pf530x-regulator.c
@@ -353,9 +353,9 @@ static const struct of_device_id pf530x_dt_ids[] = {
MODULE_DEVICE_TABLE(of, pf530x_dt_ids);
static const struct i2c_device_id pf530x_i2c_id[] = {
- { "pf5300" },
- { "pf5301" },
- { "pf5302" },
+ { .name = "pf5300" },
+ { .name = "pf5301" },
+ { .name = "pf5302" },
{ }
};
MODULE_DEVICE_TABLE(i2c, pf530x_i2c_id);
diff --git a/drivers/regulator/pf8x00-regulator.c b/drivers/regulator/pf8x00-regulator.c
index ea3611de42b4..c938b4632ef1 100644
--- a/drivers/regulator/pf8x00-regulator.c
+++ b/drivers/regulator/pf8x00-regulator.c
@@ -596,10 +596,10 @@ static const struct of_device_id pf8x00_dt_ids[] = {
MODULE_DEVICE_TABLE(of, pf8x00_dt_ids);
static const struct i2c_device_id pf8x00_i2c_id[] = {
- { "pf8100" },
- { "pf8121a" },
- { "pf8200" },
- {}
+ { .name = "pf8100" },
+ { .name = "pf8121a" },
+ { .name = "pf8200" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, pf8x00_i2c_id);
diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c
index ae1c4b9daaa1..375d9e759c47 100644
--- a/drivers/regulator/pv88060-regulator.c
+++ b/drivers/regulator/pv88060-regulator.c
@@ -360,8 +360,8 @@ static int pv88060_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id pv88060_i2c_id[] = {
- { "pv88060" },
- {}
+ { .name = "pv88060" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, pv88060_i2c_id);
diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c
index 9fe539a34786..3dc48d059791 100644
--- a/drivers/regulator/pv88080-regulator.c
+++ b/drivers/regulator/pv88080-regulator.c
@@ -523,10 +523,10 @@ static const struct of_device_id pv88080_dt_ids[] = {
MODULE_DEVICE_TABLE(of, pv88080_dt_ids);
static const struct i2c_device_id pv88080_i2c_id[] = {
- { "pv88080", (kernel_ulong_t)&pv88080_aa_regs },
- { "pv88080-aa", (kernel_ulong_t)&pv88080_aa_regs },
- { "pv88080-ba", (kernel_ulong_t)&pv88080_ba_regs },
- {}
+ { .name = "pv88080", .driver_data = (kernel_ulong_t)&pv88080_aa_regs },
+ { .name = "pv88080-aa", .driver_data = (kernel_ulong_t)&pv88080_aa_regs },
+ { .name = "pv88080-ba", .driver_data = (kernel_ulong_t)&pv88080_ba_regs },
+ { }
};
MODULE_DEVICE_TABLE(i2c, pv88080_i2c_id);
diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c
index 3c48757bbbda..ca5eeb5dfe62 100644
--- a/drivers/regulator/pv88090-regulator.c
+++ b/drivers/regulator/pv88090-regulator.c
@@ -381,8 +381,8 @@ static int pv88090_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id pv88090_i2c_id[] = {
- { "pv88090" },
- {}
+ { .name = "pv88090" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, pv88090_i2c_id);
diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c
index 3bbd4a29e6d3..d682764cdbf8 100644
--- a/drivers/regulator/slg51000-regulator.c
+++ b/drivers/regulator/slg51000-regulator.c
@@ -497,8 +497,8 @@ static int slg51000_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id slg51000_i2c_id[] = {
- { "slg51000" },
- {}
+ { .name = "slg51000" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, slg51000_i2c_id);
diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c
index d79a4cc25a0d..b2b835c60262 100644
--- a/drivers/regulator/sy8106a-regulator.c
+++ b/drivers/regulator/sy8106a-regulator.c
@@ -130,7 +130,7 @@ static const struct of_device_id sy8106a_i2c_of_match[] = {
MODULE_DEVICE_TABLE(of, sy8106a_i2c_of_match);
static const struct i2c_device_id sy8106a_i2c_id[] = {
- { "sy8106a" },
+ { .name = "sy8106a" },
{ }
};
MODULE_DEVICE_TABLE(i2c, sy8106a_i2c_id);
diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c
index 5bec84db25f1..3f07e7da90cb 100644
--- a/drivers/regulator/sy8824x.c
+++ b/drivers/regulator/sy8824x.c
@@ -213,10 +213,10 @@ static const struct of_device_id sy8824_dt_ids[] = {
MODULE_DEVICE_TABLE(of, sy8824_dt_ids);
static const struct i2c_device_id sy8824_id[] = {
- { "sy8824c", (kernel_ulong_t)&sy8824c_cfg },
- { "sy8824e", (kernel_ulong_t)&sy8824e_cfg },
- { "sy20276", (kernel_ulong_t)&sy20276_cfg },
- { "sy20278", (kernel_ulong_t)&sy20278_cfg },
+ { .name = "sy8824c", .driver_data = (kernel_ulong_t)&sy8824c_cfg },
+ { .name = "sy8824e", .driver_data = (kernel_ulong_t)&sy8824e_cfg },
+ { .name = "sy20276", .driver_data = (kernel_ulong_t)&sy20276_cfg },
+ { .name = "sy20278", .driver_data = (kernel_ulong_t)&sy20278_cfg },
{ }
};
MODULE_DEVICE_TABLE(i2c, sy8824_id);
diff --git a/drivers/regulator/sy8827n.c b/drivers/regulator/sy8827n.c
index 0b811514782f..a1cac8cc3d96 100644
--- a/drivers/regulator/sy8827n.c
+++ b/drivers/regulator/sy8827n.c
@@ -180,8 +180,8 @@ static const struct of_device_id sy8827n_dt_ids[] = {
MODULE_DEVICE_TABLE(of, sy8827n_dt_ids);
static const struct i2c_device_id sy8827n_id[] = {
- { "sy8827n", },
- { },
+ { .name = "sy8827n" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, sy8827n_id);
diff --git a/drivers/regulator/tps6286x-regulator.c b/drivers/regulator/tps6286x-regulator.c
index e29aab06bf79..1ab53bee9f6e 100644
--- a/drivers/regulator/tps6286x-regulator.c
+++ b/drivers/regulator/tps6286x-regulator.c
@@ -145,11 +145,11 @@ static int tps6286x_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id tps6286x_i2c_id[] = {
- { "tps62864" },
- { "tps62866" },
- { "tps62868" },
- { "tps62869" },
- {}
+ { .name = "tps62864" },
+ { .name = "tps62866" },
+ { .name = "tps62868" },
+ { .name = "tps62869" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, tps6286x_i2c_id);
diff --git a/drivers/regulator/tps6287x-regulator.c b/drivers/regulator/tps6287x-regulator.c
index 7b7d3ae39206..c0bc4a6192c4 100644
--- a/drivers/regulator/tps6287x-regulator.c
+++ b/drivers/regulator/tps6287x-regulator.c
@@ -229,11 +229,11 @@ static const struct of_device_id tps6287x_dt_ids[] = {
MODULE_DEVICE_TABLE(of, tps6287x_dt_ids);
static const struct i2c_device_id tps6287x_i2c_id[] = {
- { "tps62870" },
- { "tps62871" },
- { "tps62872" },
- { "tps62873" },
- {}
+ { .name = "tps62870" },
+ { .name = "tps62871" },
+ { .name = "tps62872" },
+ { .name = "tps62873" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, tps6287x_i2c_id);
--
2.47.3
^ permalink raw reply related
* Re: [PATCH RFC v2 0/4] Add support for DisplayPort link training information report
From: Kory Maincent @ 2026-06-19 17:49 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
Tvrtko Ursulin, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Dmitry Baryshkov, Daniel Stone
Cc: Thomas Petazzoni, Mark Yacoub, Sean Paul, Manasi Navare,
Drew Davenport, Louis Chauvet, dri-devel, linux-kernel, intel-gfx,
intel-xe, linux-mediatek, linux-arm-kernel
In-Reply-To: <20260619-feat_link_cap-v2-0-a3dec4c02ad9@bootlin.com>
Hello
On Fri, 19 Jun 2026 16:08:42 +0200
Kory Maincent <kory.maincent@bootlin.com> wrote:
> DisplayPort link training negotiates the physical-layer parameters needed
> for a reliable connection: lane count, link rate, and optionally Display
> Stream Compression (DSC). Currently, each driver exposes this state in
> its own way, often through driver-specific debugfs entries, with no
> standard interface for userspace diagnostic and monitoring tools.
>
> This series introduces generic, managed and unmanaged DisplayPort
> connector initialization helpers, for exposing DP link capabilities and
> state as standard sysfs entries, modeled after the existing HDMI helper
> drmm_connector_hdmi_init().
>
> The aim of such development is to guide users to select the most suitable
> DisplayPort connector for their needs. For example, if you have a USB-C
> hub with lesser capabilities than your computer’s native DisplayPort
> connector (such as HBR2 versus HBR3 support), the system could recommend
> connecting high-resolution displays directly to the computer’s port
> instead of through the hub to ensure optimal performance.
>
> These new drmm_connector_dp_init() and drm_connector_dp_init_with_ddc()
> helpers initialize a DP connector and expose link training capabilities
> and state to userspace via sysfs attributes under dp_link.
>
> Additional helpers are provided to manage link capabilities and parameters
> at runtime.
>
> Two drivers are updated as reference implementations: i915 (direct
> connector path) and MediaTek (via the bridge connector framework using a
> new DRM_BRIDGE_OP_DP flag).
>
> The changes updating the i915 driver to use DRM managed resources have been
> removed due to cleanup path issues. The core problem is that some functions
> do not consistently propagate errors through their call paths (whether this
> is intentional or not) making it difficult to properly handle cleanup of
> DRM objects (planes, encoders, connectors). A potential solution would be
> to implement something similar to devres_group for each DRM object type,
> but this represents a substantial undertaking that falls outside the scope
> of this patch series.
>
> The MST case in i915 driver is not supported yet.
I have seen and fixed the reviews from Sashiko.
I prefer to wait for human reviews about the core design before sending a v3, so
don't hesitate to look at the series. Mainly the first patch which tackle core
DRM changes.
Regards,
--
Köry Maincent, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH v1] ARM: highbank: Fix OF node refcount leaks
From: 최유호 @ 2026-06-19 18:38 UTC (permalink / raw)
To: Andre Przywara, Russell King; +Cc: linux-arm-kernel, linux-kernel
In-Reply-To: <20260525031312.1341109-1-dbgh9129@gmail.com>
Hi,
Just a gentle ping on this patch.
I would appreciate any feedback when you have a chance to review this.
Thanks
^ permalink raw reply
* Re: [PATCH 00/11] ARM: NXP: Drop NOMMU platform support
From: Arnd Bergmann @ 2026-06-19 19:17 UTC (permalink / raw)
To: Vladimir Zapolskiy, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Stefan Agner, Fabio Estevam, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Russell King, Abel Vesa,
Peng Fan, Michael Turquette, Stephen Boyd, Brian Masney,
Aisheng Dong, Jacky Bai, NXP S32 Linux Team, Linus Walleij,
Piotr Wojtaszczyk, Kees Cook, Gustavo A. R. Silva
Cc: linux-arm-kernel, imx, devicetree, linux-kernel, linux-clk,
open list:GPIO SUBSYSTEM, linux-hardening, Frank Li
In-Reply-To: <7d946861-c3cb-4512-9d5f-9f4cb9b7ee8a@kernel.org>
On Fri, Jun 19, 2026, at 18:07, Vladimir Zapolskiy wrote:
> On 6/19/26 18:40, Frank.Li@oss.nxp.com wrote:
>> Commercial users and hardware vendors migrated to Zephyr or other RTOS
>> solutions years ago, leaving the NOMMU platform support effectively
>> unused and unmaintained.
>>
>> Remove the obsolete support to reduce maintenance burden and simplify the
>> Freescale/nxp platform code.
>>
>> Some driver code still be kept and may clean up later since it is possible
>> reused by other SoC.
Thanks a lot for going through these already!
>> Signed-off-by: Frank Li <Frank.Li@nxp.com>
>
> This change is a bit too early to happen, I prefer to get it orchestrated
> by Arnd. So, as for today I NAK the change for its NXP LPC part.
I am planning to post a series of deprecation notices for platforms
that I would like to remove for one reason or another. Since it's only
one more merge before the next (S)LTS kernel, my idea was to post
the series once v7.2-rc1 is out, merge it into 7.3-LTS and remove
the deprecated code early next year once the LTS release is announced.
I have rebased uploaded my current draft to
https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git/log/?h=rfc-arm-deprecation-7.2
None of those are finalized of course, and we can do any part
of it earlier or later (or not at all) if there is a good reason.
If you to remove the vf610m4/imx7d-cm4/lpc43xx/lpc18xx portions
earlier, that is definitely fine with me. For imxrt1050, there a
slightly higher chance that this is still used, so I would
prefer to wait for the LTS kernel on that one.
>> Frank Li (11):
>> ARM: dts: vf610m4: Remove NOMMU platform support
>> ARM: dts: imxrt1050: Remove NOMMU platform support
>> ARM: imx: Remove NOMMU platform support
>> clk: imx: imxrt1050: Remove NOMMU platform support
>> pinctrl: freescale: IMXRT: Remove NOMMU platform support
>> ARM: imxrt_defconfig: Remove NOMMU platform support
>> ARM: dts: lpc: Remove NOMMU platform support
>> ARM: mach-lpc: Remove NOMMU platform support
>> ARM: configs: lpc*: Remove NOMMU platform support
>> clk: nxp: lpc: Remove NOMMU platform support
>> pinctrl: nxp: lpc: Remove NOMMU platform support
>
> NXP LPC32xx is ARMv5 and it has MMU, hence it's plainly out of scope of
> the proposed "dropping NOMMU platform support".
Agreed. There are a few more platforms with MMU that I would like
to drop because they were never converted to devicetree support,
but there is nothing wrong with lpc32xx.
Arnd
^ permalink raw reply
* Re: [PATCH RFC 1/3] cpu/hotplug: Introduce CONFIG_PARALLEL_SMT_PRIMARY_FIRST
From: Thomas Gleixner @ 2026-06-19 19:27 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Jinjie Ruan, catalin.marinas, will, tsbogend, pjw, palmer, aou,
alex, mingo, bp, dave.hansen, hpa, kees, nathan, linusw, ojeda,
david.kaplan, lukas.bulwahn, ryan.roberts, maz, timothy.hayes,
lpieralisi, thuth, oupton, yeoreum.yun, miko.lenczewski, broonie,
kevin.brodsky, james.clark, tabba, mrigendra.chaubey, arnd,
anshuman.khandual, x86, linux-kernel, linux-arm-kernel,
linux-mips, linux-riscv
In-Reply-To: <20260619094130.GU49951@noisy.programming.kicks-ass.net>
On Fri, Jun 19 2026 at 11:41, Peter Zijlstra wrote:
> On Thu, Jun 18, 2026 at 05:17:03PM +0200, Thomas Gleixner wrote:
>
>> Something simple like the uncompiled below should just work, no?
>>
>> ---
>> --- a/arch/Kconfig
>> +++ b/arch/Kconfig
>> @@ -102,6 +102,10 @@ config HOTPLUG_PARALLEL
>> bool
>> select HOTPLUG_SPLIT_STARTUP
>>
>> +config HOTPLUG_PARALLEL_SMT
>> + bool
>> + select HOTPLUG_PARALLEL
>
> depends on ARCH_SUPPORTS_SCHED_SMT ?
Probably. Did not think about that as this has to be anyway selected by
the architecture.
^ permalink raw reply
* Re: [PATCH] iommu/io-pgtable-arm: Add support for contiguous hint bit
From: Daniel Mentz @ 2026-06-19 19:40 UTC (permalink / raw)
To: Vijayanand Jitta
Cc: Joerg Roedel (AMD), Will Deacon, Robin Murphy, linux-arm-msm,
iommu, linux-kernel, linux-arm-kernel, Prakash Gupta
In-Reply-To: <20260618-iommu_contig_hint-v1-1-4502a59e6388@oss.qualcomm.com>
On Thu, Jun 18, 2026 at 2:06 AM Vijayanand Jitta
<vijayanand.jitta@oss.qualcomm.com> wrote:
> Support is gated behind CONFIG_IOMMU_IO_PGTABLE_CONTIG_HINT, which
> provides a compile-time opt-out for hardware affected by SMMU errata
> related to the contiguous bit.
Have you considered making this a runtime option? Compare this with
arm_smmu_device_iidr_probe() where the smmuv3 driver disables certain
features based on the identified implementation and the errata
affecting that implementation.
> On the mapping side, __arm_lpae_map() detects when the requested size
> matches a contiguous range at the next level, sets the CONT bit on all
> PTEs in the group, then recurses with the base block size and an
> adjusted pgcount.
I would perform this check at the current level not the previous
level. See comments below.
>
> On the unmapping side, the CONT bit is cleared from all PTEs in the
> affected contiguous group before any individual entry is invalidated,
> following the Break-Before-Make requirement of the architecture.
My understanding is that for unmap operations, the following rule applies:
The IOVA range targeted by an unmap operation must exactly match the
IOVA range of a previous map operation. Partial unmap operations are
not allowed.
The iopgtable code previously had a function named
arm_lpae_split_blk_unmap() which allowed a block mapping to be split
up. However, that function has since been removed, which aligns with
prohibiting partial unmaps.
The other concern I have is a potential race condition: While one
thread clears the contiguous bit, another thread could try to unmap
the same descriptor.
Consider dropping support for partial unmap and just triggering a
WARN_ON() if you detect that a contiguous group is partially unmapped.
> +static inline int arm_lpae_cont_pmds(unsigned long size)
PMD is not a term that is used in this file. I advise against
introducing this term.
> +static u32 arm_lpae_find_num_cont(struct arm_lpae_io_pgtable *data, int lvl)
> +{
> + if (lvl == ARM_LPAE_MAX_LEVELS - 2)
> + return arm_lpae_cont_pmds(ARM_LPAE_BLOCK_SIZE(lvl, data));
> + else if (lvl == ARM_LPAE_MAX_LEVELS - 1)
> + return arm_lpae_cont_ptes(ARM_LPAE_BLOCK_SIZE(lvl, data));
Consider supporting the contiguous bit at lookup level 1.
> static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
> phys_addr_t paddr, size_t size, size_t pgcount,
> arm_lpae_iopte prot, int lvl, arm_lpae_iopte *ptep,
> @@ -463,6 +583,7 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
> size_t tblsz = ARM_LPAE_GRANULE(data);
> struct io_pgtable_cfg *cfg = &data->iop.cfg;
> int ret = 0, num_entries, max_entries, map_idx_start;
> + u32 num_cont = 1;
>
> /* Find our entry at the current level */
> map_idx_start = ARM_LPAE_LVL_IDX(iova, lvl, data);
> @@ -505,6 +626,24 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
> return -EEXIST;
> }
>
> + if (arm_lpae_pte_is_contiguous_range(data, size, lvl + 1, &num_cont)) {
I would recommend performing this check at the actual level not at the
previous lookup level i.e. not at the (lvl - 1) level. Imagine the
following situation: The granule size is 4KB, the initial lookup level
is 2, and size is 32MB. I'm wondering if in that case, it'll just keep
recursing until it hits (WARN_ON(lvl >= ARM_LPAE_MAX_LEVELS - 1)).
> +#ifdef CONFIG_IOMMU_IO_PGTABLE_CONTIG_HINT
> +static void arm_lpae_cont_clear(struct arm_lpae_io_pgtable *data,
> + unsigned long iova, int lvl,
> + arm_lpae_iopte *ptep, size_t num_entries)
> +{
> + struct io_pgtable_cfg *cfg = &data->iop.cfg;
> + u32 num_cont = arm_lpae_find_num_cont(data, lvl);
> + arm_lpae_iopte *cont_ptep;
> + arm_lpae_iopte *cont_ptep_start;
> + unsigned long cont_iova;
> + int offset, itr;
> +
> + cont_ptep = ptep - ARM_LPAE_LVL_IDX(iova, lvl, data);
> + cont_iova = round_down(iova,
> + ARM_LPAE_BLOCK_SIZE(lvl, data) * num_cont);
As a result of this round_down() function, you are accessing a
descriptor that describes an IOVA outside the range targeted by the
iommu_unmap call. Consequently, you might race against another thread
accessing the same descriptor.
> + cont_ptep += ARM_LPAE_LVL_IDX(cont_iova, lvl, data);
> + cont_ptep_start = cont_ptep;
> +
> + /*
> + * iova may not be aligned to the contiguous group boundary; include
> + * any leading entries so round_up() covers all overlapping groups.
> + */
> + offset = ARM_LPAE_LVL_IDX(iova, lvl, data) -
> + ARM_LPAE_LVL_IDX(cont_iova, lvl, data);
> + num_entries = round_up(offset + num_entries, num_cont);
> +
> + for (itr = 0; itr < num_entries; itr++) {
> + WRITE_ONCE(*cont_ptep, READ_ONCE(*cont_ptep) & ~ARM_LPAE_PTE_CONT);
This read-modify-write operation is not safe due to the potential race
described above.
> + cont_ptep++;
> + }
> +
> + if (!cfg->coherent_walk)
> + __arm_lpae_sync_pte(cont_ptep_start, num_entries, cfg);
> +}
> +#else
> +static void arm_lpae_cont_clear(struct arm_lpae_io_pgtable *data,
> + unsigned long iova, int lvl,
> + arm_lpae_iopte *ptep, size_t num_entries)
> +{
> +}
> +#endif
> +
> static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
> struct iommu_iotlb_gather *gather,
> unsigned long iova, size_t size, size_t pgcount,
> @@ -660,7 +841,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
> {
> arm_lpae_iopte pte;
> struct io_pgtable *iop = &data->iop;
> - int i = 0, num_entries, max_entries, unmap_idx_start;
> + int i = 0, num_cont = 1, num_entries, max_entries, unmap_idx_start;
>
> /* Something went horribly wrong and we ran out of page table */
> if (WARN_ON(lvl == ARM_LPAE_MAX_LEVELS))
> @@ -675,9 +856,15 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
> }
>
> /* If the size matches this level, we're in the right place */
> - if (size == ARM_LPAE_BLOCK_SIZE(lvl, data)) {
> + if (size == ARM_LPAE_BLOCK_SIZE(lvl, data) ||
> + (size == arm_lpae_find_num_cont(data, lvl) *
> + ARM_LPAE_BLOCK_SIZE(lvl, data))) {
> + size_t pte_size;
> +
> max_entries = arm_lpae_max_entries(unmap_idx_start, data);
> - num_entries = min_t(int, pgcount, max_entries);
> + num_cont = arm_lpae_check_num_cont(data, size, lvl);
> + num_entries = min_t(int, num_cont * pgcount, max_entries);
> + pte_size = size / num_cont;
>
> /* Find and handle non-leaf entries */
> for (i = 0; i < num_entries; i++) {
> @@ -687,11 +874,27 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
> break;
> }
>
> + /*
> + * Break-Before-Make: before invalidating any leaf
> + * entry, clear the CONT bit from every entry in the
> + * contiguous group(s) and flush the TLB, as required
> + * by the architecture. arm_lpae_cont_clear() covers
> + * the full [iova, iova + num_entries * pte_size) range
> + * via round_up(), so subsequent entries read back
> + * CONT=0 and skip this block.
> + */
> + if (pte & ARM_LPAE_PTE_CONT) {
> + arm_lpae_cont_clear(data, iova, lvl, ptep, num_entries);
> + io_pgtable_tlb_flush_walk(iop, iova,
> + num_entries * pte_size,
> + ARM_LPAE_GRANULE(data));
I believe this is inefficient. Consider the case where we unmap 2MB
worth of IOVA space mapped by 512 4KB page descriptors with the
contiguous bit set. If I'm not mistaken, you're running CMOs
(__arm_lpae_sync_pte) twice for every page descriptor. In addition,
io_pgtable_tlb_flush_walk() will submit an extra CMD_SYNC and wait for
it's completion.
Additionally, you perform rounding in arm_lpae_cont_clear(). However,
io_pgtable_tlb_flush_walk() is called on the original, potentially
unaligned range. Can this lead to under invalidation? Again, my
preference would be to drop support for partial unmaps which would
also remove the requirement for calling io_pgtable_tlb_flush_walk()
here.
> + }
> +
> if (!iopte_leaf(pte, lvl, iop->fmt)) {
> __arm_lpae_clear_pte(&ptep[i], &iop->cfg, 1);
>
> /* Also flush any partial walks */
> - io_pgtable_tlb_flush_walk(iop, iova + i * size, size,
> + io_pgtable_tlb_flush_walk(iop, iova + i * pte_size, pte_size,
> ARM_LPAE_GRANULE(data));
> __arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data));
> }
^ permalink raw reply
* ❌ FAIL: Test report for for-kernelci (7.1.0-rc7, upstream-arm-next, 92e3f6ef)
From: cki-project @ 2026-06-19 19:52 UTC (permalink / raw)
To: will, catalin.marinas, linux-arm-kernel, fs-test
Hi, we tested your kernel and here are the results:
Overall result: FAILED
Merge: OK
Compile: OK
Test: FAILED
Kernel information:
Commit message: Merge branch 'for-next/core' into for-kernelci
You can find all the details about the test run at
https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:2615019607
One or more kernel tests failed:
Unrecognized or new issues:
xfstests - btrfs
aarch64
Logs: https://datawarehouse.cki-project.org/kcidb/tests/redhat:2615019607_aarch64_kernel_kcidb_tool_21495614_9
Non-passing ran subtests:
❌ FAIL generic/301
We also see the following known issues which are not related to your changes:
Issue: [upstream] Hardware - Firmware test suite - auto-waive failures
URL: https://gitlab.com/cki-project/infrastructure/-/issues/779
Affected tests:
Hardware - Firmware test suite [aarch64]
If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.
Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.
,-. ,-.
( C ) ( K ) Continuous
`-',-.`-' Kernel
( I ) Integration
`-'
______________________________________________________________________________
^ permalink raw reply
* [PATCH v1] irqchip/gic-v3-its: Fix OF node reference leak
From: Yuho Choi @ 2026-06-19 18:58 UTC (permalink / raw)
To: Marc Zyngier, Thomas Gleixner; +Cc: linux-arm-kernel, linux-kernel, Yuho Choi
of_get_cpu_node() returns a referenced device node. In
its_cpu_init_collection(), the node is only used to get the CPU NUMA
node for the Cavium 23144 workaround, but the reference is never
dropped.
Store the NUMA node locally and call of_node_put() before either
continuing with collection setup or returning early for a NUMA mismatch.
Fixes: 920181ce8469 ("irqchip/gic-v3-its: Add ability to resend MAPC on resume")
Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
---
drivers/irqchip/irq-gic-v3-its.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index b57d81ad33a0..f82035eb77e5 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3291,10 +3291,14 @@ static void its_cpu_init_collection(struct its_node *its)
/* avoid cross node collections and its mapping */
if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
struct device_node *cpu_node;
+ int cpu_nid;
cpu_node = of_get_cpu_node(cpu, NULL);
+ cpu_nid = of_node_to_nid(cpu_node);
+ of_node_put(cpu_node);
+
if (its->numa_node != NUMA_NO_NODE &&
- its->numa_node != of_node_to_nid(cpu_node))
+ its->numa_node != cpu_nid)
return;
}
--
2.43.0
^ permalink raw reply related
* [PATCH] mfd: db8500-prcmu: Fold dbx500 header into db8500
From: Linus Walleij @ 2026-06-19 20:27 UTC (permalink / raw)
To: Russell King, Ulf Hansson, Michael Turquette, Stephen Boyd,
Brian Masney, Rafael J. Wysocki, Daniel Lezcano, Christian Loehle,
Lee Jones, Liam Girdwood, Mark Brown, Zhang Rui, Lukasz Luba,
Wim Van Sebroeck, Guenter Roeck, Jaroslav Kysela, Takashi Iwai
Cc: linux-arm-kernel, linux-clk, linux-pm, linux-watchdog,
linux-sound, kernel test robot, Linus Walleij
Move the DBx500 PRCMU definitions into the DB8500 PRCMU
header and delete the wrapper header.
Convert users of simple PRCMU wrappers to call the DB8500 helpers
directly.
The dbx500-prcmu.h header was the result of an earlier attempt to
abstract several DBx5x SoC PRCMU units to use the same abstract
header. They are deleted from the kernel and this is not just
causing maintenance burden and build errors.
The stub code is using -ENOSYS in a way checkpatch complains about
so replace these with -EINVAL while we're at it.
Assisted-by: Codex:gpt-5-5
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202606180825.vUSQntkJ-lkp@intel.com/
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
| 6 +-
| 20 +-
| 2 +-
| 6 +-
| 2 +-
| 6 +-
| 12 +-
| 10 +-
| 22 +-
| 252 ++++++++++++++++-
| 575 ---------------------------------------
| 2 +-
12 files changed, 294 insertions(+), 621 deletions(-)
--git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index b1a70f203372..0d7530fb6ad0 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -12,7 +12,7 @@
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/platform_data/arm-ux500-pm.h>
#include <linux/platform_device.h>
#include <linux/io.h>
@@ -81,7 +81,7 @@ static void __init ux500_init_irq(void)
struct resource r;
irqchip_init();
- prcmu_early_init();
+ db8500_prcmu_early_init();
np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu");
of_address_to_resource(np, 0, &r);
of_node_put(np);
@@ -101,7 +101,7 @@ static void ux500_restart(enum reboot_mode mode, const char *cmd)
local_irq_disable();
local_fiq_disable();
- prcmu_system_reset(0);
+ db8500_prcmu_system_reset(0);
}
static const struct of_device_id u8500_local_bus_nodes[] = {
--git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
index ddc86551bf57..ac96c46bd1bb 100644
--- a/drivers/clk/ux500/clk-prcmu.c
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -7,7 +7,7 @@
*/
#include <linux/clk-provider.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/err.h>
@@ -35,13 +35,13 @@ static int clk_prcmu_prepare(struct clk_hw *hw)
{
struct clk_prcmu *clk = to_clk_prcmu(hw);
- return prcmu_request_clock(clk->cg_sel, true);
+ return db8500_prcmu_request_clock(clk->cg_sel, true);
}
static void clk_prcmu_unprepare(struct clk_hw *hw)
{
struct clk_prcmu *clk = to_clk_prcmu(hw);
- if (prcmu_request_clock(clk->cg_sel, false))
+ if (db8500_prcmu_request_clock(clk->cg_sel, false))
pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
clk_hw_get_name(hw));
}
@@ -86,7 +86,7 @@ static int clk_prcmu_opp_prepare(struct clk_hw *hw)
clk->opp_requested = 1;
}
- err = prcmu_request_clock(clk->cg_sel, true);
+ err = db8500_prcmu_request_clock(clk->cg_sel, true);
if (err) {
prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
(char *)clk_hw_get_name(hw));
@@ -101,7 +101,7 @@ static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
{
struct clk_prcmu *clk = to_clk_prcmu(hw);
- if (prcmu_request_clock(clk->cg_sel, false)) {
+ if (db8500_prcmu_request_clock(clk->cg_sel, false)) {
pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
clk_hw_get_name(hw));
return;
@@ -120,7 +120,7 @@ static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
struct clk_prcmu *clk = to_clk_prcmu(hw);
if (!clk->opp_requested) {
- err = prcmu_request_ape_opp_100_voltage(true);
+ err = db8500_prcmu_request_ape_opp_100_voltage(true);
if (err) {
pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n",
__func__, clk_hw_get_name(hw));
@@ -129,9 +129,9 @@ static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
clk->opp_requested = 1;
}
- err = prcmu_request_clock(clk->cg_sel, true);
+ err = db8500_prcmu_request_clock(clk->cg_sel, true);
if (err) {
- prcmu_request_ape_opp_100_voltage(false);
+ db8500_prcmu_request_ape_opp_100_voltage(false);
clk->opp_requested = 0;
return err;
}
@@ -143,14 +143,14 @@ static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
{
struct clk_prcmu *clk = to_clk_prcmu(hw);
- if (prcmu_request_clock(clk->cg_sel, false)) {
+ if (db8500_prcmu_request_clock(clk->cg_sel, false)) {
pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
clk_hw_get_name(hw));
return;
}
if (clk->opp_requested) {
- prcmu_request_ape_opp_100_voltage(false);
+ db8500_prcmu_request_ape_opp_100_voltage(false);
clk->opp_requested = 0;
}
}
--git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c
index 6f78808387b1..d2499815226f 100644
--- a/drivers/clk/ux500/u8500_of_clk.c
+++ b/drivers/clk/ux500/u8500_of_clk.c
@@ -9,7 +9,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/clk-provider.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include "clk.h"
#include "prcc.h"
--git a/drivers/cpuidle/cpuidle-ux500.c b/drivers/cpuidle/cpuidle-ux500.c
index f7d778580e9b..6d6c52c0bcc2 100644
--- a/drivers/cpuidle/cpuidle-ux500.c
+++ b/drivers/cpuidle/cpuidle-ux500.c
@@ -11,7 +11,7 @@
#include <linux/spinlock.h>
#include <linux/atomic.h>
#include <linux/smp.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/platform_data/arm-ux500-pm.h>
#include <linux/platform_device.h>
@@ -66,7 +66,7 @@ static inline int ux500_enter_idle(struct cpuidle_device *dev,
/* Go to the retention state, the prcmu will wait for the
* cpu to go WFI and this is what happens after exiting this
* 'master' critical section */
- if (prcmu_set_power_state(PRCMU_AP_IDLE, true, true))
+ if (db8500_prcmu_set_power_state(PRCMU_AP_IDLE, true, true))
goto out;
/* When we switch to retention, the prcmu is in charge
@@ -109,7 +109,7 @@ static struct cpuidle_driver ux500_idle_driver = {
static int dbx500_cpuidle_probe(struct platform_device *pdev)
{
/* Configure wake up reasons */
- prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
+ db8500_prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
PRCMU_WAKEUP(ABB));
return cpuidle_register(&ux500_idle_driver, NULL);
--git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index f0bc0b5a6f4a..86fa99022cb3 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -19,7 +19,7 @@
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/of.h>
/*
--git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 21e68a382b11..6672c55f2ebc 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -32,7 +32,7 @@
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <linux/mfd/core.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/regulator/db8500-prcmu.h>
#include <linux/regulator/machine.h>
@@ -2285,7 +2285,7 @@ void db8500_prcmu_system_reset(u16 reset_code)
/**
* db8500_prcmu_get_reset_code - Retrieve SW reset reason code
*
- * Retrieves the reset reason code stored by prcmu_system_reset() before
+ * Retrieves the reset reason code stored by db8500_prcmu_system_reset() before
* last restart.
*/
u16 db8500_prcmu_get_reset_code(void)
@@ -3041,7 +3041,7 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
db8500_irq_init(np);
- prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
+ db8500_prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
err = mfd_add_devices(&pdev->dev, 0, common_prcmu_devs,
ARRAY_SIZE(common_prcmu_devs), NULL, 0, db8500_irq_domain);
--git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c
index 1ec2e1348891..751fe36580fa 100644
--- a/drivers/regulator/db8500-prcmu.c
+++ b/drivers/regulator/db8500-prcmu.c
@@ -13,7 +13,7 @@
#include <linux/err.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/db8500-prcmu.h>
@@ -93,13 +93,13 @@ static int enable_epod(u16 epod_id, bool ramret)
if (ramret) {
if (!epod_on[epod_id]) {
- ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
if (ret < 0)
return ret;
}
epod_ramret[epod_id] = true;
} else {
- ret = prcmu_set_epod(epod_id, EPOD_STATE_ON);
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_ON);
if (ret < 0)
return ret;
epod_on[epod_id] = true;
@@ -114,18 +114,18 @@ static int disable_epod(u16 epod_id, bool ramret)
if (ramret) {
if (!epod_on[epod_id]) {
- ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_OFF);
if (ret < 0)
return ret;
}
epod_ramret[epod_id] = false;
} else {
if (epod_ramret[epod_id]) {
- ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
if (ret < 0)
return ret;
} else {
- ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
+ ret = db8500_prcmu_set_epod(epod_id, EPOD_STATE_OFF);
if (ret < 0)
return ret;
}
--git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
index 576f88b6a1b3..cf1706569e6d 100644
--- a/drivers/thermal/db8500_thermal.c
+++ b/drivers/thermal/db8500_thermal.c
@@ -10,7 +10,7 @@
#include <linux/cpu_cooling.h>
#include <linux/interrupt.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -82,7 +82,7 @@ static void db8500_thermal_update_config(struct db8500_thermal_zone *th,
unsigned long next_low,
unsigned long next_high)
{
- prcmu_stop_temp_sense();
+ db8500_prcmu_stop_temp_sense();
th->cur_index = idx;
th->interpolated_temp = (next_low + next_high)/2;
@@ -91,8 +91,8 @@ static void db8500_thermal_update_config(struct db8500_thermal_zone *th,
* The PRCMU accept absolute temperatures in celsius so divide
* down the millicelsius with 1000
*/
- prcmu_config_hotmon((u8)(next_low/1000), (u8)(next_high/1000));
- prcmu_start_temp_sense(PRCMU_DEFAULT_MEASURE_TIME);
+ db8500_prcmu_config_hotmon((u8)(next_low / 1000), (u8)(next_high / 1000));
+ db8500_prcmu_start_temp_sense(PRCMU_DEFAULT_MEASURE_TIME);
}
static irqreturn_t prcmu_low_irq_handler(int irq, void *irq_data)
@@ -204,7 +204,7 @@ static int db8500_thermal_probe(struct platform_device *pdev)
static int db8500_thermal_suspend(struct platform_device *pdev,
pm_message_t state)
{
- prcmu_stop_temp_sense();
+ db8500_prcmu_stop_temp_sense();
return 0;
}
--git a/drivers/watchdog/db8500_wdt.c b/drivers/watchdog/db8500_wdt.c
index 97148ac0aa54..70ccea13288d 100644
--- a/drivers/watchdog/db8500_wdt.c
+++ b/drivers/watchdog/db8500_wdt.c
@@ -16,7 +16,7 @@
#include <linux/watchdog.h>
#include <linux/platform_device.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#define WATCHDOG_TIMEOUT 600 /* 10 minutes */
@@ -37,24 +37,24 @@ MODULE_PARM_DESC(nowayout,
static int db8500_wdt_start(struct watchdog_device *wdd)
{
- return prcmu_enable_a9wdog(PRCMU_WDOG_ALL);
+ return db8500_prcmu_enable_a9wdog(PRCMU_WDOG_ALL);
}
static int db8500_wdt_stop(struct watchdog_device *wdd)
{
- return prcmu_disable_a9wdog(PRCMU_WDOG_ALL);
+ return db8500_prcmu_disable_a9wdog(PRCMU_WDOG_ALL);
}
static int db8500_wdt_keepalive(struct watchdog_device *wdd)
{
- return prcmu_kick_a9wdog(PRCMU_WDOG_ALL);
+ return db8500_prcmu_kick_a9wdog(PRCMU_WDOG_ALL);
}
static int db8500_wdt_set_timeout(struct watchdog_device *wdd,
unsigned int timeout)
{
db8500_wdt_stop(wdd);
- prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
+ db8500_prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
db8500_wdt_start(wdd);
return 0;
@@ -91,10 +91,10 @@ static int db8500_wdt_probe(struct platform_device *pdev)
watchdog_set_nowayout(&db8500_wdt, nowayout);
/* disable auto off on sleep */
- prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
+ db8500_prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
/* set HW initial value */
- prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
+ db8500_prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
ret = devm_watchdog_register_device(dev, &db8500_wdt);
if (ret)
@@ -110,9 +110,9 @@ static int db8500_wdt_suspend(struct platform_device *pdev,
{
if (watchdog_active(&db8500_wdt)) {
db8500_wdt_stop(&db8500_wdt);
- prcmu_config_a9wdog(PRCMU_WDOG_CPU1, true);
+ db8500_prcmu_config_a9wdog(PRCMU_WDOG_CPU1, true);
- prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
+ db8500_prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
db8500_wdt_start(&db8500_wdt);
}
return 0;
@@ -122,9 +122,9 @@ static int db8500_wdt_resume(struct platform_device *pdev)
{
if (watchdog_active(&db8500_wdt)) {
db8500_wdt_stop(&db8500_wdt);
- prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
+ db8500_prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
- prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
+ db8500_prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
db8500_wdt_start(&db8500_wdt);
}
return 0;
--git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h
index a62de3d155ed..c939c9a1170a 100644
--- a/include/linux/mfd/db8500-prcmu.h
+++ b/include/linux/mfd/db8500-prcmu.h
@@ -12,6 +12,9 @@
#include <linux/interrupt.h>
#include <linux/bitops.h>
+#include <linux/err.h>
+
+#include <dt-bindings/mfd/dbx500-prcmu.h> /* For clock identifiers */
/*
* Registers
@@ -24,6 +27,38 @@
#define DB8500_PRCM_DSI_SW_RESET_DSI1_SW_RESETN BIT(1)
#define DB8500_PRCM_DSI_SW_RESET_DSI2_SW_RESETN BIT(2)
+/* Offset for the firmware version within the TCPM */
+#define DB8500_PRCMU_FW_VERSION_OFFSET 0xA4
+
+#define DB8500_PRCMU_LEGACY_OFFSET 0xDD4
+
+/*
+ * CLKOUT sources
+ */
+#define PRCMU_CLKSRC_CLK38M 0x00
+#define PRCMU_CLKSRC_ACLK 0x01
+#define PRCMU_CLKSRC_SYSCLK 0x02
+#define PRCMU_CLKSRC_LCDCLK 0x03
+#define PRCMU_CLKSRC_SDMMCCLK 0x04
+#define PRCMU_CLKSRC_TVCLK 0x05
+#define PRCMU_CLKSRC_TIMCLK 0x06
+#define PRCMU_CLKSRC_CLK009 0x07
+/* These are only valid for CLKOUT1: */
+#define PRCMU_CLKSRC_SIAMMDSPCLK 0x40
+#define PRCMU_CLKSRC_I2CCLK 0x41
+#define PRCMU_CLKSRC_MSP02CLK 0x42
+#define PRCMU_CLKSRC_ARMPLL_OBSCLK 0x43
+#define PRCMU_CLKSRC_HSIRXCLK 0x44
+#define PRCMU_CLKSRC_HSITXCLK 0x45
+#define PRCMU_CLKSRC_ARMCLKFIX 0x46
+#define PRCMU_CLKSRC_HDMICLK 0x47
+
+/*
+ * Definitions for controlling ESRAM0 in deep sleep.
+ */
+#define ESRAM0_DEEP_SLEEP_STATE_OFF 1
+#define ESRAM0_DEEP_SLEEP_STATE_RET 2
+
/* This portion previously known as <mach/prcmu-fw-defs_v1.h> */
/**
@@ -451,10 +486,173 @@ enum prcmu_power_status {
PRCMU_ARMPENDINGIT_ER = 0x93,
};
+/* PRCMU Wakeup defines */
+enum prcmu_wakeup_index {
+ PRCMU_WAKEUP_INDEX_RTC,
+ PRCMU_WAKEUP_INDEX_RTT0,
+ PRCMU_WAKEUP_INDEX_RTT1,
+ PRCMU_WAKEUP_INDEX_HSI0,
+ PRCMU_WAKEUP_INDEX_HSI1,
+ PRCMU_WAKEUP_INDEX_USB,
+ PRCMU_WAKEUP_INDEX_ABB,
+ PRCMU_WAKEUP_INDEX_ABB_FIFO,
+ PRCMU_WAKEUP_INDEX_ARM,
+ PRCMU_WAKEUP_INDEX_CD_IRQ,
+ NUM_PRCMU_WAKEUP_INDICES
+};
+
+#define PRCMU_WAKEUP(_name) (BIT(PRCMU_WAKEUP_INDEX_##_name))
+
+/**
+ * enum prcmu_wdog_id - PRCMU watchdog IDs
+ * @PRCMU_WDOG_ALL: use all timers
+ * @PRCMU_WDOG_CPU1: use first CPU timer only
+ * @PRCMU_WDOG_CPU2: use second CPU timer conly
+ */
+enum prcmu_wdog_id {
+ PRCMU_WDOG_ALL = 0x00,
+ PRCMU_WDOG_CPU1 = 0x01,
+ PRCMU_WDOG_CPU2 = 0x02,
+};
+
+/**
+ * enum ape_opp - APE OPP states definition
+ * @APE_OPP_INIT:
+ * @APE_NO_CHANGE: The APE operating point is unchanged
+ * @APE_100_OPP: The new APE operating point is ape100opp
+ * @APE_50_OPP: 50%
+ * @APE_50_PARTLY_25_OPP: 50%, except some clocks at 25%.
+ */
+enum ape_opp {
+ APE_OPP_INIT = 0x00,
+ APE_NO_CHANGE = 0x01,
+ APE_100_OPP = 0x02,
+ APE_50_OPP = 0x03,
+ APE_50_PARTLY_25_OPP = 0xFF,
+};
+
+/**
+ * enum arm_opp - ARM OPP states definition
+ * @ARM_OPP_INIT:
+ * @ARM_NO_CHANGE: The ARM operating point is unchanged
+ * @ARM_100_OPP: The new ARM operating point is arm100opp
+ * @ARM_50_OPP: The new ARM operating point is arm50opp
+ * @ARM_MAX_OPP: Operating point is "max" (more than 100)
+ * @ARM_MAX_FREQ100OPP: Set max opp if available, else 100
+ * @ARM_EXTCLK: The new ARM operating point is armExtClk
+ */
+enum arm_opp {
+ ARM_OPP_INIT = 0x00,
+ ARM_NO_CHANGE = 0x01,
+ ARM_100_OPP = 0x02,
+ ARM_50_OPP = 0x03,
+ ARM_MAX_OPP = 0x04,
+ ARM_MAX_FREQ100OPP = 0x05,
+ ARM_EXTCLK = 0x07
+};
+
+/**
+ * enum ddr_opp - DDR OPP states definition
+ * @DDR_100_OPP: The new DDR operating point is ddr100opp
+ * @DDR_50_OPP: The new DDR operating point is ddr50opp
+ * @DDR_25_OPP: The new DDR operating point is ddr25opp
+ */
+enum ddr_opp {
+ DDR_100_OPP = 0x00,
+ DDR_50_OPP = 0x01,
+ DDR_25_OPP = 0x02,
+};
+
+/**
+ * enum ddr_pwrst - DDR power states definition
+ * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged
+ * @DDR_PWR_STATE_ON:
+ * @DDR_PWR_STATE_OFFLOWLAT:
+ * @DDR_PWR_STATE_OFFHIGHLAT:
+ */
+enum ddr_pwrst {
+ DDR_PWR_STATE_UNCHANGED = 0x00,
+ DDR_PWR_STATE_ON = 0x01,
+ DDR_PWR_STATE_OFFLOWLAT = 0x02,
+ DDR_PWR_STATE_OFFHIGHLAT = 0x03
+};
+
/*
* Definitions for autonomous power management configuration.
*/
+/* EPOD (power domain) IDs */
+
+/*
+ * DB8500 EPODs
+ * - EPOD_ID_SVAMMDSP: power domain for SVA MMDSP
+ * - EPOD_ID_SVAPIPE: power domain for SVA pipe
+ * - EPOD_ID_SIAMMDSP: power domain for SIA MMDSP
+ * - EPOD_ID_SIAPIPE: power domain for SIA pipe
+ * - EPOD_ID_SGA: power domain for SGA
+ * - EPOD_ID_B2R2_MCDE: power domain for B2R2 and MCDE
+ * - EPOD_ID_ESRAM12: power domain for ESRAM 1 and 2
+ * - EPOD_ID_ESRAM34: power domain for ESRAM 3 and 4
+ * - NUM_EPOD_ID: number of power domains
+ *
+ * TODO: These should be prefixed.
+ */
+#define EPOD_ID_SVAMMDSP 0
+#define EPOD_ID_SVAPIPE 1
+#define EPOD_ID_SIAMMDSP 2
+#define EPOD_ID_SIAPIPE 3
+#define EPOD_ID_SGA 4
+#define EPOD_ID_B2R2_MCDE 5
+#define EPOD_ID_ESRAM12 6
+#define EPOD_ID_ESRAM34 7
+#define NUM_EPOD_ID 8
+
+/*
+ * state definition for EPOD (power domain)
+ * - EPOD_STATE_NO_CHANGE: The EPOD should remain unchanged
+ * - EPOD_STATE_OFF: The EPOD is switched off
+ * - EPOD_STATE_RAMRET: The EPOD is switched off with its internal RAM in
+ * retention
+ * - EPOD_STATE_ON_CLK_OFF: The EPOD is switched on, clock is still off
+ * - EPOD_STATE_ON: Same as above, but with clock enabled
+ */
+#define EPOD_STATE_NO_CHANGE 0x00
+#define EPOD_STATE_OFF 0x01
+#define EPOD_STATE_RAMRET 0x02
+#define EPOD_STATE_ON_CLK_OFF 0x03
+#define EPOD_STATE_ON 0x04
+
+#define PRCMU_FW_PROJECT_U8500 2
+#define PRCMU_FW_PROJECT_U8400 3
+#define PRCMU_FW_PROJECT_U9500 4 /* Customer specific */
+#define PRCMU_FW_PROJECT_U8500_MBB 5
+#define PRCMU_FW_PROJECT_U8500_C1 6
+#define PRCMU_FW_PROJECT_U8500_C2 7
+#define PRCMU_FW_PROJECT_U8500_C3 8
+#define PRCMU_FW_PROJECT_U8500_C4 9
+#define PRCMU_FW_PROJECT_U9500_MBL 10
+#define PRCMU_FW_PROJECT_U8500_SSG1 11 /* Samsung specific */
+#define PRCMU_FW_PROJECT_U8500_MBL2 12 /* Customer specific */
+#define PRCMU_FW_PROJECT_U8520 13
+#define PRCMU_FW_PROJECT_U8420 14
+#define PRCMU_FW_PROJECT_U8500_SSG2 15 /* Samsung specific */
+#define PRCMU_FW_PROJECT_U8420_SYSCLK 17
+#define PRCMU_FW_PROJECT_A9420 20
+/* [32..63] 9540 and derivatives */
+#define PRCMU_FW_PROJECT_U9540 32
+/* [64..95] 8540 and derivatives */
+#define PRCMU_FW_PROJECT_L8540 64
+/* [96..126] 8580 and derivatives */
+#define PRCMU_FW_PROJECT_L8580 96
+
+#define PRCMU_FW_PROJECT_NAME_LEN 20
+
+/* PRCMU QoS APE OPP class */
+#define PRCMU_QOS_APE_OPP 1
+#define PRCMU_QOS_DDR_OPP 2
+#define PRCMU_QOS_ARM_OPP 3
+#define PRCMU_QOS_DEFAULT_VALUE -1
+
#define PRCMU_AUTO_PM_OFF 0
#define PRCMU_AUTO_PM_ON 1
@@ -469,6 +667,14 @@ enum prcmu_auto_pm_policy {
PRCMU_AUTO_PM_POLICY_DSP_CLK_OFF_HWP_CLK_OFF,
};
+struct prcmu_fw_version {
+ u32 project; /* Notice, project shifted with 8 on ux540 */
+ u8 api_version;
+ u8 func_version;
+ u8 errata;
+ char project_name[PRCMU_FW_PROJECT_NAME_LEN];
+};
+
/**
* struct prcmu_auto_pm_config - Autonomous power management configuration.
* @sia_auto_pm_enable: SIA autonomous pm enable. (PRCMU_AUTO_PM_{OFF,ON})
@@ -501,6 +707,9 @@ void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
bool prcmu_is_auto_pm_enabled(void);
int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
+unsigned long prcmu_clock_rate(u8 clock);
+long prcmu_round_clock_rate(u8 clock, unsigned long rate);
+int prcmu_set_clock_rate(u8 clock, unsigned long rate);
int prcmu_set_clock_divider(u8 clock, u8 divider);
int db8500_prcmu_config_hotdog(u8 threshold);
int db8500_prcmu_config_hotmon(u8 low, u8 high);
@@ -508,6 +717,8 @@ int db8500_prcmu_start_temp_sense(u16 cycles32k);
int db8500_prcmu_stop_temp_sense(void);
int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value,
+ u8 *mask, u8 size);
int prcmu_ac_wake_req(void);
void prcmu_ac_sleep_req(void);
@@ -610,6 +821,21 @@ static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
return 0;
}
+static inline unsigned long prcmu_clock_rate(u8 clock)
+{
+ return 0;
+}
+
+static inline long prcmu_round_clock_rate(u8 clock, unsigned long rate)
+{
+ return 0;
+}
+
+static inline int prcmu_set_clock_rate(u8 clock, unsigned long rate)
+{
+ return 0;
+}
+
static inline int prcmu_set_clock_divider(u8 clock, u8 divider)
{
return 0;
@@ -637,12 +863,18 @@ static inline int db8500_prcmu_stop_temp_sense(void)
static inline int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
{
- return -ENOSYS;
+ return -EINVAL;
}
static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
{
- return -ENOSYS;
+ return -EINVAL;
+}
+
+static inline int prcmu_abb_write_masked(u8 slave, u8 reg,
+ u8 *value, u8 *mask, u8 size)
+{
+ return -EINVAL;
}
static inline int prcmu_ac_wake_req(void)
@@ -745,4 +977,20 @@ static inline void db8500_prcmu_write_masked(unsigned int reg, u32 mask,
#endif /* !CONFIG_MFD_DB8500_PRCMU */
+static inline int prcmu_qos_add_requirement(int prcmu_qos_class,
+ char *name, s32 value)
+{
+ return 0;
+}
+
+static inline int prcmu_qos_update_requirement(int prcmu_qos_class,
+ char *name, s32 new_value)
+{
+ return 0;
+}
+
+static inline void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name)
+{
+}
+
#endif /* __MFD_DB8500_PRCMU_H */
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
deleted file mode 100644
index 828362b7860c..000000000000
--- a/include/linux/mfd/dbx500-prcmu.h
+++ /dev/null
@@ -1,575 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) ST Ericsson SA 2011
- *
- * STE Ux500 PRCMU API
- */
-#ifndef __MACH_PRCMU_H
-#define __MACH_PRCMU_H
-
-#include <linux/interrupt.h>
-#include <linux/notifier.h>
-#include <linux/err.h>
-
-#include <dt-bindings/mfd/dbx500-prcmu.h> /* For clock identifiers */
-
-/* Offset for the firmware version within the TCPM */
-#define DB8500_PRCMU_FW_VERSION_OFFSET 0xA4
-#define DBX540_PRCMU_FW_VERSION_OFFSET 0xA8
-
-/* PRCMU Wakeup defines */
-enum prcmu_wakeup_index {
- PRCMU_WAKEUP_INDEX_RTC,
- PRCMU_WAKEUP_INDEX_RTT0,
- PRCMU_WAKEUP_INDEX_RTT1,
- PRCMU_WAKEUP_INDEX_HSI0,
- PRCMU_WAKEUP_INDEX_HSI1,
- PRCMU_WAKEUP_INDEX_USB,
- PRCMU_WAKEUP_INDEX_ABB,
- PRCMU_WAKEUP_INDEX_ABB_FIFO,
- PRCMU_WAKEUP_INDEX_ARM,
- PRCMU_WAKEUP_INDEX_CD_IRQ,
- NUM_PRCMU_WAKEUP_INDICES
-};
-#define PRCMU_WAKEUP(_name) (BIT(PRCMU_WAKEUP_INDEX_##_name))
-
-/* EPOD (power domain) IDs */
-
-/*
- * DB8500 EPODs
- * - EPOD_ID_SVAMMDSP: power domain for SVA MMDSP
- * - EPOD_ID_SVAPIPE: power domain for SVA pipe
- * - EPOD_ID_SIAMMDSP: power domain for SIA MMDSP
- * - EPOD_ID_SIAPIPE: power domain for SIA pipe
- * - EPOD_ID_SGA: power domain for SGA
- * - EPOD_ID_B2R2_MCDE: power domain for B2R2 and MCDE
- * - EPOD_ID_ESRAM12: power domain for ESRAM 1 and 2
- * - EPOD_ID_ESRAM34: power domain for ESRAM 3 and 4
- * - NUM_EPOD_ID: number of power domains
- *
- * TODO: These should be prefixed.
- */
-#define EPOD_ID_SVAMMDSP 0
-#define EPOD_ID_SVAPIPE 1
-#define EPOD_ID_SIAMMDSP 2
-#define EPOD_ID_SIAPIPE 3
-#define EPOD_ID_SGA 4
-#define EPOD_ID_B2R2_MCDE 5
-#define EPOD_ID_ESRAM12 6
-#define EPOD_ID_ESRAM34 7
-#define NUM_EPOD_ID 8
-
-/*
- * state definition for EPOD (power domain)
- * - EPOD_STATE_NO_CHANGE: The EPOD should remain unchanged
- * - EPOD_STATE_OFF: The EPOD is switched off
- * - EPOD_STATE_RAMRET: The EPOD is switched off with its internal RAM in
- * retention
- * - EPOD_STATE_ON_CLK_OFF: The EPOD is switched on, clock is still off
- * - EPOD_STATE_ON: Same as above, but with clock enabled
- */
-#define EPOD_STATE_NO_CHANGE 0x00
-#define EPOD_STATE_OFF 0x01
-#define EPOD_STATE_RAMRET 0x02
-#define EPOD_STATE_ON_CLK_OFF 0x03
-#define EPOD_STATE_ON 0x04
-
-/*
- * CLKOUT sources
- */
-#define PRCMU_CLKSRC_CLK38M 0x00
-#define PRCMU_CLKSRC_ACLK 0x01
-#define PRCMU_CLKSRC_SYSCLK 0x02
-#define PRCMU_CLKSRC_LCDCLK 0x03
-#define PRCMU_CLKSRC_SDMMCCLK 0x04
-#define PRCMU_CLKSRC_TVCLK 0x05
-#define PRCMU_CLKSRC_TIMCLK 0x06
-#define PRCMU_CLKSRC_CLK009 0x07
-/* These are only valid for CLKOUT1: */
-#define PRCMU_CLKSRC_SIAMMDSPCLK 0x40
-#define PRCMU_CLKSRC_I2CCLK 0x41
-#define PRCMU_CLKSRC_MSP02CLK 0x42
-#define PRCMU_CLKSRC_ARMPLL_OBSCLK 0x43
-#define PRCMU_CLKSRC_HSIRXCLK 0x44
-#define PRCMU_CLKSRC_HSITXCLK 0x45
-#define PRCMU_CLKSRC_ARMCLKFIX 0x46
-#define PRCMU_CLKSRC_HDMICLK 0x47
-
-/**
- * enum prcmu_wdog_id - PRCMU watchdog IDs
- * @PRCMU_WDOG_ALL: use all timers
- * @PRCMU_WDOG_CPU1: use first CPU timer only
- * @PRCMU_WDOG_CPU2: use second CPU timer conly
- */
-enum prcmu_wdog_id {
- PRCMU_WDOG_ALL = 0x00,
- PRCMU_WDOG_CPU1 = 0x01,
- PRCMU_WDOG_CPU2 = 0x02,
-};
-
-/**
- * enum ape_opp - APE OPP states definition
- * @APE_OPP_INIT:
- * @APE_NO_CHANGE: The APE operating point is unchanged
- * @APE_100_OPP: The new APE operating point is ape100opp
- * @APE_50_OPP: 50%
- * @APE_50_PARTLY_25_OPP: 50%, except some clocks at 25%.
- */
-enum ape_opp {
- APE_OPP_INIT = 0x00,
- APE_NO_CHANGE = 0x01,
- APE_100_OPP = 0x02,
- APE_50_OPP = 0x03,
- APE_50_PARTLY_25_OPP = 0xFF,
-};
-
-/**
- * enum arm_opp - ARM OPP states definition
- * @ARM_OPP_INIT:
- * @ARM_NO_CHANGE: The ARM operating point is unchanged
- * @ARM_100_OPP: The new ARM operating point is arm100opp
- * @ARM_50_OPP: The new ARM operating point is arm50opp
- * @ARM_MAX_OPP: Operating point is "max" (more than 100)
- * @ARM_MAX_FREQ100OPP: Set max opp if available, else 100
- * @ARM_EXTCLK: The new ARM operating point is armExtClk
- */
-enum arm_opp {
- ARM_OPP_INIT = 0x00,
- ARM_NO_CHANGE = 0x01,
- ARM_100_OPP = 0x02,
- ARM_50_OPP = 0x03,
- ARM_MAX_OPP = 0x04,
- ARM_MAX_FREQ100OPP = 0x05,
- ARM_EXTCLK = 0x07
-};
-
-/**
- * enum ddr_opp - DDR OPP states definition
- * @DDR_100_OPP: The new DDR operating point is ddr100opp
- * @DDR_50_OPP: The new DDR operating point is ddr50opp
- * @DDR_25_OPP: The new DDR operating point is ddr25opp
- */
-enum ddr_opp {
- DDR_100_OPP = 0x00,
- DDR_50_OPP = 0x01,
- DDR_25_OPP = 0x02,
-};
-
-/*
- * Definitions for controlling ESRAM0 in deep sleep.
- */
-#define ESRAM0_DEEP_SLEEP_STATE_OFF 1
-#define ESRAM0_DEEP_SLEEP_STATE_RET 2
-
-/**
- * enum ddr_pwrst - DDR power states definition
- * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged
- * @DDR_PWR_STATE_ON:
- * @DDR_PWR_STATE_OFFLOWLAT:
- * @DDR_PWR_STATE_OFFHIGHLAT:
- */
-enum ddr_pwrst {
- DDR_PWR_STATE_UNCHANGED = 0x00,
- DDR_PWR_STATE_ON = 0x01,
- DDR_PWR_STATE_OFFLOWLAT = 0x02,
- DDR_PWR_STATE_OFFHIGHLAT = 0x03
-};
-
-#define DB8500_PRCMU_LEGACY_OFFSET 0xDD4
-
-#define PRCMU_FW_PROJECT_U8500 2
-#define PRCMU_FW_PROJECT_U8400 3
-#define PRCMU_FW_PROJECT_U9500 4 /* Customer specific */
-#define PRCMU_FW_PROJECT_U8500_MBB 5
-#define PRCMU_FW_PROJECT_U8500_C1 6
-#define PRCMU_FW_PROJECT_U8500_C2 7
-#define PRCMU_FW_PROJECT_U8500_C3 8
-#define PRCMU_FW_PROJECT_U8500_C4 9
-#define PRCMU_FW_PROJECT_U9500_MBL 10
-#define PRCMU_FW_PROJECT_U8500_SSG1 11 /* Samsung specific */
-#define PRCMU_FW_PROJECT_U8500_MBL2 12 /* Customer specific */
-#define PRCMU_FW_PROJECT_U8520 13
-#define PRCMU_FW_PROJECT_U8420 14
-#define PRCMU_FW_PROJECT_U8500_SSG2 15 /* Samsung specific */
-#define PRCMU_FW_PROJECT_U8420_SYSCLK 17
-#define PRCMU_FW_PROJECT_A9420 20
-/* [32..63] 9540 and derivatives */
-#define PRCMU_FW_PROJECT_U9540 32
-/* [64..95] 8540 and derivatives */
-#define PRCMU_FW_PROJECT_L8540 64
-/* [96..126] 8580 and derivatives */
-#define PRCMU_FW_PROJECT_L8580 96
-
-#define PRCMU_FW_PROJECT_NAME_LEN 20
-struct prcmu_fw_version {
- u32 project; /* Notice, project shifted with 8 on ux540 */
- u8 api_version;
- u8 func_version;
- u8 errata;
- char project_name[PRCMU_FW_PROJECT_NAME_LEN];
-};
-
-#include <linux/mfd/db8500-prcmu.h>
-
-#if defined(CONFIG_UX500_SOC_DB8500)
-
-static inline void __init prcmu_early_init(void)
-{
- db8500_prcmu_early_init();
-}
-
-static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
- bool keep_ap_pll)
-{
- return db8500_prcmu_set_power_state(state, keep_ulp_clk,
- keep_ap_pll);
-}
-
-static inline u8 prcmu_get_power_state_result(void)
-{
- return db8500_prcmu_get_power_state_result();
-}
-
-static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
-{
- return db8500_prcmu_set_epod(epod_id, epod_state);
-}
-
-static inline void prcmu_enable_wakeups(u32 wakeups)
-{
- db8500_prcmu_enable_wakeups(wakeups);
-}
-
-static inline void prcmu_disable_wakeups(void)
-{
- prcmu_enable_wakeups(0);
-}
-
-static inline void prcmu_config_abb_event_readout(u32 abb_events)
-{
- db8500_prcmu_config_abb_event_readout(abb_events);
-}
-
-static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
-{
- db8500_prcmu_get_abb_event_buffer(buf);
-}
-
-int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
-int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
-int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size);
-
-int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
-
-static inline int prcmu_request_clock(u8 clock, bool enable)
-{
- return db8500_prcmu_request_clock(clock, enable);
-}
-
-unsigned long prcmu_clock_rate(u8 clock);
-long prcmu_round_clock_rate(u8 clock, unsigned long rate);
-int prcmu_set_clock_rate(u8 clock, unsigned long rate);
-
-static inline int prcmu_get_ddr_opp(void)
-{
- return db8500_prcmu_get_ddr_opp();
-}
-
-static inline int prcmu_set_arm_opp(u8 opp)
-{
- return db8500_prcmu_set_arm_opp(opp);
-}
-
-static inline int prcmu_get_arm_opp(void)
-{
- return db8500_prcmu_get_arm_opp();
-}
-
-static inline int prcmu_set_ape_opp(u8 opp)
-{
- return db8500_prcmu_set_ape_opp(opp);
-}
-
-static inline int prcmu_get_ape_opp(void)
-{
- return db8500_prcmu_get_ape_opp();
-}
-
-static inline int prcmu_request_ape_opp_100_voltage(bool enable)
-{
- return db8500_prcmu_request_ape_opp_100_voltage(enable);
-}
-
-static inline void prcmu_system_reset(u16 reset_code)
-{
- db8500_prcmu_system_reset(reset_code);
-}
-
-static inline u16 prcmu_get_reset_code(void)
-{
- return db8500_prcmu_get_reset_code();
-}
-
-int prcmu_ac_wake_req(void);
-void prcmu_ac_sleep_req(void);
-static inline void prcmu_modem_reset(void)
-{
- db8500_prcmu_modem_reset();
-}
-
-static inline bool prcmu_is_ac_wake_requested(void)
-{
- return db8500_prcmu_is_ac_wake_requested();
-}
-
-static inline int prcmu_config_esram0_deep_sleep(u8 state)
-{
- return db8500_prcmu_config_esram0_deep_sleep(state);
-}
-
-static inline int prcmu_config_hotdog(u8 threshold)
-{
- return db8500_prcmu_config_hotdog(threshold);
-}
-
-static inline int prcmu_config_hotmon(u8 low, u8 high)
-{
- return db8500_prcmu_config_hotmon(low, high);
-}
-
-static inline int prcmu_start_temp_sense(u16 cycles32k)
-{
- return db8500_prcmu_start_temp_sense(cycles32k);
-}
-
-static inline int prcmu_stop_temp_sense(void)
-{
- return db8500_prcmu_stop_temp_sense();
-}
-
-static inline u32 prcmu_read(unsigned int reg)
-{
- return db8500_prcmu_read(reg);
-}
-
-static inline void prcmu_write(unsigned int reg, u32 value)
-{
- db8500_prcmu_write(reg, value);
-}
-
-static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
-{
- db8500_prcmu_write_masked(reg, mask, value);
-}
-
-static inline int prcmu_enable_a9wdog(u8 id)
-{
- return db8500_prcmu_enable_a9wdog(id);
-}
-
-static inline int prcmu_disable_a9wdog(u8 id)
-{
- return db8500_prcmu_disable_a9wdog(id);
-}
-
-static inline int prcmu_kick_a9wdog(u8 id)
-{
- return db8500_prcmu_kick_a9wdog(id);
-}
-
-static inline int prcmu_load_a9wdog(u8 id, u32 timeout)
-{
- return db8500_prcmu_load_a9wdog(id, timeout);
-}
-
-static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
-{
- return db8500_prcmu_config_a9wdog(num, sleep_auto_off);
-}
-#else
-
-static inline void prcmu_early_init(void) {}
-
-static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
- bool keep_ap_pll)
-{
- return 0;
-}
-
-static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
-{
- return 0;
-}
-
-static inline void prcmu_enable_wakeups(u32 wakeups) {}
-
-static inline void prcmu_disable_wakeups(void) {}
-
-static inline int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
-{
- return -ENOSYS;
-}
-
-static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
-{
- return -ENOSYS;
-}
-
-static inline int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
- u8 size)
-{
- return -ENOSYS;
-}
-
-static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
-{
- return 0;
-}
-
-static inline int prcmu_request_clock(u8 clock, bool enable)
-{
- return 0;
-}
-
-static inline long prcmu_round_clock_rate(u8 clock, unsigned long rate)
-{
- return 0;
-}
-
-static inline int prcmu_set_clock_rate(u8 clock, unsigned long rate)
-{
- return 0;
-}
-
-static inline unsigned long prcmu_clock_rate(u8 clock)
-{
- return 0;
-}
-
-static inline int prcmu_set_ape_opp(u8 opp)
-{
- return 0;
-}
-
-static inline int prcmu_get_ape_opp(void)
-{
- return APE_100_OPP;
-}
-
-static inline int prcmu_request_ape_opp_100_voltage(bool enable)
-{
- return 0;
-}
-
-static inline int prcmu_set_arm_opp(u8 opp)
-{
- return 0;
-}
-
-static inline int prcmu_get_arm_opp(void)
-{
- return ARM_100_OPP;
-}
-
-static inline int prcmu_get_ddr_opp(void)
-{
- return DDR_100_OPP;
-}
-
-static inline void prcmu_system_reset(u16 reset_code) {}
-
-static inline u16 prcmu_get_reset_code(void)
-{
- return 0;
-}
-
-static inline int prcmu_ac_wake_req(void)
-{
- return 0;
-}
-
-static inline void prcmu_ac_sleep_req(void) {}
-
-static inline void prcmu_modem_reset(void) {}
-
-static inline bool prcmu_is_ac_wake_requested(void)
-{
- return false;
-}
-
-static inline int prcmu_config_esram0_deep_sleep(u8 state)
-{
- return 0;
-}
-
-static inline void prcmu_config_abb_event_readout(u32 abb_events) {}
-
-static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
-{
- *buf = NULL;
-}
-
-static inline int prcmu_config_hotdog(u8 threshold)
-{
- return 0;
-}
-
-static inline int prcmu_config_hotmon(u8 low, u8 high)
-{
- return 0;
-}
-
-static inline int prcmu_start_temp_sense(u16 cycles32k)
-{
- return 0;
-}
-
-static inline int prcmu_stop_temp_sense(void)
-{
- return 0;
-}
-
-static inline u32 prcmu_read(unsigned int reg)
-{
- return 0;
-}
-
-static inline void prcmu_write(unsigned int reg, u32 value) {}
-
-static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {}
-
-#endif
-
-static inline void prcmu_set(unsigned int reg, u32 bits)
-{
- prcmu_write_masked(reg, bits, bits);
-}
-
-static inline void prcmu_clear(unsigned int reg, u32 bits)
-{
- prcmu_write_masked(reg, bits, 0);
-}
-
-/* PRCMU QoS APE OPP class */
-#define PRCMU_QOS_APE_OPP 1
-#define PRCMU_QOS_DDR_OPP 2
-#define PRCMU_QOS_ARM_OPP 3
-#define PRCMU_QOS_DEFAULT_VALUE -1
-
-static inline int prcmu_qos_add_requirement(int prcmu_qos_class,
- char *name, s32 value)
-{
- return 0;
-}
-
-static inline int prcmu_qos_update_requirement(int prcmu_qos_class,
- char *name, s32 new_value)
-{
- return 0;
-}
-
-static inline void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name)
-{
-}
-
-#endif /* __MACH_PRCMU_H */
--git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
index 7798957c6504..499e826d7120 100644
--- a/sound/soc/ux500/ux500_msp_dai.c
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -14,7 +14,7 @@
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/mfd/db8500-prcmu.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
---
base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
change-id: 20260619-mfd-prcmu-merge-headers-bc84905195b4
Best regards,
--
Linus Walleij <linusw@kernel.org>
^ permalink raw reply related
* [PATCH] arm64: dts: broadcom: bcm2712: Remove non-functional EL2 virtual timer
From: Daniel Drake @ 2026-06-19 20:48 UTC (permalink / raw)
To: maz, robh, krzk+dt, conor+dt, florian.fainelli,
bcm-kernel-feedback-list
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, m.szyprowski,
andrea.porta, Daniel Drake
Commit d87773de9efe1 ("clocksource/drivers/arm_arch_timer: Default to
EL2 virtual timer when running VHE") causes boot to hang on
Raspberry Pi 5. The newly-selected EL2 virtual timer does not generate
any interrupts, even though the GIC_DIST_ENABLE_SET flag has been
confirmed set via readback.
The reasons for this failure are unknown, however it is likely that
this timer was never tested. Raspberry Pi's original devicetree did
not include this timer interrupt; it was only introduced via a
suggestion[1] made in code review as part of the upstreaming process.
(Current RPi firmware versions do include this timer, but only because
they rebased on top of the upstreamed devicetree starting with
Linux 6.12)
Until more is known about this non-firing timer interrupt, remove
the devicetree entry to enable RPi5 devices to boot.
[1] https://lore.kernel.org/all/12363be5b11c752b7155cc0c416fdfd2@kernel.org/
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Closes: https://lore.kernel.org/all/ea15cce1-b393-43f6-8d58-3d6f90f0c0cd@samsung.com/
Signed-off-by: Daniel Drake <dan@reactivated.net>
---
arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 2 --
1 file changed, 2 deletions(-)
diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
index 761c59d90ffc..09ff5e9959d3 100644
--- a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
@@ -678,8 +678,6 @@ IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
- IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 12 (GIC_CPU_MASK_SIMPLE(4) |
IRQ_TYPE_LEVEL_LOW)>;
};
--
2.54.0
^ permalink raw reply related
* Re: [PATCH] arm64: dts: broadcom: bcm2712: Remove non-functional EL2 virtual timer
From: Marek Szyprowski @ 2026-06-19 21:04 UTC (permalink / raw)
To: Daniel Drake, maz, robh, krzk+dt, conor+dt, florian.fainelli,
bcm-kernel-feedback-list
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, andrea.porta
In-Reply-To: <20260619204832.586079-1-dan@reactivated.net>
On 19.06.2026 22:48, Daniel Drake wrote:
> Commit d87773de9efe1 ("clocksource/drivers/arm_arch_timer: Default to
> EL2 virtual timer when running VHE") causes boot to hang on
> Raspberry Pi 5. The newly-selected EL2 virtual timer does not generate
> any interrupts, even though the GIC_DIST_ENABLE_SET flag has been
> confirmed set via readback.
>
> The reasons for this failure are unknown, however it is likely that
> this timer was never tested. Raspberry Pi's original devicetree did
> not include this timer interrupt; it was only introduced via a
> suggestion[1] made in code review as part of the upstreaming process.
> (Current RPi firmware versions do include this timer, but only because
> they rebased on top of the upstreamed devicetree starting with
> Linux 6.12)
>
> Until more is known about this non-firing timer interrupt, remove
> the devicetree entry to enable RPi5 devices to boot.
>
> [1] https://lore.kernel.org/all/12363be5b11c752b7155cc0c416fdfd2@kernel.org/
>
> Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Closes: https://lore.kernel.org/all/ea15cce1-b393-43f6-8d58-3d6f90f0c0cd@samsung.com/
> Signed-off-by: Daniel Drake <dan@reactivated.net>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
> arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
> index 761c59d90ffc..09ff5e9959d3 100644
> --- a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
> +++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
> @@ -678,8 +678,6 @@ IRQ_TYPE_LEVEL_LOW)>,
> <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
> IRQ_TYPE_LEVEL_LOW)>,
> <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
> - IRQ_TYPE_LEVEL_LOW)>,
> - <GIC_PPI 12 (GIC_CPU_MASK_SIMPLE(4) |
> IRQ_TYPE_LEVEL_LOW)>;
> };
>
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply
* Re: [PATCH v3 2/7] gpio: regmap: add gpio_regmap_get_gpiochip() accessor
From: Linus Walleij @ 2026-06-19 21:08 UTC (permalink / raw)
To: Michael Walle
Cc: Bartosz Golaszewski, Andy Shevchenko, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, afaerber@suse.com,
wbg@kernel.org, mathieu.dubois-briand@bootlin.com,
lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org,
nuno.sa@analog.com, andy@kernel.org, dlechner@baylibre.com,
TY_Chang[張子逸], linux-gpio@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-realtek-soc@lists.infradead.org, linux-iio@vger.kernel.org,
CY_Huang[黃鉦晏],
Stanley Chang[昌育德],
James Tai [戴志峰],
Yu-Chun Lin [林祐君]
In-Reply-To: <DJ3QVMZ6XLW9.1M9W541O92QWJ@kernel.org>
On Mon, Jun 8, 2026 at 4:41 PM Michael Walle <mwalle@kernel.org> wrote:
> >>> Without an accessor like gpio_regmap_get_gpiochip(), we cannot retrieve the
> >>> gpio_chip instantiated inside gpio-regmap.c to fulfill these requirements in our
> >>> map() function.
>
> Why is gpiochip_irq_reqres() called in the first place? Isn't that
> only called if the irq handling is set up via gc->irq.chip and not
> via gpiochip_irqchip_add_domain() like in gpio-regmap?
Not really, the gpiochip_irq_reqres() is called to mark that a
GPIO line is used for IRQ, so the gpiolib cannot turn this
GPIO into an output line, gpiod_direction_out() will fail
on lines used for IRQ. So it's a failsafe.
You can live without it of course, but then you don't get
this failsafe.
Yours,
Linus Walleij
^ permalink raw reply
* [STATUS] arm64/for-kernelci - 92e3f6ef4ffb1f65e7774f4611c27fb764b3bc14
From: KernelCI bot @ 2026-06-20 2:30 UTC (permalink / raw)
To: kernelci-results; +Cc: will, linux-arm-kernel
Hello,
Status summary for arm64/for-kernelci
Dashboard:
https://d.kernelci.org/c/arm64/for-kernelci/92e3f6ef4ffb1f65e7774f4611c27fb764b3bc14/
giturl: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
branch: for-kernelci
commit hash: 92e3f6ef4ffb1f65e7774f4611c27fb764b3bc14
origin: maestro
test start time: 2026-06-19 17:25:47.988000+00:00
Builds: 8 ✅ 0 ❌ 0 ⚠️
Boots: 24 ✅ 0 ❌ 1 ⚠️
Tests: 10579 ✅ 84 ❌ 93 ⚠️
### POSSIBLE REGRESSIONS
No possible regressions observed.
### FIXED REGRESSIONS
No fixed regressions observed.
### UNSTABLE TESTS
Hardware: bcm2711-rpi-4-b
> Config: defconfig+lab-setup+kselftest
- Architecture/compiler: arm64/gcc-14
- boot
last run: https://d.kernelci.org/test/maestro:6a3587e0ec8c023893a36461
history: > ✅ > ✅ > ⚠️ > ✅ > ✅
Sent every day if there were changes in the past 24 hours.
Legend: ✅ PASS ❌ FAIL ⚠️ INCONCLUSIVE
--
This is an experimental report format. Please send feedback in!
Talk to us at kernelci@lists.linux.dev
Made with love by the KernelCI team - https://kernelci.org
^ permalink raw reply
* Re: [PATCH v7 0/2] arm64: dts: rockchip: add Vicharak Axon board support
From: Hrushiraj Gandhi @ 2026-06-20 5:37 UTC (permalink / raw)
To: heiko
Cc: krzk+dt, robh, conor+dt, devicetree, linux-arm-kernel,
linux-rockchip, linux-kernel
In-Reply-To: <20260608060940.52549-1-hrushirajg23@gmail.com>
Hi Heiko,
Just a friendly ping on this series.
The binding patch has received an Acked-by from Krzysztof and the
requested review comments from previous revisions have been addressed.
Could you please take a look when you have a chance? Any additional
feedback on either the binding or DTS patch would be greatly appreciated.
Thanks for your time.
Best regards,
Hrushiraj
^ permalink raw reply
* [PATCH 0/4] spi: fix PM error handling in several drivers
From: Jiawen Liu @ 2026-06-20 8:39 UTC (permalink / raw)
To: broonie
Cc: cl634, william.zhang, kursad.oney, jonas.gorski,
bcm-kernel-feedback-list, anand.gore, f.fainelli, rafal, olteanv,
han.xu, haibo.chen, yogeshgaur.83, linux-spi, linux-kernel,
linux-arm-kernel, imx, Jiawen Liu
This series fixes several SPI PM error paths where drivers continued
tearing down or reported success after a controller suspend or runtime PM
operation failed.
The patches are independent and only touch the local error paths in each
driver.
Jiawen Liu (4):
spi: atcspi200: return error from failed controller suspend
spi: bcmbca-hsspi: return error from failed controller suspend
spi: fsl-dspi: clean up after failed suspend and resume
spi: nxp-fspi: disable runtime PM on probe failures
drivers/spi/spi-atcspi200.c | 5 ++++-
drivers/spi/spi-bcmbca-hsspi.c | 6 +++++-
drivers/spi/spi-fsl-dspi.c | 21 ++++++++++++++++++---
drivers/spi/spi-nxp-fspi.c | 31 ++++++++++++++++++++++---------
4 files changed, 49 insertions(+), 14 deletions(-)
base-commit: 9e7e6633458362db72427b48effad8d759131c35
--
2.34.1
^ permalink raw reply
* [PATCH 1/4] spi: atcspi200: return error from failed controller suspend
From: Jiawen Liu @ 2026-06-20 8:39 UTC (permalink / raw)
To: broonie
Cc: cl634, william.zhang, kursad.oney, jonas.gorski,
bcm-kernel-feedback-list, anand.gore, f.fainelli, rafal, olteanv,
han.xu, haibo.chen, yogeshgaur.83, linux-spi, linux-kernel,
linux-arm-kernel, imx, Jiawen Liu
In-Reply-To: <20260620083931.1120616-1-1298662399@qq.com>
spi_controller_suspend() can fail when the SPI core cannot stop the
controller. atcspi_suspend() ignored that error and disabled the
controller clock anyway.
Return the error before disabling the clock.
Signed-off-by: Jiawen Liu <1298662399@qq.com>
---
drivers/spi/spi-atcspi200.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi-atcspi200.c b/drivers/spi/spi-atcspi200.c
index 6d4b6aeb3f5b..e0fd101a62bc 100644
--- a/drivers/spi/spi-atcspi200.c
+++ b/drivers/spi/spi-atcspi200.c
@@ -599,8 +599,11 @@ static int atcspi_suspend(struct device *dev)
{
struct spi_controller *host = dev_get_drvdata(dev);
struct atcspi_dev *spi = spi_controller_get_devdata(host);
+ int ret;
- spi_controller_suspend(host);
+ ret = spi_controller_suspend(host);
+ if (ret)
+ return ret;
clk_disable_unprepare(spi->clk);
--
2.34.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox