* Re: [PATCH v3 1/1] coresight: fix issue where coresight component has no claimtags
From: Leo Yan @ 2026-06-22 10:26 UTC (permalink / raw)
To: Mike Leach
Cc: coresight, linux-arm-kernel, linux-kernel, suzuki.poulose,
james.clark
In-Reply-To: <20260619160148.499223-2-mike.leach@arm.com>
Hi Mike,
On Fri, Jun 19, 2026 at 05:01:48PM +0100, Mike Leach wrote:
[...]
> Any device which is not verified to support claim tags, will now get a
> success return from the claim/disclaim calls.
Do we really want to relax this?
AFAIK, all Arm standard modules should follow the claim tag protocol.
SoC specific modules that do not support claim tags should not enable
claim tag handling in the first place. In that case, they would not
need any claim tag-related operations.
The tricky part is that if a module provides CORESIGHT_CLAIMSET, it
likely supports claim tags. Conversely, if a module does not provide
CORESIGHT_CLAIMSET, validating claim tags using that offset seems
pointless.
As a result, can we constraint to only two cases as below?
enum coresight_claim_tag_info {
CS_CLAIM_TAG_STD_PROTOCOL,
CS_CLAIM_TAG_IGNORE,
};
For CS_CLAIM_TAG_STD_PROTOCOL type, it must pass the validation.
Otherwise, the claim tag operations will be totally ignored.
[...]
> diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
> index 43abe13995cf..d8a0ecc502af 100644
> --- a/drivers/hwtracing/coresight/coresight-catu.c
> +++ b/drivers/hwtracing/coresight/coresight-catu.c
> @@ -574,10 +574,14 @@ static int __catu_probe(struct device *dev, struct resource *res)
> catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
> catu_desc.ops = &catu_ops;
>
> - coresight_clear_self_claim_tag(&catu_desc.access);
> drvdata->csdev = coresight_register(&catu_desc);
> if (IS_ERR(drvdata->csdev))
> ret = PTR_ERR(drvdata->csdev);
> +
> + ret = coresight_init_claim_tags(drvdata->csdev);
> + if (ret)
> + coresight_unregister(drvdata->csdev);
> +
coresight_init_claim_tags() is much simpler than coresight_register(),
this is why we can put coresight_init_claim_tags() before
coresight_register() to avoid complex rollback operations for claim init
failure.
I have no strong opinion for this, as the sequence in this patch should
can work as well.
> +/* helper for checking if claim tag protocol in use */
> +static bool coresight_using_claim_tag_protocol(struct coresight_device *csdev)
> +{
> + return (bool)(csdev->claim_tag_info == CS_CLAIM_TAG_STD_PROTOCOL);
> +}
Redundant for bool cast?
> +
> +/* helper to check initialised */
> +static bool coresight_claim_tag_noinit(struct coresight_device *csdev)
> +{
> + return (bool)(csdev->claim_tag_info == CS_CLAIM_TAG_UNKNOWN);
Ditto.
> +/* cpu bound devices (etms) may need to run on bound cpu */
> +int coresight_init_claim_tags_cpu_smp(struct coresight_device *csdev, int cpu)
> +{
> + int ret = 0;
> + struct cs_claim_tag_init_arg arg = { };
> +
> + arg.csdev = csdev;
> + ret = smp_call_function_single(cpu,
> + coresight_init_claim_tags_smp_call,
> + &arg, 1);
> +
> + if (!ret)
> + ret = arg.rc;
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(coresight_init_claim_tags_cpu_smp);
Do we really need a specific SMP call for this? I understand this will
be used by ETMv3/v4 drivers, can we simply init claim tags in the local
functions (e.g., etm4_init_arch_data() for ETMv4), same as the current
implemenation?
Thanks,
Leo
^ permalink raw reply
* Re: [PATCH v2 8/8] KVM: arm64: Implement lazy vCPU state sync for non-protected guests
From: Fuad Tabba @ 2026-06-22 10:14 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: <ajj3KzUrZZ1-2UQZ@google.com>
On Mon, 22 Jun 2026 at 09:49, Vincent Donnefort <vdonnefort@google.com> wrote:
>
> [...]
>
> > > > 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.
>
> Ah yes of course, I was hoping we could just have a switch here, just like
> handle_exit() does, but that's not possible because of ARM_SERROR_PENDING().
>
> Perhaps it would look cleaner if done in a separate function
> handle_exit_pkvm_state()?
Agreed, that reads better. Pulling it into handle_exit_pkvm_state()
also gets inject_serror out of handle_exit_early(), which only used it
for this. Done for the next respin.
Cheers,
/fuad
>
>
> >
> > 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] KVM: arm64: account pKVM reclaim against the VM mm
From: Marc Zyngier @ 2026-06-22 8:32 UTC (permalink / raw)
To: Will Deacon, Bradley Morgan
Cc: Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
Suzuki K Poulose, Zenghui Yu, Catalin Marinas, linux-arm-kernel,
kvmarm, linux-kernel
In-Reply-To: <20260621213155.6019-1-include@grrlz.net>
On Sun, 21 Jun 2026 22:31:55 +0100,
Bradley Morgan <include@grrlz.net> wrote:
>
> Protected guest faults charge long term pins to the VM's mm. Teardown
> can run later from file release, where current->mm may be unrelated.
>
> Drop the charge from kvm->mm instead.
>
> Fixes: 4e6e03f9eadd ("KVM: arm64: Hook up reclaim hypercall to pkvm_pgtable_stage2_destroy()")
> Signed-off-by: Bradley Morgan <include@grrlz.net>
> ---
> arch/arm64/kvm/pkvm.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
> index 053e4f733e4b..428723b1b0f5 100644
> --- a/arch/arm64/kvm/pkvm.c
> +++ b/arch/arm64/kvm/pkvm.c
> @@ -352,7 +352,7 @@ static int __pkvm_pgtable_stage2_reclaim(struct kvm_pgtable *pgt, u64 start, u64
> page = pfn_to_page(mapping->pfn);
> WARN_ON_ONCE(mapping->nr_pages != 1);
> unpin_user_pages_dirty_lock(&page, 1, true);
> - account_locked_vm(current->mm, 1, false);
> + account_locked_vm(kvm->mm, 1, false);
> pkvm_mapping_remove(mapping, &pgt->pkvm_mappings);
> kfree(mapping);
> }
Seems correct to me, as the final mmdrop(kvm->mm) occurs after S2
teardown.
Will, what do you think?
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v5 1/8] dt-bindings: thermal: amlogic: Add support for T7
From: Krzysztof Kozlowski @ 2026-06-22 10:02 UTC (permalink / raw)
To: linux-kernel-dev, Guillaume La Roque, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Kevin Hilman,
Jerome Brunet, Martin Blumenstingl
Cc: linux-pm, linux-amlogic, devicetree, linux-kernel,
linux-arm-kernel, Conor Dooley
In-Reply-To: <20260424-add-thermal-t7-vim4-v5-1-9040ca36afe2@aliel.fr>
On 24/04/2026 17:45, Ronald Claveau via B4 Relay wrote:
> + - |
> + temperature-sensor@20000 {
> + compatible = "amlogic,t7-thermal";
> + reg = <0x0 0x20000 0x0 0x50>;
> + interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
This wasn't ever even built! Really, it fails immediately. I will send
fixes, but quite disappointing that contributor does not test its own code.-
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v3 2/2] iio: adc: add Axiado SARADC driver
From: Joshua Crofts @ 2026-06-22 9:55 UTC (permalink / raw)
To: Petar Stepanovic
Cc: Akhila Kavi, Prasad Bolisetty, Jonathan Cameron, David Lechner,
Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Harshit Shah, linux-iio, devicetree,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260622-axiado-ax3000-ax3005-saradc-v3-2-e57c7c7ae675@axiado.com>
On Mon, 22 Jun 2026 00:47:28 -0700
Petar Stepanovic <pstepanovic@axiado.com> wrote:
> Add support for the SARADC controller found on Axiado AX3000 and
> AX3005 SoCs.
>
> The driver supports single-shot voltage reads through the IIO
> subsystem. The number of available input channels is selected from
> the SoC match data, allowing AX3000 and AX3005 variants to use the
> same driver.
>
> Signed-off-by: Petar Stepanovic <pstepanovic@axiado.com>
> ---
> + info->clk_rate = clk_get_rate(info->clk);
> + if (!info->clk_rate)
> + return dev_err_probe(dev, -EINVAL, "invalid clock rate\n");
> +
> + ret = devm_regulator_get_enable_read_voltage(dev, "vref");
> + if (ret < 0)
> + return dev_err_probe(dev, info->vref_uV,
> + "failed to get vref voltage\n");
Sashiko raised an issue that I've missed on previous reads - why
are you using info->vref_uV in dev_err_probe()? The info struct
is not zeroed out on initialization, which means that dev_err_probe
will return a different value each time when read_voltage() fails.
It was designed to accept the retval from whatever function we're
checking.
--
Kind regards
CJD
^ permalink raw reply
* Re: [PATCH v6 15/19] drm/connector: Add new atomic_create_state callback
From: Maxime Ripard @ 2026-06-22 9:53 UTC (permalink / raw)
To: Luca Ceresoli
Cc: 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, dri-devel, linux-doc,
linux-kernel, Daniel Stone, intel-gfx, intel-xe, linux-arm-kernel,
linux-sunxi, Laurent Pinchart
In-Reply-To: <DJD5YZ2K1047.3UJ5QMMLQO6UY@bootlin.com>
[-- Attachment #1: Type: text/plain, Size: 5721 bytes --]
On Fri, Jun 19, 2026 at 06:24:46PM +0200, Luca Ceresoli wrote:
> 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.
That's true, but I don't see how this particular patch affects it? The
call sites of reset are now falling back to atomic_create_state, but it
doesn't change anything wrt when reset is (or was?) called, which seems
to be what you're talking about.
> 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'.
But it's pretty much the same story here? it changes the implementation,
but it should be called at the same time it used to.
> 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?
Generally speaking, either drm_mode_config_reset() or
drm_mode_config_create_initial_state will fill $object->state on most
drivers. For dynamic connectors, you'll need to create the initial state
when creating the new connector.
That's what intel (in intel_connector_alloc()) is doing
https://elixir.bootlin.com/linux/v7.0.11/source/drivers/gpu/drm/i915/display/intel_dp_mst.c#L1684
amdgpu through the call to amdgpu_dm_connector_funcs_reset():
https://elixir.bootlin.com/linux/v7.0.11/source/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c#L632
nouveau through the call to mstc->connector.funcs->reset()
https://elixir.bootlin.com/linux/v7.0.11/source/drivers/gpu/drm/nouveau/dispnv50/disp.c#L1262
Would it be possible that it's not a regression but rather that you just noticed it?
Maxime
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]
^ permalink raw reply
* Re: [PATCH v2 2/4] irqchip/gic-v3: Refactor GIC600 limited to 32bit PA erratum handling
From: Geert Uytterhoeven @ 2026-06-22 9:52 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-pci, Marc Zyngier, Krzysztof Wilczyński, Bjorn Helgaas,
Catalin Marinas, Conor Dooley, Geert Uytterhoeven,
Krzysztof Kozlowski, Lorenzo Pieralisi, Manivannan Sadhasivam,
Rob Herring, Yoshihiro Shimoda, devicetree, linux-arm-kernel,
linux-doc, linux-kernel, linux-renesas-soc
In-Reply-To: <20260618220427.14325-3-marek.vasut+renesas@mailbox.org>
Hi Marek,
On Fri, 19 Jun 2026 at 00:04, Marek Vasut
<marek.vasut+renesas@mailbox.org> wrote:
> The GIC600 implementation is now known to be used on multiple 64-bit
> SoCs, where it has address width for AXI or APB interface configured
> to 32 bit, and it can access only the first 4GiB of physical address
> space.
>
> Rework the handling of the quirk to work around this limitation such
> that new entries can be added purely as new compatible strings, with
> no need to add additional functions or new its_quirk array entries.
>
> Suggested-by: Marc Zyngier <maz@kernel.org>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Thanks for your patch!
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -4890,10 +4890,17 @@ static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data)
> return true;
> }
>
> -static bool __maybe_unused its_enable_rk3568002(void *data)
> +static const char * const dma_32bit_impaired_platforms[] = {
> +#ifdef CONFIG_ROCKCHIP_ERRATUM_3568002
> + "rockchip,rk3566",
> + "rockchip,rk3568",
> +#endif
> + NULL,
> +};
> +
> +static bool __maybe_unused its_enable_dma32(void *data)
__maybe_unused can be dropped...
> {
> - if (!of_machine_is_compatible("rockchip,rk3566") &&
> - !of_machine_is_compatible("rockchip,rk3568"))
> + if (!of_machine_compatible_match(dma_32bit_impaired_platforms))
> return false;
>
> gfp_flags_quirk |= GFP_DMA32;
> @@ -4968,14 +4975,12 @@ static const struct gic_quirk its_quirks[] = {
> .property = "dma-noncoherent",
> .init = its_set_non_coherent,
> },
> -#ifdef CONFIG_ROCKCHIP_ERRATUM_3568002
... as the #ifdef is removed.
> {
> - .desc = "ITS: Rockchip erratum RK3568002",
> + .desc = "ITS: Broken GIC600 integration limited to 32bit PA",
> .iidr = 0x0201743b,
> .mask = 0xffffffff,
> - .init = its_enable_rk3568002,
> + .init = its_enable_dma32,
> },
> -#endif
> {
> }
> };
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [RFC] arm64: early_ioremap fails to map ACPI MADT on 64K pages
From: Lorenzo Pieralisi @ 2026-06-22 9:49 UTC (permalink / raw)
To: Hanjun Guo
Cc: Will Deacon, Yu Peng, Catalin Marinas, linux-arm-kernel,
Rafael J. Wysocki, Len Brown, linux-acpi, Andrew Morton, linux-mm,
linux-kernel, sudeep.holla
In-Reply-To: <3cceb66d-4496-1a46-60ab-f43b0669fb71@huawei.com>
On Mon, Jun 22, 2026 at 04:55:29PM +0800, Hanjun Guo wrote:
> On 2026/6/19 22:43, Will Deacon wrote:
> > +arm64 ACPI maintainers
> >
> > On Wed, Jun 17, 2026 at 02:01:10PM +0800, Yu Peng wrote:
> > > I hit an early boot failure on an arm64 system built with 64K pages while
> > > parsing the ACPI MADT.
> > >
> > > The failing system reports:
> > >
> > > PAGE_SIZE: 64K
> > > MADT physical address: 0x5a7ae018
> > > MADT length: 0x32094
> >
> > The MADT isn't even 4k aligned, so why does the page size matter in this
> > case?
> >
> > > The failure happens when acpi_table_parse_madt() calls into early_memremap()
> > > via __acpi_map_table(). The MADT itself is smaller than 256K, but its
> > > placement causes the early mapping to require 5 64K pages:
> > >
> > > offset within 64K page = 0x5a7ae018 & 0xffff = 0xe018
> > > mapped range = PAGE_ALIGN(0xe018 + 0x32094)
> > > = PAGE_ALIGN(0x400ac)
> > > = 0x50000
> > > nrpages = 0x50000 / 0x10000 = 5
> > >
> > > On arm64, NR_FIX_BTMAPS is currently derived from a 256K per-slot budget:
> > >
> > > #define NR_FIX_BTMAPS (SZ_256K / PAGE_SIZE)
> > >
> > > So for 64K pages, NR_FIX_BTMAPS is 4. The mapping therefore fails the
> > > early_ioremap() check:
> > >
> > > if (WARN_ON(nrpages > NR_FIX_BTMAPS))
> > > return NULL;
> > >
> > > After that, MADT parsing fails and the boot continues with symptoms such as:
> > >
> > > ACPI: APIC not present
> > > missing boot CPU MPIDR, not enabling secondaries
> > > Kernel panic - not syncing: No interrupt controller found.
> > >
> > > A firmware change can avoid this by placing MADT so that:
> > >
> > > (madt_phys & 0xffff) + madt_length <= SZ_256K
> > >
> > > However, I do not think ACPI requires such placement, so this looks like a
> > > kernel-side robustness issue as well, especially on large arm64 systems where
> > > MADT can grow with CPU topology.
> > >
> > > One possible kernel-side change is to increase the boot-time mapping budget for
> > > CONFIG_ARM64_64K_PAGES, for example using a 512K per-slot budget only in that
> > > configuration. I do not think this should be applied unconditionally to all
> > > page sizes, since the arm64 early fixmap code expects the boot-ioremap range
> > > to stay within one PMD.
> > >
> > > Has anyone seen similar failures on arm64 64K systems?
First bug report I am aware of, perhaps this was papered over in FW,
MADT parsing failure is the first thing you would notice in bootstrapping
an ACPI system (FADT is not that big).
> > >
> > > Would maintainers prefer treating this as a firmware layout issue, or would
> > > increasing the early_ioremap budget for 64K pages be acceptable?
> >
> > It think it boils down to what ACPI says about the alignment of the MADT.
>
> I checked the ACPI spec and it didn't require the alignment for ACPI
> tables, but in UEFI spec, it says (for aarch64):
>
> ACPI Tables loaded at boot time can be contained in memory of type
> EfiACPIReclaimMemory (recommended) or EfiACPIMemoryNVS.
>
> EFI memory descriptors of type EfiACPIReclaimMemory and EfiACPIMemoryNVS
> must be aligned on a 4 KiB boundary and must be a multiple of 4 KiB in
> size.
>
> It only requires EfiACPIReclaimMemory type to be 4K aligned, not
> for each ACPI table, because ACPI tables can be packed into the
> allocated EfiACPIReclaimMemory type, correct me if I'm wrong!
I am afraid you are not wrong - we can't blame firmware (yet), this
has to be addressed.
Lorenzo
^ permalink raw reply
* Re: [PATCH v3 1/1] reset: imx7: Correct polarity of MIPI CSI resets on i.MX8MQ
From: guoniu.zhou @ 2026-06-22 9:50 UTC (permalink / raw)
To: robby.cai
Cc: p.zabel, Frank.Li, s.hauer, festevam, krzk+dt, andrew.smirnov,
kernel, imx, linux-arm-kernel, linux-kernel, aisheng.dong,
guoniu.zhou
In-Reply-To: <20260619073115.3778313-1-robby.cai@oss.nxp.com>
On Fri, 19 Jun 2026 15:31:15 +0800, robby.cai@oss.nxp.com <robby.cai@oss.nxp.com> wrote:
> reset: imx7: Correct polarity of MIPI CSI resets on i.MX8MQ
Reviewed-by: Guoniu Zhou <guoniu.zhou@oss.nxp.com>
--
Guoniu Zhou <guoniu.zhou@oss.nxp.com>
^ permalink raw reply
* Re: [PATCH v3] drm/bridge: imx93-mipi-dsi: Fix mode validation
From: Maxime Ripard @ 2026-06-22 9:38 UTC (permalink / raw)
To: Liu Ying
Cc: Luca Ceresoli, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Dmitry Baryshkov, dri-devel, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <ajjpuroFPI_U2Fw6@raspi>
[-- Attachment #1: Type: text/plain, Size: 582 bytes --]
On Mon, Jun 22, 2026 at 03:52:26PM +0800, Liu Ying wrote:
> > 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?
>
> I see several upstream drivers rely on it, see "git grep '0.5%' drivers/gpu/"
> output. And every display mode allows -/+ 0.5% pixel clock rate deviation
> according to VESA Display Monitor Timing Standard [1], though [1] is a found
> by a random Google search.
Yes, it's what we've been using for some time now. Is there any
particular concern about it?
Maxime
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]
^ permalink raw reply
* [PATCH v1] arm64: dts: freescale: imx95-toradex-smarc: add alias for lpuart5
From: Francesco Dolcini @ 2026-06-22 9:35 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
Cc: Francesco Dolcini, devicetree, imx, linux-arm-kernel,
linux-kernel
From: Francesco Dolcini <francesco.dolcini@toradex.com>
Add alias for lpuart5 so the UART gets a stable line number.
Without this alias, the lpuart driver fails:
fsl-lpuart 42590000.serial: failed to get alias id, errno -19
This prevents the Bluetooth controller connected to this UART from
working.
Fixes: 104a391bb6ff ("arm64: dts: freescale: imx95-toradex-smarc: Enable bluetooth on lpuart5")
Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
---
arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi b/arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi
index 7d760470201f..a6c5398a81e3 100644
--- a/arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi
@@ -24,6 +24,7 @@ aliases {
serial1 = &lpuart1;
serial2 = &lpuart6;
serial3 = &lpuart3;
+ serial4 = &lpuart5;
};
chosen {
--
2.47.3
^ permalink raw reply related
* [PATCH net v2] net: airoha: Add retry mechanism to airoha_qdma_set_trtcm_param()
From: Lorenzo Bianconi @ 2026-06-22 9:35 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Lorenzo Bianconi
Cc: Leto Liu, linux-arm-kernel, linux-mediatek, netdev, Brown Huang
From: Brown Huang <brown.huang@airoha.com>
CPU accesses QDMA via the bus. When multiple modules are using the bus
simultaneously, CPU access to QDMA may encounter bus timeouts and fails,
resulting in QDMA configuration failures and potentially causing packet
transmission issues. In order to mitigate the issue, introduce a retry
mechanism to airoha_qdma_set_trtcm_param routine in order to ensure the
configuration is correctly applied to the hardware.
Fixes: ef1ca9271313b ("net: airoha: Add sched HTB offload support")
Signed-off-by: Brown Huang <brown.huang@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
Changes in v2:
- Wait for write configuration to be completed before running
airoha_qdma_get_trtcm_param() in airoha_qdma_set_trtcm_param().
- Link to v1: https://lore.kernel.org/r/20260608-airoha_qdma_set_trtcm_param-retry-fix-v1-1-f07704f0d8c5@kernel.org
---
drivers/net/ethernet/airoha/airoha_eth.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 3370c3df7c10..bb5c0599a4ee 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2673,14 +2673,30 @@ static int airoha_qdma_set_trtcm_param(struct airoha_qdma *qdma, int channel,
FIELD_PREP(TRTCM_METER_GROUP_MASK, group) |
FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) |
FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode);
+ int i;
- airoha_qdma_wr(qdma, REG_TRTCM_DATA_LOW(addr), val);
- airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config);
+ for (i = 0; i < 100; i++) {
+ u32 data;
- return read_poll_timeout(airoha_qdma_rr, val,
- val & TRTCM_PARAM_RW_DONE_MASK,
- USEC_PER_MSEC, 10 * USEC_PER_MSEC, true,
- qdma, REG_TRTCM_CFG_PARAM(addr));
+ airoha_qdma_wr(qdma, REG_TRTCM_DATA_LOW(addr), val);
+ wmb();
+ airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config);
+
+ if (read_poll_timeout(airoha_qdma_rr, data,
+ data & TRTCM_PARAM_RW_DONE_MASK,
+ USEC_PER_MSEC, 10 * USEC_PER_MSEC,
+ true, qdma, REG_TRTCM_CFG_PARAM(addr)))
+ return -ETIMEDOUT;
+
+ if (airoha_qdma_get_trtcm_param(qdma, channel, addr, param,
+ mode, &data, NULL))
+ continue;
+
+ if (data == val)
+ return 0;
+ }
+
+ return -EBUSY;
}
static int airoha_qdma_set_trtcm_config(struct airoha_qdma *qdma, int channel,
---
base-commit: d07d80b6a129a44538cda1549b7acf95154fb197
change-id: 20260605-airoha_qdma_set_trtcm_param-retry-fix-a9d2956b9b2f
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* [PATCH v4 3/4] gpio: realtek: Add driver for Realtek DHC RTD1625 SoC
From: Yu-Chun Lin @ 2026-06-22 9:23 UTC (permalink / raw)
To: linusw, brgl, robh, krzk+dt, conor+dt, afaerber, mwalle,
andriy.shevchenko, tychang
Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, cy.huang, stanley_chang, eleanor.lin,
james.tai
In-Reply-To: <20260622092335.1166876-1-eleanor.lin@realtek.com>
From: Tzuyi Chang <tychang@realtek.com>
Add support for the GPIO controller found on Realtek DHC RTD1625 SoCs.
Unlike the existing Realtek GPIO driver (drivers/gpio/gpio-rtd.c),
which manages pins via shared bank registers, the RTD1625 introduces
a per-pin register architecture. Each GPIO line now has its own
dedicated 32-bit control register to manage configuration independently,
including direction, output value, input value, interrupt enable, and
debounce. Therefore, this distinct hardware design requires a separate
driver.
Additionally, the RTD1625 GPIO controller has a specific hardware quirk:
it fires both 'assert' and 'de-assert' interrupts simultaneously on any
edge toggle. To handle this, we utilize the polarity register to route
the requested edge (rising/falling) to the 'assert' IRQ line. The driver
then filters out the unwanted 'de-assert' interrupt in the IRQ handler
and pre-clears edge interrupts to prevent interrupt storms caused by
unhandled dropped interrupts.
Interrupt support is optional for this device, matching the dt-bindings.
If the interrupts property is not provided, the driver simply skips IRQ
initialization and operates purely as a basic GPIO controller.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Tzuyi Chang <tychang@realtek.com>
Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
Changes between v2 and v4:
IRQ Handling Fix
- Added enum rtd1625_irq_index with named constants to replace magic array
indices 0/1/2.
- Documented hardware quirk.
Coding style & cleanup:
- In rtd1625_gpio_irq_set_type(), using return directly in each switch case.
- Changed int loop counters to unsigned int.
- Replaced devm_kzalloc() with devm_kcalloc() in probe.
- Moved of_device_id table closer to its user.
- Added static to DEFINE_NOIRQ_DEV_PM_OPS.
- Formatting consistency: zero-padded hex constants.
New header:
- Added #include <linux/cleanup.h> (required for the guard() / scoped_guard()
macros).
Copyright year updated:
- 2023 -> 2023-2026.
---
drivers/gpio/Kconfig | 12 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-rtd1625.c | 611 ++++++++++++++++++++++++++++++++++++
3 files changed, 624 insertions(+)
create mode 100644 drivers/gpio/gpio-rtd1625.c
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ed2bc3113374..f03c05288376 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -656,6 +656,18 @@ config GPIO_RTD
Say yes here to support GPIO functionality and GPIO interrupt on
Realtek DHC SoCs.
+config GPIO_RTD1625
+ tristate "Realtek DHC RTD1625 GPIO support"
+ depends on ARCH_REALTEK || COMPILE_TEST
+ default ARCH_REALTEK
+ select GPIOLIB_IRQCHIP
+ help
+ This option enables support for the GPIO controller on Realtek
+ DHC (Digital Home Center) RTD1625 SoC.
+
+ Say yes here to support both basic GPIO line functionality
+ and GPIO interrupt handling capabilities for this platform.
+
config GPIO_SAMA5D2_PIOBU
tristate "SAMA5D2 PIOBU GPIO support"
depends on OF
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 4d0e900402fc..fa14581e3995 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -160,6 +160,7 @@ obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o
obj-$(CONFIG_GPIO_REG) += gpio-reg.o
obj-$(CONFIG_GPIO_ROCKCHIP) += gpio-rockchip.o
obj-$(CONFIG_GPIO_RTD) += gpio-rtd.o
+obj-$(CONFIG_GPIO_RTD1625) += gpio-rtd1625.o
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o
obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o
diff --git a/drivers/gpio/gpio-rtd1625.c b/drivers/gpio/gpio-rtd1625.c
new file mode 100644
index 000000000000..409e540bf40b
--- /dev/null
+++ b/drivers/gpio/gpio-rtd1625.c
@@ -0,0 +1,611 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Realtek DHC RTD1625 gpio driver
+ *
+ * Copyright (c) 2023-2026 Realtek Semiconductor Corp.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/cleanup.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#define RTD1625_GPIO_DIR BIT(0)
+#define RTD1625_GPIO_OUT BIT(2)
+#define RTD1625_GPIO_IN BIT(4)
+#define RTD1625_GPIO_EDGE_INT_DP BIT(6)
+#define RTD1625_GPIO_EDGE_INT_EN BIT(8)
+#define RTD1625_GPIO_LEVEL_INT_EN BIT(16)
+#define RTD1625_GPIO_LEVEL_INT_DP BIT(18)
+#define RTD1625_GPIO_DEBOUNCE GENMASK(30, 28)
+#define RTD1625_GPIO_DEBOUNCE_WREN BIT(31)
+
+#define RTD1625_GPIO_WREN(x) ((x) << 1)
+
+/* Write-enable masks for all GPIO configs and reserved hardware bits */
+#define RTD1625_ISO_GPIO_WREN_ALL 0x8000aa8a
+#define RTD1625_ISOM_GPIO_WREN_ALL 0x800aaa8a
+
+#define RTD1625_GPIO_DEBOUNCE_1US 0
+#define RTD1625_GPIO_DEBOUNCE_10US 1
+#define RTD1625_GPIO_DEBOUNCE_100US 2
+#define RTD1625_GPIO_DEBOUNCE_1MS 3
+#define RTD1625_GPIO_DEBOUNCE_10MS 4
+#define RTD1625_GPIO_DEBOUNCE_20MS 5
+#define RTD1625_GPIO_DEBOUNCE_30MS 6
+#define RTD1625_GPIO_DEBOUNCE_50MS 7
+
+#define GPIO_CONTROL(gpio) ((gpio) * 4)
+
+enum rtd1625_irq_index {
+ RTD1625_IRQ_ASSERT,
+ RTD1625_IRQ_DEASSERT,
+ RTD1625_IRQ_LEVEL,
+ RTD1625_MAX_IRQS
+};
+
+/**
+ * struct rtd1625_gpio_info - Specific GPIO register information
+ * @num_gpios: The number of GPIOs
+ * @irq_type_support: Supported IRQ types
+ * @gpa_offset: Offset for GPIO assert interrupt status registers
+ * @gpda_offset: Offset for GPIO deassert interrupt status registers
+ * @level_offset: Offset of level interrupt status register
+ * @write_en_all: Write-enable mask for all configurable bits
+ */
+struct rtd1625_gpio_info {
+ unsigned int num_gpios;
+ unsigned int irq_type_support;
+ unsigned int base_offset;
+ unsigned int gpa_offset;
+ unsigned int gpda_offset;
+ unsigned int level_offset;
+ unsigned int write_en_all;
+};
+
+struct rtd1625_gpio {
+ struct gpio_chip gpio_chip;
+ const struct rtd1625_gpio_info *info;
+ void __iomem *base;
+ void __iomem *irq_base;
+ unsigned int irqs[RTD1625_MAX_IRQS];
+ raw_spinlock_t lock;
+ unsigned int *save_regs;
+};
+
+static unsigned int rtd1625_gpio_gpa_offset(struct rtd1625_gpio *data, unsigned int offset)
+{
+ return data->info->gpa_offset + ((offset / 32) * 4);
+}
+
+static unsigned int rtd1625_gpio_gpda_offset(struct rtd1625_gpio *data, unsigned int offset)
+{
+ return data->info->gpda_offset + ((offset / 32) * 4);
+}
+
+static unsigned int rtd1625_gpio_level_offset(struct rtd1625_gpio *data, unsigned int offset)
+{
+ return data->info->level_offset + ((offset / 32) * 4);
+}
+
+static int rtd1625_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
+ unsigned int debounce)
+{
+ struct rtd1625_gpio *data = gpiochip_get_data(chip);
+ u8 deb_val;
+ u32 val;
+
+ switch (debounce) {
+ case 1:
+ deb_val = RTD1625_GPIO_DEBOUNCE_1US;
+ break;
+ case 10:
+ deb_val = RTD1625_GPIO_DEBOUNCE_10US;
+ break;
+ case 100:
+ deb_val = RTD1625_GPIO_DEBOUNCE_100US;
+ break;
+ case 1000:
+ deb_val = RTD1625_GPIO_DEBOUNCE_1MS;
+ break;
+ case 10000:
+ deb_val = RTD1625_GPIO_DEBOUNCE_10MS;
+ break;
+ case 20000:
+ deb_val = RTD1625_GPIO_DEBOUNCE_20MS;
+ break;
+ case 30000:
+ deb_val = RTD1625_GPIO_DEBOUNCE_30MS;
+ break;
+ case 50000:
+ deb_val = RTD1625_GPIO_DEBOUNCE_50MS;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ val = FIELD_PREP(RTD1625_GPIO_DEBOUNCE, deb_val) | RTD1625_GPIO_DEBOUNCE_WREN;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+
+ writel_relaxed(val, data->base + GPIO_CONTROL(offset));
+
+ return 0;
+}
+
+static int rtd1625_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ unsigned long config)
+{
+ u32 debounce;
+
+ if (pinconf_to_config_param(config) == PIN_CONFIG_INPUT_DEBOUNCE) {
+ debounce = pinconf_to_config_argument(config);
+ return rtd1625_gpio_set_debounce(chip, offset, debounce);
+ }
+
+ return gpiochip_generic_config(chip, offset, config);
+}
+
+static int rtd1625_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
+{
+ struct rtd1625_gpio *data = gpiochip_get_data(chip);
+ u32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_OUT);
+
+ if (value)
+ val |= RTD1625_GPIO_OUT;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+
+ writel_relaxed(val, data->base + GPIO_CONTROL(offset));
+
+ return 0;
+}
+
+static int rtd1625_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct rtd1625_gpio *data = gpiochip_get_data(chip);
+ u32 val;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+
+ val = readl_relaxed(data->base + GPIO_CONTROL(offset));
+
+ if (val & RTD1625_GPIO_DIR)
+ return !!(val & RTD1625_GPIO_OUT);
+ else
+ return !!(val & RTD1625_GPIO_IN);
+}
+
+static int rtd1625_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct rtd1625_gpio *data = gpiochip_get_data(chip);
+ u32 val;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+
+ val = readl_relaxed(data->base + GPIO_CONTROL(offset));
+
+ if (val & RTD1625_GPIO_DIR)
+ return GPIO_LINE_DIRECTION_OUT;
+
+ return GPIO_LINE_DIRECTION_IN;
+}
+
+static int rtd1625_gpio_set_direction(struct gpio_chip *chip, unsigned int offset, bool out)
+{
+ struct rtd1625_gpio *data = gpiochip_get_data(chip);
+ u32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_DIR);
+
+ if (out)
+ val |= RTD1625_GPIO_DIR;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+
+ writel_relaxed(val, data->base + GPIO_CONTROL(offset));
+
+ return 0;
+}
+
+static int rtd1625_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
+{
+ return rtd1625_gpio_set_direction(chip, offset, false);
+}
+
+static int rtd1625_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value)
+{
+ rtd1625_gpio_set(chip, offset, value);
+
+ return rtd1625_gpio_set_direction(chip, offset, true);
+}
+
+static void rtd1625_gpio_irq_handle(struct irq_desc *desc)
+{
+ unsigned int (*get_reg_offset)(struct rtd1625_gpio *gpio, unsigned int offset);
+ struct rtd1625_gpio *data = irq_desc_get_handler_data(desc);
+ struct irq_domain *domain = data->gpio_chip.irq.domain;
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned int irq = irq_desc_get_irq(desc);
+ unsigned long status;
+ unsigned int reg_offset, i, j;
+ unsigned int girq;
+ irq_hw_number_t hwirq;
+ u32 irq_type;
+
+ if (irq == data->irqs[RTD1625_IRQ_ASSERT])
+ get_reg_offset = &rtd1625_gpio_gpa_offset;
+ else if (irq == data->irqs[RTD1625_IRQ_DEASSERT])
+ get_reg_offset = &rtd1625_gpio_gpda_offset;
+ else if (irq == data->irqs[2])
+ get_reg_offset = &rtd1625_gpio_level_offset;
+ else
+ return;
+
+ chained_irq_enter(chip, desc);
+
+ for (i = 0; i < data->info->num_gpios; i += 32) {
+ reg_offset = get_reg_offset(data, i);
+ status = readl_relaxed(data->irq_base + reg_offset);
+
+ /*
+ * Hardware quirk: The controller fires both "assert" and "de-assert"
+ * interrupts simultaneously on any edge toggle.
+ * We must pre-clear edge interrupts here. If we drop an unwanted
+ * de-assert interrupt below, it will never reach the IRQ core
+ * (generic_handle_domain_irq), meaning ->irq_ack() won't be called.
+ * Failing to clear it here leads to an interrupt storm.
+ */
+ if (irq != data->irqs[RTD1625_IRQ_LEVEL])
+ writel_relaxed(status, data->irq_base + reg_offset);
+
+ for_each_set_bit(j, &status, 32) {
+ hwirq = i + j;
+ girq = irq_find_mapping(domain, hwirq);
+ irq_type = irq_get_trigger_type(girq);
+
+ /*
+ * Filter out the hardware-forced de-assert interrupt unless
+ * the user explicitly requested IRQ_TYPE_EDGE_BOTH.
+ */
+ if (irq == data->irqs[RTD1625_IRQ_DEASSERT] &&
+ irq_type != IRQ_TYPE_EDGE_BOTH)
+ continue;
+
+ generic_handle_domain_irq(domain, hwirq);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void rtd1625_gpio_ack_irq(struct irq_data *d)
+{
+ struct rtd1625_gpio *data = irq_data_get_irq_chip_data(d);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 irq_type = irqd_get_trigger_type(d);
+ u32 bit_mask = BIT(hwirq % 32);
+ int reg_offset;
+
+ if (irq_type & IRQ_TYPE_LEVEL_MASK) {
+ reg_offset = rtd1625_gpio_level_offset(data, hwirq);
+ writel_relaxed(bit_mask, data->irq_base + reg_offset);
+ }
+}
+
+static void rtd1625_gpio_enable_edge_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
+{
+ int gpda_reg_offset = rtd1625_gpio_gpda_offset(data, hwirq);
+ int gpa_reg_offset = rtd1625_gpio_gpa_offset(data, hwirq);
+ u32 clr_mask = BIT(hwirq % 32);
+ u32 val;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+
+ writel_relaxed(clr_mask, data->irq_base + gpa_reg_offset);
+ writel_relaxed(clr_mask, data->irq_base + gpda_reg_offset);
+ val = RTD1625_GPIO_EDGE_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_EN);
+ writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
+}
+
+static void rtd1625_gpio_disable_edge_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
+{
+ u32 val;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+
+ val = RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_EN);
+ writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
+}
+
+static void rtd1625_gpio_enable_level_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
+{
+ int level_reg_offset = rtd1625_gpio_level_offset(data, hwirq);
+ u32 clr_mask = BIT(hwirq % 32);
+ u32 val;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+
+ writel_relaxed(clr_mask, data->irq_base + level_reg_offset);
+ val = RTD1625_GPIO_LEVEL_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_EN);
+ writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
+}
+
+static void rtd1625_gpio_disable_level_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
+{
+ u32 val;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+
+ val = RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_EN);
+ writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
+}
+
+static void rtd1625_gpio_enable_irq(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct rtd1625_gpio *data = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 irq_type = irqd_get_trigger_type(d);
+
+ gpiochip_enable_irq(gc, hwirq);
+
+ if (irq_type & IRQ_TYPE_EDGE_BOTH)
+ rtd1625_gpio_enable_edge_irq(data, hwirq);
+ else if (irq_type & IRQ_TYPE_LEVEL_MASK)
+ rtd1625_gpio_enable_level_irq(data, hwirq);
+}
+
+static void rtd1625_gpio_disable_irq(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct rtd1625_gpio *data = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 irq_type = irqd_get_trigger_type(d);
+
+ if (irq_type & IRQ_TYPE_EDGE_BOTH)
+ rtd1625_gpio_disable_edge_irq(data, hwirq);
+ else if (irq_type & IRQ_TYPE_LEVEL_MASK)
+ rtd1625_gpio_disable_level_irq(data, hwirq);
+
+ gpiochip_disable_irq(gc, hwirq);
+}
+
+static int rtd1625_gpio_irq_set_level_type(struct irq_data *d, bool level)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct rtd1625_gpio *data = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_DP);
+
+ if (!(data->info->irq_type_support & IRQ_TYPE_LEVEL_MASK))
+ return -EINVAL;
+
+ if (level)
+ val |= RTD1625_GPIO_LEVEL_INT_DP;
+
+ scoped_guard(raw_spinlock_irqsave, &data->lock)
+ writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
+
+ irq_set_handler_locked(d, handle_level_irq);
+
+ return 0;
+}
+
+static int rtd1625_gpio_irq_set_edge_type(struct irq_data *d, bool polarity)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct rtd1625_gpio *data = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_DP);
+
+ if (!(data->info->irq_type_support & IRQ_TYPE_EDGE_BOTH))
+ return -EINVAL;
+
+ if (polarity)
+ val |= RTD1625_GPIO_EDGE_INT_DP;
+
+ scoped_guard(raw_spinlock_irqsave, &data->lock)
+ writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
+
+ irq_set_handler_locked(d, handle_edge_irq);
+
+ return 0;
+}
+
+static int rtd1625_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_RISING:
+ return rtd1625_gpio_irq_set_edge_type(d, 1);
+
+ case IRQ_TYPE_EDGE_FALLING:
+ return rtd1625_gpio_irq_set_edge_type(d, 0);
+
+ case IRQ_TYPE_EDGE_BOTH:
+ return rtd1625_gpio_irq_set_edge_type(d, 1);
+
+ case IRQ_TYPE_LEVEL_HIGH:
+ return rtd1625_gpio_irq_set_level_type(d, 0);
+
+ case IRQ_TYPE_LEVEL_LOW:
+ return rtd1625_gpio_irq_set_level_type(d, 1);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static struct irq_chip rtd1625_iso_gpio_irq_chip = {
+ .name = "rtd1625-gpio",
+ .irq_ack = rtd1625_gpio_ack_irq,
+ .irq_mask = rtd1625_gpio_disable_irq,
+ .irq_unmask = rtd1625_gpio_enable_irq,
+ .irq_set_type = rtd1625_gpio_irq_set_type,
+ .flags = IRQCHIP_IMMUTABLE | IRQCHIP_SKIP_SET_WAKE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static int rtd1625_gpio_setup_irq(struct platform_device *pdev, struct rtd1625_gpio *data)
+{
+ struct gpio_irq_chip *irq_chip;
+ unsigned int num_irqs;
+ int irq;
+
+ /*
+ * Interrupt support is optional. All IRQs must be provided together.
+ * If index 0 is missing, we assume no interrupts are configured in DT
+ * and fall back to basic GPIO operation.
+ */
+ irq = platform_get_irq_optional(pdev, 0);
+ if (irq == -ENXIO)
+ return 0;
+ if (irq < 0)
+ return irq;
+
+ num_irqs = (data->info->irq_type_support & IRQ_TYPE_LEVEL_MASK) ? 3 : 2;
+ data->irqs[RTD1625_IRQ_ASSERT] = irq;
+
+ for (unsigned int i = 1; i < num_irqs; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0)
+ return irq;
+ data->irqs[i] = irq;
+ }
+
+ irq_chip = &data->gpio_chip.irq;
+ irq_chip->handler = handle_bad_irq;
+ irq_chip->default_type = IRQ_TYPE_NONE;
+ irq_chip->parent_handler = rtd1625_gpio_irq_handle;
+ irq_chip->parent_handler_data = data;
+ irq_chip->num_parents = num_irqs;
+ irq_chip->parents = data->irqs;
+
+ gpio_irq_chip_set_chip(irq_chip, &rtd1625_iso_gpio_irq_chip);
+
+ return 0;
+}
+
+static int rtd1625_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rtd1625_gpio *data;
+ void __iomem *irq_base;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->info = device_get_match_data(dev);
+ if (!data->info)
+ return -EINVAL;
+
+ raw_spin_lock_init(&data->lock);
+
+ irq_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(irq_base))
+ return PTR_ERR(irq_base);
+
+ data->irq_base = irq_base;
+ data->base = irq_base + data->info->base_offset;
+
+ data->save_regs = devm_kcalloc(dev, data->info->num_gpios, sizeof(*data->save_regs),
+ GFP_KERNEL);
+ if (!data->save_regs)
+ return -ENOMEM;
+
+ data->gpio_chip.label = dev_name(dev);
+ data->gpio_chip.base = -1;
+ data->gpio_chip.ngpio = data->info->num_gpios;
+ data->gpio_chip.request = gpiochip_generic_request;
+ data->gpio_chip.free = gpiochip_generic_free;
+ data->gpio_chip.get_direction = rtd1625_gpio_get_direction;
+ data->gpio_chip.direction_input = rtd1625_gpio_direction_input;
+ data->gpio_chip.direction_output = rtd1625_gpio_direction_output;
+ data->gpio_chip.set = rtd1625_gpio_set;
+ data->gpio_chip.get = rtd1625_gpio_get;
+ data->gpio_chip.set_config = rtd1625_gpio_set_config;
+ data->gpio_chip.parent = dev;
+
+ ret = rtd1625_gpio_setup_irq(pdev, data);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, data);
+
+ return devm_gpiochip_add_data(dev, &data->gpio_chip, data);
+}
+
+static const struct rtd1625_gpio_info rtd1625_iso_gpio_info = {
+ .num_gpios = 166,
+ .irq_type_support = IRQ_TYPE_EDGE_BOTH,
+ .base_offset = 0x100,
+ .gpa_offset = 0x000,
+ .gpda_offset = 0x020,
+ .write_en_all = RTD1625_ISO_GPIO_WREN_ALL,
+};
+
+static const struct rtd1625_gpio_info rtd1625_isom_gpio_info = {
+ .num_gpios = 4,
+ .irq_type_support = IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_LOW |
+ IRQ_TYPE_LEVEL_HIGH,
+ .base_offset = 0x20,
+ .gpa_offset = 0x00,
+ .gpda_offset = 0x04,
+ .level_offset = 0x18,
+ .write_en_all = RTD1625_ISOM_GPIO_WREN_ALL,
+};
+
+static int rtd1625_gpio_suspend(struct device *dev)
+{
+ struct rtd1625_gpio *data = dev_get_drvdata(dev);
+ const struct rtd1625_gpio_info *info = data->info;
+
+ for (unsigned int i = 0; i < info->num_gpios; i++)
+ data->save_regs[i] = readl_relaxed(data->base + GPIO_CONTROL(i));
+
+ return 0;
+}
+
+static int rtd1625_gpio_resume(struct device *dev)
+{
+ struct rtd1625_gpio *data = dev_get_drvdata(dev);
+ const struct rtd1625_gpio_info *info = data->info;
+
+ for (unsigned int i = 0; i < info->num_gpios; i++)
+ writel_relaxed(data->save_regs[i] | info->write_en_all,
+ data->base + GPIO_CONTROL(i));
+
+ return 0;
+}
+
+static DEFINE_NOIRQ_DEV_PM_OPS(rtd1625_gpio_pm_ops, rtd1625_gpio_suspend, rtd1625_gpio_resume);
+
+static const struct of_device_id rtd1625_gpio_of_matches[] = {
+ { .compatible = "realtek,rtd1625-iso-gpio", .data = &rtd1625_iso_gpio_info },
+ { .compatible = "realtek,rtd1625-isom-gpio", .data = &rtd1625_isom_gpio_info },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rtd1625_gpio_of_matches);
+
+static struct platform_driver rtd1625_gpio_platform_driver = {
+ .driver = {
+ .name = "gpio-rtd1625",
+ .of_match_table = rtd1625_gpio_of_matches,
+ .pm = pm_sleep_ptr(&rtd1625_gpio_pm_ops),
+ },
+ .probe = rtd1625_gpio_probe,
+};
+module_platform_driver(rtd1625_gpio_platform_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Realtek Semiconductor Corporation");
+MODULE_DESCRIPTION("Realtek DHC SoC RTD1625 gpio driver");
--
2.43.0
^ permalink raw reply related
* [PATCH v4 1/4] dt-bindings: gpio: realtek: Add realtek,rtd1625-gpio
From: Yu-Chun Lin @ 2026-06-22 9:23 UTC (permalink / raw)
To: linusw, brgl, robh, krzk+dt, conor+dt, afaerber, mwalle,
andriy.shevchenko, tychang
Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, cy.huang, stanley_chang, eleanor.lin,
james.tai, Krzysztof Kozlowski
In-Reply-To: <20260622092335.1166876-1-eleanor.lin@realtek.com>
From: Tzuyi Chang <tychang@realtek.com>
Add the device tree bindings for the Realtek DHC (Digital Home Center)
RTD1625 GPIO controllers.
The RTD1625 GPIO controller features a per-pin register architecture
that differs significantly from previous generations. It utilizes
separate register blocks for GPIO configuration and interrupt control.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Tzuyi Chang <tychang@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
Changes in v4:
- None.
---
.../bindings/gpio/realtek,rtd1625-gpio.yaml | 71 +++++++++++++++++++
1 file changed, 71 insertions(+)
create mode 100644 Documentation/devicetree/bindings/gpio/realtek,rtd1625-gpio.yaml
diff --git a/Documentation/devicetree/bindings/gpio/realtek,rtd1625-gpio.yaml b/Documentation/devicetree/bindings/gpio/realtek,rtd1625-gpio.yaml
new file mode 100644
index 000000000000..f13c910b73c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/realtek,rtd1625-gpio.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2023 Realtek Semiconductor Corporation
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/realtek,rtd1625-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek DHC RTD1625 GPIO controller
+
+maintainers:
+ - Tzuyi Chang <tychang@realtek.com>
+
+description: |
+ GPIO controller for the Realtek RTD1625 SoC, featuring a per-pin register
+ architecture that differs significantly from earlier RTD series controllers.
+ Each GPIO has dedicated registers for configuration (direction, input/output
+ values, debounce), and interrupt control supporting edge and level detection
+ modes.
+
+properties:
+ compatible:
+ enum:
+ - realtek,rtd1625-iso-gpio
+ - realtek,rtd1625-isom-gpio
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: Interrupt number of the assert GPIO interrupt, which is
+ triggered when there is a rising edge.
+ - description: Interrupt number of the deassert GPIO interrupt, which is
+ triggered when there is a falling edge.
+ - description: Interrupt number of the level-sensitive GPIO interrupt,
+ triggered by a configured logic level.
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 2
+
+ gpio-ranges: true
+
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 2
+
+required:
+ - compatible
+ - reg
+ - gpio-ranges
+ - gpio-controller
+ - "#gpio-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ gpio@89100 {
+ compatible = "realtek,rtd1625-isom-gpio";
+ reg = <0x89100 0x30>;
+ interrupt-parent = <&iso_m_irq_mux>;
+ interrupts = <0>, <1>, <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&isom_pinctrl 0 0 4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
--
2.43.0
^ permalink raw reply related
* [PATCH v4 0/4] gpio: realtek: Add support for Realtek DHC RTD1625
From: Yu-Chun Lin @ 2026-06-22 9:23 UTC (permalink / raw)
To: linusw, brgl, robh, krzk+dt, conor+dt, afaerber, mwalle,
andriy.shevchenko, tychang
Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, cy.huang, stanley_chang, eleanor.lin,
james.tai
This series adds GPIO support for the Realtek DHC RTD1625 SoC.
Unlike the existing driver (gpio-rtd.c) which uses shared bank registers,
the RTD1625 features a per-pin register architecture where each GPIO line
is managed by its own dedicated 32-bit control register. This distinct
hardware design requires a new, separate driver.
Best Regards,
Yu-Chun Lin
---
Patches 1-3 (fix, dt-bindings, and driver) are targeted for the GPIO tree.
Patch 4 (dts) will be taken via the Realtek SoC tree later. It is included
here for context.
Changes in v4:
- Reverted to the v2 approach (without gpio-regmap integration).
As a result, dropped patches 2, 3, and 4 from the v3 series.
Changes in Patch 3 (driver) since v2:
- IRQ handling fixes:
- Added enum rtd1625_irq_index with named constants.
- Documented the hardware quirk.
- Code cleanup and coding style improvements.
- Included the <linux/cleanup.h> header.
- Updated the copyright year.
- Retained Linus Walleij's Reviewed-by tag from v1, as the recent updates are
cleanups and fixes rather than major feature changes.
(Linus, please let me know if you have any concerns regarding this).
v3: https://lore.kernel.org/lkml/20260512033317.1602537-1-eleanor.lin@realtek.com/
v2: https://lore.kernel.org/lkml/20260408025243.1155482-1-eleanor.lin@realtek.com/
v1: https://lore.kernel.org/lkml/20260331113835.3510341-1-eleanor.lin@realtek.com/
Tzuyi Chang (2):
dt-bindings: gpio: realtek: Add realtek,rtd1625-gpio
gpio: realtek: Add driver for Realtek DHC RTD1625 SoC
Yu-Chun Lin (2):
gpio: Replace "default y" with "default ARCH_REALTEK" in Kconfig
arm64: dts: realtek: Add GPIO support for RTD1625
.../bindings/gpio/realtek,rtd1625-gpio.yaml | 71 ++
arch/arm64/boot/dts/realtek/kent.dtsi | 39 ++
drivers/gpio/Kconfig | 14 +-
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-rtd1625.c | 611 ++++++++++++++++++
5 files changed, 735 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/gpio/realtek,rtd1625-gpio.yaml
create mode 100644 drivers/gpio/gpio-rtd1625.c
--
2.43.0
^ permalink raw reply
* [PATCH v4 4/4] arm64: dts: realtek: Add GPIO support for RTD1625
From: Yu-Chun Lin @ 2026-06-22 9:23 UTC (permalink / raw)
To: linusw, brgl, robh, krzk+dt, conor+dt, afaerber, mwalle,
andriy.shevchenko, tychang
Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, cy.huang, stanley_chang, eleanor.lin,
james.tai, Bartosz Golaszewski
In-Reply-To: <20260622092335.1166876-1-eleanor.lin@realtek.com>
Add the GPIO node for the Realtek RTD1625 SoC.
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
Changes in v4:
- None.
---
arch/arm64/boot/dts/realtek/kent.dtsi | 39 +++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/arch/arm64/boot/dts/realtek/kent.dtsi b/arch/arm64/boot/dts/realtek/kent.dtsi
index 8d4293cd4c03..228b82dfdb7a 100644
--- a/arch/arm64/boot/dts/realtek/kent.dtsi
+++ b/arch/arm64/boot/dts/realtek/kent.dtsi
@@ -151,6 +151,37 @@ uart0: serial@7800 {
status = "disabled";
};
+ gpio: gpio@31000 {
+ compatible = "realtek,rtd1625-iso-gpio";
+ reg = <0x31000 0x398>;
+ gpio-controller;
+ gpio-ranges = <&isom_pinctrl 0 0 2>,
+ <&ve4_pinctrl 2 0 6>,
+ <&iso_pinctrl 8 0 4>,
+ <&ve4_pinctrl 12 6 2>,
+ <&main2_pinctrl 14 0 2>,
+ <&ve4_pinctrl 16 8 4>,
+ <&main2_pinctrl 20 2 3>,
+ <&ve4_pinctrl 23 12 3>,
+ <&iso_pinctrl 26 4 2>,
+ <&isom_pinctrl 28 2 2>,
+ <&ve4_pinctrl 30 15 6>,
+ <&main2_pinctrl 36 5 6>,
+ <&ve4_pinctrl 42 21 3>,
+ <&iso_pinctrl 45 6 6>,
+ <&ve4_pinctrl 51 24 1>,
+ <&iso_pinctrl 52 12 1>,
+ <&ve4_pinctrl 53 25 11>,
+ <&main2_pinctrl 64 11 28>,
+ <&ve4_pinctrl 92 36 2>,
+ <&iso_pinctrl 94 13 19>,
+ <&iso_pinctrl 128 32 4>,
+ <&ve4_pinctrl 132 38 13>,
+ <&iso_pinctrl 145 36 19>,
+ <&ve4_pinctrl 164 51 2>;
+ #gpio-cells = <2>;
+ };
+
iso_pinctrl: pinctrl@4e000 {
compatible = "realtek,rtd1625-iso-pinctrl";
reg = <0x4e000 0x1a4>;
@@ -161,6 +192,14 @@ main2_pinctrl: pinctrl@4f200 {
reg = <0x4f200 0x50>;
};
+ iso_m_gpio: gpio@89100 {
+ compatible = "realtek,rtd1625-isom-gpio";
+ reg = <0x89100 0x30>;
+ gpio-controller;
+ gpio-ranges = <&isom_pinctrl 0 0 4>;
+ #gpio-cells = <2>;
+ };
+
isom_pinctrl: pinctrl@146200 {
compatible = "realtek,rtd1625-isom-pinctrl";
reg = <0x146200 0x34>;
--
2.43.0
^ permalink raw reply related
* [PATCH v4 2/4] gpio: Replace "default y" with "default ARCH_REALTEK" in Kconfig
From: Yu-Chun Lin @ 2026-06-22 9:23 UTC (permalink / raw)
To: linusw, brgl, robh, krzk+dt, conor+dt, afaerber, mwalle,
andriy.shevchenko, tychang
Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, cy.huang, stanley_chang, eleanor.lin,
james.tai
In-Reply-To: <20260622092335.1166876-1-eleanor.lin@realtek.com>
Replace "default y" with "default ARCH_REALTEK" to avoid bloating the build
for non-Realtek platforms when COMPILE_TEST is enabled on other platforms.
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
Changes in v4:
- None.
---
drivers/gpio/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 28cf6d2e83c2..ed2bc3113374 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -646,7 +646,7 @@ config GPIO_ROCKCHIP
config GPIO_RTD
tristate "Realtek DHC GPIO support"
depends on ARCH_REALTEK || COMPILE_TEST
- default y
+ default ARCH_REALTEK
select GPIOLIB_IRQCHIP
help
This option enables support for GPIOs found on Realtek DHC(Digital
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v7 5/7] KVM: arm64: Validate the offset to the mem access descriptor
From: Sebastian Ene @ 2026-06-22 9:23 UTC (permalink / raw)
To: Vincent Donnefort
Cc: catalin.marinas, oupton, sudeep.holla, will, jens.wiklander,
joey.gouly, kvmarm, linux-arm-kernel, linux-kernel, android-kvm,
maz, mrigendra.chaubey, op-tee, perlarsen, seiden, smostafa,
sumit.garg, suzuki.poulose, yuzenghui
In-Reply-To: <ajQjOH9Cjk1UqdT-@google.com>
On Thu, Jun 18, 2026 at 05:56:24PM +0100, Vincent Donnefort wrote:
> On Wed, Jun 17, 2026 at 02:51:28PM +0000, Sebastian Ene wrote:
> > Prevent the pKVM hypervisor from making assumptions that the
> > endpoint memory access descriptor (EMAD) comes right after the
> > FF-A memory region header.
> > Prior to FF-A version 1.1 the header of the memory region
> > didn't contain an offset to the endpoint memory access descriptor.
> > The layout of a memory transaction looks like this from 1.1 onward:
> > Type | Field name | Offset
> > [ Header | ffa_mem_region | 0
> > EMAD 1 | ffa_mem_region_attributes) | ffa_mem_region.ep_mem_offset
> > ]
> > Verify that the offset to the first endpoint memory access descriptor
> > is within the mailbox buffer bounds.
> >
> > Also, fix one hardcoded sizeof(struct ffa_mem_region_attributes) that
> > should be replaced ffa_emad_size_get() for compatibility with FFA v1.0.
> >
> > Fixes: 42fb33dde42b ("KVM: arm64: Use FF-A 1.1 with pKVM")
> > Signed-off-by: Sebastian Ene <sebastianene@google.com>
> > Signed-off-by: Mostafa Saleh <smostafa@google.com>
> > ---
> > arch/arm64/kvm/hyp/nvhe/ffa.c | 29 +++++++++++++++++++++--------
> > 1 file changed, 21 insertions(+), 8 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> > index 2d211661952e..1a2abd0154c6 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> > @@ -476,11 +476,14 @@ static void __do_ffa_mem_xfer(const u64 func_id,
> > DECLARE_REG(u32, fraglen, ctxt, 2);
> > DECLARE_REG(u64, addr_mbz, ctxt, 3);
> > DECLARE_REG(u32, npages_mbz, ctxt, 4);
> > + u32 offset, nr_ranges, checked_offset, em_mem_access_off;
> > struct ffa_mem_region_attributes *ep_mem_access;
> > struct ffa_composite_mem_region *reg;
> > struct ffa_mem_region *buf;
> > - u32 offset, nr_ranges, checked_offset;
> > int ret = 0;
> > + size_t mem_region_len = !FFA_MEM_REGION_HAS_EP_MEM_OFFSET(hyp_ffa_version) ?
> > + offsetof(struct ffa_mem_region, ep_mem_offset) :
> > + sizeof(struct ffa_mem_region);
> >
> > if (addr_mbz || npages_mbz || fraglen > len ||
> > fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
> > @@ -488,8 +491,7 @@ static void __do_ffa_mem_xfer(const u64 func_id,
> > goto out;
> > }
> >
> > - if (fraglen < sizeof(struct ffa_mem_region) +
> > - sizeof(struct ffa_mem_region_attributes)) {
> > + if (fraglen < mem_region_len + ffa_emad_size_get(hyp_ffa_version)) {
>
> Can't we replace mem_region_len with ffa_mem_desc_offset()? that pretty much
> looks like the same thing.
>
We can't because `ffa_mem_desc_offset` dereferences struct
ffa_mem_region to extract ep_mem_offset as per the latest updates.
>
> > ret = FFA_RET_INVALID_PARAMETERS;
> > goto out;
> > }
> > @@ -508,8 +510,13 @@ static void __do_ffa_mem_xfer(const u64 func_id,
> > buf = hyp_buffers.tx;
> > memcpy(buf, host_buffers.tx, fraglen);
> >
> > - ep_mem_access = (void *)buf +
> > - ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
> > + em_mem_access_off = ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
> > + if ((u64)em_mem_access_off + ffa_emad_size_get(hyp_ffa_version) > fraglen) {
>
> This check looks like ffa_mem_desc_offset() with count to 1.
>
>
> > + ret = FFA_RET_INVALID_PARAMETERS;
> > + goto out_unlock;
> > + }
> > +
> > + ep_mem_access = (void *)buf + em_mem_access_off;
> > offset = ep_mem_access->composite_off;
> > if (!offset || buf->ep_count != 1 || buf->sender_id != HOST_FFA_ID) {
> > ret = FFA_RET_INVALID_PARAMETERS;
> > @@ -574,9 +581,9 @@ static void do_ffa_mem_reclaim(struct arm_smccc_1_2_regs *res,
> > DECLARE_REG(u32, handle_lo, ctxt, 1);
> > DECLARE_REG(u32, handle_hi, ctxt, 2);
> > DECLARE_REG(u32, flags, ctxt, 3);
> > + u32 offset, len, fraglen, fragoff, em_mem_access_off;
> > struct ffa_mem_region_attributes *ep_mem_access;
> > struct ffa_composite_mem_region *reg;
> > - u32 offset, len, fraglen, fragoff;
> > struct ffa_mem_region *buf;
> > int ret = 0;
> > u64 handle;
> > @@ -599,8 +606,14 @@ static void do_ffa_mem_reclaim(struct arm_smccc_1_2_regs *res,
> > len = res->a1;
> > fraglen = res->a2;
> >
> > - ep_mem_access = (void *)buf +
> > - ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
> > + em_mem_access_off = ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
> > + if ((u64)em_mem_access_off + ffa_emad_size_get(hyp_ffa_version) > fraglen) {
>
> ditto. ffa_mem_desc_offset()
>
> > + ret = FFA_RET_INVALID_PARAMETERS;
> > + ffa_rx_release(res);
> > + goto out_unlock;
> > + }
> > +
> > + ep_mem_access = (void *)buf + em_mem_access_off;
> > offset = ep_mem_access->composite_off;
> > /*
> > * We can trust the SPMD to get this right, but let's at least
> > --
> > 2.54.0.1136.gdb2ca164c4-goog
> >
Thanks,
Sebastian
^ permalink raw reply
* Re: [PATCH] mfd: db8500-prcmu: Fold dbx500 header into db8500
From: Mark Brown @ 2026-06-22 9:18 UTC (permalink / raw)
To: Linus Walleij
Cc: Russell King, Ulf Hansson, Michael Turquette, Stephen Boyd,
Brian Masney, Rafael J. Wysocki, Daniel Lezcano, Christian Loehle,
Lee Jones, Liam Girdwood, Zhang Rui, Lukasz Luba,
Wim Van Sebroeck, Guenter Roeck, Jaroslav Kysela, Takashi Iwai,
linux-arm-kernel, linux-clk, linux-pm, linux-watchdog,
linux-sound, kernel test robot
In-Reply-To: <20260619-mfd-prcmu-merge-headers-v1-1-8ea0ee23b4d6@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 204 bytes --]
On Fri, Jun 19, 2026 at 10:27:10PM +0200, Linus Walleij wrote:
> Move the DBx500 PRCMU definitions into the DB8500 PRCMU
> header and delete the wrapper header.
Acked-by: Mark Brown <broonie@kernel.org>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH RFC 3/3] arm64: Add HOTPLUG_PARALLEL support for secondary CPUs
From: Jinjie Ruan @ 2026-06-22 9:16 UTC (permalink / raw)
To: Will Deacon
Cc: Michael Kelley, catalin.marinas@arm.com,
tsbogend@alpha.franken.de, pjw@kernel.org, palmer@dabbelt.com,
aou@eecs.berkeley.edu, alex@ghiti.fr, tglx@kernel.org,
mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com,
hpa@zytor.com, peterz@infradead.org, kees@kernel.org,
nathan@kernel.org, linusw@kernel.org, ojeda@kernel.org,
david.kaplan@amd.com, lukas.bulwahn@redhat.com,
ryan.roberts@arm.com, maz@kernel.org, timothy.hayes@arm.com,
lpieralisi@kernel.org, thuth@redhat.com, oupton@kernel.org,
yeoreum.yun@arm.com, miko.lenczewski@arm.com, broonie@kernel.org,
kevin.brodsky@arm.com, james.clark@linaro.org, tabba@google.com,
mrigendra.chaubey@gmail.com, arnd@arndb.de,
anshuman.khandual@arm.com, x86@kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, linux-mips@vger.kernel.org,
linux-riscv@lists.infradead.org
In-Reply-To: <ajPitENEHWa8lDfC@willie-the-truck>
On 6/18/2026 8:21 PM, Will Deacon wrote:
> Hi Jinjie,
>
> On Mon, Jun 15, 2026 at 04:51:48PM +0800, Jinjie Ruan wrote:
>> On 6/12/2026 11:45 PM, Michael Kelley wrote:
>>> From: Jinjie Ruan <ruanjinjie@huawei.com> Sent: Thursday, June 11, 2026 6:38 AM
>>>>
>>>> Support for parallel secondary CPU bringup is already utilized by x86,
>>>> MIPS, and RISC-V. This patch brings this capability to the arm64
>>>> architecture.
>>>>
>>>> Rework the global `secondary_data` accessed during early boot into
>>>> a per-CPU array. This array maps logical CPU IDs to MPIDR_EL1 values,
>>>> enabling the early boot code in head.S to resolve each secondary CPU's
>>>> logical ID concurrently.
>>>>
>>>> To fully enable HOTPLUG_PARALLEL, this patch implements:
>>>> 1) An arm64-specific arch_cpuhp_kick_ap_alive() handler.
>>>> 2) Callbacks to cpuhp_ap_sync_alive() inside secondary_start_kernel().
>>>>
>>>> Successfully tested on QEMU ARM64 virt machine (KVM on, 128 vCPUs).
>>>>
>>>> | test kernel | secondary CPUs boot time |
>>>> | --------------------- | -------------------- |
>>>> | Without this patch | 155.672 |
>>>> | cpuhp.parallel=0 | 62.897 |
>>>> | cpuhp.parallel=1 | 166.703 |
>>>
>>> The last two rows seem mixed up. I would expect parallel=0 to
>>> result in a longer boot time.
>>
>> Hi, Michael,
>>
>> The results are correct and not mixed up.
>>
>> Compared to the original non‑HOTPLUG_PARALLEL approach, the advantage of
>> cpuhp.parallel=0 lies in its use of cpu_relax(`yield` on arm64) instead
>> of the wait_for_completion_timeout() mechanism (which may cause sleep
>> and context switching). This significantly reduces the overhead of VM
>> exits and context switches in a KVM guest, thereby cutting the secondary
>> CPU boot time by more than half.
>
> I don't think that's a particularly compelling reason to enable this for
> arm64, in all honesty. The yield instruction typically doesn't do
> anything on actual arm64 silicon, so this probably means that you're
> introducing busy-loops which tend to be bad for power and scalability.
>
> I implemented this a while ago [1] but didn't manage to see much in terms
> of performance improvement and so I didn't bother to send the patches out
> after talking about it at KVM forum [2]. However, as mentioned at the end
> of that talk, it _is_ still useful for confidential VMs using PSCI so
> let me dust off my old series and send it out to see what you think.
Hi Will,
Thanks for the insights! Your point about using PSCI v0.2's Context ID
to avoid the NR_CPUS array for input parameters (like
secondary_data.task) is incredibly elegant.
However, if I understand your series correctly, it seems your approach
primarily targets preventing the concurrent use of secondary_data.task,
but it doesn't seem to account for the potential data trampling on
secondary_data.status when multiple secondary CPUs are brought up
simultaneously.
update_cpu_boot_status()
-> WRITE_ONCE(secondary_data.status.flags[val], 1)
arch_cpuhp_cleanup_kick_cpu()
-> status = READ_ONCE(secondary_data.status)
Best regards,
Jinjie
>
> It relies on PSCI v0.2, which means we don't need the NR_CPUS size array
> for secondary_data and I also have some support for error handling (it
> doesn't look like you handle __early_cpu_boot_status properly).
>
> It looks like I could include your first patch, though!
>
> Will
>
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git/log/?h=cpu-hotplug
> [2] https://www.youtube.com/watch?v=Q6kOshnnQuE
>
^ permalink raw reply
* Re: [PATCH] KVM: arm64: account pKVM reclaim against the VM mm
From: Marc Zyngier @ 2026-06-22 9:16 UTC (permalink / raw)
To: Fuad Tabba
Cc: Bradley Morgan, Oliver Upton, Joey Gouly, Steffen Eiden,
Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
linux-arm-kernel, kvmarm, linux-kernel
In-Reply-To: <CA+EHjTztL4O6NH-sNpPywchgER6SswetOCgmaaSGjtKaRtL8XA@mail.gmail.com>
On Mon, 22 Jun 2026 09:32:45 +0100,
Fuad Tabba <fuad.tabba@linux.dev> wrote:
>
> On Sun, 21 Jun 2026 at 22:32, Bradley Morgan <include@grrlz.net> wrote:
> >
> > Protected guest faults charge long term pins to the VM's mm. Teardown
> > can run later from file release, where current->mm may be unrelated.
> >
> > Drop the charge from kvm->mm instead.
> >
> > Fixes: 4e6e03f9eadd ("KVM: arm64: Hook up reclaim hypercall to pkvm_pgtable_stage2_destroy()")
> > Signed-off-by: Bradley Morgan <include@grrlz.net>
>
> Reproduced by creating a protected VM, running the vCPU to fault in a
> page, then forking and having the child close the last fd reference.
> Without the fix, the parent's VmLck leaks (the reclaim decrements the
> child's mm, which is freed on exit). With the fix the parent's VmLck
> returns to zero.
>
> One minor observation: account_locked_vm() also passes `current` as
> the task pointer to __account_locked_vm(), but on the decrement path
> that is only used in the pr_debug log line, so it is technically wrong
> but functionally harmless.
I don't think this is wrong. Awkward, maybe. It is just that the
rlimit check and the accounting may be different contexts, and the
pr_debug() call covers both inc and dec.
>
> Reviewed-by: Fuad Tabba <fuad.tabba@linux.dev>
> Tested-by: Fuad Tabba < fuad.tabba@linux.dev>
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v4 1/3] dt-bindings: net: add Realtek RTL8125 PCIe Ethernet
From: Krzysztof Kozlowski @ 2026-06-22 9:08 UTC (permalink / raw)
To: Heiner Kallweit
Cc: ricardo, nic_swsd, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Heiko Stuebner, Sebastian Reichel, netdev,
devicetree, linux-kernel, linux-arm-kernel, linux-rockchip
In-Reply-To: <876a38f8-75ea-4b32-bb65-216cb3adb436@gmail.com>
On Wed, Jun 17, 2026 at 06:43:42PM +0200, Heiner Kallweit wrote:
> On 17.06.2026 14:58, Ricardo Pardini via B4 Relay wrote:
> > From: Ricardo Pardini <ricardo@pardini.net>
> >
> > Add a binding for fixed/soldered Realtek RTL8125 PCIe Ethernet
> > controller.
> >
> > The "pciVVVV,DDDD" compatibles are the Open Firmware PCI Bus Binding
> > spelling, auto-derived from PCI-SIG vendor/device IDs, but they still
> > need a binding when used in a board DT - analogous to "usbVVVV,PPPP"
Ricardo,
No, they do not need. They are already documented, they already have a
binding, see: dtschema/schemas/pci/pci-device.yaml
> > compatibles documented in their own bindings (e.g. microchip,lan95xx)
> > so board DTs attaching properties (fixed MAC, nvmem cell, ...) to
> > these PCI function nodes can be validated.
> >
> > Suggested-by: Sebastian Reichel <sebastian.reichel@collabora.com>
> > Signed-off-by: Ricardo Pardini <ricardo@pardini.net>
> > ---
> > .../devicetree/bindings/net/realtek,rtl8125.yaml | 43 ++++++++++++++++++++++
> > MAINTAINERS | 1 +
> > 2 files changed, 44 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/net/realtek,rtl8125.yaml b/Documentation/devicetree/bindings/net/realtek,rtl8125.yaml
> > new file mode 100644
> > index 0000000000000..eee13fbc1e6a6
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/net/realtek,rtl8125.yaml
> > @@ -0,0 +1,43 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/net/realtek,rtl8125.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Realtek RTL8125 2.5 Gigabit PCIe Ethernet Controller
> > +
> > +maintainers:
> > + - Heiner Kallweit <hkallweit1@gmail.com>
> > +
> > +description:
> > + The Realtek RTL8125 is a 2.5GBASE-T Ethernet controller with a PCIe host
> > + interface.
> > +
> > +allOf:
> > + - $ref: ethernet-controller.yaml#
> > +
> > +properties:
> > + compatible:
> > + const: pci10ec,8125
>
> IIRC we came to the conclusion that the compatible string isn't used in the
> relevant code path. Then why add it here? Is there an alignment on this?
Heiner, it is used - in the DTS.
> If it should be added here, then an explaining comment would be helpful.
Commit msg should explain that. The compatible is used, so it
must be documented and in fact already is, so you need to specify them
ONLY if device nodes have some other properties, like being an ethernet
controller.
I assume that this is the case here, although that should be mentioned
in the commit msg.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v4 2/2] media: i2c: ov5640: Add reset controller support with GPIO fallback
From: Philipp Zabel @ 2026-06-22 9:05 UTC (permalink / raw)
To: Frank Li, robby.cai
Cc: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, festevam,
sebastian.krzyszkowiak, slongerbeam, sakari.ailus, mchehab,
kieran.bingham, kernel, devicetree, imx, linux-arm-kernel,
linux-kernel
In-Reply-To: <ajVPzoWVBi1vsqRQ@SMW015318>
On Fr, 2026-06-19 at 09:18 -0500, Frank Li wrote:
> On Fri, Jun 19, 2026 at 06:05:32PM +0800, robby.cai@oss.nxp.com wrote:
> > [You don't often get email from robby.cai@oss.nxp.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
> >
> > From: Robby Cai <robby.cai@nxp.com>
> >
> > Add support for the reset controller framework by acquiring the reset
> > line using devm_reset_control_get_optional_shared_deasserted(). This
> > allows the driver to handle reset lines provided by a reset controller,
> > including shared ones, while avoiding unbalanced deassert counts.
> >
> > Retain support for legacy reset-gpios as a fallback when no reset
> > controller is defined. In that case, request the GPIO and keep it in the
> > deasserted state as the initial configuration.
> >
> > This enables the driver to support both reset-controller-backed reset
> > lines and older GPIO-based descriptions while preserving the existing
> > power-up sequencing behavior.
> >
> > Signed-off-by: Robby Cai <robby.cai@nxp.com>
> > ---
> > drivers/media/i2c/ov5640.c | 80 +++++++++++++++++++++++++++++++++-----
> > 1 file changed, 70 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> > index 85ecc23b3587..5e6db8aacb11 100644
> > --- a/drivers/media/i2c/ov5640.c
> > +++ b/drivers/media/i2c/ov5640.c
> > @@ -17,6 +17,7 @@
> > #include <linux/module.h>
> > #include <linux/pm_runtime.h>
> > #include <linux/regulator/consumer.h>
> > +#include <linux/reset.h>
> > #include <linux/slab.h>
> > #include <linux/types.h>
> > #include <media/v4l2-async.h>
> > @@ -442,6 +443,7 @@ struct ov5640_dev {
> > u32 xclk_freq;
> >
> > struct regulator_bulk_data supplies[OV5640_NUM_SUPPLIES];
> > + struct reset_control *reset;
> > struct gpio_desc *reset_gpio;
> > struct gpio_desc *pwdn_gpio;
> > bool upside_down;
> > @@ -2431,6 +2433,48 @@ static int ov5640_restore_mode(struct ov5640_dev *sensor)
> > return ov5640_set_framefmt(sensor, &sensor->fmt);
> > }
> >
> > +static int ov5640_get_reset(struct device *dev, struct ov5640_dev *sensor)
> > +{
> > + /* use deasserted version to avoid unbalanced deassert counts */
> > + sensor->reset =
> > + devm_reset_control_get_optional_shared_deasserted(dev, NULL);
> > + if (IS_ERR(sensor->reset))
> > + return dev_err_probe(dev, PTR_ERR(sensor->reset),
> > + "Failed to get reset\n");
> > + else if (sensor->reset)
> > + return 0;
> > +
> > + /*
> > + * fallback to legacy reset-gpios
> > + * GPIOD_OUT_HIGH ensures deasserted state for ACTIVE_LOW reset
> > + */
> > + sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset",
> > + GPIOD_OUT_HIGH);
> > + if (IS_ERR(sensor->reset_gpio))
> > + return dev_err_probe(dev, PTR_ERR(sensor->reset_gpio),
> > + "Failed to get reset gpio");
>
> I think needn't fallback here, NO ABI change, just change to use reset-gpio
> driver.
Please keep the gpiod fallback, the reset-gpio driver may not be
available on all platforms using ov5640.
> > +
> > + return 0;
> > +}
> > +
> > +static int ov5640_reset_assert(struct ov5640_dev *sensor)
> > +{
> > + if (sensor->reset)
> > + return reset_control_assert(sensor->reset);
>
> needn't check sensor->reset, reset_control_assert() is no ops if NULL.
>
> > +
> > + gpiod_set_value_cansleep(sensor->reset_gpio, 1);
>
> Needn't fallback, directly replace.
See above.
regards
Philipp
^ permalink raw reply
* Re: [PATCH kvmtool v2 7/7] arm64: Improve KVM_ARM_VCPU_PMU_V3_CTRL diagnostics
From: Alexandru Elisei @ 2026-06-22 9:04 UTC (permalink / raw)
To: Oliver Upton
Cc: will, julien.thierry.kdev, maz, jean-philippe.brucker,
andre.przywara, suzuki.poulose, kvm, linux-arm-kernel, kvmarm
In-Reply-To: <ajRBpMnlcNkhWzQL@kernel.org>
Hi Oliver,
On Thu, Jun 18, 2026 at 12:06:12PM -0700, Oliver Upton wrote:
> On Thu, Jun 18, 2026 at 04:50:01PM +0100, Alexandru Elisei wrote:
> > kvmtool issues several ioctls when configuring the PMU, and each of them
> > can fail for different reasons. Be more specific about the ioctl that
> > failed when that happens.
> >
> > Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
> > ---
> > arm64/pmu.c | 31 ++++++++++++++++++++++++-------
> > 1 file changed, 24 insertions(+), 7 deletions(-)
> >
> > diff --git a/arm64/pmu.c b/arm64/pmu.c
> > index 92cacd62479e..78c15f153fad 100644
> > --- a/arm64/pmu.c
> > +++ b/arm64/pmu.c
> > @@ -12,6 +12,24 @@
> >
> > #include "asm/pmu.h"
> >
> > +static const char *pmu_attr_names[] = {
> > + [KVM_ARM_VCPU_PMU_V3_IRQ] = "KVM_ARM_VCPU_PMU_V3_IRQ",
> > + [KVM_ARM_VCPU_PMU_V3_INIT] = "KVM_ARM_VCPU_PMU_V3_INIT",
> > + [KVM_ARM_VCPU_PMU_V3_FILTER] = "KVM_ARM_VCPU_PMU_V3_FILTER",
> > + [KVM_ARM_VCPU_PMU_V3_SET_PMU] = "KVM_ARM_VCPU_PMU_V3_SET_PMU",
> > + [KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTERS] = "KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTER",
> > +};
> > +
> > +static const char *pmu_get_attr_name(u64 attr)
> > +{
> > + switch (attr) {
> > + case KVM_ARM_VCPU_PMU_V3_IRQ ... KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTERS:
> > + return pmu_attr_names[attr];
> > + default:
> > + return "UNKNOWN";
> > + }
> > +}
> > +
> > static bool pmu_has_attr(struct kvm_cpu *vcpu, u64 attr)
> > {
> > struct kvm_device_attr pmu_attr = {
> > @@ -32,13 +50,12 @@ static void set_pmu_attr(struct kvm_cpu *vcpu, void *addr, u64 attr)
> > };
> > int ret;
> >
> > - if (pmu_has_attr(vcpu, attr)) {
> > - ret = ioctl(vcpu->vcpu_fd, KVM_SET_DEVICE_ATTR, &pmu_attr);
> > - if (ret)
> > - die_perror("PMU KVM_SET_DEVICE_ATTR");
> > - } else {
> > - die_perror("PMU KVM_HAS_DEVICE_ATTR");
> > - }
> > + if (!pmu_has_attr(vcpu, attr))
> > + die_perror("KVM_HAS_DEVICE_ATTR(%s)", pmu_get_attr_name(attr));
> > +
> > + ret = ioctl(vcpu->vcpu_fd, KVM_SET_DEVICE_ATTR, &pmu_attr);
> > + if (ret)
> > + die_perror("KVM_SET_DEVICE_ATTR(%s)", pmu_get_attr_name(attr));
> > }
>
> The whole if (ret) die_perror(...) thing is a bit repetetive IMO. A
> treewide cleanup replacing this with macros would be nice, then you could
> stringize the ioctl under the hood.
Thank you for having a look, that's a great idea, it will avoid out of bounds
array access if KVM gets a new PMU ioctl and the name array is not updated at
the same time - that's quite possible since ioctl numbers are pulled by running
update_headers.sh, and the dependency is not obvious.
I think the compilation errors are a bit higher priority than this, and a
treewide change would more involved, possibly involving a change in behaviour
(the gic seems to propagate the error instead of calling die_perror(), for
example), would you mind if for this series I'll only introduce the macro for
the pmu and convert the rest of the code in a separate series?
Thanks,
Alex
>
> diff --git a/arm64/pmu.c b/arm64/pmu.c
> index 5f31d6b..0d9f3df 100644
> --- a/arm64/pmu.c
> +++ b/arm64/pmu.c
> @@ -23,23 +23,19 @@ static bool pmu_has_attr(struct kvm_cpu *vcpu, u64 attr)
> return ret == 0;
> }
>
> -static void set_pmu_attr(struct kvm_cpu *vcpu, void *addr, u64 attr)
> -{
> - struct kvm_device_attr pmu_attr = {
> - .group = KVM_ARM_VCPU_PMU_V3_CTRL,
> - .addr = (u64)addr,
> - .attr = attr,
> - };
> - int ret;
> -
> - if (pmu_has_attr(vcpu, attr)) {
> - ret = ioctl(vcpu->vcpu_fd, KVM_SET_DEVICE_ATTR, &pmu_attr);
> - if (ret)
> - die_perror("PMU KVM_SET_DEVICE_ATTR");
> - } else {
> - die_perror("PMU KVM_HAS_DEVICE_ATTR");
> - }
> -}
> +#define kvm_set_device_attr(fd, _group, _attr, _addr) \
> +do { \
> + struct kvm_device_attr __attr = { \
> + .group = (_group), \
> + .attr = (_attr), \
> + .addr = (u64)(_addr), \
> + }; \
> + int r; \
> + \
> + r = ioctl((fd), KVM_SET_DEVICE_ATTR, &__attr); \
> + if (r) \
> + die_perror("KVM_SET_DEVICE_ATTR(group:"#_group", attr:"#_attr")"); \
> +} while (0)
>
> #define SYS_EVENT_SOURCE "/sys/bus/event_source/devices/"
> /*
> @@ -218,14 +214,18 @@ void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
>
> for (i = 0; i < kvm->nrcpus; i++) {
> vcpu = kvm->cpus[i];
> - set_pmu_attr(vcpu, &irq, KVM_ARM_VCPU_PMU_V3_IRQ);
> + kvm_set_device_attr(vcpu->vcpu_fd, KVM_ARM_VCPU_PMU_V3_CTRL,
> + KVM_ARM_VCPU_PMU_V3_IRQ, &irq);
> /*
> * PMU IDs 0-5 are reserved; a positive value means a PMU was
> * found.
> */
> if (pmu_id > 0)
> - set_pmu_attr(vcpu, &pmu_id, KVM_ARM_VCPU_PMU_V3_SET_PMU);
> - set_pmu_attr(vcpu, NULL, KVM_ARM_VCPU_PMU_V3_INIT);
> + kvm_set_device_attr(vcpu->vcpu_fd, KVM_ARM_VCPU_PMU_V3_CTRL,
> + KVM_ARM_VCPU_PMU_V3_SET_PMU, &pmu_id);
> +
> + kvm_set_device_attr(vcpu->vcpu_fd, KVM_ARM_VCPU_PMU_V3_CTRL,
> + KVM_ARM_VCPU_PMU_V3_INIT, NULL);
> }
>
> _FDT(fdt_begin_node(fdt, "pmu"));
^ permalink raw reply
* Re: [PATCH v5 4/4] arm64: dts: cix: sky1: add audss cru
From: Krzysztof Kozlowski @ 2026-06-22 9:02 UTC (permalink / raw)
To: joakim.zhang
Cc: mturquette, sboyd, bmasney, robh, krzk+dt, conor+dt, p.zabel,
gary.yang, cix-kernel-upstream, linux-clk, devicetree,
linux-kernel, linux-arm-kernel
In-Reply-To: <20260622022520.3127103-5-joakim.zhang@cixtech.com>
On Mon, Jun 22, 2026 at 10:25:20AM +0800, joakim.zhang@cixtech.com wrote:
>
> + audss_cru: clock-controller@7110000 {
> + compatible = "cix,sky1-audss-cru";
> + reg = <0x0 0x07110000 0x0 0x10000>;
> + #clock-cells = <1>;
> + #reset-cells = <1>;
> + clocks = <&scmi_clk CLK_TREE_AUDIO_CLK0>,
> + <&scmi_clk CLK_TREE_AUDIO_CLK2>,
> + <&scmi_clk CLK_TREE_AUDIO_CLK4>,
> + <&scmi_clk CLK_TREE_AUDIO_CLK5>;
> + clock-names = "x8k", "x11k", "sys", "48m";
> + power-domains = <&smc_devpd SKY1_PD_AUDIO>;
> + resets = <&s5_syscon SKY1_AUDIO_HIFI5_NOC_RESET_N>;
> + status = "okay";
Drop.
> + };
> +
Best regards,
Krzysztof
^ permalink raw reply
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