* Re: [PATCH 05/13] drm/meson: encoder_hdmi: Use CEC phys addr from display_info
From: Hans Verkuil @ 2026-05-19 6:36 UTC (permalink / raw)
To: Jonas Karlman, Neil Armstrong, Kevin Hilman, Heiko Stuebner,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jerome Brunet, Martin Blumenstingl
Cc: dri-devel, linux-amlogic, linux-arm-kernel, linux-kernel,
linux-rockchip
In-Reply-To: <20260518194744.2483580-6-jonas@kwiboo.se>
On 18/05/2026 21:47, Jonas Karlman wrote:
> The dw-hdmi bridge detect() func now updates EDID for the connector.
> Something that ensures that display_info.source_physical_address has an
> updated CEC phys addr when the hpd_notify() func is called.
>
> Change to use display_info source_physical_address directly instead of
> re-reading EDID to set the CEC phys addr at HPD interrupt.
>
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Acked-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Regards,
Hans
> ---
> drivers/gpu/drm/meson/meson_encoder_hdmi.c | 26 ++++------------------
> 1 file changed, 4 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
> index 55c0601df3c6..1b9a1d9ed3d3 100644
> --- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c
> +++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
> @@ -330,28 +330,10 @@ static void meson_encoder_hdmi_hpd_notify(struct drm_bridge *bridge,
> if (!encoder_hdmi->cec_notifier)
> return;
>
> - if (status == connector_status_connected) {
> - const struct drm_edid *drm_edid;
> - const struct edid *edid;
> -
> - drm_edid = drm_bridge_edid_read(encoder_hdmi->bridge.next_bridge,
> - encoder_hdmi->connector);
> - if (!drm_edid)
> - return;
> -
> - /*
> - * FIXME: The CEC physical address should be set using
> - * cec_notifier_set_phys_addr(encoder_hdmi->cec_notifier,
> - * connector->display_info.source_physical_address) from a path
> - * that has read the EDID and called
> - * drm_edid_connector_update().
> - */
> - edid = drm_edid_raw(drm_edid);
> -
> - cec_notifier_set_phys_addr_from_edid(encoder_hdmi->cec_notifier, edid);
> -
> - drm_edid_free(drm_edid);
> - } else
> + if (status == connector_status_connected)
> + cec_notifier_set_phys_addr(encoder_hdmi->cec_notifier,
> + connector->display_info.source_physical_address);
> + else
> cec_notifier_phys_addr_invalidate(encoder_hdmi->cec_notifier);
> }
>
^ permalink raw reply
* Re: [PATCH v7 17/23] drm: bridge: dw_hdmi: Declare bridge CEC notifier support
From: Hans Verkuil @ 2026-05-19 6:35 UTC (permalink / raw)
To: Jonas Karlman, Andrzej Hajda, Neil Armstrong, Robert Foss,
Heiko Stuebner, Laurent Pinchart, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-18-jonas@kwiboo.se>
On 18/05/2026 20:01, Jonas Karlman wrote:
> EDID and CEC phys addr is now being updated in bridge detect() func,
> making it possible to have CEC notifier support using the bridge
> connector.
>
> Add the CEC notifier bridge op to instruct the bridge connector to make
> use of the generic CEC notifier helpers.
>
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Acked-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Regards,
Hans
> ---
> v7: Only declare CEC notifier support when CEC device register succeeds
> v6: New patch
> ---
> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index 0c4388e7aa5e..5dacb8a99715 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -3515,6 +3515,10 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
> pdevinfo.dma_mask = 0;
>
> hdmi->cec = platform_device_register_full(&pdevinfo);
> + if (!IS_ERR(hdmi->cec)) {
> + hdmi->bridge.ops |= DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER;
> + hdmi->bridge.hdmi_cec_dev = hdmi->dev;
> + }
> }
>
> drm_bridge_add(&hdmi->bridge);
^ permalink raw reply
* Re: [PATCH v7 15/23] drm: bridge: dw_hdmi: Use generic CEC notifier helpers
From: Hans Verkuil @ 2026-05-19 6:32 UTC (permalink / raw)
To: Jonas Karlman, Andrzej Hajda, Neil Armstrong, Robert Foss,
Heiko Stuebner, Laurent Pinchart, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-16-jonas@kwiboo.se>
On 18/05/2026 20:01, Jonas Karlman wrote:
> The commit 8b1a8f8b2002 ("drm/display: add CEC helpers code") added
> generic CEC helpers to be used by HDMI drivers.
>
> Replace the open-coded CEC notifier handling with use of the generic CEC
> notifier helpers. Ensure DRM_DISPLAY_HDMI_CEC_NOTIFIER_HELPER is also
> selected when DRM_DW_HDMI_CEC is enabled so that the CEC helpers is
> available.
>
> The drmm release action for the generic CEC notifier should run just
> before dw_hdmi_connector_destroy(), closely matching the lifetime of
> the replaced CEC notifier and the connector.
>
> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
> Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Acked-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Regards,
Hans
> ---
> v7: No change
> v6: Update commit message,
> Collect t-b tag
> v5: Collect r-b tag
> v4: New patch
> ---
> drivers/gpu/drm/bridge/synopsys/Kconfig | 1 +
> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 26 +++++------------------
> 2 files changed, 6 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
> index a46df7583bcf..e6723af03b43 100644
> --- a/drivers/gpu/drm/bridge/synopsys/Kconfig
> +++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
> @@ -49,6 +49,7 @@ config DRM_DW_HDMI_CEC
> depends on DRM_DW_HDMI
> select CEC_CORE
> select CEC_NOTIFIER
> + select DRM_DISPLAY_HDMI_CEC_NOTIFIER_HELPER
> help
> Support the CE interface which is part of the Synopsys
> Designware HDMI block.
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index 0e84dff72470..37406555af7b 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -23,12 +23,11 @@
> #include <linux/dma-mapping.h>
> #include <linux/spinlock.h>
>
> -#include <media/cec-notifier.h>
> -
> #include <linux/media-bus-format.h>
> #include <linux/videodev2.h>
>
> #include <drm/bridge/dw_hdmi.h>
> +#include <drm/display/drm_hdmi_cec_helper.h>
> #include <drm/display/drm_hdmi_helper.h>
> #include <drm/display/drm_scdc_helper.h>
> #include <drm/drm_atomic.h>
> @@ -183,8 +182,6 @@ struct dw_hdmi {
> void (*enable_audio)(struct dw_hdmi *hdmi);
> void (*disable_audio)(struct dw_hdmi *hdmi);
>
> - struct cec_notifier *cec_notifier;
> -
> hdmi_codec_plugged_cb plugged_cb;
> struct device *codec_dev;
> enum drm_connector_status last_connector_result;
> @@ -2453,7 +2450,7 @@ dw_hdmi_connector_status_update(struct dw_hdmi *hdmi,
>
> if (status == connector_status_disconnected) {
> drm_edid_connector_update(connector, NULL);
> - cec_notifier_phys_addr_invalidate(hdmi->cec_notifier);
> + drm_connector_cec_phys_addr_invalidate(connector);
> return;
> }
>
> @@ -2462,8 +2459,7 @@ dw_hdmi_connector_status_update(struct dw_hdmi *hdmi,
> drm_edid_free(drm_edid);
>
> if (status == connector_status_connected)
> - cec_notifier_set_phys_addr(hdmi->cec_notifier,
> - connector->display_info.source_physical_address);
> + drm_connector_cec_phys_addr_set(connector);
> }
>
> static enum drm_connector_status
> @@ -2525,9 +2521,6 @@ static void dw_hdmi_connector_destroy(struct drm_connector *connector)
> {
> struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
>
> - cec_notifier_conn_unregister(hdmi->cec_notifier);
> - hdmi->cec_notifier = NULL;
> -
> drm_connector_cleanup(connector);
> drm_bridge_put(&hdmi->bridge);
> }
> @@ -2550,8 +2543,6 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs =
> static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
> {
> struct drm_connector *connector = &hdmi->connector;
> - struct cec_connector_info conn_info;
> - struct cec_notifier *notifier;
> int ret;
>
> if (hdmi->version >= 0x200a)
> @@ -2587,15 +2578,8 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
>
> drm_connector_attach_encoder(connector, hdmi->bridge.encoder);
>
> - cec_fill_conn_info_from_drm(&conn_info, connector);
> -
> - notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info);
> - if (!notifier)
> - return -ENOMEM;
> -
> - hdmi->cec_notifier = notifier;
> -
> - return 0;
> + return drmm_connector_hdmi_cec_notifier_register(connector, NULL,
> + hdmi->dev);
> }
>
> /* -----------------------------------------------------------------------------
^ permalink raw reply
* Re: [PATCH v14 14/44] arm64: RMI: Basic infrastructure for creating a realm.
From: Aneesh Kumar K.V @ 2026-05-19 6:31 UTC (permalink / raw)
To: Steven Price, kvm, kvmarm
Cc: Steven Price, Catalin Marinas, Marc Zyngier, Will Deacon,
James Morse, Oliver Upton, Suzuki K Poulose, Zenghui Yu,
linux-arm-kernel, linux-kernel, Joey Gouly, Alexandru Elisei,
Christoffer Dall, Fuad Tabba, linux-coco, Ganapatrao Kulkarni,
Gavin Shan, Shanker Donthineni, Alper Gun, Emi Kisanuki,
Vishal Annapurve, WeiLin.Chang, Lorenzo.Pieralisi2
In-Reply-To: <20260513131757.116630-15-steven.price@arm.com>
Steven Price <steven.price@arm.com> writes:
> @@ -1114,7 +1119,10 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
> write_unlock(&kvm->mmu_lock);
>
> if (pgt) {
> - kvm_stage2_destroy(pgt);
> + if (!kvm_is_realm(kvm))
> + kvm_stage2_destroy(pgt);
> + else
> + kvm_pgtable_stage2_destroy_pgd(pgt);
> kfree(pgt);
> }
> }
Maybe add a comment here explaining the difference.
We now have:
kvm_arch_destroy_vm()
-> kvm_uninit_stage2_mmu()
-> kvm_realm_uninit_stage2()
-> unmap_range(0, max_ipa) // for Realm VMs
-> kvm_free_stage2_pgd()
-> unmap and free PGD // for non-Realm VMs
-> kvm_destroy_realm() // for Realm VMs
-> kvm_free_stage2_pgd()
-> free PGD // for Realm VMs
I wonder whether this can be simplified using different functions names?
(can we call kvm_pgtable_stage2_destroy_pgd() from kvm_destroy_realm()? )
-aneesh
^ permalink raw reply
* Re: [PATCH v5 8/8] unwind: arm64: Use sframe to unwind interrupt frames
From: Dylan Hatch @ 2026-05-19 6:29 UTC (permalink / raw)
To: Mark Rutland
Cc: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
Jiri Kosina, Jens Remus, Prasanna Kumar T S M, Puranjay Mohan,
Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <afTYzAF_x41pyilu@J2N7QTR9R3>
Hi Mark,
I'm sending a v6 shortly that should address all/most of your
feedback, but I wanted to circle back on a question you had:
On Fri, May 1, 2026 at 9:46 AM Mark Rutland <mark.rutland@arm.com> wrote:
> > + /*
> > + * Consume RA and FP from the stack. The frame record puts FP at a lower
> > + * address than RA, so we always read FP first.
> > + */
> > + if (frame.fp.rule & UNWIND_RULE_DEREF &&
> > + !get_word(&state->common, &fp))
> > + return -EINVAL;
>
> Why is this get_word() rather than get_consume_word()?
I use get_word() here because get_consume_word(), in calling
unwind_consume_stack() under the hood, consumes the stack up to the
given address+size such that another unwind step cannot consume it
again. If the subsequent call to get_consume_word() fails, the stack
needs to be in a state such that we can fall back on a frame pointer
unwind. But if we were to use get_consume_word() here, the fallback
call to kunwind_next_frame_record() would not be able to consume the
FP from the stack because it would already have been consumed by the
failed call to unwind_next_frame_sframe().
By only calling get_consume_word() on the RA at the end, we defer
making any changes to the underlying unwind state stack until we are
sure the SFrame unwind step will succeed.
>
> > +
> > + if (frame.ra.rule & UNWIND_RULE_DEREF &&
> > + get_consume_word(&state->common, &ra))
> > + return -EINVAL;
> > +
> > + state->common.pc = ra;
> > + state->common.sp = cfa;
Please let me know if this reasoning seems sound.
Thanks,
Dylan
^ permalink raw reply
* Re: [PATCH v7 13/23] drm: bridge: dw_hdmi: Use dw_hdmi_connector_status_update()
From: Hans Verkuil @ 2026-05-19 6:29 UTC (permalink / raw)
To: Jonas Karlman, Andrzej Hajda, Neil Armstrong, Robert Foss,
Heiko Stuebner, Laurent Pinchart, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-14-jonas@kwiboo.se>
On 18/05/2026 20:01, Jonas Karlman wrote:
> Update connector EDID and CEC phys addr from detect and force funcs to
> ensure that userspace always have access to latest read EDID after a
> sink use a HPD low voltage pulse to indicate that EDID has changed.
>
> With EDID being updated in detect and force funcs, there should no
> longer be a need to re-read EDID in get_modes funcs, so drop it.
>
> This change make the dw-hdmi connector work more closely like the bridge
> connector does with a hdmi bridge.
>
> Reviewed-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Acked-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Regards,
Hans
> ---
> v7: No change
> v6: Pass struct dw_hdmi as a parameter,
> Collect t-b tag
> v5: No change
> v4: Move last_connector_result assign in force ops to this patch,
> Collect r-b tag
> v3: Reworked 'Update EDID during hotplug processing' patch
> ---
> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 28 ++++++++++++-----------
> 1 file changed, 15 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index a056e147731b..a4ecf830103d 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -2473,36 +2473,36 @@ dw_hdmi_connector_status_update(struct dw_hdmi *hdmi,
> {
> const struct drm_edid *drm_edid;
>
> + if (status == connector_status_disconnected) {
> + drm_edid_connector_update(connector, NULL);
> + cec_notifier_phys_addr_invalidate(hdmi->cec_notifier);
> + return;
> + }
> +
> drm_edid = dw_hdmi_edid_read(hdmi, connector);
> drm_edid_connector_update(connector, drm_edid);
> drm_edid_free(drm_edid);
>
> - cec_notifier_set_phys_addr(hdmi->cec_notifier,
> - connector->display_info.source_physical_address);
> + if (status == connector_status_connected)
> + cec_notifier_set_phys_addr(hdmi->cec_notifier,
> + connector->display_info.source_physical_address);
> }
>
> static enum drm_connector_status
> dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
> {
> - struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> - connector);
> + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
> enum drm_connector_status status;
>
> status = dw_hdmi_detect(hdmi);
>
> - if (status == connector_status_disconnected)
> - cec_notifier_phys_addr_invalidate(hdmi->cec_notifier);
> + dw_hdmi_connector_status_update(hdmi, connector, status);
>
> return status;
> }
>
> static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
> {
> - struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> - connector);
> -
> - dw_hdmi_connector_status_update(hdmi, connector, connector->status);
> -
> return drm_edid_connector_add_modes(connector);
> }
>
> @@ -2532,13 +2532,15 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
>
> static void dw_hdmi_connector_force(struct drm_connector *connector)
> {
> - struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> - connector);
> + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
>
> mutex_lock(&hdmi->mutex);
> hdmi->force = connector->force;
> + hdmi->last_connector_result = connector->status;
> dw_hdmi_update_phy_mask(hdmi);
> mutex_unlock(&hdmi->mutex);
> +
> + dw_hdmi_connector_status_update(hdmi, connector, connector->status);
> }
>
> static void dw_hdmi_connector_destroy(struct drm_connector *connector)
^ permalink raw reply
* Re: [PATCH v7 11/23] drm: bridge: dw_hdmi: Remove cec_notifier_mutex
From: Hans Verkuil @ 2026-05-19 6:28 UTC (permalink / raw)
To: Jonas Karlman, Andrzej Hajda, Neil Armstrong, Robert Foss,
Heiko Stuebner, Laurent Pinchart, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-12-jonas@kwiboo.se>
On 18/05/2026 20:01, Jonas Karlman wrote:
> With CEC phys addr invalidation moved away from the irq handler there is
> no longer a need for cec_notifier_mutex, remove it.
>
> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
> Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Acked-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Nice, I wondered why that mutex was there at all.
Regards,
Hans
> ---
> v7: No change
> v6: Collect t-b tag
> v5: No change, cec_notifier_conn_unregister() call moved
> v4: No change
> v3: No change
> v2: Collect r-b tag
> ---
> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 11 +----------
> 1 file changed, 1 insertion(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index aae1b890167b..0dd4c823c60a 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -189,7 +189,6 @@ struct dw_hdmi {
> void (*enable_audio)(struct dw_hdmi *hdmi);
> void (*disable_audio)(struct dw_hdmi *hdmi);
>
> - struct mutex cec_notifier_mutex;
> struct cec_notifier *cec_notifier;
>
> hdmi_codec_plugged_cb plugged_cb;
> @@ -2476,11 +2475,8 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
>
> status = dw_hdmi_detect(hdmi);
>
> - if (status == connector_status_disconnected) {
> - mutex_lock(&hdmi->cec_notifier_mutex);
> + if (status == connector_status_disconnected)
> cec_notifier_phys_addr_invalidate(hdmi->cec_notifier);
> - mutex_unlock(&hdmi->cec_notifier_mutex);
> - }
>
> return status;
> }
> @@ -2542,10 +2538,8 @@ static void dw_hdmi_connector_destroy(struct drm_connector *connector)
> {
> struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
>
> - mutex_lock(&hdmi->cec_notifier_mutex);
> cec_notifier_conn_unregister(hdmi->cec_notifier);
> hdmi->cec_notifier = NULL;
> - mutex_unlock(&hdmi->cec_notifier_mutex);
>
> drm_connector_cleanup(connector);
> drm_bridge_put(&hdmi->bridge);
> @@ -2612,9 +2606,7 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
> if (!notifier)
> return -ENOMEM;
>
> - mutex_lock(&hdmi->cec_notifier_mutex);
> hdmi->cec_notifier = notifier;
> - mutex_unlock(&hdmi->cec_notifier_mutex);
>
> return 0;
> }
> @@ -3323,7 +3315,6 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
>
> mutex_init(&hdmi->mutex);
> mutex_init(&hdmi->audio_mutex);
> - mutex_init(&hdmi->cec_notifier_mutex);
> spin_lock_init(&hdmi->audio_lock);
>
> ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
^ permalink raw reply
* Re: [PATCH v7 12/23] drm: bridge: dw_hdmi: Extract dw_hdmi_connector_status_update()
From: Hans Verkuil @ 2026-05-19 6:26 UTC (permalink / raw)
To: Jonas Karlman, Andrzej Hajda, Neil Armstrong, Robert Foss,
Heiko Stuebner, Laurent Pinchart, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-13-jonas@kwiboo.se>
On 18/05/2026 20:01, Jonas Karlman wrote:
> Move connector EDID update and CEC phys addr handling to a helper
> function as a preparation before moving EDID refresh from get_modes
> funcs to detect/force funcs.
>
> Reviewed-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Acked-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Regards,
Hans
> ---
> v7: No change
> v6: Pass struct dw_hdmi as a parameter, to allow calls from bridge funcs,
> Collect t-b tag
> v5: No change
> v4: Collect r-b tag
> v3: New patch
> ---
> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 27 ++++++++++++++---------
> 1 file changed, 17 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index 0dd4c823c60a..a056e147731b 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -2466,6 +2466,21 @@ static const struct drm_edid *dw_hdmi_edid_read(struct dw_hdmi *hdmi,
> * DRM Connector Operations
> */
>
> +static void
> +dw_hdmi_connector_status_update(struct dw_hdmi *hdmi,
> + struct drm_connector *connector,
> + enum drm_connector_status status)
> +{
> + const struct drm_edid *drm_edid;
> +
> + drm_edid = dw_hdmi_edid_read(hdmi, connector);
> + drm_edid_connector_update(connector, drm_edid);
> + drm_edid_free(drm_edid);
> +
> + cec_notifier_set_phys_addr(hdmi->cec_notifier,
> + connector->display_info.source_physical_address);
> +}
> +
> static enum drm_connector_status
> dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
> {
> @@ -2485,18 +2500,10 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
> {
> struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> connector);
> - const struct drm_edid *drm_edid;
> - int ret;
>
> - drm_edid = dw_hdmi_edid_read(hdmi, connector);
> + dw_hdmi_connector_status_update(hdmi, connector, connector->status);
>
> - drm_edid_connector_update(connector, drm_edid);
> - cec_notifier_set_phys_addr(hdmi->cec_notifier,
> - connector->display_info.source_physical_address);
> - ret = drm_edid_connector_add_modes(connector);
> - drm_edid_free(drm_edid);
> -
> - return ret;
> + return drm_edid_connector_add_modes(connector);
> }
>
> static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
^ permalink raw reply
* Re: [PATCH v7 10/23] drm: bridge: dw_hdmi: Invalidate CEC phys addr from connector detect
From: Hans Verkuil @ 2026-05-19 6:25 UTC (permalink / raw)
To: Jonas Karlman, Andrzej Hajda, Neil Armstrong, Robert Foss,
Heiko Stuebner, Laurent Pinchart, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-11-jonas@kwiboo.se>
On 18/05/2026 20:01, Jonas Karlman wrote:
> Wait until the connector detect ops is called to invalidate CEC phys
> addr instead of doing it directly from the irq handler.
>
> The CEC notifier is only registered for the dw-hdmi connector so this
> has no impact when the bridge connector is used.
>
> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
> Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Acked-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Regards,
Hans
> ---
> v7: Update commit message
> v6: Collect t-b tag
> v5: No change
> v4: No change
> v3: No change
> v2: Collect r-b tag
> ---
> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 18 +++++++++++-------
> 1 file changed, 11 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index 5fd26ff8f55b..aae1b890167b 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -2472,7 +2472,17 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
> {
> struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> connector);
> - return dw_hdmi_detect(hdmi);
> + enum drm_connector_status status;
> +
> + status = dw_hdmi_detect(hdmi);
> +
> + if (status == connector_status_disconnected) {
> + mutex_lock(&hdmi->cec_notifier_mutex);
> + cec_notifier_phys_addr_invalidate(hdmi->cec_notifier);
> + mutex_unlock(&hdmi->cec_notifier_mutex);
> + }
> +
> + return status;
> }
>
> static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
> @@ -3106,12 +3116,6 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
> phy_stat & HDMI_PHY_HPD,
> phy_stat & HDMI_PHY_RX_SENSE);
>
> - if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) {
> - mutex_lock(&hdmi->cec_notifier_mutex);
> - cec_notifier_phys_addr_invalidate(hdmi->cec_notifier);
> - mutex_unlock(&hdmi->cec_notifier_mutex);
> - }
> -
> if ((intr_stat & HDMI_IH_PHY_STAT0_HPD) &&
> (phy_stat & HDMI_PHY_HPD))
> status = connector_status_connected;
^ permalink raw reply
* Re: [PATCH v7 09/23] drm: bridge: dw_hdmi: Unregister CEC notifier during connector cleanup
From: Hans Verkuil @ 2026-05-19 6:22 UTC (permalink / raw)
To: Jonas Karlman, Andrzej Hajda, Neil Armstrong, Robert Foss,
Heiko Stuebner, Laurent Pinchart, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-10-jonas@kwiboo.se>
On 18/05/2026 20:01, Jonas Karlman wrote:
> The CEC notifier is being unregistered when the bridge detach,
> something that happens earlier than normal connector cleanup.
>
> Change to unregister the CEC notifier at connector cleanup, in the
> connector .destroy() func, to align the lifetime of the connector and
> the CEC notifier and closer match a drmres handled generic CEC notifier.
>
> Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Acked-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Regards,
Hans
> ---
> v7: No change
> v6: Collect t-b tag
> v5: New patch
> ---
> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 16 +++++-----------
> 1 file changed, 5 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index cbbd15578042..5fd26ff8f55b 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -2532,6 +2532,11 @@ static void dw_hdmi_connector_destroy(struct drm_connector *connector)
> {
> struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
>
> + mutex_lock(&hdmi->cec_notifier_mutex);
> + cec_notifier_conn_unregister(hdmi->cec_notifier);
> + hdmi->cec_notifier = NULL;
> + mutex_unlock(&hdmi->cec_notifier_mutex);
> +
> drm_connector_cleanup(connector);
> drm_bridge_put(&hdmi->bridge);
> }
> @@ -2909,16 +2914,6 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
> return dw_hdmi_connector_create(hdmi);
> }
>
> -static void dw_hdmi_bridge_detach(struct drm_bridge *bridge)
> -{
> - struct dw_hdmi *hdmi = bridge->driver_private;
> -
> - mutex_lock(&hdmi->cec_notifier_mutex);
> - cec_notifier_conn_unregister(hdmi->cec_notifier);
> - hdmi->cec_notifier = NULL;
> - mutex_unlock(&hdmi->cec_notifier_mutex);
> -}
> -
> static enum drm_mode_status
> dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
> const struct drm_display_info *info,
> @@ -2996,7 +2991,6 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
> .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
> .atomic_reset = drm_atomic_helper_bridge_reset,
> .attach = dw_hdmi_bridge_attach,
> - .detach = dw_hdmi_bridge_detach,
> .atomic_check = dw_hdmi_bridge_atomic_check,
> .atomic_get_output_bus_fmts = dw_hdmi_bridge_atomic_get_output_bus_fmts,
> .atomic_get_input_bus_fmts = dw_hdmi_bridge_atomic_get_input_bus_fmts,
^ permalink raw reply
* Re: [PATCH v7 03/23] drm: bridge: dw_hdmi: Free IRQ before CEC adapter is unregistered
From: Hans Verkuil @ 2026-05-19 6:21 UTC (permalink / raw)
To: Jonas Karlman, Andrzej Hajda, Neil Armstrong, Robert Foss,
Heiko Stuebner, Laurent Pinchart, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Russell King, Hans Verkuil, Archit Taneja
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-4-jonas@kwiboo.se>
On 18/05/2026 20:01, Jonas Karlman wrote:
> The interrupt allocated with devm_request_threaded_irq() can be
> use-after-free when the devres release action try to free_irq().
>
> KASAN report a slab-use-after-free in dw_hdmi_cec_hardirq during unbind:
>
> Call trace:
> [...]
> dw_hdmi_cec_hardirq+0x4cc/0x560
> free_irq+0x48c/0x7e4
> devm_irq_release+0x54/0x90
> dr_node_release+0x38/0x5c
> release_nodes+0xac/0x130
> devres_release_all+0xf4/0x1b0
> device_unbind_cleanup+0x28/0x1f8
> device_release_driver_internal+0x358/0x470
> device_release_driver+0x18/0x24
> bus_remove_device+0x33c/0x4f0
> device_del+0x2d8/0x790
> platform_device_del+0x34/0x1e0
> platform_device_unregister+0x14/0x3c
> dw_hdmi_remove+0x74/0x180
> [...]
>
> Freed by:
> [...]
> kfree+0x1dc/0x5dc
> cec_delete_adapter+0xd4/0x118
> cec_devnode_release+0xa4/0xe0
> device_release+0xa0/0x200
> kobject_put+0x14c/0x26c
> put_device+0x14/0x30
> cec_unregister_adapter+0x20c/0x280
> dw_hdmi_cec_remove+0x8c/0xd0
> [...]
>
> Explicitly devm_free_irq() before the CEC adapter is unregistered to
> fix this possible use-after-free issue.
>
> Fixes: a616e63c56ef ("drm/bridge: dw-hdmi: add cec driver")
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Acked-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Regards,
Hans
> ---
> v7: New patch
>
> KASAN report a slab-use-after-free in dw_hdmi_cec_hardirq when,
> echo fe0a0000.hdmi > /sys/bus/platform/drivers/dwhdmi-rockchip/unbind
> on a Rockchip RK3566 device prior to this fix.
> ---
> drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
> index 9549dabde941..67a2a242d3ca 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
> @@ -309,6 +309,7 @@ static void dw_hdmi_cec_remove(struct platform_device *pdev)
> struct dw_hdmi_cec *cec = platform_get_drvdata(pdev);
>
> cec_notifier_cec_adap_unregister(cec->notify, cec->adap);
> + devm_free_irq(&pdev->dev, cec->irq, cec->adap);
> cec_unregister_adapter(cec->adap);
> }
>
^ permalink raw reply
* Re: [PATCH v2 2/5] arm64/mm: drop vmemmap_pmd helpers and use generic code
From: Muchun Song @ 2026-05-19 6:15 UTC (permalink / raw)
To: Will Deacon
Cc: Muchun Song, Catalin Marinas, linux-mm, akpm, Ryan Roberts,
David Hildenbrand, Kevin Brodsky, Dev Jain, Lorenzo Stoakes,
Anshuman Khandual, Yang Shi, Chaitanya S Prakash,
linux-arm-kernel, linux-kernel
In-Reply-To: <agsHINLR-D-tRiGd@willie-the-truck>
> On May 18, 2026, at 20:33, Will Deacon <will@kernel.org> wrote:
>
> On Sat, Apr 04, 2026 at 08:20:55PM +0800, Muchun Song wrote:
>> The generic implementations now suffice; remove the arm64 copies.
>>
>> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
>> ---
>> arch/arm64/mm/mmu.c | 14 --------------
>> 1 file changed, 14 deletions(-)
>>
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index ec1c6971a561..b87053452641 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -1745,20 +1745,6 @@ static void free_empty_tables(unsigned long addr, unsigned long end,
>> }
>> #endif
>>
>> -void __meminit vmemmap_set_pmd(pmd_t *pmdp, void *p, int node,
>> - unsigned long addr, unsigned long next)
>> -{
>> - pmd_set_huge(pmdp, __pa(p), __pgprot(PROT_SECT_NORMAL));
>> -}
>> -
>> -int __meminit vmemmap_check_pmd(pmd_t *pmdp, int node,
>> - unsigned long addr, unsigned long next)
>> -{
>> - vmemmap_verify((pte_t *)pmdp, node, addr, next);
>> -
>> - return pmd_sect(READ_ONCE(*pmdp));
>> -}
>
> I think this is fine:
>
> Acked-by: Will Deacon <will@kernel.org>
Thanks.
>
> but note that, since c25c4aa3f79a ("arm64: mm: Add PTE_DIRTY back to
> PAGE_KERNEL* to fix kexec/hibernation"), I think that using PAGE_KERNEL
> (like the generic code does in the first patch of this series) means
> that this change isn't a no-op -- it means that the huge entries will
> now be marked as dirty. That's possibly a bug fix (?)
I think you are right. We should mark kernel mapping as dirty.
Thanks,
Muchun
>
> Will
^ permalink raw reply
* [PATCH] ACPI: Use LIST_HEAD() to initialize on stack list head
From: Jisheng Zhang @ 2026-05-19 5:54 UTC (permalink / raw)
To: Rafael J . Wysocki, Len Brown, Lorenzo Pieralisi, Hanjun Guo,
Sudeep Holla, Catalin Marinas, Will Deacon
Cc: linux-acpi, linux-kernel, linux-arm-kernel
Use LIST_HEAD to initialize on stack list head. No intentional
functional impact.
Change generated with below coccinelle script:
@@
identifier name;
@@
- struct list_head name;
+ LIST_HEAD(name);
... when != name
- INIT_LIST_HEAD(&name);
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
drivers/acpi/acpi_apd.c | 3 +--
drivers/acpi/arm64/amba.c | 3 +--
drivers/acpi/resource.c | 3 +--
drivers/acpi/scan.c | 3 +--
drivers/acpi/x86/lpss.c | 3 +--
5 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index bed0791c17fc..fa28acc541fe 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -68,14 +68,13 @@ static int fch_misc_setup(struct apd_private_data *pdata)
struct platform_device *clkdev;
struct fch_clk_data *clk_data;
struct resource_entry *rentry;
- struct list_head resource_list;
+ LIST_HEAD(resource_list);
int ret;
clk_data = devm_kzalloc(&adev->dev, sizeof(*clk_data), GFP_KERNEL);
if (!clk_data)
return -ENOMEM;
- INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_memory_resources(adev, &resource_list);
if (ret < 0)
return -ENOENT;
diff --git a/drivers/acpi/arm64/amba.c b/drivers/acpi/arm64/amba.c
index 1350083bce5f..ec342404306b 100644
--- a/drivers/acpi/arm64/amba.c
+++ b/drivers/acpi/arm64/amba.c
@@ -39,7 +39,7 @@ static int amba_handler_attach(struct acpi_device *adev,
struct acpi_device *parent = acpi_dev_parent(adev);
struct amba_device *dev;
struct resource_entry *rentry;
- struct list_head resource_list;
+ LIST_HEAD(resource_list);
bool address_found = false;
int irq_no = 0;
int ret;
@@ -55,7 +55,6 @@ static int amba_handler_attach(struct acpi_device *adev,
return -ENOMEM;
}
- INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
if (ret < 0)
goto err_free;
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index bc8050d8a6f5..ff78311c136b 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -1118,11 +1118,10 @@ EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
static int acpi_dev_consumes_res(struct acpi_device *adev, struct resource *res)
{
- struct list_head resource_list;
+ LIST_HEAD(resource_list);
struct resource_entry *rentry;
int ret, found = 0;
- INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
if (ret < 0)
return 0;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 530547cda8b2..bd599d0a9348 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1738,7 +1738,7 @@ static bool acpi_is_indirect_io_slave(struct acpi_device *device)
static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
{
- struct list_head resource_list;
+ LIST_HEAD(resource_list);
bool is_serial_bus_slave = false;
static const struct acpi_device_id ignore_serial_bus_ids[] = {
/*
@@ -1792,7 +1792,6 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
if (!acpi_match_device_ids(device, ignore_serial_bus_ids))
return false;
- INIT_LIST_HEAD(&resource_list);
acpi_dev_get_resources(device, &resource_list,
acpi_check_serial_bus_slave,
&is_serial_bus_slave);
diff --git a/drivers/acpi/x86/lpss.c b/drivers/acpi/x86/lpss.c
index 0171eef00484..d33dc34a2894 100644
--- a/drivers/acpi/x86/lpss.c
+++ b/drivers/acpi/x86/lpss.c
@@ -615,7 +615,7 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
const struct lpss_device_desc *dev_desc;
struct lpss_private_data *pdata;
struct resource_entry *rentry;
- struct list_head resource_list;
+ LIST_HEAD(resource_list);
struct platform_device *pdev;
int ret;
@@ -627,7 +627,6 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
if (!pdata)
return -ENOMEM;
- INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_memory_resources(adev, &resource_list);
if (ret < 0)
goto err_out;
--
2.53.0
^ permalink raw reply related
* [PATCH next] firmware: imx: fix use after free in init_device_context()
From: Dan Carpenter @ 2026-05-19 6:13 UTC (permalink / raw)
To: Pankaj Gupta
Cc: Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Frieder Schrempf, imx, linux-arm-kernel, linux-kernel,
kernel-janitors
Add a missing return statement on the error path. Otherwise we have a
use after free when it dereferences "dev_ctx" on the next line.
Fixes: 63536a73a3bb ("firmware: drivers: imx: adds miscdev")
Signed-off-by: Dan Carpenter <error27@gmail.com>
---
This was in the original fix but I guess there was a merge problem.
https://lore.kernel.org/all/20260514090457.2186933-1-pankaj.gupta@nxp.com/
drivers/firmware/imx/se_ctrl.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c
index 9327d47e4312..010af8221dfe 100644
--- a/drivers/firmware/imx/se_ctrl.c
+++ b/drivers/firmware/imx/se_ctrl.c
@@ -486,6 +486,7 @@ static int init_device_context(struct se_if_priv *priv, int ch_id,
kfree(dev_ctx->devname);
kfree(dev_ctx);
*new_dev_ctx = NULL;
+ return ret;
}
list_add_tail(&dev_ctx->link, &priv->dev_ctx_list);
--
2.53.0
^ permalink raw reply related
* RE: [PATCH V14 02/12] PCI: host-generic: Add common helpers for parsing Root Port properties
From: Sherry Sun (OSS) @ 2026-05-19 6:07 UTC (permalink / raw)
To: mani@kernel.org
Cc: Bjorn Helgaas, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org, Frank Li, s.hauer@pengutronix.de,
kernel@pengutronix.de, festevam@gmail.com, lpieralisi@kernel.org,
kwilczynski@kernel.org, bhelgaas@google.com, Hongxing Zhu,
l.stach@pengutronix.de, imx@lists.linux.dev,
linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <xyued2adtz2fs47nnl537aef7rsjuhswivcaieh6lxhlxpohkr@gpxmdcpczik7>
> Subject: Re: [PATCH V14 02/12] PCI: host-generic: Add common helpers for
> parsing Root Port properties
>
> On Mon, May 18, 2026 at 08:42:38AM +0000, Sherry Sun wrote:
> > > Subject: Re: [PATCH V14 02/12] PCI: host-generic: Add common helpers
> > > for parsing Root Port properties
> > >
> > > On Wed, Apr 22, 2026 at 05:35:39PM +0800, Sherry Sun wrote:
> > > > Introduce generic helper functions to parse Root Port device tree
> > > > nodes and extract common properties like reset GPIOs. This allows
> > > > multiple PCI host controller drivers to share the same parsing logic.
> > > >
> > > > Define struct pci_host_port to hold common Root Port properties
> > > > (currently only list of PERST# GPIO descriptors) and add
> > > > pci_host_common_parse_ports() to parse Root Port nodes from device
> > > tree.
> > > >
> > > > Also add the 'ports' list to struct pci_host_bridge for better
> > > > maintain parsed Root Port information.
> > > > ...
> > >
> > > > +static int pci_host_common_parse_port(struct device *dev,
> > > > + struct pci_host_bridge *bridge,
> > > > + struct device_node *node) {
> > > > + struct pci_host_port *port;
> > > > + int ret;
> > > > +
> > > > + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> > > > + if (!port)
> > > > + return -ENOMEM;
> > > > +
> > > > + INIT_LIST_HEAD(&port->perst);
> > > > +
> > > > + ret = pci_host_common_parse_perst(dev, port, node);
> > > > + if (ret)
> > > > + return ret;
> > > > +
> > > > + /*
> > > > + * 1. PERST# found in RP or its child nodes - list is not empty, continue
> > > > + * 2. PERST# not found in RP/children, but found in RC node -
> > > > +return -
> > > ENODEV
> > > > + * to fallback legacy binding
> > > > + * 3. PERST# not found anywhere - list is empty, continue
> > > > +(optional
> > > PERST#)
> > > > + */
> > > > + if (list_empty(&port->perst)) {
> > > > + if (of_property_present(dev->of_node, "reset-gpios") ||
> > > > + of_property_present(dev->of_node, "reset-gpio"))
> > > > + return -ENODEV;
> > >
> > > This doesn't seem right to me. The parser of per-Root Port
> > > properties should not be responsible for deciding whether legacy
> > > methods are valid, i.e., whether a property is in the Root Complex
> > > node. I think it's up to the caller to decide whether it needs to look
> elsewhere.
> > >
> > > I don't think this even needs to return a "success/failure" value
> > > because there may be more properties in the future, and not all will
> > > be required. This function can't tell which properties a specific
> > > driver requires and which are optional.
> > >
> > > The caller can check whether we found what it needs and fall back to
> > > a legacy method as needed.
> >
> > Hi Bjorn,
> > The code here was suggested by Mani,
> https://lore.ke/
> rnel.org%2Fall%2Flnzprzrdwra7pn7d6m3sbj5pvjy64blwpjl6i3lmlnfbyho63b%4
> 0czpyhpgz5vum%2F&data=05%7C02%7Csherry.sun%40nxp.com%7C4fe904a4
> 5dd242113c0008deb56ad494%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0
> %7C0%7C639147667610810003%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0e
> U1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCI
> sIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=jo875iGio19v5xllCJ%2Fxa3xQO
> BRUXA6PLk1llD8%2FP70%3D&reserved=0.
> > I think your suggestion here is reasonable, the per-Root Port parser
> > shouldn't check the RC-level binding. That's a policy decision that belongs to
> the caller.
> >
> > Hi Mani, if you also agree, I'll rework this so that:
> > 1. pci_host_common_parse_port() only parses properties from the Root
> Port
> > (and its children) without checking the RC node.
> > 2. The function won't return failure for "property not found" - it will only
> return
> > errors for real failures (e.g., -ENOMEM, GPIO acquisition errors).
> > 3. The legacy fallback logic will be moved to the caller, which can inspect the
> > parsed result and decide whether to fall back to the legacy binding.
> >
>
> Fine with me. The reason for suggesting fallback within this API itself was to
> avoid duplicating the fallback code as it will be mostly generic. But I do agree
> with Bjorn on the fact that individual host controller drivers might have
> optional properties in the RC node and we can't incorporate all of them here.
>
> But no need to rework this series as it got applied for v7.2. You can send
> rework patches on top of this series.
>
Ok, will do, thanks!
Best Regards
Sherry
^ permalink raw reply
* Re: [PATCH v14 10/44] arm64: RMI: Add support for SRO
From: Aneesh Kumar K.V @ 2026-05-19 6:02 UTC (permalink / raw)
To: Steven Price, kvm, kvmarm
Cc: Steven Price, Catalin Marinas, Marc Zyngier, Will Deacon,
James Morse, Oliver Upton, Suzuki K Poulose, Zenghui Yu,
linux-arm-kernel, linux-kernel, Joey Gouly, Alexandru Elisei,
Christoffer Dall, Fuad Tabba, linux-coco, Ganapatrao Kulkarni,
Gavin Shan, Shanker Donthineni, Alper Gun, Emi Kisanuki,
Vishal Annapurve, WeiLin.Chang, Lorenzo.Pieralisi2
In-Reply-To: <20260513131757.116630-11-steven.price@arm.com>
Steven Price <steven.price@arm.com> writes:
> +static unsigned long donate_req_to_size(unsigned long donatereq)
> +{
> + unsigned long unit_size = RMI_DONATE_SIZE(donatereq);
> +
> + switch (unit_size) {
> + case 0:
> + return PAGE_SIZE;
> + case 1:
> + return PMD_SIZE;
> + case 2:
> + return PUD_SIZE;
> + case 3:
> + return P4D_SIZE;
> + }
> + unreachable();
> +}
>
> +
> +static void rmi_smccc_invoke(struct arm_smccc_1_2_regs *regs_in,
> + struct arm_smccc_1_2_regs *regs_out)
> +{
> + struct arm_smccc_1_2_regs regs = *regs_in;
> + unsigned long status;
> +
> + do {
> + arm_smccc_1_2_invoke(®s, regs_out);
> + status = RMI_RETURN_STATUS(regs_out->a0);
> + } while (status == RMI_BUSY || status == RMI_BLOCKED);
> +}
> +
> +int free_delegated_page(phys_addr_t phys)
> +{
> + if (WARN_ON(rmi_undelegate_page(phys))) {
> + /* Undelegate failed: leak the page */
> + return -EBUSY;
> + }
> +
> + free_page((unsigned long)phys_to_virt(phys));
> +
> + return 0;
> +}
> +
> +static int rmi_sro_ensure_capacity(struct rmi_sro_state *sro,
> + unsigned long count)
> +{
> + if (WARN_ON_ONCE(sro->addr_count > RMI_MAX_ADDR_LIST))
> + return -EOVERFLOW;
> +
> + if (count > RMI_MAX_ADDR_LIST - sro->addr_count)
> + return -ENOSPC;
> +
> + return 0;
> +}
> +
> +static int rmi_sro_donate_contig(struct rmi_sro_state *sro,
> + unsigned long sro_handle,
> + unsigned long donatereq,
> + struct arm_smccc_1_2_regs *out_regs,
> + gfp_t gfp)
> +{
> + unsigned long unit_size = RMI_DONATE_SIZE(donatereq);
> + unsigned long unit_size_bytes = donate_req_to_size(donatereq);
> + unsigned long count = RMI_DONATE_COUNT(donatereq);
> + unsigned long state = RMI_DONATE_STATE(donatereq);
> + unsigned long size = unit_size_bytes * count;
> + unsigned long addr_range;
>
Looking at above and the related code, I am wondering whether we should
use u64 instead of unsigned long for everything that the specification
defines as 64-bit.
-aneesh
^ permalink raw reply
* Re: [PATCH net-next v2 2/2] net: ti: icssg: Add HSR and LRE PA statistics
From: Luka Gejak @ 2026-05-19 5:55 UTC (permalink / raw)
To: Jakub Kicinski, MD Danish Anwar, Felix Maurer
Cc: David S. Miller, Eric Dumazet, Paolo Abeni, Simon Horman,
Jonathan Corbet, Shuah Khan, Roger Quadros, Andrew Lunn,
Meghana Malladi, Jacob Keller, David Carlier, Vadim Fedorenko,
Kevin Hao, netdev, linux-doc, linux-kernel, linux-arm-kernel,
Vladimir Oltean, luka.gejak
In-Reply-To: <20260518184506.694c584e@kernel.org>
On May 19, 2026 3:45:06 AM GMT+02:00, Jakub Kicinski <kuba@kernel.org> wrote:
>On Thu, 14 May 2026 13:26:05 +0530 MD Danish Anwar wrote:
>> Add new firmware PA statistics counters for HSR and LRE to the ethtool
>> statistics exposed by the ICSSG driver.
>>
>> New statistics added:
>> - FW_HSR_FWD_CHECK_FAIL_DROP: Packets dropped on the HSR forwarding path
>> - FW_HSR_HE_CHECK_FAIL_DROP: Packets dropped on the HSR host egress path
>> - FW_HSR_SKIP_HOST_DUP_DISCARD_FRAMES: Frames with duplicate discard
>> skipped
>> - FW_LRE_CNT_UNIQUE/DUPLICATE/MULTIPLE_RX: LRE duplicate detection
>> counters
>> - FW_LRE_CNT_RX/TX: LRE per-port frame counters
>> - FW_LRE_CNT_OWN_RX: Own HSR tagged frames received
>> - FW_LRE_CNT_ERRWRONGLAN: Frames with wrong LAN identifier (PRP)
>>
>> Document the new HSR/LRE statistics in icssg_prueth.rst.
>
>To an untrained eye these stats look like stuff that could
>be standardized across drivers.
>
>Luka, Felix, others on CC, do you think we should expose these
>from HSR over netlink as "standard" offload stats different drivers
>can plug into or not worth it?
Hi Jakub,
I think there is a case for standardizing part of this, but I would
not standardize the whole set as-is.
The LRE counters look generic enough to me, especially:
- unique rx
- duplicate rx
- multiple rx
- rx / tx
- own rx
- wrong LAN, PRP only
Those are protocol/LRE concepts rather than TI firmware details, so
exposing them from the HSR/PRP layer sounds useful. I would expect
both the software implementation and offloaded implementations to be
able to provide at least some of them, with unsupported counters
omitted or reported as not available.
I would not put the firmware check/drop counters in the same standard
bucket, though:
- FW_HSR_FWD_CHECK_FAIL_DROP
- FW_HSR_HE_CHECK_FAIL_DROP
- FW_HSR_SKIP_HOST_DUP_DISCARD_FRAMES
Those sound more like implementation/debug counters for the ICSSG
firmware pipeline. They are still useful in ethtool driver stats, but
I would be hesitant to bake their exact semantics into HSR UAPI.
So my preference would be:
1. Keep driver-private ethtool stats for the full firmware counter set.
2. Add a small HSR/PRP standard stats set separately, limited to
well-defined LRE counters.
3. Make the HSR layer expose them, with offload drivers plugging in via
an optional callback or offload stats op.
4. Define the counters carefully, including whether they are per-HSR
device or per-port A/B, and what PRP-only counters mean for HSR.
I do not think this patch should blindly become the UAPI definition,
but I do think it points at a useful follow-up. If we want to avoid
adding driver-private names first and then standardizing different
names later, then it may be worth asking Danish to split the
protocol-level LRE counters out and route those through a common HSR
stats interface.
Best regards,
Luka Gejak
^ permalink raw reply
* Re: [PATCH v14 08/44] arm64: RMI: Ensure that the RMM has GPT entries for memory
From: Aneesh Kumar K.V @ 2026-05-19 5:55 UTC (permalink / raw)
To: Steven Price, kvm, kvmarm
Cc: Steven Price, Catalin Marinas, Marc Zyngier, Will Deacon,
James Morse, Oliver Upton, Suzuki K Poulose, Zenghui Yu,
linux-arm-kernel, linux-kernel, Joey Gouly, Alexandru Elisei,
Christoffer Dall, Fuad Tabba, linux-coco, Ganapatrao Kulkarni,
Gavin Shan, Shanker Donthineni, Alper Gun, Emi Kisanuki,
Vishal Annapurve, WeiLin.Chang, Lorenzo.Pieralisi2
In-Reply-To: <20260513131757.116630-9-steven.price@arm.com>
> +
> +bool rmi_is_available(void)
> +{
> + return arm64_rmi_is_available;
> +}
> +
Can we rename to is_rmi_available(void) ?
-aneesh
^ permalink raw reply
* [PATCH] arm64: dts: imx943-evk: Fix PCIe EP vpcie-supply
From: Sherry Sun (OSS) @ 2026-05-19 5:54 UTC (permalink / raw)
To: Frank.Li, s.hauer, kernel, festevam, robh, krzk+dt, conor+dt,
hongxing.zhu
Cc: imx, linux-arm-kernel, devicetree, linux-kernel
From: Sherry Sun <sherry.sun@nxp.com>
The vpcie-supply property should reference the regulator that controls
the actual M.2 power supply, not the W_DISABLE1# signal.
On imx943-evk:
- reg_m2_wlan controls M.2 W_DISABLE1# signal
- reg_m2_pwr controls the actual M.2 power supply
Fix the vpcie-supply to use reg_m2_pwr for proper power control in
PCIe endpoint mode.
Fixes: 1962c596d51c ("arm64: dts: imx943-evk: Add pcie[0,1] and pcie-ep[0,1] support")
Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
---
arch/arm64/boot/dts/freescale/imx943-evk.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/freescale/imx943-evk.dts b/arch/arm64/boot/dts/freescale/imx943-evk.dts
index 1346a6a56883..7cfd42468950 100644
--- a/arch/arm64/boot/dts/freescale/imx943-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx943-evk.dts
@@ -1043,7 +1043,7 @@ &pcie0 {
&pcie0_ep {
pinctrl-0 = <&pinctrl_pcie0>;
pinctrl-names = "default";
- vpcie-supply = <®_m2_wlan>;
+ vpcie-supply = <®_m2_pwr>;
status = "disabled";
};
base-commit: 5f9e9f83aee0fa8f2124c6f192505de2cdf7c5dc
--
2.37.1
^ permalink raw reply related
* Re: [PATCH V14 02/12] PCI: host-generic: Add common helpers for parsing Root Port properties
From: mani @ 2026-05-19 5:52 UTC (permalink / raw)
To: Sherry Sun
Cc: Bjorn Helgaas, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org, Frank Li, s.hauer@pengutronix.de,
kernel@pengutronix.de, festevam@gmail.com, lpieralisi@kernel.org,
kwilczynski@kernel.org, bhelgaas@google.com, Hongxing Zhu,
l.stach@pengutronix.de, imx@lists.linux.dev,
linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <VI0PR04MB1211452312EB9BC6EF1ED2E0192032@VI0PR04MB12114.eurprd04.prod.outlook.com>
On Mon, May 18, 2026 at 08:42:38AM +0000, Sherry Sun wrote:
> > Subject: Re: [PATCH V14 02/12] PCI: host-generic: Add common helpers for
> > parsing Root Port properties
> >
> > On Wed, Apr 22, 2026 at 05:35:39PM +0800, Sherry Sun wrote:
> > > Introduce generic helper functions to parse Root Port device tree
> > > nodes and extract common properties like reset GPIOs. This allows
> > > multiple PCI host controller drivers to share the same parsing logic.
> > >
> > > Define struct pci_host_port to hold common Root Port properties
> > > (currently only list of PERST# GPIO descriptors) and add
> > > pci_host_common_parse_ports() to parse Root Port nodes from device
> > tree.
> > >
> > > Also add the 'ports' list to struct pci_host_bridge for better
> > > maintain parsed Root Port information.
> > > ...
> >
> > > +static int pci_host_common_parse_port(struct device *dev,
> > > + struct pci_host_bridge *bridge,
> > > + struct device_node *node)
> > > +{
> > > + struct pci_host_port *port;
> > > + int ret;
> > > +
> > > + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> > > + if (!port)
> > > + return -ENOMEM;
> > > +
> > > + INIT_LIST_HEAD(&port->perst);
> > > +
> > > + ret = pci_host_common_parse_perst(dev, port, node);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + /*
> > > + * 1. PERST# found in RP or its child nodes - list is not empty, continue
> > > + * 2. PERST# not found in RP/children, but found in RC node - return -
> > ENODEV
> > > + * to fallback legacy binding
> > > + * 3. PERST# not found anywhere - list is empty, continue (optional
> > PERST#)
> > > + */
> > > + if (list_empty(&port->perst)) {
> > > + if (of_property_present(dev->of_node, "reset-gpios") ||
> > > + of_property_present(dev->of_node, "reset-gpio"))
> > > + return -ENODEV;
> >
> > This doesn't seem right to me. The parser of per-Root Port properties should
> > not be responsible for deciding whether legacy methods are valid, i.e.,
> > whether a property is in the Root Complex node. I think it's up to the caller
> > to decide whether it needs to look elsewhere.
> >
> > I don't think this even needs to return a "success/failure" value because there
> > may be more properties in the future, and not all will be required. This
> > function can't tell which properties a specific driver requires and which are
> > optional.
> >
> > The caller can check whether we found what it needs and fall back to a legacy
> > method as needed.
>
> Hi Bjorn,
> The code here was suggested by Mani, https://lore.kernel.org/all/lnzprzrdwra7pn7d6m3sbj5pvjy64blwpjl6i3lmlnfbyho63b@czpyhpgz5vum/.
> I think your suggestion here is reasonable, the per-Root Port parser shouldn't
> check the RC-level binding. That's a policy decision that belongs to the caller.
>
> Hi Mani, if you also agree, I'll rework this so that:
> 1. pci_host_common_parse_port() only parses properties from the Root Port
> (and its children) without checking the RC node.
> 2. The function won't return failure for "property not found" - it will only return
> errors for real failures (e.g., -ENOMEM, GPIO acquisition errors).
> 3. The legacy fallback logic will be moved to the caller, which can inspect the
> parsed result and decide whether to fall back to the legacy binding.
>
Fine with me. The reason for suggesting fallback within this API itself was to
avoid duplicating the fallback code as it will be mostly generic. But I do agree
with Bjorn on the fact that individual host controller drivers might have
optional properties in the RC node and we can't incorporate all of them here.
But no need to rework this series as it got applied for v7.2. You can send
rework patches on top of this series.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* [PATCH v2 4/4] drm/verisilicon: add Nuvoton MA35D1 DCU Lite display controller support
From: Joey Lu @ 2026-05-19 5:51 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260519055114.1886525-1-a0987203069@gmail.com>
The Nuvoton MA35D1 SoC integrates a Verisilicon DCU Lite display
controller. While its register layout is broadly similar to the DC8200,
several differences require dedicated hardware ops:
1. No CONFIG_EX commit path: framebuffer updates use enable (bit 0) and
reset (bit 4) bits in FB_CONFIG instead of the DC8200 staging registers
(FB_CONFIG_EX, FB_TOP_LEFT, FB_BOTTOM_RIGHT, FB_BLEND_CONFIG,
PANEL_CONFIG_EX).
2. No PANEL_START register: panel output starts when
PANEL_CONFIG.RUNNING is set; no multi-display sync start register
is used.
3. Different IRQ registers: DCU Lite uses DISP_IRQ_STA (0x147C) /
DISP_IRQ_EN (0x1480) versus DC8200's TOP_IRQ_ACK (0x0010) /
TOP_IRQ_EN (0x0014).
4. Per-frame commit cycle: DCU Lite requires the VALID bit in FB_CONFIG
to be set at the start of each atomic commit (crtc_begin) and cleared
after (crtc_flush).
5. Simpler clock topology: only "core" (bus gate) and "pix0" (pixel
divider) clocks; no axi or ahb clocks. Make axi_clk and ahb_clk
optional (devm_clk_get_optional_enabled) so DCU Lite nodes without
those clocks are handled gracefully.
Add vs_dcu_lite.c implementing the vs_dc_funcs vtable for the above
differences. After chip identity detection, vs_dc_probe() now selects
vs_dcu_lite_funcs when the identified model is VSDC_MODEL_DCU_LITE
(model register reads 0, revision 0x5560, customer_id 0x305).
Extend Kconfig to allow building on ARCH_MA35 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/Kconfig | 2 +-
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_dc.c | 9 ++-
drivers/gpu/drm/verisilicon/vs_dc.h | 1 +
drivers/gpu/drm/verisilicon/vs_dcu_lite.c | 78 +++++++++++++++++++++++
5 files changed, 87 insertions(+), 5 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dcu_lite.c
diff --git a/drivers/gpu/drm/verisilicon/Kconfig b/drivers/gpu/drm/verisilicon/Kconfig
index 7cce86ec8603..295d246eb4b4 100644
--- a/drivers/gpu/drm/verisilicon/Kconfig
+++ b/drivers/gpu/drm/verisilicon/Kconfig
@@ -2,7 +2,7 @@
config DRM_VERISILICON_DC
tristate "DRM Support for Verisilicon DC-series display controllers"
depends on DRM && COMMON_CLK
- depends on RISCV || COMPILE_TEST
+ depends on RISCV || ARCH_MA35 || COMPILE_TEST
select DRM_BRIDGE_CONNECTOR
select DRM_CLIENT_SELECTION
select DRM_DISPLAY_HELPER
diff --git a/drivers/gpu/drm/verisilicon/Makefile b/drivers/gpu/drm/verisilicon/Makefile
index f4fbd9f7d6a2..bf88f627e65c 100644
--- a/drivers/gpu/drm/verisilicon/Makefile
+++ b/drivers/gpu/drm/verisilicon/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
-verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_drm.o vs_hwdb.o vs_plane.o vs_primary_plane.o
+verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_dcu_lite.o vs_drm.o vs_hwdb.o vs_plane.o vs_primary_plane.o
obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon-dc.o
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c
index c94957024189..77bc63c629f7 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -90,13 +90,13 @@ static int vs_dc_probe(struct platform_device *pdev)
return PTR_ERR(dc->core_clk);
}
- dc->axi_clk = devm_clk_get_enabled(dev, "axi");
+ dc->axi_clk = devm_clk_get_optional_enabled(dev, "axi");
if (IS_ERR(dc->axi_clk)) {
dev_err(dev, "can't get axi clock\n");
return PTR_ERR(dc->axi_clk);
}
- dc->ahb_clk = devm_clk_get_enabled(dev, "ahb");
+ dc->ahb_clk = devm_clk_get_optional_enabled(dev, "ahb");
if (IS_ERR(dc->ahb_clk)) {
dev_err(dev, "can't get ahb clock\n");
return PTR_ERR(dc->ahb_clk);
@@ -134,7 +134,10 @@ static int vs_dc_probe(struct platform_device *pdev)
dev_info(dev, "Found DC%x rev %x customer %x\n", dc->identity.model,
dc->identity.revision, dc->identity.customer_id);
- dc->funcs = &vs_dc8200_funcs;
+ if (dc->identity.model == VSDC_MODEL_DC8200)
+ dc->funcs = &vs_dc8200_funcs;
+ else
+ dc->funcs = &vs_dcu_lite_funcs;
if (port_count > dc->identity.display_count) {
dev_err(dev, "too many downstream ports than HW capability\n");
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.h b/drivers/gpu/drm/verisilicon/vs_dc.h
index 45172c1a525c..d77d4a1babdf 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.h
+++ b/drivers/gpu/drm/verisilicon/vs_dc.h
@@ -66,5 +66,6 @@ struct vs_dc {
};
extern const struct vs_dc_funcs vs_dc8200_funcs;
+extern const struct vs_dc_funcs vs_dcu_lite_funcs;
#endif /* _VS_DC_H_ */
diff --git a/drivers/gpu/drm/verisilicon/vs_dcu_lite.c b/drivers/gpu/drm/verisilicon/vs_dcu_lite.c
new file mode 100644
index 000000000000..11ef57d5ebaa
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dcu_lite.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 Joey Lu <yclu4@nuvoton.com>
+ */
+
+#include <linux/regmap.h>
+
+#include "vs_crtc_regs.h"
+#include "vs_dc.h"
+#include "vs_primary_plane_regs.h"
+
+static void vs_dcu_lite_bridge_enable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_RESET);
+}
+
+static void vs_dcu_lite_bridge_disable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_RESET);
+}
+
+static void vs_dcu_lite_crtc_begin(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_VALID);
+}
+
+static void vs_dcu_lite_crtc_flush(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_VALID);
+}
+
+static void vs_dcu_lite_crtc_enable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_ENABLE);
+}
+
+static void vs_dcu_lite_crtc_disable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_ENABLE);
+}
+
+static void vs_dcu_lite_enable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_DISP_IRQ_EN,
+ VSDC_DISP_IRQ_VSYNC(output));
+}
+
+static void vs_dcu_lite_disable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_DISP_IRQ_EN,
+ VSDC_DISP_IRQ_VSYNC(output));
+}
+
+static u32 vs_dcu_lite_irq_handler(struct vs_dc *dc)
+{
+ u32 irqs;
+
+ regmap_read(dc->regs, VSDC_DISP_IRQ_STA, &irqs);
+ return irqs;
+}
+
+const struct vs_dc_funcs vs_dcu_lite_funcs = {
+ .bridge_enable = vs_dcu_lite_bridge_enable,
+ .bridge_disable = vs_dcu_lite_bridge_disable,
+ .crtc_begin = vs_dcu_lite_crtc_begin,
+ .crtc_flush = vs_dcu_lite_crtc_flush,
+ .crtc_enable = vs_dcu_lite_crtc_enable,
+ .crtc_disable = vs_dcu_lite_crtc_disable,
+ .enable_vblank = vs_dcu_lite_enable_vblank,
+ .disable_vblank = vs_dcu_lite_disable_vblank,
+ .irq_handler = vs_dcu_lite_irq_handler,
+};
--
2.43.0
^ permalink raw reply related
* [PATCH v2 3/4] drm/verisilicon: introduce per-variant hardware ops table
From: Joey Lu @ 2026-05-19 5:51 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260519055114.1886525-1-a0987203069@gmail.com>
The DC driver directly calls DC8200-specific register sequences from
vs_bridge.c, vs_crtc.c and vs_primary_plane.c. Supporting a second IP
variant with a different register layout would require scattering
if/else branches throughout those files.
Instead, introduce struct vs_dc_funcs, a small vtable of function
pointers covering every hardware-specific operation:
bridge_enable/disable - panel output start/stop sequence
crtc_begin/flush - per-frame commit begin/end hooks
crtc_enable/disable - display output power on/off
enable_vblank/disable_vblank - IRQ mask for vsync events
plane_enable_ex/disable_ex - framebuffer enable/disable
plane_update_ex - variant-specific plane update registers
irq_handler - read and acknowledge pending IRQs
Extract all DC8200-specific register operations from vs_bridge.c,
vs_crtc.c, vs_primary_plane.c and vs_dc.c into a new vs_dc8200.c
source file that implements the full vs_dc_funcs vtable and exposes
vs_dc8200_funcs.
Add atomic_begin and atomic_flush hooks in vs_crtc.c to dispatch to
crtc_begin/crtc_flush; these are optional (NULL-checked) so that
variants without a per-frame commit cycle can leave them unimplemented.
After vs_fill_chip_identity() confirms a DC8200 (or compatible)
identity, vs_dc_probe() assigns dc->funcs = &vs_dc8200_funcs so all
callers automatically dispatch to the correct implementation.
No functional change for DC8200 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_bridge.c | 20 +---
drivers/gpu/drm/verisilicon/vs_crtc.c | 38 ++++++-
drivers/gpu/drm/verisilicon/vs_dc.c | 6 +-
drivers/gpu/drm/verisilicon/vs_dc.h | 32 ++++++
drivers/gpu/drm/verisilicon/vs_dc8200.c | 107 ++++++++++++++++++
.../gpu/drm/verisilicon/vs_primary_plane.c | 32 +-----
7 files changed, 186 insertions(+), 51 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8200.c
diff --git a/drivers/gpu/drm/verisilicon/Makefile b/drivers/gpu/drm/verisilicon/Makefile
index fd8d805fbcde..f4fbd9f7d6a2 100644
--- a/drivers/gpu/drm/verisilicon/Makefile
+++ b/drivers/gpu/drm/verisilicon/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
-verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_drm.o vs_hwdb.o vs_plane.o vs_primary_plane.o
+verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_drm.o vs_hwdb.o vs_plane.o vs_primary_plane.o
obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon-dc.o
diff --git a/drivers/gpu/drm/verisilicon/vs_bridge.c b/drivers/gpu/drm/verisilicon/vs_bridge.c
index 7a93049368db..6a9af10c64e6 100644
--- a/drivers/gpu/drm/verisilicon/vs_bridge.c
+++ b/drivers/gpu/drm/verisilicon/vs_bridge.c
@@ -162,15 +162,8 @@ static void vs_bridge_enable_common(struct vs_crtc *crtc,
VSDC_DISP_PANEL_CONFIG_DE_EN |
VSDC_DISP_PANEL_CONFIG_DAT_EN |
VSDC_DISP_PANEL_CONFIG_CLK_EN);
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
- VSDC_DISP_PANEL_CONFIG_RUNNING);
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_MULTI_DISP_SYNC);
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_RUNNING(output));
-
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(crtc->id),
- VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+
+ dc->funcs->bridge_enable(dc, output);
}
static void vs_bridge_atomic_enable_dpi(struct drm_bridge *bridge,
@@ -228,14 +221,7 @@ static void vs_bridge_atomic_disable(struct drm_bridge *bridge,
struct vs_dc *dc = crtc->dc;
unsigned int output = crtc->id;
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_MULTI_DISP_SYNC |
- VSDC_DISP_PANEL_START_RUNNING(output));
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
- VSDC_DISP_PANEL_CONFIG_RUNNING);
-
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(crtc->id),
- VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+ dc->funcs->bridge_disable(dc, output);
}
static const struct drm_bridge_funcs vs_dpi_bridge_funcs = {
diff --git a/drivers/gpu/drm/verisilicon/vs_crtc.c b/drivers/gpu/drm/verisilicon/vs_crtc.c
index 9080344398ca..a87caa6f73ba 100644
--- a/drivers/gpu/drm/verisilicon/vs_crtc.c
+++ b/drivers/gpu/drm/verisilicon/vs_crtc.c
@@ -16,10 +16,33 @@
#include "vs_crtc_regs.h"
#include "vs_crtc.h"
#include "vs_dc.h"
-#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#include "vs_plane.h"
+static void vs_crtc_atomic_begin(struct drm_crtc *crtc,
+ struct drm_atomic_commit *state)
+{
+ struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
+ struct vs_dc *dc = vcrtc->dc;
+ unsigned int output = vcrtc->id;
+
+ if (dc->funcs->crtc_begin)
+ dc->funcs->crtc_begin(dc, output);
+}
+
+static void vs_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_atomic_commit *state)
+{
+ struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
+ struct vs_dc *dc = vcrtc->dc;
+ unsigned int output = vcrtc->id;
+
+ if (dc->funcs->crtc_flush)
+ dc->funcs->crtc_flush(dc, output);
+
+ drm_crtc_vblank_atomic_flush(crtc, state);
+}
+
static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_atomic_commit *state)
{
@@ -30,6 +53,9 @@ static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
drm_crtc_vblank_off(crtc);
clk_disable_unprepare(dc->pix_clk[output]);
+
+ if (dc->funcs->crtc_disable)
+ dc->funcs->crtc_disable(dc, output);
}
static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
@@ -42,6 +68,9 @@ static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
drm_WARN_ON(&dc->drm_dev->base,
clk_prepare_enable(dc->pix_clk[output]));
+ if (dc->funcs->crtc_enable)
+ dc->funcs->crtc_enable(dc, output);
+
drm_crtc_vblank_on(crtc);
}
@@ -119,7 +148,8 @@ static bool vs_crtc_mode_fixup(struct drm_crtc *crtc,
}
static const struct drm_crtc_helper_funcs vs_crtc_helper_funcs = {
- .atomic_flush = drm_crtc_vblank_atomic_flush,
+ .atomic_begin = vs_crtc_atomic_begin,
+ .atomic_flush = vs_crtc_atomic_flush,
.atomic_enable = vs_crtc_atomic_enable,
.atomic_disable = vs_crtc_atomic_disable,
.mode_set_nofb = vs_crtc_mode_set_nofb,
@@ -132,7 +162,7 @@ static int vs_crtc_enable_vblank(struct drm_crtc *crtc)
struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_TOP_IRQ_EN, VSDC_TOP_IRQ_VSYNC(vcrtc->id));
+ dc->funcs->enable_vblank(dc, vcrtc->id);
return 0;
}
@@ -142,7 +172,7 @@ static void vs_crtc_disable_vblank(struct drm_crtc *crtc)
struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
struct vs_dc *dc = vcrtc->dc;
- regmap_clear_bits(dc->regs, VSDC_TOP_IRQ_EN, VSDC_TOP_IRQ_VSYNC(vcrtc->id));
+ dc->funcs->disable_vblank(dc, vcrtc->id);
}
static const struct drm_crtc_funcs vs_crtc_funcs = {
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c
index dad9967bc10b..c94957024189 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -8,9 +8,7 @@
#include <linux/of.h>
#include <linux/of_graph.h>
-#include "vs_crtc.h"
#include "vs_dc.h"
-#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#include "vs_hwdb.h"
@@ -33,7 +31,7 @@ static irqreturn_t vs_dc_irq_handler(int irq, void *private)
struct vs_dc *dc = private;
u32 irqs;
- regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &irqs);
+ irqs = dc->funcs->irq_handler(dc);
vs_drm_handle_irq(dc, irqs);
@@ -136,6 +134,8 @@ static int vs_dc_probe(struct platform_device *pdev)
dev_info(dev, "Found DC%x rev %x customer %x\n", dc->identity.model,
dc->identity.revision, dc->identity.customer_id);
+ dc->funcs = &vs_dc8200_funcs;
+
if (port_count > dc->identity.display_count) {
dev_err(dev, "too many downstream ports than HW capability\n");
ret = -EINVAL;
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.h b/drivers/gpu/drm/verisilicon/vs_dc.h
index ed1016f18758..45172c1a525c 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.h
+++ b/drivers/gpu/drm/verisilicon/vs_dc.h
@@ -14,6 +14,7 @@
#include <linux/reset.h>
#include <drm/drm_device.h>
+#include <drm/drm_plane.h>
#include "vs_hwdb.h"
@@ -22,6 +23,34 @@
struct vs_drm_dev;
struct vs_crtc;
+struct vs_dc;
+
+struct vs_dc_funcs {
+ /* Bridge: atomic_enable, atomic_disable */
+ void (*bridge_enable)(struct vs_dc *dc, unsigned int output);
+ void (*bridge_disable)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: atomic_begin, atomic_flush */
+ void (*crtc_begin)(struct vs_dc *dc, unsigned int output);
+ void (*crtc_flush)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: atomic_enable, atomic_disable */
+ void (*crtc_enable)(struct vs_dc *dc, unsigned int output);
+ void (*crtc_disable)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: enable_vblank, disable_vblank */
+ void (*enable_vblank)(struct vs_dc *dc, unsigned int output);
+ void (*disable_vblank)(struct vs_dc *dc, unsigned int output);
+
+ /* Primary plane: atomic_enable, atomic_disable, atomic_update */
+ void (*plane_enable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*plane_disable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*plane_update_ex)(struct vs_dc *dc, unsigned int output,
+ struct drm_plane_state *state);
+
+ /* IRQ handler */
+ u32 (*irq_handler)(struct vs_dc *dc);
+};
struct vs_dc {
struct regmap *regs;
@@ -33,6 +62,9 @@ struct vs_dc {
struct vs_drm_dev *drm_dev;
struct vs_chip_identity identity;
+ const struct vs_dc_funcs *funcs;
};
+extern const struct vs_dc_funcs vs_dc8200_funcs;
+
#endif /* _VS_DC_H_ */
diff --git a/drivers/gpu/drm/verisilicon/vs_dc8200.c b/drivers/gpu/drm/verisilicon/vs_dc8200.c
new file mode 100644
index 000000000000..db9e1b3cd903
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dc8200.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 Icenowy Zheng <uwu@icenowy.me>
+ */
+
+#include <linux/regmap.h>
+
+#include "vs_bridge_regs.h"
+#include "vs_dc.h"
+#include "vs_dc_top_regs.h"
+#include "vs_plane.h"
+#include "vs_primary_plane_regs.h"
+
+static void vs_dc8200_bridge_enable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
+ VSDC_DISP_PANEL_CONFIG_RUNNING);
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_MULTI_DISP_SYNC);
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_RUNNING(output));
+
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(output),
+ VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_bridge_disable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
+ VSDC_DISP_PANEL_CONFIG_RUNNING);
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_MULTI_DISP_SYNC |
+ VSDC_DISP_PANEL_START_RUNNING(output));
+
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(output),
+ VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_enable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_TOP_IRQ_EN,
+ VSDC_TOP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8200_disable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_TOP_IRQ_EN,
+ VSDC_TOP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8200_plane_commit(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_plane_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_FB_EN);
+ regmap_update_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_DISPLAY_ID_MASK,
+ VSDC_FB_CONFIG_EX_DISPLAY_ID(output));
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static void vs_dc8200_plane_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_FB_EN);
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static void vs_dc8200_plane_update_ex(struct vs_dc *dc, unsigned int output,
+ struct drm_plane_state *state)
+{
+ regmap_write(dc->regs, VSDC_FB_TOP_LEFT(output),
+ VSDC_MAKE_PLANE_POS(state->crtc_x, state->crtc_y));
+ regmap_write(dc->regs, VSDC_FB_BOTTOM_RIGHT(output),
+ VSDC_MAKE_PLANE_POS(state->crtc_x + state->crtc_w,
+ state->crtc_y + state->crtc_h));
+ regmap_write(dc->regs, VSDC_FB_BLEND_CONFIG(output),
+ VSDC_FB_BLEND_CONFIG_BLEND_DISABLE);
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static u32 vs_dc8200_irq_handler(struct vs_dc *dc)
+{
+ u32 irqs;
+
+ regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &irqs);
+ return irqs;
+}
+
+const struct vs_dc_funcs vs_dc8200_funcs = {
+ .bridge_enable = vs_dc8200_bridge_enable,
+ .bridge_disable = vs_dc8200_bridge_disable,
+ .enable_vblank = vs_dc8200_enable_vblank,
+ .disable_vblank = vs_dc8200_disable_vblank,
+ .plane_enable_ex = vs_dc8200_plane_enable_ex,
+ .plane_disable_ex = vs_dc8200_plane_disable_ex,
+ .plane_update_ex = vs_dc8200_plane_update_ex,
+ .irq_handler = vs_dc8200_irq_handler,
+};
diff --git a/drivers/gpu/drm/verisilicon/vs_primary_plane.c b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
index 1f2be41ae496..75bc36a078f7 100644
--- a/drivers/gpu/drm/verisilicon/vs_primary_plane.c
+++ b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
@@ -53,12 +53,6 @@ static int vs_primary_plane_atomic_check(struct drm_plane *plane,
return 0;
}
-static void vs_primary_plane_commit(struct vs_dc *dc, unsigned int output)
-{
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_COMMIT);
-}
-
static void vs_primary_plane_atomic_enable(struct drm_plane *plane,
struct drm_atomic_commit *atomic_state)
{
@@ -69,13 +63,8 @@ static void vs_primary_plane_atomic_enable(struct drm_plane *plane,
unsigned int output = vcrtc->id;
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_FB_EN);
- regmap_update_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_DISPLAY_ID_MASK,
- VSDC_FB_CONFIG_EX_DISPLAY_ID(output));
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->plane_enable_ex)
+ dc->funcs->plane_enable_ex(dc, output);
}
static void vs_primary_plane_atomic_disable(struct drm_plane *plane,
@@ -88,10 +77,8 @@ static void vs_primary_plane_atomic_disable(struct drm_plane *plane,
unsigned int output = vcrtc->id;
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_FB_EN);
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->plane_disable_ex)
+ dc->funcs->plane_disable_ex(dc, output);
}
static void vs_primary_plane_atomic_update(struct drm_plane *plane,
@@ -133,18 +120,11 @@ static void vs_primary_plane_atomic_update(struct drm_plane *plane,
regmap_write(dc->regs, VSDC_FB_STRIDE(output),
fb->pitches[0]);
- regmap_write(dc->regs, VSDC_FB_TOP_LEFT(output),
- VSDC_MAKE_PLANE_POS(state->crtc_x, state->crtc_y));
- regmap_write(dc->regs, VSDC_FB_BOTTOM_RIGHT(output),
- VSDC_MAKE_PLANE_POS(state->crtc_x + state->crtc_w,
- state->crtc_y + state->crtc_h));
regmap_write(dc->regs, VSDC_FB_SIZE(output),
VSDC_MAKE_PLANE_SIZE(state->crtc_w, state->crtc_h));
- regmap_write(dc->regs, VSDC_FB_BLEND_CONFIG(output),
- VSDC_FB_BLEND_CONFIG_BLEND_DISABLE);
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->plane_update_ex)
+ dc->funcs->plane_update_ex(dc, output, state);
}
static const struct drm_plane_helper_funcs vs_primary_plane_helper_funcs = {
--
2.43.0
^ permalink raw reply related
* [PATCH v2 2/4] drm/verisilicon: add model ID constants and DCU Lite chip identity
From: Joey Lu @ 2026-05-19 5:51 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260519055114.1886525-1-a0987203069@gmail.com>
Introduce symbolic constants VSDC_MODEL_DC8200 and VSDC_MODEL_DCU_LITE
to replace magic numbers in the hardware database and probe path.
Register the DCU Lite chip identity (model 0x0, revision 0x5560,
customer_id 0x305) in vs_chip_identities[], making the existing
vs_fill_chip_identity() path able to recognise Nuvoton MA35D1 hardware
purely through register reads.
Also add three register-level macros for forthcoming DCU Lite support:
- VSDC_DISP_IRQ_VSYNC(n) in vs_crtc_regs.h, for per-output VSYNC IRQ
bits used by the DCU Lite IRQ enable/status registers.
- VSDC_FB_CONFIG_ENABLE, VSDC_FB_CONFIG_VALID and VSDC_FB_CONFIG_RESET
in vs_primary_plane_regs.h, for the framebuffer enable and
commit-cycle bits used by the DCU Lite plane update path.
No behaviour change for existing DC8200 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/vs_crtc_regs.h | 1 +
drivers/gpu/drm/verisilicon/vs_hwdb.c | 16 ++++++++++++----
drivers/gpu/drm/verisilicon/vs_hwdb.h | 3 +++
.../gpu/drm/verisilicon/vs_primary_plane_regs.h | 3 +++
4 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/verisilicon/vs_crtc_regs.h b/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
index c7930e817635..d4da22b08cd5 100644
--- a/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
+++ b/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
@@ -54,6 +54,7 @@
#define VSDC_DISP_GAMMA_DATA(n) (0x1460 + 0x4 * (n))
#define VSDC_DISP_IRQ_STA 0x147C
+#define VSDC_DISP_IRQ_VSYNC(n) BIT(n)
#define VSDC_DISP_IRQ_EN 0x1480
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.c b/drivers/gpu/drm/verisilicon/vs_hwdb.c
index 09336af0900a..a25c4b16181d 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.c
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.c
@@ -90,7 +90,7 @@ static const struct vs_formats vs_formats_with_yuv444 = {
static struct vs_chip_identity vs_chip_identities[] = {
{
- .model = 0x8200,
+ .model = VSDC_MODEL_DC8200,
.revision = 0x5720,
.customer_id = ~0U,
@@ -98,7 +98,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.formats = &vs_formats_no_yuv444,
},
{
- .model = 0x8200,
+ .model = VSDC_MODEL_DC8200,
.revision = 0x5721,
.customer_id = 0x30B,
@@ -106,7 +106,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.formats = &vs_formats_no_yuv444,
},
{
- .model = 0x8200,
+ .model = VSDC_MODEL_DC8200,
.revision = 0x5720,
.customer_id = 0x310,
@@ -114,13 +114,21 @@ static struct vs_chip_identity vs_chip_identities[] = {
.formats = &vs_formats_with_yuv444,
},
{
- .model = 0x8200,
+ .model = VSDC_MODEL_DC8200,
.revision = 0x5720,
.customer_id = 0x311,
.display_count = 2,
.formats = &vs_formats_no_yuv444,
},
+ {
+ .model = VSDC_MODEL_DCU_LITE,
+ .revision = 0x5560,
+ .customer_id = 0x305,
+
+ .display_count = 1,
+ .formats = &vs_formats_no_yuv444,
+ },
};
int vs_fill_chip_identity(struct regmap *regs,
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.h b/drivers/gpu/drm/verisilicon/vs_hwdb.h
index 92192e4fa086..cca126bd2da5 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.h
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.h
@@ -9,6 +9,9 @@
#include <linux/regmap.h>
#include <linux/types.h>
+#define VSDC_MODEL_DC8200 0x8200
+#define VSDC_MODEL_DCU_LITE 0x0
+
struct vs_formats {
const u32 *array;
unsigned int num;
diff --git a/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h b/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
index cbb125c46b39..67d4b00f294e 100644
--- a/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
+++ b/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
@@ -16,6 +16,9 @@
#define VSDC_FB_STRIDE(n) (0x1408 + 0x4 * (n))
#define VSDC_FB_CONFIG(n) (0x1518 + 0x4 * (n))
+#define VSDC_FB_CONFIG_ENABLE BIT(0)
+#define VSDC_FB_CONFIG_VALID BIT(3)
+#define VSDC_FB_CONFIG_RESET BIT(4)
#define VSDC_FB_CONFIG_CLEAR_EN BIT(8)
#define VSDC_FB_CONFIG_ROT_MASK GENMASK(13, 11)
#define VSDC_FB_CONFIG_ROT(v) ((v) << 11)
--
2.43.0
^ permalink raw reply related
* [PATCH v2 1/4] dt-bindings: display: verisilicon,dc: generalize for single-output variants
From: Joey Lu @ 2026-05-19 5:51 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260519055114.1886525-1-a0987203069@gmail.com>
The existing schema assumes a fixed clock/reset topology and dual-output
port structure matching the DC8200 IP block. This prevents reuse for
single-output variants such as the Verisilicon DCU Lite used in the
Nuvoton MA35D1 SoC.
Rework the schema so that variant-specific constraints are expressed
via allOf/if-then-else:
- The thead,th1520-dc8200 compatible keeps its existing five-clock,
three-reset, dual-port requirements.
- A standalone verisilicon,dc compatible covers IPs whose identity is
discovered entirely through hardware registers; these have flexible
clock and reset counts, a single 'port' property, and no 'ports'
requirement.
Changes to the base schema:
- Replace the fixed clock/reset items lists with minItems/maxItems
ranges; variant sub-schemas tighten the constraints via if-then-else.
- Add a 'port' property (graph.yaml single-port alias) alongside the
existing 'ports', for single-output variants.
- Drop the unconditional 'ports' requirement; each if-branch enforces
its own port topology.
- Tighten additionalProperties to unevaluatedProperties to allow
per-variant schemas to add their own constraints cleanly.
- Fix a stray space in the port@0 description.
- Add a DT example for the generic verisilicon,dc compatible
(Nuvoton MA35D1 DCU Lite).
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
.../bindings/display/verisilicon,dc.yaml | 135 ++++++++++++++----
1 file changed, 108 insertions(+), 27 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
index 9dc35ab973f2..3a814c2e083e 100644
--- a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
+++ b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
@@ -14,10 +14,12 @@ properties:
pattern: "^display@[0-9a-f]+$"
compatible:
- items:
- - enum:
- - thead,th1520-dc8200
- - const: verisilicon,dc # DC IPs have discoverable ID/revision registers
+ oneOf:
+ - items:
+ - enum:
+ - thead,th1520-dc8200
+ - const: verisilicon,dc
+ - const: verisilicon,dc # DC IPs have discoverable ID/revision registers
reg:
maxItems: 1
@@ -26,32 +28,24 @@ properties:
maxItems: 1
clocks:
- items:
- - description: DC Core clock
- - description: DMA AXI bus clock
- - description: Configuration AHB bus clock
- - description: Pixel clock of output 0
- - description: Pixel clock of output 1
+ minItems: 2
+ maxItems: 5
clock-names:
- items:
- - const: core
- - const: axi
- - const: ahb
- - const: pix0
- - const: pix1
+ minItems: 2
+ maxItems: 5
resets:
- items:
- - description: DC Core reset
- - description: DMA AXI bus reset
- - description: Configuration AHB bus reset
+ minItems: 1
+ maxItems: 3
reset-names:
- items:
- - const: core
- - const: axi
- - const: ahb
+ minItems: 1
+ maxItems: 3
+
+ port:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Single video output port for single-output variants.
ports:
$ref: /schemas/graph.yaml#/properties/ports
@@ -59,7 +53,7 @@ properties:
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
- description: The first output channel , endpoint 0 should be
+ description: The first output channel, endpoint 0 should be
used for DPI format output and endpoint 1 should be used
for DP format output.
@@ -75,9 +69,75 @@ required:
- interrupts
- clocks
- clock-names
- - ports
-additionalProperties: false
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: thead,th1520-dc8200
+ then:
+ properties:
+ clocks:
+ items:
+ - description: DC Core clock
+ - description: DMA AXI bus clock
+ - description: Configuration AHB bus clock
+ - description: Pixel clock of output 0
+ - description: Pixel clock of output 1
+
+ clock-names:
+ items:
+ - const: core
+ - const: axi
+ - const: ahb
+ - const: pix0
+ - const: pix1
+
+ resets:
+ items:
+ - description: DC Core reset
+ - description: DMA AXI bus reset
+ - description: Configuration AHB bus reset
+
+ reset-names:
+ items:
+ - const: core
+ - const: axi
+ - const: ahb
+
+ required:
+ - ports
+
+ else:
+ properties:
+ clocks:
+ items:
+ - description: Bus clock that gates register access
+ - description: Pixel clock divider for display timing
+
+ clock-names:
+ items:
+ - const: core
+ - const: pix0
+
+ resets:
+ maxItems: 1
+ description:
+ Reset line for the display controller.
+
+ reset-names:
+ items:
+ - const: core
+
+ required:
+ - port
+
+ not:
+ required:
+ - ports
+
+unevaluatedProperties: false
examples:
- |
@@ -120,3 +180,24 @@ examples:
};
};
};
+
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/nuvoton,ma35d1-clk.h>
+ #include <dt-bindings/reset/nuvoton,ma35d1-reset.h>
+
+ display@40260000 {
+ compatible = "verisilicon,dc";
+ reg = <0x40260000 0x20000>;
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk DCU_GATE>, <&clk DCUP_DIV>;
+ clock-names = "core", "pix0";
+ resets = <&sys MA35D1_RESET_DISP>;
+ reset-names = "core";
+
+ port {
+ dpi_out: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
+ };
+ };
--
2.43.0
^ permalink raw reply related
* [PATCH v2 0/4] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support
From: Joey Lu @ 2026-05-19 5:51 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
This series adds support for the Verisilicon DCU Lite display controller
as integrated in the Nuvoton MA35D1 SoC.
The Verisilicon DC driver and its DT binding were originally written by
Icenowy Zheng <zhengxingda@iscas.ac.cn> for the T-Head TH1520 SoC, which
carries a DC8200 IP block. The present series builds on that foundation
with gratitude to Icenowy for the original work.
The DCU Lite is a different variant in the DC IP family. While the two
IPs share a broadly similar register layout, a number of differences
prevent the existing driver from working on the MA35D1 without
modification:
- No CONFIG_EX commit path: the DC8200 staging registers
(FB_CONFIG_EX, FB_TOP_LEFT, FB_BOTTOM_RIGHT, FB_BLEND_CONFIG,
PANEL_CONFIG_EX) are absent. The DCU Lite uses enable (bit 0) and
reset (bit 4) bits in FB_CONFIG for direct framebuffer updates, and
requires a per-frame VALID bit toggle (FB_CONFIG bit 3) to latch
configuration changes.
- No PANEL_START register: panel output begins when
PANEL_CONFIG.RUNNING is set; the DC8200 multi-display sync start
register at 0x1CCC does not exist.
- Different IRQ registers: DISP_IRQ_STA at 0x147C / DISP_IRQ_EN at
0x1480, versus the DC8200's TOP_IRQ_ACK at 0x0010 / TOP_IRQ_EN at
0x0014.
- Simpler clock topology: two clocks ("core" bus gate and "pix0" pixel
divider); no axi or ahb clocks required.
- Single display output: no per-output indexing beyond index 0 is
needed.
- Hardware-discoverable identity: the DCU Lite exposes chip identity
registers whose model field reads 0x0 (revision 0x5560,
customer_id 0x305), allowing the existing vs_fill_chip_identity()
path to identify the variant purely through register reads. No
separate OF compatible string is introduced.
Patch 1 generalises the verisilicon,dc DT binding to accommodate
variants with flexible clock/reset counts and a single output, using
allOf/if-then-else to keep per-variant constraints in-schema.
Patches 2-4 introduce the driver changes in three logical steps:
register-level constants and the DCU Lite chip identity table entry;
the vs_dc_funcs hardware ops table with DC8200 ops extracted into
vs_dc8200.c; and finally the DCU Lite ops in vs_dcu_lite.c with the
necessary Kconfig and clock-optionality changes.
All patches have been tested on Nuvoton MA35D1 hardware.
Changes from v1:
- Corrected "DC8000" to "DC8200" throughout (the existing supported
IP is DC8200, not DC8000).
- Dropped the separate nuvoton,ma35d1-dcu.yaml; variant constraints
are now expressed inline in verisilicon,dc.yaml via allOf/if-then-else.
The MA35D1 uses the generic "verisilicon,dc" compatible string.
- Replaced the vs_dc_info platform-data flags approach with a
vs_dc_funcs hardware ops table, giving cleaner per-variant dispatch
without scattering if/else branches across multiple files.
- DCU Lite variant is identified through hardware registers rather than
the OF match table.
- Series split from 2 patches to 4 for clearer logical progression.
- Renamed plane ops in vs_dc_funcs: plane_enable/disable to
plane_enable_ex/disable_ex, plane_update_ext to plane_update_ex.
Joey Lu (4):
dt-bindings: display: verisilicon,dc: generalize for single-output
variants
drm/verisilicon: add model ID constants and DCU Lite chip identity
drm/verisilicon: introduce per-variant hardware ops table
drm/verisilicon: add Nuvoton MA35D1 DCU Lite display controller
support
.../bindings/display/verisilicon,dc.yaml | 135 ++++++++++++++----
drivers/gpu/drm/verisilicon/Kconfig | 2 +-
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_bridge.c | 20 +--
drivers/gpu/drm/verisilicon/vs_crtc.c | 38 ++++-
drivers/gpu/drm/verisilicon/vs_crtc_regs.h | 1 +
drivers/gpu/drm/verisilicon/vs_dc.c | 13 +-
drivers/gpu/drm/verisilicon/vs_dc.h | 33 +++++
drivers/gpu/drm/verisilicon/vs_dc8200.c | 107 ++++++++++++++
drivers/gpu/drm/verisilicon/vs_dcu_lite.c | 78 ++++++++++
drivers/gpu/drm/verisilicon/vs_hwdb.c | 16 ++-
drivers/gpu/drm/verisilicon/vs_hwdb.h | 3 +
.../gpu/drm/verisilicon/vs_primary_plane.c | 32 +----
.../drm/verisilicon/vs_primary_plane_regs.h | 3 +
14 files changed, 398 insertions(+), 85 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8200.c
create mode 100644 drivers/gpu/drm/verisilicon/vs_dcu_lite.c
--
2.43.0
^ 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