Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [GIT PULL] SoC fixes for 7.2
From: Arnd Bergmann @ 2026-07-17 15:36 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, linux-arm-kernel, soc

The following changes since commit 8cdeaa50eae8dad34885515f62559ee83e7e8dda:

  Linux 7.2-rc2 (2026-07-05 14:44:06 -1000)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git tags/soc-fixes-7.2-1

for you to fetch changes up to 3d9855d114f0955d590420f5670152c1099c1638:

  Merge tag 'renesas-fixes-for-v7.2-tag1' of https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel into arm/fixes (2026-07-16 15:59:57 +0200)

----------------------------------------------------------------
SoC fixes for 7.2

There are only three devicetree fixes this time: one critical memory
corruption fix for Renesas and three minor corrections for Tegra.

The MAINTAINERS file is updated for a new maintainer of the CIX platform
and two address changes.

The rest is all driver fixes, mostly firmware:

 - multiple runtime issues in ARM SCMI and FF-A firmware code, dealing
   with error handling for corner cases in firmware.

 - multiple fixes for reset drivers, dealing with individual platform
   specific mistakes and more error handling

 - minor build and runtime fixes for the Tegra SoC drivers

----------------------------------------------------------------
Akhil R (1):
      arm64: tegra: Remove fallback compatible for GPCDMA

Arnd Bergmann (8):
      soc/tegra: pmc: fix #ifdef block in header
      Merge tag 'reset-fixes-for-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/pza/linux into arm/fixes
      Merge tag 'tegra-for-7.2-pmc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into arm/fixes
      Merge tag 'tegra-for-7.2-soc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into arm/fixes
      Merge tag 'tegra-for-7.2-arm64-dt-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into arm/fixes
      Merge tag 'tee-update-for-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/jenswi/linux-tee into arm/fixes
      Merge tag 'scmi-ffa-fixes-7.2' of https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/fixes
      Merge tag 'renesas-fixes-for-v7.2-tag1' of https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel into arm/fixes

Breno Leitao (1):
      soc/tegra: fuse: Fix spurious straps warning on SMCCC platforms

Christophe JAILLET (1):
      drm/tegra: Fix a strange error handling path

Gary Yang (1):
      MAINTAINERS: Update maintainer and git tree for CIX SoC

Geert Uytterhoeven (1):
      firmware: arm_scmi: Grammar s/may needed/may be needed/

Jens Wiklander (1):
      MAINTAINERS: .mailmap: update Jens Wiklander's email address

Marek Vasut (1):
      arm64: dts: renesas: ironhide: Describe inline ECC carveouts

Pushpendra Singh (1):
      firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context

Robby Cai (1):
      reset: imx7: Correct polarity of MIPI CSI resets on i.MX8MQ

Seth Forshee (1):
      firmware: arm_ffa: Respect firmware advertised RX/TX buffer size limits

Steve Dunnagan (1):
      firmware: arm_scmi: Use 64-bit division for clock rate rounding

Sudeep Holla (1):
      Merge branches 'for-next/scmi/fixes' and 'for-next/ffa/fixes'

Sumit Gupta (2):
      arm64: tegra: Fix CPU compatible string to cortex-a78ae on Tegra234
      arm64: tegra: Fix CPU1 node unit-address on Tegra264

Tanmay Kathpalia (1):
      dt-bindings: reset: altr: add COMBOPHY_RESET for Agilex5

Unnathi Chalicheemala (1):
      firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get()

Uwe Kleine-König (The Capable Hub) (1):
      ARM: Don't let ARMv5 platforms select USE_OF

Yixun Lan (2):
      reset: spacemit: k3: fix USB2 ahb reset
      MAINTAINERS: Update SpacemiT SoC git tree repository

Zhao Dongdong (1):
      reset: sunxi: fix memory region leak on ioremap failure

 .mailmap                                          |  1 +
 MAINTAINERS                                       | 12 +++----
 arch/arm/mach-ixp4xx/Kconfig                      |  1 -
 arch/arm/mach-pxa/Kconfig                         |  3 --
 arch/arm64/boot/dts/nvidia/tegra234.dtsi          | 24 ++++++-------
 arch/arm64/boot/dts/nvidia/tegra264.dtsi          |  4 +--
 arch/arm64/boot/dts/renesas/r8a78000-ironhide.dts | 41 +++++++++++++++++++++++
 drivers/firmware/arm_ffa/driver.c                 | 29 +++++++++++-----
 drivers/firmware/arm_scmi/Kconfig                 |  4 +--
 drivers/firmware/arm_scmi/clock.c                 | 11 +++---
 drivers/firmware/arm_scmi/notify.c                |  6 ++--
 drivers/gpu/drm/tegra/sor.c                       |  6 ++--
 drivers/reset/reset-imx7.c                        |  6 ++++
 drivers/reset/reset-sunxi.c                       |  4 ++-
 drivers/reset/spacemit/reset-spacemit-k3.c        |  2 +-
 drivers/soc/tegra/fuse/tegra-apbmisc.c            |  2 +-
 include/dt-bindings/reset/altr,rst-mgr-s10.h      |  2 +-
 include/soc/tegra/pmc.h                           |  5 ++-
 18 files changed, 113 insertions(+), 50 deletions(-)


^ permalink raw reply

* Re: [PATCH v6 0/3] Add support for Variscite VAR-SOM-MX8QM and Symphony board
From: Frank.Li @ 2026-07-17 15:32 UTC (permalink / raw)
  To: linux-kernel, devicetree, imx, linux-arm-kernel, Stefano Radaelli
  Cc: Frank Li, pierluigi.p, Stefano Radaelli, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Shawn Guo, Daniel Baluta,
	Josua Mayer, Alexander Stein, Ernest Van Hoecke, Maud Spierings,
	Francesco Dolcini, Hugo Villeneuve
In-Reply-To: <cover.1784284092.git.stefano.r@variscite.com>

From: Frank Li <Frank.Li@nxp.com>


On Fri, 17 Jul 2026 12:29:36 +0200, Stefano Radaelli wrote:
> This patch series adds support for the Variscite VAR-SOM-MX8 QuadMax
> system on module and the Symphony carrier board.
> 
> The series includes:
> - SOM device tree with on-module peripherals
> - Symphony carrier board device tree with board-specific features
> 
> [...]

Applied, thanks!

[1/3] dt-bindings: arm: fsl: add Variscite VAR-SOM-MX8 QuadMax Boards
      commit: 4a3f4d08f53242dd6524285fd37c01886aacd0bc
[2/3] arm64: dts: freescale: Add support for Variscite VAR-SOM-MX8 QuadMax
      commit: 868ced4df4ef1169802c400a685820f2f1fc059b
[3/3] arm64: dts: imx8qm-var-som: Add support for Variscite Symphony board
      commit: a40fdbf706cc643671e41b9ac2f9ec3a832e769e

Best regards,
-- 
Frank Li <Frank.Li@nxp.com>


^ permalink raw reply

* Re: [RFC PATCH v1 8/8] misc/arm-cla: Add userspace interface
From: Arnd Bergmann @ 2026-07-17 15:31 UTC (permalink / raw)
  To: Ryan Roberts, Greg Kroah-Hartman, Catalin Marinas, Will Deacon,
	Mark Rutland, Jean-Philippe Brucker, Oded Gabbay, Jonathan Corbet
  Cc: linux-kernel, linux-arm-kernel, dri-devel, linux-doc
In-Reply-To: <5012970d-a0f0-461c-b0b6-61823e0aab2d@arm.com>

On Fri, Jul 17, 2026, at 16:35, Ryan Roberts wrote:
> On 17/07/2026 13:54, Arnd Bergmann wrote:
>> On Fri, Jul 17, 2026, at 12:47, Ryan Roberts wrote:
>>> Expose CLA devices through a character device so userspace can enumerate
>>> the available hardware and map accelerator register frames.
>>>
>>> Define version 1 of the CLA UAPI with a GET_PARAM ioctl. Report device
>>> topology, CPU affinity, domain membership, mmap offsets, architecture
>>> version and attached accelerator masks, together with the IIDR, DEVARCH
>>> and REVIDR of each accelerator.
>>>
>>> CLA registers can only be read from the CPU local to the device, while
>>> enumeration may occur on any CPU. Validate the supported CLA
>>> architecture version during device setup and cache the CLA and
>>> accelerator identification registers for later ioctl queries.
>> 
>> This interface looks very raw at the moment, I expect this will have
>> one or more larger redesigns.
>
> Are you referring to the overall UABI or specifically to the ioctl interface
> here? I could imagine the ioctl interface evolving before we get this merged
> (although it is based on similar patterns used by some DRM and accel drivers -
> it's intended to be easily extensible while existing params remain stable).
>
> The aspect where the CLA MMIO is directly mapped into user space is an aspect we
> are keen to keep though since it has significant performance implications if we
> need to redirect through the kernel.

I see no problem with having a per-accelerator VM area for MMIO
operations mapped to userspace, this is obviously part of all
designs like this one that sneak custom coprocessor instructions
in by disguising them as MMIO.

My concern is about how userspace gets to that mapping, both
the chardev itself, but also the ioctls.

>> Most importantly, a single character device to expose an arbitrary
>> number of underlying hardware features is an inherently flawed security
>> model. If any specific accelerator is ever found to have a
>> major vulnerability, that would mean administrators will have to
>> disable all of them by default.
>
> Note that we are exposing MMIO per CLA, not per accelerator. So preventing
> access to a single CLA would prevent access to all accelerators attached to it.
> There is a per-accelerator availability masking control that the kernel can use
> to disable access to selected accelerators though, which might help with the
> vulnerability example.
>
> The rationale for choosing a single device file was driven by performance: At
> domain reassignment time, we need to unmap and invalidate the TLB entries for
> all the devices in the domain from the out-going process's address space. By
> having all the devices in a single file and all devices within the same domain
> adjacent, they can all be mapped to a single VMA, meaning the driver can use a
> single call to the existing zap_special_vma_range(), which will result in a
> single TLBI-by-range instruction, which is faster than a TLBI-by-va for every
> device.
>
> If you think it is important for security to have each CLA exposed by an
> independent device file, I'll take another look.

Without concrete implementation examples, I find it hard to imagine
how granular the CLA and accelerator blocks are. What I'm interested
in is separating things into special character devices when they
refer to units that you want to manage separately in userspace.

If you have e.g. one accelerator for tensor operations and one for
handling gzip, I would very much want to see those have a separate
chardev nodes so a local administrator can give permissions to each
one separately, and have device names that are sensible to the
functionality underneath.

If you have separate accelerators for AES encryption and decryption,
or a large set of identical accelerators that can run concurrently,
those would of course get managed as a single device file.

Most importantly, I don't think a global /dev/cla device node
is a sensible interface from a management perspective as that
would give unprivileged userspace direct control to something
that is essentially arbitrary (or buggy) vendor firmware
with DMA permissions.

>>> Support shared read-write mmap of one or more CLA register pages. Create
>>> a context for every domain covered by the mapping and resolve faults
>>> only while that context owns the domain. Queue unassigned contexts with
>>> the domain scheduler, drop mmap_lock while waiting for assignment and
>>> retry the fault after the context is woken.
>> 
>> I still need some time to better understand what this means.
>
> I can probably do a better job of explaining this: The kernel keeps a cla_ctx
> object which represents a single {file description, mm_struct} context that
> wants to use the cla_domain (collection of 1 or more cla_dev). Initially the VMA
> is not populated so when user space tries to access, it will fault to the
> driver. If the cla_domain is assigned to a different cla_ctx, the faulting
> thread is put to sleep until the driver determines that it's the turn of that
> cla_ctx to be assigned the domain. At that point the waiting thread(s) are woken
> and map the devices from the domain to the VMA and return to user space. The
> out-going cla_ctx had it's mappings removed during the reassignment process so
> any user space access will now fault and sleep waiting for assignment.

Got it, thanks

>> Does a CPU have multiple concurrently running contexts? 
>
> The HW only has a single HW context, hence the timesliced assignment approach
> described above (assuming there is more than 1 concurrent user).

Sorry, I think we have a clash of terminology. I meant whether
a CPU can start multiple operations on one or more accelerator
in a single cla_domain, and have each of those operate at the
same time while the hardware is asynchronously processing them
in parallel.

It sounds like a single accelerator has one register to wait for
completion and can only have single operation in progress at any
time, but if multiple accelerators are in the same cla_ctx,
can a single thread start an operation in each one before waiting
for the first to complete?

>> Is a
>> user process able to starve the allocation of other processes
>> by just requesting a lot of them?
>
> In the current code, a process can theoretically create the same number of
> cla_ctx as the number of file descriptors it can open(). It would then need to
> mmap and access to get into the queue to be assigned the domain. I see it as
> similar to threads; if process A creates 10 threads and process B creates 1
> thread, then in the long run (ignoring cgroups et al) you'd expect A to get
> 10/11th of the CPU time (IIUC?).
>
> Do you think this consitutes a DoS?

I need to think about it more. Probably not a DoS, but if the resource
is managed like CPU timeslices, I wonder whether you'd have to also
consider things like realtime tasks or priority inversion.
 
>>> +	wait_event_interruptible(ctx->waitq,
>>> +				 READ_ONCE(domain->assigned_ctx) == ctx ||
>>> +				 cla_ctx_is_dying(ctx) ||
>>> +				 READ_ONCE(domain->broken));
>> 
>> If you call wait_event_interruptible(), you have to check the return
>> code and deal with it being interrupted.
>
> I believe this is already correct - I'm reeturning VM_FAULT_RETRY
> unconditionally at this point, which is also the correct return code if we get
> interrupted. This unwinds to arm64's do_page_fault() which then notices and
> handles the fault:
>
> 	/* Quick path to respond to signals */
> 	if (fault_signal_pending(fault, regs)) {
> 		if (!user_mode(regs))
> 			goto no_context;
> 		return 0;
> 	}

Ok, makes sense.

> I believe GUP and other handle_mm_fault() callers have similar logic.
>
> I'll add a comment to make that clear.

Thanks

   Arnd


^ permalink raw reply

* Re: [PATCH v3] media: rkvdec: fix clk reference leak on unbind
From: Nicolas Dufresne @ 2026-07-17 15:29 UTC (permalink / raw)
  To: Francesco Saverio Pavone, jonas, detlev.casanova, hverkuil,
	mchehab
  Cc: ezequiel, heiko, linux-media, linux-rockchip, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260717150440.77079-1-pavone.lawyer@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 6942 bytes --]

Hi Francesco,


This was sent as a reply to v2, best practice is that new version should be its
own thread. This convention is best for patchwork tracking and other tools.

cheers,
Nicolas

Le vendredi 17 juillet 2026 à 17:04 +0200, Francesco Saverio Pavone a écrit :
> From: Jonas Karlman <jonas@kwiboo.se>
> 
> remove() calls pm_runtime_disable() before
> pm_runtime_dont_use_autosuspend(), so the second call can never suspend
> the device: it reaches rpm_idle(), which returns -EACCES once PM runtime
> is disabled. The probe error path has had the two the other way round
> since the driver was merged.
> 
> This shows up when the device is unbound while the 100ms autosuspend
> window is still open, which is what an rmmod right after a decode does.
> device_release_driver() calls pm_runtime_put_sync() before .remove(),
> and rpm_idle() adds RPM_AUTO on its own, so that put only arms the
> autosuspend timer. pm_runtime_disable() then cancels the timer, and
> pm_runtime_reinit() relabels the device suspended without calling the
> driver back. The clk_bulk reference taken by rkvdec_runtime_resume() is
> never dropped, and a later probe does not reclaim it, so every such
> unbind leaks one enable count.
> 
> Drop autosuspend first, so the callback still runs and releases the
> clocks.
> 
> The PM calls also have to move ahead of rkvdec_v4l2_cleanup() rather
> than just swap with each other. rkvdec_runtime_suspend() looks its state
> up with dev_get_drvdata(), and v4l2_device_unregister() clears it:
> struct rkvdec_dev has v4l2_device as its first member, so
> &rkvdec->v4l2_dev and rkvdec are the same address and the check in
> v4l2_device_disconnect() matches. That is harmless today because
> pm_runtime_disable() suppresses the callback, but once the callback can
> run, a suspend after the V4L2 teardown dereferences NULL. Swapping only
> the two PM calls oopses on every unbind.
> 
> Fixes: cd33c830448b ("media: rkvdec: Add the rkvdec driver")
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
> [fsp: wrote the commit message; the diff is unchanged]
> Tested-by: Francesco Saverio Pavone <pavone.lawyer@gmail.com>
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Francesco Saverio Pavone <pavone.lawyer@gmail.com>
> ---
> Changes in v3:
>  - Rewrote the commit message, and dropped the VP9 claim from v1 and v2.
>    Those said this fixed a VP9 inter-prediction bug on RK3588, green chroma
>    from the second ALTREF frame onward. The bug is real, but this is not
>    what fixes it, and I should have established that before sending v1.
> 
>    What happened: I took this patch out of chewitt's tree along with two
>    others and tested the three as a batch. The green is fixed by "media:
>    rkvdec: implement reset controls" from Alex Bee, which adds the
>    reset_control handling that recovers the VDPU381 after a transient error
>    (COLMV_REF_ERR_STA and friends) instead of leaving it dirty for the next
>    inter frame. Randy Li's PMU idle export goes with it. This patch was the
>    third one in that batch and got the credit.
> 
>    Retested this week on the same Rock 5B+ with an unpatched driver: a VP9
>    Profile 0 1080p clip with alt-ref frames decodes byte-identical to the
>    libvpx reference, across five rmmod/insmod cycles and after an unbind
>    inside the autosuspend window. The green does not come back, because the
>    reset_control work is in the tree I test on. Sorry for the review and the
>    testing you spent on that basis.
> 
>  - Worth flagging separately: mainline rkvdec has no reset_control support
>    at all, so the VDPU381 is never recovered after a transient error. That
>    is a real gap, it is just not this patch. I can write it up properly if
>    that is useful.
> 
>  - The diff is unchanged from v1 and v2. It is Jonas's 2020 commit verbatim,
>    and his original one-line subject already described exactly what it does.
>    The wrong story was mine, not his.
> 
>  - The subject changed with the message: "media: rkvdec: fix PM runtime
>    teardown ordering in remove" in v1 and v2, "media: rkvdec: fix clk
>    reference leak on unbind" here, since that is what it actually fixes.
> 
>  - What is left is measured. With a dev_info() at the top of
>    rkvdec_runtime_suspend(), autosuspend_delay raised to 60s to take the
>    timer out of the race, and unbind driven through sysfs:
>        unpatched: 0 suspend callbacks, aclk_rkvdec0 enable_count 1 -> 2
>        patched:   1 suspend callback,  enable_count 1 -> 1
>    The leak survives rmmod and accumulates one per unbind. With
>    autosuspend_delay=0 both orders suspend once, which is the control: the
>    difference only exists inside the window.
> 
>  - Fixes: was wrong in v1 and v2. ff8c5622f9f7 has the two pm_runtime calls
>    as context and only added iommu_domain_free(). cd33c830448b added remove()
>    with the reversed order, and the probe error path with the right one, so
>    the tag points there now.
> 
>  - Dropped Cc: stable. A clk reference leaked on unbind is not backport
>    material, and the tag was only there for the VP9 claim.
> 
>  - Dropped your Reviewed-by and Tested-by from v2: they were given for a fix
>    to something else.
> 
>  - Not included, happy to send as follow-ups: clearing empty_domain after
>    iommu_domain_free(), and hoisting the unregisters to the top of remove()
>    as you suggested on v2.
> 
> Tested on a Radxa Rock 5B+ (RK3588) on a 7.1 tree where the six calls in
> rkvdec_v4l2_cleanup() are open-coded; the executed sequence is the one this
> patch produces. VP9 decode stays byte-identical to libvpx, and five
> rmmod/insmod cycles leave dmesg clean.
> 
> Link to v1:
> https://lore.kernel.org/all/20260518105413.42147-1-pavone.lawyer@gmail.com/
> Link to v2:
> https://lore.kernel.org/all/20260518145414.64514-1-pavone.lawyer@gmail.com/
>  drivers/media/platform/rockchip/rkvdec/rkvdec.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> index 1d1e9bfef8e9..0ec3fca9cccc 100644
> --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
> @@ -1869,12 +1869,13 @@ static void rkvdec_remove(struct platform_device
> *pdev)
>  
>  	cancel_delayed_work_sync(&rkvdec->watchdog_work);
>  
> -	rkvdec_v4l2_cleanup(rkvdec);
> -	pm_runtime_disable(&pdev->dev);
>  	pm_runtime_dont_use_autosuspend(&pdev->dev);
>  
>  	if (rkvdec->empty_domain)
>  		iommu_domain_free(rkvdec->empty_domain);
> +
> +	pm_runtime_disable(&pdev->dev);
> +	rkvdec_v4l2_cleanup(rkvdec);
>  }
>  
>  #ifdef CONFIG_PM

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* [PATCH v5 4/4] clk: sunxi-ng: sun6i-rtc: add a733 support
From: Jerome Brunet @ 2026-07-17 15:24 UTC (permalink / raw)
  To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Michael Turquette, Stephen Boyd, Maxime Ripard
  Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260717-a733-rtc-v5-0-3874cc26abf7@baylibre.com>

Add support for the sun60i a733 CCU RTC.

Compared to the a523, this SoC has a different input oscillator divider
which auto-detects the oscillator rate and select a divider to provide
a fixed 32768Hz clock. It also provides several phy reference clocks
with dedicated clock gates.

Reviewed-by: Chen-Yu Tsai <wens@kernel.org>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 77 ++++++++++++++++++++++++++++++++++--
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.h |  2 +-
 2 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index 25dd87e78eb7..98ae10307f43 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -44,9 +44,15 @@
 #define DCXO_CTRL_REG			0x160
 #define DCXO_CTRL_CLK16M_RC_EN		BIT(0)
 
+#define DCXO_GATING_REG			0x16c
+
+#define CLK_NUMBER_NO_GATES		(CLK_OSC24M_32K_DIV + 1)
+
 struct sun6i_rtc_match_data {
 	bool				have_ext_osc32k		: 1;
 	bool				have_iosc_calibration	: 1;
+	bool				have_dcxo_status	: 1;
+	bool				have_phy_ref_gates	: 1;
 	bool				rtc_32k_single_parent	: 1;
 	const struct clk_parent_data	*osc32k_fanout_parents;
 	u8				osc32k_fanout_nparents;
@@ -213,7 +219,12 @@ static struct ccu_mux osc32k_clk = {
 	},
 };
 
-/* This falls back to the global name for fwnodes without a named reference. */
+/*
+ * This falls back to the global name for fwnodes without a named reference.
+ * NOTE: osc24M name might be misleading the oscillator could also be a 26MHz
+ * or a 19.2MHz one starting with the a733. The original name is kept anyway
+ * in case anything is relying on it.
+ */
 static const struct clk_parent_data osc24M[] = {
 	{ .fw_name = "hosc", .name = "osc24M" }
 };
@@ -227,8 +238,30 @@ static struct clk_fixed_factor osc24M_32k_div_clk = {
 					    0),
 };
 
-static SUNXI_CCU_GATE_HW(osc24M_32k_clk, "osc24M-32k", &osc24M_32k_div_clk.hw,
-			 LOSC_OUT_GATING_REG, BIT(16), 0);
+static struct clk_div_table osc24M_32k_div_a733_table[] = {
+	{ .val = 0, .div = 732 },
+	{ .val = 1, .div = 586 },
+	{ .val = 2, .div = 793 },
+	{ .val = 3, .div = 732 },
+	{ /* Sentinel */ },
+};
+
+static struct ccu_div osc24M_32k_div_a733_clk = {
+	.enable = BIT(1),
+	.div	= _SUNXI_CCU_DIV_TABLE_FLAGS(14, 2,
+					     osc24M_32k_div_a733_table,
+					     CLK_DIVIDER_READ_ONLY),
+	.common	= {
+		.reg		= DCXO_CTRL_REG,
+		.hw.init	= CLK_HW_INIT_PARENTS_DATA("osc24M-32k-div",
+							   osc24M,
+							   &ccu_rodiv_ops,
+							   0),
+	},
+};
+
+static SUNXI_CCU_GATE(osc24M_32k_clk, "osc24M-32k", "osc24M-32k-div",
+		      LOSC_OUT_GATING_REG, BIT(16), 0);
 
 static const struct clk_hw *rtc_32k_parents[] = {
 	&osc32k_clk.common.hw,
@@ -267,6 +300,15 @@ static struct ccu_mux osc32k_fanout_clk = {
 	},
 };
 
+static SUNXI_CCU_GATE_FW(hosc_serdes1_clk, "hosc-serdes1", "hosc",
+		      DCXO_GATING_REG, BIT(5), 0);
+static SUNXI_CCU_GATE_FW(hosc_serdes0_clk, "hosc-serdes0", "hosc",
+		      DCXO_GATING_REG, BIT(4), 0);
+static SUNXI_CCU_GATE_FW(hosc_hdmi_clk, "hosc-hdmi", "hosc",
+		      DCXO_GATING_REG, BIT(1), 0);
+static SUNXI_CCU_GATE_FW(hosc_ufs_clk, "hosc-ufs", "hosc",
+		      DCXO_GATING_REG, BIT(0), 0);
+
 static struct ccu_common *sun6i_rtc_ccu_clks[] = {
 	&iosc_clk,
 	&iosc_32k_clk,
@@ -275,6 +317,11 @@ static struct ccu_common *sun6i_rtc_ccu_clks[] = {
 	&osc24M_32k_clk.common,
 	&rtc_32k_clk.common,
 	&osc32k_fanout_clk.common,
+	&osc24M_32k_div_a733_clk.common,
+	&hosc_serdes1_clk.common,
+	&hosc_serdes0_clk.common,
+	&hosc_hdmi_clk.common,
+	&hosc_ufs_clk.common,
 };
 
 static struct clk_hw_onecell_data sun6i_rtc_ccu_hw_clks = {
@@ -288,6 +335,10 @@ static struct clk_hw_onecell_data sun6i_rtc_ccu_hw_clks = {
 		[CLK_OSC24M_32K]	= &osc24M_32k_clk.common.hw,
 		[CLK_RTC_32K]		= &rtc_32k_clk.common.hw,
 		[CLK_OSC24M_32K_DIV]	= &osc24M_32k_div_clk.hw,
+		[CLK_HOSC_UFS]		= &hosc_ufs_clk.common.hw,
+		[CLK_HOSC_HDMI]		= &hosc_hdmi_clk.common.hw,
+		[CLK_HOSC_SERDES0]	= &hosc_serdes0_clk.common.hw,
+		[CLK_HOSC_SERDES1]	= &hosc_serdes1_clk.common.hw,
 	},
 };
 
@@ -330,6 +381,15 @@ static const struct sun6i_rtc_match_data sun55i_a523_rtc_ccu_data = {
 	.osc32k_fanout_nparents	= ARRAY_SIZE(sun50i_r329_osc32k_fanout_parents),
 };
 
+static const struct sun6i_rtc_match_data sun60i_a733_rtc_ccu_data = {
+	.have_ext_osc32k	= true,
+	.have_iosc_calibration	= true,
+	.have_dcxo_status	= true,
+	.have_phy_ref_gates	= true,
+	.osc32k_fanout_parents	= sun50i_r329_osc32k_fanout_parents,
+	.osc32k_fanout_nparents	= ARRAY_SIZE(sun50i_r329_osc32k_fanout_parents),
+};
+
 static const struct of_device_id sun6i_rtc_ccu_match[] = {
 	{
 		.compatible	= "allwinner,sun50i-h616-rtc",
@@ -343,6 +403,10 @@ static const struct of_device_id sun6i_rtc_ccu_match[] = {
 		.compatible	= "allwinner,sun55i-a523-rtc",
 		.data		= &sun55i_a523_rtc_ccu_data,
 	},
+	{
+		.compatible	= "allwinner,sun60i-a733-rtc",
+		.data		= &sun60i_a733_rtc_ccu_data,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, sun6i_rtc_ccu_match);
@@ -375,6 +439,13 @@ int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
 	osc32k_fanout_init_data.parent_data = data->osc32k_fanout_parents;
 	osc32k_fanout_init_data.num_parents = data->osc32k_fanout_nparents;
 
+	if (data->have_dcxo_status)
+		sun6i_rtc_ccu_hw_clks.hws[CLK_OSC24M_32K_DIV] =
+			&osc24M_32k_div_a733_clk.common.hw;
+
+	if (!data->have_phy_ref_gates)
+		sun6i_rtc_ccu_hw_clks.num = CLK_NUMBER_NO_GATES;
+
 	return devm_sunxi_ccu_probe(dev, reg, &sun6i_rtc_ccu_desc);
 }
 
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
index ab7b92b47f59..4f4f4cb00f1d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
@@ -11,6 +11,6 @@
 #define CLK_RTC_32K		6
 #define CLK_OSC24M_32K_DIV	7
 
-#define CLK_NUMBER		(CLK_OSC24M_32K_DIV + 1)
+#define CLK_NUMBER		(CLK_HOSC_SERDES1 + 1)
 
 #endif /* _CCU_SUN6I_RTC_H */

-- 
2.47.3



^ permalink raw reply related

* [PATCH v5 3/4] clk: sunxi-ng: sun6i-rtc: split main oscillator div and gate.
From: Jerome Brunet @ 2026-07-17 15:24 UTC (permalink / raw)
  To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Michael Turquette, Stephen Boyd, Maxime Ripard
  Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260717-a733-rtc-v5-0-3874cc26abf7@baylibre.com>

On the a733 the "osc24M-32k" clock has the same gate bits as the previously
supported SoC but a different divider implementation.

Instead of a fixed 750 divider, the divider is selected based on the
rate of the oscillator. It can be seen as a simple read-only divider.

On the A733 the gate and the divider are on different register which is
not supported by sunxi combined clocks. These element will be split on the
A733. Split them for the older SoC as well to keep on sharing the gate
definition.

Reviewed-by: Chen-Yu Tsai <wens@kernel.org>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 20 +++++++++++---------
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.h |  3 ++-
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index b24c8b196e66..25dd87e78eb7 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -218,17 +218,18 @@ static const struct clk_parent_data osc24M[] = {
 	{ .fw_name = "hosc", .name = "osc24M" }
 };
 
-static struct ccu_gate osc24M_32k_clk = {
-	.enable	= BIT(16),
-	.common	= {
-		.reg		= LOSC_OUT_GATING_REG,
-		.prediv		= 750,
-		.features	= CCU_FEATURE_ALL_PREDIV,
-		.hw.init	= CLK_HW_INIT_PARENTS_DATA("osc24M-32k", osc24M,
-							   &ccu_gate_ops, 0),
-	},
+static struct clk_fixed_factor osc24M_32k_div_clk = {
+	.mult = 1,
+	.div = 750,
+	.hw.init = CLK_HW_INIT_PARENTS_DATA("osc24M-32k-div",
+					    osc24M,
+					    &clk_fixed_factor_ops,
+					    0),
 };
 
+static SUNXI_CCU_GATE_HW(osc24M_32k_clk, "osc24M-32k", &osc24M_32k_div_clk.hw,
+			 LOSC_OUT_GATING_REG, BIT(16), 0);
+
 static const struct clk_hw *rtc_32k_parents[] = {
 	&osc32k_clk.common.hw,
 	&osc24M_32k_clk.common.hw
@@ -286,6 +287,7 @@ static struct clk_hw_onecell_data sun6i_rtc_ccu_hw_clks = {
 		[CLK_EXT_OSC32K_GATE]	= &ext_osc32k_gate_clk.common.hw,
 		[CLK_OSC24M_32K]	= &osc24M_32k_clk.common.hw,
 		[CLK_RTC_32K]		= &rtc_32k_clk.common.hw,
+		[CLK_OSC24M_32K_DIV]	= &osc24M_32k_div_clk.hw,
 	},
 };
 
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
index 9ae821fc2599..ab7b92b47f59 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
@@ -9,7 +9,8 @@
 #define CLK_EXT_OSC32K_GATE	4
 #define CLK_OSC24M_32K		5
 #define CLK_RTC_32K		6
+#define CLK_OSC24M_32K_DIV	7
 
-#define CLK_NUMBER		(CLK_RTC_32K + 1)
+#define CLK_NUMBER		(CLK_OSC24M_32K_DIV + 1)
 
 #endif /* _CCU_SUN6I_RTC_H */

-- 
2.47.3



^ permalink raw reply related

* [PATCH v5 2/4] clk: sunxi-ng: div: add read-only operation support
From: Jerome Brunet @ 2026-07-17 15:24 UTC (permalink / raw)
  To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Michael Turquette, Stephen Boyd, Maxime Ripard
  Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260717-a733-rtc-v5-0-3874cc26abf7@baylibre.com>

Add support for sunxi-ng read-only dividers. This will be
useful to the a733 oscillator detection logic.

Reviewed-by: Chen-Yu Tsai <wens@kernel.org>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/sunxi-ng/ccu_div.c | 30 ++++++++++++++++++++++++++++--
 drivers/clk/sunxi-ng/ccu_div.h |  1 +
 drivers/clk/sunxi-ng/ccu_mux.c |  2 +-
 drivers/clk/sunxi-ng/ccu_mux.h |  4 ++++
 4 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c
index 62d680ccb524..93cb4cb93abe 100644
--- a/drivers/clk/sunxi-ng/ccu_div.c
+++ b/drivers/clk/sunxi-ng/ccu_div.c
@@ -20,8 +20,22 @@ static int ccu_div_determine_rate_helper(struct ccu_mux_internal *mux,
 	if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		req->rate *= cd->fixed_post_div;
 
-	ret = divider_determine_rate(&cd->common.hw, req, cd->div.table,
-				     cd->div.width, cd->div.flags);
+	if (cd->div.flags & CLK_DIVIDER_READ_ONLY) {
+		unsigned long val;
+		u32 reg;
+
+		reg = readl(cd->common.base + cd->common.reg);
+		val = reg >> cd->div.shift;
+		val &= (1 << cd->div.width) - 1;
+
+		ret = divider_ro_determine_rate(&cd->common.hw, req, cd->div.table,
+						cd->div.width, cd->div.flags, val);
+
+	} else {
+		ret = divider_determine_rate(&cd->common.hw, req, cd->div.table,
+					     cd->div.width, cd->div.flags);
+	}
+
 	if (ret)
 		return ret;
 
@@ -143,3 +157,15 @@ const struct clk_ops ccu_div_ops = {
 	.set_rate	= ccu_div_set_rate,
 };
 EXPORT_SYMBOL_NS_GPL(ccu_div_ops, "SUNXI_CCU");
+
+const struct clk_ops ccu_rodiv_ops = {
+	.disable	= ccu_div_disable,
+	.enable		= ccu_div_enable,
+	.is_enabled	= ccu_div_is_enabled,
+
+	.get_parent	= ccu_div_get_parent,
+
+	.determine_rate	= ccu_div_determine_rate,
+	.recalc_rate	= ccu_div_recalc_rate,
+};
+EXPORT_SYMBOL_NS_GPL(ccu_rodiv_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_div.h b/drivers/clk/sunxi-ng/ccu_div.h
index be00b3277e97..a30a92780a05 100644
--- a/drivers/clk/sunxi-ng/ccu_div.h
+++ b/drivers/clk/sunxi-ng/ccu_div.h
@@ -300,5 +300,6 @@ static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
 }
 
 extern const struct clk_ops ccu_div_ops;
+extern const struct clk_ops ccu_rodiv_ops;
 
 #endif /* _CCU_DIV_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index 75ec3457324c..905570375711 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -67,7 +67,7 @@ unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common,
 	return parent_rate / ccu_mux_get_prediv(common, cm, parent_index);
 }
 
-static unsigned long ccu_mux_helper_unapply_prediv(struct ccu_common *common,
+unsigned long ccu_mux_helper_unapply_prediv(struct ccu_common *common,
 					    struct ccu_mux_internal *cm,
 					    int parent_index,
 					    unsigned long parent_rate)
diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
index c94a4bde5d01..272a2c36a8f2 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.h
+++ b/drivers/clk/sunxi-ng/ccu_mux.h
@@ -134,6 +134,10 @@ unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common,
 					  struct ccu_mux_internal *cm,
 					  int parent_index,
 					  unsigned long parent_rate);
+unsigned long ccu_mux_helper_unapply_prediv(struct ccu_common *common,
+					    struct ccu_mux_internal *cm,
+					    int parent_index,
+					    unsigned long parent_rate);
 int ccu_mux_helper_determine_rate(struct ccu_common *common,
 				  struct ccu_mux_internal *cm,
 				  struct clk_rate_request *req,

-- 
2.47.3



^ permalink raw reply related

* [PATCH v5 1/4] clk: sunxi-ng: mux: fix determine helper rate propagation
From: Jerome Brunet @ 2026-07-17 15:24 UTC (permalink / raw)
  To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Michael Turquette, Stephen Boyd, Maxime Ripard
  Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260717-a733-rtc-v5-0-3874cc26abf7@baylibre.com>

Applying the pre divider on the parent rate is wrong because, while
handling rate propagation through determine_rate(), the framework will
likely round the parent rate again while cycling through the possibilities,
throwing away the prediv applied. This means, the parent rate will then
be wrong when the prediv is unapplied from a parent rate on which it
was never applied to begin with.

The right way to do it is to unapply the prediv from the requested rate,
which is the wanted rate at the input on the clock element, and pass this
to framework to do its thing.

Change the determine rate mux helper in this way.

Fixes: 1c8d7af61b37 ("clk: sunxi-ng: convert from divider_round_rate_parent() to divider_determine_rate()")
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/sunxi-ng/ccu_mux.c | 56 ++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 29 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index 09230728c400..75ec3457324c 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -92,66 +92,64 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common,
 		struct clk_rate_request adj_req = *req;
 
 		best_parent = clk_hw_get_parent(hw);
-		best_parent_rate = clk_hw_get_rate(best_parent);
-
+		adj_req.best_parent_rate = clk_hw_get_rate(best_parent);
 		adj_req.best_parent_hw = best_parent;
-		adj_req.best_parent_rate = ccu_mux_helper_apply_prediv(common, cm, -1,
-								       best_parent_rate);
+
+		/*
+		 * This effectively treat the predivider as a postdivider.
+		 * It stays mathematically correct and ensure whatever
+		 * round() will do stays correct while walking the tree.
+		 * It may query the parent rate too while handling rate propagation
+		 */
+		adj_req.rate = ccu_mux_helper_unapply_prediv(common, cm, -1,
+							     req->rate);
 
 		ret = round(cm, &adj_req, data);
 		if (ret)
 			return ret;
 
-		best_rate = adj_req.rate;
-
 		/*
-		 * best_parent_rate might have been modified by our clock.
-		 * Unapply the pre-divider if there's one, and give
-		 * the actual frequency the parent needs to run at.
+		 * parent_rate might have been modified by our clock as part
+		 * of the rate propagation mechnanism. Same goes below.
 		 */
-		best_parent_rate = ccu_mux_helper_unapply_prediv(common, cm, -1,
-								 adj_req.best_parent_rate);
+		best_parent_rate = adj_req.best_parent_rate;
+		best_rate = ccu_mux_helper_apply_prediv(common, cm, -1,
+							adj_req.rate);
 
 		goto out;
 	}
 
 	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
 		struct clk_rate_request tmp_req = *req;
-		unsigned long parent_rate;
+		unsigned long rate;
 		struct clk_hw *parent;
 
 		parent = clk_hw_get_parent_by_index(hw, i);
 		if (!parent)
 			continue;
 
-		parent_rate = ccu_mux_helper_apply_prediv(common, cm, i,
-							  clk_hw_get_rate(parent));
-
 		tmp_req.best_parent_hw = parent;
-		tmp_req.best_parent_rate = parent_rate;
+		tmp_req.best_parent_rate = clk_hw_get_rate(parent);
+		tmp_req.rate = ccu_mux_helper_unapply_prediv(common, cm, i,
+							     req->rate);
 
 		ret = round(cm, &tmp_req, data);
 		if (ret)
 			continue;
 
-		/*
-		 * parent_rate might have been modified by our clock.
-		 * Unapply the pre-divider if there's one, and give
-		 * the actual frequency the parent needs to run at.
-		 */
-		parent_rate = ccu_mux_helper_unapply_prediv(common, cm, i,
-							    tmp_req.best_parent_rate);
+		rate = ccu_mux_helper_apply_prediv(common, cm, i,
+						   tmp_req.rate);
 
-		if (tmp_req.rate == req->rate) {
+		if (rate == req->rate) {
 			best_parent = parent;
-			best_parent_rate = parent_rate;
-			best_rate = tmp_req.rate;
+			best_parent_rate = tmp_req.best_parent_rate;
+			best_rate = rate;
 			goto out;
 		}
 
-		if (ccu_is_better_rate(common, req->rate, tmp_req.rate, best_rate)) {
-			best_rate = tmp_req.rate;
-			best_parent_rate = parent_rate;
+		if (ccu_is_better_rate(common, req->rate, rate, best_rate)) {
+			best_rate = rate;
+			best_parent_rate = tmp_req.best_parent_rate;
 			best_parent = parent;
 		}
 	}

-- 
2.47.3



^ permalink raw reply related

* [PATCH v5 0/4] clk: sun6i-rtc: Add support for Allwinner A733 SoC
From: Jerome Brunet @ 2026-07-17 15:24 UTC (permalink / raw)
  To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Michael Turquette, Stephen Boyd, Maxime Ripard
  Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, linux-clk, Jerome Brunet

Add support for the Allwinner A733 RTC and its internal Clock Control
Unit (CCU). Reuse the rtc-sun6i rtc driver while introducing a new
SoC-specific RTC CCU driver to handle the hardware's evolved clock
structure.

The A733 implementation supports hardware detection of three external
crystal frequencies (19.2MHz, 24MHz and 26MHz), which is represented in
the driver via read-only divider operations. Implement logic to derive a
normalized 32kHz reference from these DCXO sources using fixed
pre-dividers. Additionally, provide several new DCXO gate clocks for
peripherals, including SerDes, HDMI, and UFS.

This was tested on a Raxda Cubie A7A.

Changes in v5:
- Droped already applied changes
- Fix determine rate mux helper calculation
- Changed clock split commit description
- Added a macro for the clock number without gates
- Link to v4: https://patch.msgid.link/20260706-a733-rtc-v4-0-f330728db3d3@baylibre.com

Changes in v4:
- Remove unneeded export of mux prediv helpers
- Link to v3: https://patch.msgid.link/20260702-a733-rtc-v3-0-eb2580374de6@baylibre.com

Changes in v3:
- Disallow clock-output-names DT property for h616/r329 chips
- Fix ccu probe helper to properly unregister clocks on error
- Implement .determine_rate for ccu divider RO ops
- Drop unused DCXO_CTRL_REG_EN define
- Link to v2: https://patch.msgid.link/20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com

Changes in v2:
* Changed DT bindings as suggested. Those have changed significantly
  since v1 so I did not pick up Rob's review trailer
* Support added in the existing RTC CCU driver rather than a separate driver
* Added DT parsing clean up of the existing driver
* Xtal detection exposed by RO divider rather than a MUX.
* Dropped conversion to aux device for now. This is not strictly related
  the a733 support and will submitted again later on.
* Link to v1: https://lore.kernel.org/r/20260121-a733-rtc-v1-0-d359437f23a7@pigmoral.tech

---
Jerome Brunet (4):
      clk: sunxi-ng: mux: fix determine helper rate propagation
      clk: sunxi-ng: div: add read-only operation support
      clk: sunxi-ng: sun6i-rtc: split main oscillator div and gate.
      clk: sunxi-ng: sun6i-rtc: add a733 support

 drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 89 ++++++++++++++++++++++++++++++++----
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.h |  3 +-
 drivers/clk/sunxi-ng/ccu_div.c       | 30 +++++++++++-
 drivers/clk/sunxi-ng/ccu_div.h       |  1 +
 drivers/clk/sunxi-ng/ccu_mux.c       | 58 ++++++++++++-----------
 drivers/clk/sunxi-ng/ccu_mux.h       |  4 ++
 6 files changed, 144 insertions(+), 41 deletions(-)
---
base-commit: c52b5090bf1e3b88745f8a81f264f34100ecde42
change-id: 20251226-a733-rtc-c5167df14e6e

Best regards,
--  
Jerome



^ permalink raw reply

* Re: [PATCH v2 2/6] iommu/qcom: Use devm_pm_runtime_enable() in qcom_iommu_device_probe()
From: Konrad Dybcio @ 2026-07-17 15:23 UTC (permalink / raw)
  To: Mukesh Ojha, Rob Clark, Will Deacon, Joerg Roedel (AMD),
	Alex Williamson
  Cc: Robin Murphy, iommu, linux-arm-msm, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260717144608.3216274-3-mukesh.ojha@oss.qualcomm.com>

On 7/17/26 4:46 PM, Mukesh Ojha wrote:
> Switch from pm_runtime_enable() to devm_pm_runtime_enable() so that
> the matching pm_runtime_disable() is handled automatically via devres,
> both on probe failure and on device removal.
> 
> This removes the err_pm_disable error label from the probe function and
> the explicit pm_runtime_disable() call from qcom_iommu_device_remove().
> 
> Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
> ---

the single-use goto could be inlined now, but anyway

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>

Konrad


^ permalink raw reply

* Re: [PATCH v4 3/6] KVM: arm64: Add auto DBM support for hardware dirty tracking
From: Leonardo Bras @ 2026-07-17 15:21 UTC (permalink / raw)
  To: Tian Zheng
  Cc: Leonardo Bras, Oliver Upton, maz, catalin.marinas, will,
	yuzenghui, wangzhou1, yangjinqian1, caijian11, liuyonglong,
	yezhenyu2, yubihong, linuxarm, joey.gouly, kvmarm, kvm,
	linux-arm-kernel, linux-kernel, seiden, suzuki.poulose
In-Reply-To: <0943eb14-9ffb-4dbb-9219-060e97bca2a7@huawei.com>

On Fri, Jul 17, 2026 at 11:58:06AM +0800, Tian Zheng wrote:
> 
> On 7/16/2026 3:39 PM, Oliver Upton wrote:
> > Hi Tian,
> > 
> > On Thu, Jul 09, 2026 at 06:40:23PM +0800, Tian Zheng wrote:
> > > -	if (prot & KVM_PGTABLE_PROT_W)
> > > +	if (prot & KVM_PGTABLE_PROT_W) {
> > >   		set |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
> > > 
> > > +		/*
> > > +		 * No DEVICE filter needed here: relax_perms is only called
> > > +		 * on FSC_PERM faults. Device pages always get full RW from
> > > +		 * initial mapping and are never write-protected during
> > > +		 * migration, so they never trigger a permission fault.
> > > +		 */
> > > +		if (pgt->flags & KVM_PGTABLE_S2_DBM)
> > > +			set |= KVM_PTE_LEAF_ATTR_HI_S2_DBM;
> > > +	} else {
> > > +		/*
> > > +		 * Clear DBM on W→RO downgrade to prevent hardware from
> > > +		 * silently upgrading RO+DBM back to W+dirty, which would
> > > +		 * bypass KVM's write tracking and cause data corruption.
> > > +		 */
> > > +		clr |= KVM_PTE_LEAF_ATTR_HI_S2_DBM;
> > > +	}
> > > +
> > This block makes it pretty evident that the DBM bit really *is* the
> > write permission bit. I'd much rather we introduce the concept of dirty
> > state to the page table library and migrate the abstract write
> > permission to the DBM field, even if we don't have FEAT_HAFDBS.
> >

Ohh, that's an amazing idea!

 
> > That way everything 'just works' from outside the page-table library:
> > write-protecting hugepages would have the effect of clearing DBM and we
> > can separately reap dirty state from page descriptors.
> > 
> > If/when the architecture forces FEAT_S2PIE upon us we will need to make
> > this change anyway since dirty state management is unconditional and
> > handled separately from the actual permissions.
> >
> > Thanks,
> > Oliver
> 
> Hi Oliver,
> 
> Thanks again for your insightful review. Following your suggestion, I've
> 
> reworked the design around a unified three-state model that works regardless
> 
> of whether FEAT_HAFDBS is implemented:
> 
> **State table**
> State               | DBM    | S2AP[1] | Without HTTU            | With  HTTU  (HAFDBS)
> Non-writable   (N)  |  0     |    0    | write -> fault, inject  | write -> fault, inject
> Writable-clean (C)  |  1     |    0    | write -> fault, sw C->D | write -> hw C->D, no fault, HDBSS logs
> Writable-dirty (D)  |  1     |    1    | writable, no fault      | writable, no fault
> 

Yeah, that's how the table works with HAFDBS/HDBSS/HACDBS.

> **Proposed changes**
> 1. Remove KVM_PGTABLE_S2_DBM from enum kvm_pgtable_stage2_flags
> 
> — VTCR_EL2.{HD,HDBSS,HA} enablement in kvm_arm_enable_hdbss_global()
> 
> already keys off kvm->arch.enable_hdbss / system_supports_hdbss().
> 

We may need a system_support_hdbss() for the actual hdbss routines, though.


> 2. stage2_set_prot_attr() — set DBM unconditionally on writable pages:
> ```
> if (prot & KVM_PGTABLE_PROT_W) {
>     attr |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
>     /* Writable-dirty: DBM=1 conveys write intent, S2AP[1]=1 marks dirty */
>     attr |= KVM_PTE_LEAF_ATTR_HI_S2_DBM;
> }
> ```
> 
> 3. kvm_pgtable_stage2_relax_perms() — drop the else branch entirely:
> ```
> if (prot & KVM_PGTABLE_PROT_W) {
>     set |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
>     /* Non-writable -> Writable-dirty: restore both write intent and dirty state */
>     set |= KVM_PTE_LEAF_ATTR_HI_S2_DBM;

In the future, depending on the setup of HDBSS/splitting, we may want to 
change this behavior. But for software only, it looks nice. 

> }
> /* no else: callers passing !W (e.g. exec faults) must not touch DBM */
> ```
> 
> 4. kvm_pgtable_stage2_wrprotect() — unchanged: it only clears S2AP1 (D->C).
> 
> DBM is preserved so HDBSS re-arms next round.
>  ```
> int kvm_pgtable_stage2_wrprotect(struct kvm_pgtable *pgt, u64 addr, u64
> size)
> {
>    /* Writable-dirty -> Writable-clean: clear dirty state (S2AP_W),
>    * preserve write intent (DBM) so HDBSS re-arms for next write.
>     */
>     return stage2_update_leaf_attrs(pgt, addr, size, 0,
>                          KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W,
>                          NULL, NULL,
>                          KVM_PGTABLE_WALK_IGNORE_EAGAIN);
> }
> ```
> 
> **One clarification**
> In the three-state model above, wrprotect() clears S2AP[1] but preserves DBM
> (D->C).
> 
> This allows HDBSS to re-arm on the next write. If we instead cleared DBM as
> well (->N),
> 
> HDBSS would be permanently disabled on that page and we'd lose the benefit
> of hardware
> 
> dirty tracking.
> 
> 
> So my understanding is:
> 
> wrprotect() (dirty tracking): D->C — clears S2AP[1], preserves DBM
> 
> mkreadonly() (true RO, future): ->N — clears both S2AP[1] and DBM
> 
> Does this match what you had in mind?
> 
> Looking forward to your thoughts.
> 
> Thanks,
> Tian
> 
> 
 
Thanks!
Leo


^ permalink raw reply

* Re: [PATCH v2 00/15] arm64: dts: freescale: imx8mn-var-som: Align SOM and Symphony DTSs
From: Frank.Li @ 2026-07-17 15:17 UTC (permalink / raw)
  To: linux-kernel, devicetree, imx, linux-arm-kernel, Stefano Radaelli
  Cc: Frank Li, pierluigi.p, Stefano Radaelli, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
In-Reply-To: <cover.1783330236.git.stefano.r@variscite.com>

From: Frank Li <Frank.Li@nxp.com>


On Mon, 06 Jul 2026 11:34:30 +0200, Stefano Radaelli wrote:
> This series aligns the i.MX8MN VAR-SOM and VAR-SOM Symphony device
> trees with the latest hardware revisions.
> 
> As the i.MX8MN device tree hierarchy closely mirrors the i.MX8MM one,
> this series applies the same alignment already accepted for the i.MX8MM
> platform, ensuring a consistent hardware description across both
> families.
> 
> [...]

Applied, thanks!

[01/15] arm64: dts: freescale: imx8mn-var-som: Move UART4 description to Symphony
        commit: 259bd77e9f635e058c045a880427570e534c8737
[02/15] arm64: dts: freescale: imx8mn-var-som: move uSD support to carrier boards
        commit: bc5217a4e354ebe0a2f52d2188ef952fd630defc
[03/15] arm64: dts: freescale: imx8mn-var-som: Align fsl,pins tables
        commit: 763a267bc2ccf637bd0f35492ca1e6ab6c9dc13b
[04/15] arm64: dts: freescale: imx8mn-var-som: Update FEC support with MaxLinear PHY
        commit: a6c8d4f9c2db6254681d78ec93f5bd944a0cf89d
[05/15] arm64: dts: freescale: imx8mn-var-som: Add support for WM8904 audio codec
        commit: ed99c5c5c5e88f31ed8de6eff9c3da2ca188d947
[06/15] arm64: dts: freescale: imx8mn-var-som: Add MCP251xFD CAN controller
        commit: 42a066c24cc673b4317acb382597c0a3230b9f6f
[07/15] arm64: dts: freescale: imx8mn-var-som: Rework WiFi/BT and add legacy dts
        commit: 040bf14c102570fee953fc2124737a988c3fb6a6
[08/15] arm64: dts: freescale: imx8mn-var-som: drop duplicate USB OTG node
        commit: 0504e4d12fd3c3b5062b49086ce17a2743c60658
[09/15] arm64: dts: freescale: imx8mn-var-som: enable FlexSPI interface
        commit: 5580a6278c5ce77a8492d76571929321894934f3
[10/15] arm64: dts: imx8mn-var-som-symphony: Add TPM2 support
        commit: 8576126c7ccf632c8edeeb69f57f17ee5e125de5
[11/15] arm64: dts: imx8mn-var-som-symphony: Enable I2C4
        commit: ab80a67f5cdb42797d0a92d7951242291bb97f3a
[12/15] arm64: dts: imx8mn-var-som-symphony: add wakeup sources
        commit: e2e47af10c90f4c5eaf415fa98f6ca2f33ef30da
[13/15] arm64: dts: imx8mn-var-som-symphony: keep RGB_SEL low
        commit: 164cb0d61a3fd0d9376005aae3b112a3dbba2e07
[14/15] arm64: dts: imx8mn-var-som-symphony: enable PWM1
        commit: 8a6c812cd5a721aa0af9b7dd35b43d12c831349e
[15/15] arm64: dts: imx8mn-var-som-symphony: Disable internal RTC
        commit: be578db51f789f0b88ec4f5e5f78e232b42c6b15

Best regards,
-- 
Frank Li <Frank.Li@nxp.com>


^ permalink raw reply

* [PATCH 7/7] soc: mediatek: mtk-mmsys: Add resets for mt8167
From: Luca Leonardo Scorcia @ 2026-07-17 15:11 UTC (permalink / raw)
  To: linux-mediatek
  Cc: Luca Leonardo Scorcia, Wim Van Sebroeck, Guenter Roeck,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Philipp Zabel, linux-watchdog,
	devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20260717151134.678839-1-l.scorcia@gmail.com>

The mt8167 SoC has 64 MMSYS resets, split in two contiguous 32-bits
registers, MMSYS_SW0_RST_B (0x140) and MMSYS_SW1_RST_B (0x144), as
also stated in the downstream kernel for the Lenovo Smart Clock
in the ddp_reg.h header.

Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
 drivers/soc/mediatek/mt8167-mmsys.h | 40 +++++++++++++++++++++++++++++
 drivers/soc/mediatek/mtk-mmsys.c    |  3 +++
 2 files changed, 43 insertions(+)

diff --git a/drivers/soc/mediatek/mt8167-mmsys.h b/drivers/soc/mediatek/mt8167-mmsys.h
index eef14083c47b..b8f38ff8cf44 100644
--- a/drivers/soc/mediatek/mt8167-mmsys.h
+++ b/drivers/soc/mediatek/mt8167-mmsys.h
@@ -3,6 +3,46 @@
 #ifndef __SOC_MEDIATEK_MT8167_MMSYS_H
 #define __SOC_MEDIATEK_MT8167_MMSYS_H
 
+#include <linux/soc/mediatek/mtk-mmsys.h>
+#include <dt-bindings/reset/mediatek,mt8167-resets.h>
+
+#define MT8167_MMSYS_SW0_RST_B				0x140
+#define MT8167_MMSYS_SW1_RST_B				0x144
+
+/* MMSYS resets */
+static const u8 mmsys_mt8167_rst_tb[] = {
+	[MT8167_MMSYS_SW0_RST_B_SMI_COMMON]	= MMSYS_RST_NR(0, 0),
+	[MT8167_MMSYS_SW0_RST_B_SMI_LARB0]	= MMSYS_RST_NR(0, 1),
+	[MT8167_MMSYS_SW0_RST_B_CAM_MDP]	= MMSYS_RST_NR(0, 2),
+	[MT8167_MMSYS_SW0_RST_B_MDP_RDMA0]	= MMSYS_RST_NR(0, 3),
+	[MT8167_MMSYS_SW0_RST_B_MDP_RSZ0]	= MMSYS_RST_NR(0, 4),
+	[MT8167_MMSYS_SW0_RST_B_MDP_RSZ1]	= MMSYS_RST_NR(0, 5),
+	[MT8167_MMSYS_SW0_RST_B_MDP_TDSHP0]	= MMSYS_RST_NR(0, 6),
+	[MT8167_MMSYS_SW0_RST_B_MDP_WDMA]	= MMSYS_RST_NR(0, 7),
+	[MT8167_MMSYS_SW0_RST_B_MDP_WROT0]	= MMSYS_RST_NR(0, 8),
+	[MT8167_MMSYS_SW0_RST_B_FAKE_ENG]	= MMSYS_RST_NR(0, 9),
+	[MT8167_MMSYS_SW0_RST_B_MUTEX]		= MMSYS_RST_NR(0, 10),
+	[MT8167_MMSYS_SW0_RST_B_DISP_OVL0]	= MMSYS_RST_NR(0, 11),
+	[MT8167_MMSYS_SW0_RST_B_DISP_RDMA0]	= MMSYS_RST_NR(0, 12),
+	[MT8167_MMSYS_SW0_RST_B_DISP_RDMA1]	= MMSYS_RST_NR(0, 13),
+	[MT8167_MMSYS_SW0_RST_B_DISP_WDMA0]	= MMSYS_RST_NR(0, 14),
+	[MT8167_MMSYS_SW0_RST_B_DISP_COLOR]	= MMSYS_RST_NR(0, 15),
+	[MT8167_MMSYS_SW0_RST_B_DISP_CCORR]	= MMSYS_RST_NR(0, 16),
+	[MT8167_MMSYS_SW0_RST_B_DISP_AAL]	= MMSYS_RST_NR(0, 17),
+	[MT8167_MMSYS_SW0_RST_B_DISP_GAMMA]	= MMSYS_RST_NR(0, 18),
+	[MT8167_MMSYS_SW0_RST_B_DISP_DITHER]	= MMSYS_RST_NR(0, 19),
+	[MT8167_MMSYS_SW0_RST_B_DISP_UFOE]	= MMSYS_RST_NR(0, 20),
+	[MT8167_MMSYS_SW0_RST_B_DISP_PWM]	= MMSYS_RST_NR(0, 21),
+	[MT8167_MMSYS_SW0_RST_B_DSI0]		= MMSYS_RST_NR(0, 22),
+	[MT8167_MMSYS_SW0_RST_B_DPI0]		= MMSYS_RST_NR(0, 23),
+	/* bit 24 is SMI_COMMON again according to data sheet */
+	/* bit 25 is SMI_LARB0 again according to data sheet */
+	/* all other bits are not described in data sheet */
+	[MT8167_MMSYS_SW1_RST_B_LVDS_ENCODER]	= MMSYS_RST_NR(1, 2),
+	[MT8167_MMSYS_SW1_RST_B_DPI1]		= MMSYS_RST_NR(1, 3),
+	[MT8167_MMSYS_SW1_RST_B_HDMI]		= MMSYS_RST_NR(1, 4),
+};
+
 #define MT8167_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN	0x030
 #define MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN	0x038
 #define MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN	0x058
diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index 2f3e0778bb17..abd96634b63c 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -57,6 +57,9 @@ static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data = {
 	.clk_driver = "clk-mt8167-mm",
 	.routes = mt8167_mmsys_routing_table,
 	.num_routes = ARRAY_SIZE(mt8167_mmsys_routing_table),
+	.sw0_rst_offset = MT8167_MMSYS_SW0_RST_B,
+	.rst_tb = mmsys_mt8167_rst_tb,
+	.num_resets = ARRAY_SIZE(mmsys_mt8167_rst_tb),
 };
 
 static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
-- 
2.43.0



^ permalink raw reply related

* [PATCH 6/7] arm64: dts: mt8167: Properly describe the SoC watchdog
From: Luca Leonardo Scorcia @ 2026-07-17 15:11 UTC (permalink / raw)
  To: linux-mediatek
  Cc: Luca Leonardo Scorcia, Wim Van Sebroeck, Guenter Roeck,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Philipp Zabel, linux-watchdog,
	devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20260717151134.678839-1-l.scorcia@gmail.com>

Currently mt8167 inherits its watchdog from the included mt8516 dtsi,
which in turn falls back on mt6589-wdt. However according to the data
sheet mt8167 has 15 sw resets instead of 12, and the reset bits are
different from mt6589.

Use the dedicated mediatek,mt8167-wdt compatible for the watchdog driver,
as it correctly describes the SoC resets.

Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
 arch/arm64/boot/dts/mediatek/mt8167.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8167.dtsi b/arch/arm64/boot/dts/mediatek/mt8167.dtsi
index 27cf32d7ae35..4ebf305c10fe 100644
--- a/arch/arm64/boot/dts/mediatek/mt8167.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8167.dtsi
@@ -95,6 +95,13 @@ power-domain@MT8167_POWER_DOMAIN_CONN {
 			};
 		};
 
+		watchdog: watchdog@10007000 {
+			compatible = "mediatek,mt8167-wdt";
+			reg = <0 0x10007000 0 0x1000>;
+			interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_LOW>;
+			#reset-cells = <1>;
+		};
+
 		pio: pinctrl@1000b000 {
 			compatible = "mediatek,mt8167-pinctrl";
 			reg = <0 0x1000b000 0 0x1000>;
-- 
2.43.0



^ permalink raw reply related

* [PATCH 5/7] watchdog: mediatek: Add support for mt8167 TOPRGU/WDT
From: Luca Leonardo Scorcia @ 2026-07-17 15:11 UTC (permalink / raw)
  To: linux-mediatek
  Cc: Luca Leonardo Scorcia, Wim Van Sebroeck, Guenter Roeck,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Philipp Zabel, linux-watchdog,
	devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20260717151134.678839-1-l.scorcia@gmail.com>

Add support for the Top Reset Generation Unit/Watchdog Timer found on
mt8167.

Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
 drivers/watchdog/mtk_wdt.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
index e61f6ae74327..10a3d4b5ee30 100644
--- a/drivers/watchdog/mtk_wdt.c
+++ b/drivers/watchdog/mtk_wdt.c
@@ -13,6 +13,7 @@
 #include <dt-bindings/reset/mediatek,mt6589-resets.h>
 #include <dt-bindings/reset/mediatek,mt6735-wdt.h>
 #include <dt-bindings/reset/mediatek,mt6795-resets.h>
+#include <dt-bindings/reset/mediatek,mt8167-resets.h>
 #include <dt-bindings/reset/mt7986-resets.h>
 #include <dt-bindings/reset/mt8183-resets.h>
 #include <dt-bindings/reset/mt8186-resets.h>
@@ -110,6 +111,10 @@ static const struct mtk_wdt_data mt7988_data = {
 	.has_swsysrst_en = true,
 };
 
+static const struct mtk_wdt_data mt8167_data = {
+	.toprgu_sw_rst_num = MT8167_TOPRGU_SW_RST_NUM,
+};
+
 static const struct mtk_wdt_data mt8183_data = {
 	.toprgu_sw_rst_num = MT8183_TOPRGU_SW_RST_NUM,
 };
@@ -503,6 +508,7 @@ static const struct of_device_id mtk_wdt_dt_ids[] = {
 	{ .compatible = "mediatek,mt6795-wdt", .data = &mt6795_data },
 	{ .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data },
 	{ .compatible = "mediatek,mt7988-wdt", .data = &mt7988_data },
+	{ .compatible = "mediatek,mt8167-wdt", .data = &mt8167_data },
 	{ .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data },
 	{ .compatible = "mediatek,mt8186-wdt", .data = &mt8186_data },
 	{ .compatible = "mediatek,mt8188-wdt", .data = &mt8188_data },
-- 
2.43.0



^ permalink raw reply related

* [PATCH 3/7] dt-bindings: watchdog: Add compatible for MediaTek mt8167
From: Luca Leonardo Scorcia @ 2026-07-17 15:11 UTC (permalink / raw)
  To: linux-mediatek
  Cc: Luca Leonardo Scorcia, Wim Van Sebroeck, Guenter Roeck,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Philipp Zabel, linux-watchdog,
	devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20260717151134.678839-1-l.scorcia@gmail.com>

Currently mt8167 inherits its watchdog from the included mt8516 dtsi,
which in turn falls back on mt6589-wdt. However according to the data
sheet mt8167 has 15 sw resets instead of 12, and their order is different
from mt6589. Update the wdt binding to add a dedicated compatible for
mt8167.

Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
 Documentation/devicetree/bindings/watchdog/mediatek,mtk-wdt.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/watchdog/mediatek,mtk-wdt.yaml b/Documentation/devicetree/bindings/watchdog/mediatek,mtk-wdt.yaml
index 953629cb9558..f514be8a5851 100644
--- a/Documentation/devicetree/bindings/watchdog/mediatek,mtk-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/mediatek,mtk-wdt.yaml
@@ -26,6 +26,7 @@ properties:
           - mediatek,mt6795-wdt
           - mediatek,mt7986-wdt
           - mediatek,mt7988-wdt
+          - mediatek,mt8167-wdt
           - mediatek,mt8183-wdt
           - mediatek,mt8186-wdt
           - mediatek,mt8188-wdt
-- 
2.43.0



^ permalink raw reply related

* [PATCH 4/7] dt-bindings: reset: Add reset controller constants for mt8167
From: Luca Leonardo Scorcia @ 2026-07-17 15:11 UTC (permalink / raw)
  To: linux-mediatek
  Cc: Luca Leonardo Scorcia, Wim Van Sebroeck, Guenter Roeck,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Philipp Zabel, linux-watchdog,
	devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20260717151134.678839-1-l.scorcia@gmail.com>

Add the various bits that identify watchdog and mmsys resets. IDs for
mmsys resets restart from zero as they are used in a different device.

Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
 .../reset/mediatek,mt8167-resets.h            | 53 +++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 include/dt-bindings/reset/mediatek,mt8167-resets.h

diff --git a/include/dt-bindings/reset/mediatek,mt8167-resets.h b/include/dt-bindings/reset/mediatek,mt8167-resets.h
new file mode 100644
index 000000000000..85d2d0e99c68
--- /dev/null
+++ b/include/dt-bindings/reset/mediatek,mt8167-resets.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8167
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8167
+
+/* TOPRGU resets, these are actual bits in the register */
+#define MT8167_TOPRGU_DDRPHY_FLASH_RST		0
+#define MT8167_TOPRGU_AUD_PAD_RST		1
+#define MT8167_TOPRGU_MM_RST			2
+#define MT8167_TOPRGU_MFG_RST			3
+#define MT8167_TOPRGU_MDSYS_RST			4
+#define MT8167_TOPRGU_CONN_RST			5
+#define MT8167_TOPRGU_PAD2CAM_DIG_MIPI_RX_RST	6
+#define MT8167_TOPRGU_DIG_MIPI_TX_RST		7
+#define MT8167_TOPRGU_SPI_PAD_MACRO_RST		8
+/* bit 9 is reserved, unused according to data sheet */
+#define MT8167_TOPRGU_APMIXED_RST		10
+#define MT8167_TOPRGU_VDEC_RST			11
+#define MT8167_TOPRGU_CONN_MCU_RST		12
+#define MT8167_TOPRGU_EFUSE_RST			13
+#define MT8167_TOPRGU_PWRAP_SPICTL_RST		14
+#define MT8167_TOPRGU_SW_RST_NUM		15
+
+/* MMSYS resets, these are IDs */
+#define MT8167_MMSYS_SW0_RST_B_SMI_COMMON	0
+#define MT8167_MMSYS_SW0_RST_B_SMI_LARB0	1
+#define MT8167_MMSYS_SW0_RST_B_CAM_MDP		2
+#define MT8167_MMSYS_SW0_RST_B_MDP_RDMA0	3
+#define MT8167_MMSYS_SW0_RST_B_MDP_RSZ0		4
+#define MT8167_MMSYS_SW0_RST_B_MDP_RSZ1		5
+#define MT8167_MMSYS_SW0_RST_B_MDP_TDSHP0	6
+#define MT8167_MMSYS_SW0_RST_B_MDP_WDMA		7
+#define MT8167_MMSYS_SW0_RST_B_MDP_WROT0	8
+#define MT8167_MMSYS_SW0_RST_B_FAKE_ENG		9
+#define MT8167_MMSYS_SW0_RST_B_MUTEX		10
+#define MT8167_MMSYS_SW0_RST_B_DISP_OVL0	11
+#define MT8167_MMSYS_SW0_RST_B_DISP_RDMA0	12
+#define MT8167_MMSYS_SW0_RST_B_DISP_RDMA1	13
+#define MT8167_MMSYS_SW0_RST_B_DISP_WDMA0	14
+#define MT8167_MMSYS_SW0_RST_B_DISP_COLOR	15
+#define MT8167_MMSYS_SW0_RST_B_DISP_CCORR	16
+#define MT8167_MMSYS_SW0_RST_B_DISP_AAL		17
+#define MT8167_MMSYS_SW0_RST_B_DISP_GAMMA	18
+#define MT8167_MMSYS_SW0_RST_B_DISP_DITHER	19
+#define MT8167_MMSYS_SW0_RST_B_DISP_UFOE	20
+#define MT8167_MMSYS_SW0_RST_B_DISP_PWM		21
+#define MT8167_MMSYS_SW0_RST_B_DSI0		22
+#define MT8167_MMSYS_SW0_RST_B_DPI0		23
+#define MT8167_MMSYS_SW0_RST_B_MIPI_TX_CONFIG	24
+#define MT8167_MMSYS_SW1_RST_B_LVDS_ENCODER	25
+#define MT8167_MMSYS_SW1_RST_B_DPI1		26
+#define MT8167_MMSYS_SW1_RST_B_HDMI		27
+
+#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT8167 */
-- 
2.43.0



^ permalink raw reply related

* [PATCH 2/7] watchdog: mediatek: Add wdt/toprgu resets for MT6589
From: Luca Leonardo Scorcia @ 2026-07-17 15:11 UTC (permalink / raw)
  To: linux-mediatek
  Cc: Luca Leonardo Scorcia, Wim Van Sebroeck, Guenter Roeck,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Philipp Zabel, linux-watchdog,
	devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20260717151134.678839-1-l.scorcia@gmail.com>

According to Android sources, MT6589 has 12 reset bits in the
WDT_SWSYSRST register. Populate toprgu_sw_rst_num to allow toprgu resets
in device trees of the many compatible devices.

Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
 drivers/watchdog/mtk_wdt.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
index 91d110646e16..e61f6ae74327 100644
--- a/drivers/watchdog/mtk_wdt.c
+++ b/drivers/watchdog/mtk_wdt.c
@@ -10,6 +10,7 @@
  */
 
 #include <dt-bindings/reset/mt2712-resets.h>
+#include <dt-bindings/reset/mediatek,mt6589-resets.h>
 #include <dt-bindings/reset/mediatek,mt6735-wdt.h>
 #include <dt-bindings/reset/mediatek,mt6795-resets.h>
 #include <dt-bindings/reset/mt7986-resets.h>
@@ -88,6 +89,10 @@ static const struct mtk_wdt_data mt2712_data = {
 	.toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM,
 };
 
+static const struct mtk_wdt_data mt6589_data = {
+	.toprgu_sw_rst_num = MT6589_TOPRGU_SW_RST_NUM,
+};
+
 static const struct mtk_wdt_data mt6735_data = {
 	.toprgu_sw_rst_num = MT6735_TOPRGU_RST_NUM,
 };
@@ -493,7 +498,7 @@ static int mtk_wdt_resume(struct device *dev)
 
 static const struct of_device_id mtk_wdt_dt_ids[] = {
 	{ .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data },
-	{ .compatible = "mediatek,mt6589-wdt" },
+	{ .compatible = "mediatek,mt6589-wdt", .data = &mt6589_data },
 	{ .compatible = "mediatek,mt6735-wdt", .data = &mt6735_data },
 	{ .compatible = "mediatek,mt6795-wdt", .data = &mt6795_data },
 	{ .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data },
-- 
2.43.0



^ permalink raw reply related

* [PATCH 1/7] dt-bindings: reset: Add MT6589 toprgu reset IDs
From: Luca Leonardo Scorcia @ 2026-07-17 15:11 UTC (permalink / raw)
  To: linux-mediatek
  Cc: Luca Leonardo Scorcia, Wim Van Sebroeck, Guenter Roeck,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Philipp Zabel, linux-watchdog,
	devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20260717151134.678839-1-l.scorcia@gmail.com>

Add reset constants for the 12 MT6589 toprgu resets.

Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
---
 .../reset/mediatek,mt6589-resets.h            | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 include/dt-bindings/reset/mediatek,mt6589-resets.h

diff --git a/include/dt-bindings/reset/mediatek,mt6589-resets.h b/include/dt-bindings/reset/mediatek,mt6589-resets.h
new file mode 100644
index 000000000000..ee08c39df513
--- /dev/null
+++ b/include/dt-bindings/reset/mediatek,mt6589-resets.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Author: Luca Leonardo Scorcia <l.scorcia@gmail.com>
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT6589
+#define _DT_BINDINGS_RESET_CONTROLLER_MT6589
+
+/* TOPRGU resets */
+#define MT6589_TOPRGU_INFRA_SW_RST		0
+#define MT6589_TOPRGU_MM_SW_RST			1
+#define MT6589_TOPRGU_MFG_SW_RST		2
+#define MT6589_TOPRGU_VENC_SW_RST		3
+#define MT6589_TOPRGU_VDEC_SW_RST		4
+#define MT6589_TOPRGU_IMG_SW_RST		5
+#define MT6589_TOPRGU_DDRPHY_SW_RST		6
+#define MT6589_TOPRGU_MD_SW_RST			7
+#define MT6589_TOPRGU_INFRA_AO_SW_RST		8
+#define MT6589_TOPRGU_MD_LITE_SW_RST		9
+#define MT6589_TOPRGU_APMIXED_SW_RST		10
+#define MT6589_TOPRGU_PWRAP_SPI_CTL_RST		11
+#define MT6589_TOPRGU_SW_RST_NUM		12
+
+#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT6589 */
-- 
2.43.0



^ permalink raw reply related

* [PATCH 0/7] Properly describe mt8167 watchdog and mmsys resets
From: Luca Leonardo Scorcia @ 2026-07-17 15:11 UTC (permalink / raw)
  To: linux-mediatek
  Cc: Luca Leonardo Scorcia, Wim Van Sebroeck, Guenter Roeck,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Philipp Zabel, linux-watchdog,
	devicetree, linux-kernel, linux-arm-kernel

Currently mt8167 inherits its watchdog from the included mt8516 dtsi,
which in turn falls back on mt6589-wdt. However according to the data
sheet mt8167 has 15 sw resets instead of 12, and the reset bits are
different from mt6589.

In the first two patches we improve the description of the resets for
mt6589 with values obtained from Android sources.

Then we introduce a dedicated mediatek,mt8167-wdt compatible for the
watchdog driver that describes correctly this SoC's resets. Also while
we're touching the bindings reset header, we add constants for the MMSYS
resets.

In the 6th patch we add a node for the mt8167 watchdog referring to the
new compatible in the SoC dtsi.

In the last patch, we define the mmsys reset table for the SoC. According
to the datasheet, there are 28 mmsys reset bits divided across two
adjacent registers.

Luca Leonardo Scorcia (7):
  dt-bindings: reset: Add MT6589 toprgu reset IDs
  watchdog: mediatek: Add wdt/toprgu resets for MT6589
  dt-bindings: watchdog: Add compatible for MediaTek mt8167
  dt-bindings: reset: Add reset controller constants for mt8167
  watchdog: mediatek: Add support for mt8167 TOPRGU/WDT
  arm64: dts: mt8167: Properly describe the SoC watchdog
  soc: mediatek: mtk-mmsys: Add resets for mt8167

 .../bindings/watchdog/mediatek,mtk-wdt.yaml   |  1 +
 arch/arm64/boot/dts/mediatek/mt8167.dtsi      |  7 +++
 drivers/soc/mediatek/mt8167-mmsys.h           | 40 ++++++++++++++
 drivers/soc/mediatek/mtk-mmsys.c              |  3 ++
 drivers/watchdog/mtk_wdt.c                    | 13 ++++-
 .../reset/mediatek,mt6589-resets.h            | 24 +++++++++
 .../reset/mediatek,mt8167-resets.h            | 53 +++++++++++++++++++
 7 files changed, 140 insertions(+), 1 deletion(-)
 create mode 100644 include/dt-bindings/reset/mediatek,mt6589-resets.h
 create mode 100644 include/dt-bindings/reset/mediatek,mt8167-resets.h

-- 
2.43.0



^ permalink raw reply

* [PATCH v3] media: rkvdec: fix clk reference leak on unbind
From: Francesco Saverio Pavone @ 2026-07-17 15:04 UTC (permalink / raw)
  To: jonas, detlev.casanova, nicolas.dufresne, hverkuil, mchehab
  Cc: ezequiel, heiko, linux-media, linux-rockchip, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260518145414.64514-1-pavone.lawyer@gmail.com>

From: Jonas Karlman <jonas@kwiboo.se>

remove() calls pm_runtime_disable() before
pm_runtime_dont_use_autosuspend(), so the second call can never suspend
the device: it reaches rpm_idle(), which returns -EACCES once PM runtime
is disabled. The probe error path has had the two the other way round
since the driver was merged.

This shows up when the device is unbound while the 100ms autosuspend
window is still open, which is what an rmmod right after a decode does.
device_release_driver() calls pm_runtime_put_sync() before .remove(),
and rpm_idle() adds RPM_AUTO on its own, so that put only arms the
autosuspend timer. pm_runtime_disable() then cancels the timer, and
pm_runtime_reinit() relabels the device suspended without calling the
driver back. The clk_bulk reference taken by rkvdec_runtime_resume() is
never dropped, and a later probe does not reclaim it, so every such
unbind leaks one enable count.

Drop autosuspend first, so the callback still runs and releases the
clocks.

The PM calls also have to move ahead of rkvdec_v4l2_cleanup() rather
than just swap with each other. rkvdec_runtime_suspend() looks its state
up with dev_get_drvdata(), and v4l2_device_unregister() clears it:
struct rkvdec_dev has v4l2_device as its first member, so
&rkvdec->v4l2_dev and rkvdec are the same address and the check in
v4l2_device_disconnect() matches. That is harmless today because
pm_runtime_disable() suppresses the callback, but once the callback can
run, a suspend after the V4L2 teardown dereferences NULL. Swapping only
the two PM calls oopses on every unbind.

Fixes: cd33c830448b ("media: rkvdec: Add the rkvdec driver")
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
[fsp: wrote the commit message; the diff is unchanged]
Tested-by: Francesco Saverio Pavone <pavone.lawyer@gmail.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Francesco Saverio Pavone <pavone.lawyer@gmail.com>
---
Changes in v3:
 - Rewrote the commit message, and dropped the VP9 claim from v1 and v2.
   Those said this fixed a VP9 inter-prediction bug on RK3588, green chroma
   from the second ALTREF frame onward. The bug is real, but this is not
   what fixes it, and I should have established that before sending v1.

   What happened: I took this patch out of chewitt's tree along with two
   others and tested the three as a batch. The green is fixed by "media:
   rkvdec: implement reset controls" from Alex Bee, which adds the
   reset_control handling that recovers the VDPU381 after a transient error
   (COLMV_REF_ERR_STA and friends) instead of leaving it dirty for the next
   inter frame. Randy Li's PMU idle export goes with it. This patch was the
   third one in that batch and got the credit.

   Retested this week on the same Rock 5B+ with an unpatched driver: a VP9
   Profile 0 1080p clip with alt-ref frames decodes byte-identical to the
   libvpx reference, across five rmmod/insmod cycles and after an unbind
   inside the autosuspend window. The green does not come back, because the
   reset_control work is in the tree I test on. Sorry for the review and the
   testing you spent on that basis.

 - Worth flagging separately: mainline rkvdec has no reset_control support
   at all, so the VDPU381 is never recovered after a transient error. That
   is a real gap, it is just not this patch. I can write it up properly if
   that is useful.

 - The diff is unchanged from v1 and v2. It is Jonas's 2020 commit verbatim,
   and his original one-line subject already described exactly what it does.
   The wrong story was mine, not his.

 - The subject changed with the message: "media: rkvdec: fix PM runtime
   teardown ordering in remove" in v1 and v2, "media: rkvdec: fix clk
   reference leak on unbind" here, since that is what it actually fixes.

 - What is left is measured. With a dev_info() at the top of
   rkvdec_runtime_suspend(), autosuspend_delay raised to 60s to take the
   timer out of the race, and unbind driven through sysfs:
       unpatched: 0 suspend callbacks, aclk_rkvdec0 enable_count 1 -> 2
       patched:   1 suspend callback,  enable_count 1 -> 1
   The leak survives rmmod and accumulates one per unbind. With
   autosuspend_delay=0 both orders suspend once, which is the control: the
   difference only exists inside the window.

 - Fixes: was wrong in v1 and v2. ff8c5622f9f7 has the two pm_runtime calls
   as context and only added iommu_domain_free(). cd33c830448b added remove()
   with the reversed order, and the probe error path with the right one, so
   the tag points there now.

 - Dropped Cc: stable. A clk reference leaked on unbind is not backport
   material, and the tag was only there for the VP9 claim.

 - Dropped your Reviewed-by and Tested-by from v2: they were given for a fix
   to something else.

 - Not included, happy to send as follow-ups: clearing empty_domain after
   iommu_domain_free(), and hoisting the unregisters to the top of remove()
   as you suggested on v2.

Tested on a Radxa Rock 5B+ (RK3588) on a 7.1 tree where the six calls in
rkvdec_v4l2_cleanup() are open-coded; the executed sequence is the one this
patch produces. VP9 decode stays byte-identical to libvpx, and five
rmmod/insmod cycles leave dmesg clean.

Link to v1: https://lore.kernel.org/all/20260518105413.42147-1-pavone.lawyer@gmail.com/
Link to v2: https://lore.kernel.org/all/20260518145414.64514-1-pavone.lawyer@gmail.com/
 drivers/media/platform/rockchip/rkvdec/rkvdec.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
index 1d1e9bfef8e9..0ec3fca9cccc 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
@@ -1869,12 +1869,13 @@ static void rkvdec_remove(struct platform_device *pdev)
 
 	cancel_delayed_work_sync(&rkvdec->watchdog_work);
 
-	rkvdec_v4l2_cleanup(rkvdec);
-	pm_runtime_disable(&pdev->dev);
 	pm_runtime_dont_use_autosuspend(&pdev->dev);
 
 	if (rkvdec->empty_domain)
 		iommu_domain_free(rkvdec->empty_domain);
+
+	pm_runtime_disable(&pdev->dev);
+	rkvdec_v4l2_cleanup(rkvdec);
 }
 
 #ifdef CONFIG_PM
-- 
2.54.0



^ permalink raw reply related

* [PATCH v2 6/6] iommu/qcom: Enable clocks before hardware access in qcom_iommu_ctx_probe()
From: Mukesh Ojha @ 2026-07-17 14:46 UTC (permalink / raw)
  To: Rob Clark, Will Deacon, Joerg Roedel (AMD), Alex Williamson
  Cc: Robin Murphy, iommu, linux-arm-msm, linux-arm-kernel,
	linux-kernel, Mukesh Ojha, Konrad Dybcio
In-Reply-To: <20260717144608.3216274-1-mukesh.ojha@oss.qualcomm.com>

qcom_iommu_ctx_probe() reads and writes the CB_FSR register to clear any
stale IRQ left by the bootloader. This happens during
devm_of_platform_populate() which is called from the parent device's
probe before any pm_runtime_get(). The parent's clocks (iface, bus, tbu)
are therefore not guaranteed to be on, making the register access
unreliable on rebind or after a suspend cycle.

Use pm_runtime_resume_and_get() on the parent device to ensure clocks
are enabled before the register access, and release the reference
immediately after.

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
---
 drivers/iommu/arm/arm-smmu/qcom_iommu.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
index ecde5ca2d476..5a9f8b39a99c 100644
--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
@@ -704,8 +704,13 @@ static int qcom_iommu_ctx_probe(struct platform_device *pdev)
 	/* clear IRQs before registering fault handler, just in case the
 	 * boot-loader left us a surprise:
 	 */
-	if (!ctx->secured_ctx)
+	if (!ctx->secured_ctx) {
+		ret = pm_runtime_resume_and_get(dev->parent);
+		if (ret)
+			return ret;
 		iommu_writel(ctx, ARM_SMMU_CB_FSR, iommu_readl(ctx, ARM_SMMU_CB_FSR));
+		pm_runtime_put_sync(dev->parent);
+	}
 
 	ret = devm_request_irq(dev, irq,
 			       qcom_iommu_fault,
-- 
2.53.0



^ permalink raw reply related

* [PATCH v2 5/6] iommu/qcom: Publish pgtbl_ops before releasing init_mutex
From: Mukesh Ojha @ 2026-07-17 14:46 UTC (permalink / raw)
  To: Rob Clark, Will Deacon, Joerg Roedel (AMD), Alex Williamson
  Cc: Robin Murphy, iommu, linux-arm-msm, linux-arm-kernel,
	linux-kernel, Mukesh Ojha, Konrad Dybcio
In-Reply-To: <20260717144608.3216274-1-mukesh.ojha@oss.qualcomm.com>

qcom_domain->pgtbl_ops was assigned after mutex_unlock(). Another thread
calling qcom_iommu_init_domain() would see qcom_domain->iommu already set
(domain fully initialized) and skip re-initialization under the mutex.
If it then called qcom_iommu_map() before the first thread set pgtbl_ops,
it would observe a NULL ops pointer and return -ENODEV for valid mappings.

Move the assignment to before mutex_unlock() so that once the mutex is
released the domain is fully visible to concurrent operations.

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
---
 drivers/iommu/arm/arm-smmu/qcom_iommu.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
index 222bb7febd03..ecde5ca2d476 100644
--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
@@ -306,13 +306,12 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
 		ctx->domain = domain;
 	}
 
-	mutex_unlock(&qcom_domain->init_mutex);
-
 	/* Publish page table ops for map/unmap */
 	qcom_domain->pgtbl_ops = pgtbl_ops;
 
-	return 0;
+	mutex_unlock(&qcom_domain->init_mutex);
 
+	return 0;
 out_clear_iommu:
 	free_io_pgtable_ops(pgtbl_ops);
 	qcom_domain->iommu = NULL;
-- 
2.53.0



^ permalink raw reply related

* [PATCH v2 4/6] iommu/qcom: Fix pgtbl_ops leak in qcom_iommu_init_domain() error path
From: Mukesh Ojha @ 2026-07-17 14:46 UTC (permalink / raw)
  To: Rob Clark, Will Deacon, Joerg Roedel (AMD), Alex Williamson
  Cc: Robin Murphy, iommu, linux-arm-msm, linux-arm-kernel,
	linux-kernel, Mukesh Ojha, Konrad Dybcio
In-Reply-To: <20260717144608.3216274-1-mukesh.ojha@oss.qualcomm.com>

alloc_io_pgtable_ops() can succeed and then qcom_scm_restore_sec_cfg()
can fail for one of the context banks. The goto out_clear_iommu path
only cleared qcom_domain->iommu; the locally allocated pgtbl_ops was
never freed, leaking it permanently since qcom_domain->pgtbl_ops is only
assigned on the success path.

free_io_pgtable_ops() safely handles a NULL argument (covers the case
where alloc_io_pgtable_ops() itself failed), so add it unconditionally in
the out_clear_iommu handler.

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
---
 drivers/iommu/arm/arm-smmu/qcom_iommu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
index 1d04f0a19124..222bb7febd03 100644
--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
@@ -314,6 +314,7 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
 	return 0;
 
 out_clear_iommu:
+	free_io_pgtable_ops(pgtbl_ops);
 	qcom_domain->iommu = NULL;
 out_unlock:
 	mutex_unlock(&qcom_domain->init_mutex);
-- 
2.53.0



^ permalink raw reply related

* [PATCH v2 3/6] iommu/qcom: Check pm_runtime_resume_and_get() return in probe
From: Mukesh Ojha @ 2026-07-17 14:46 UTC (permalink / raw)
  To: Rob Clark, Will Deacon, Joerg Roedel (AMD), Alex Williamson
  Cc: Robin Murphy, iommu, linux-arm-msm, linux-arm-kernel,
	linux-kernel, Mukesh Ojha, Konrad Dybcio
In-Reply-To: <20260717144608.3216274-1-mukesh.ojha@oss.qualcomm.com>

The SMMU_INTR_SEL_NS register write in qcom_iommu_device_probe() uses
pm_runtime_get_sync() without checking the return value. If runtime
resume fails the subsequent writel_relaxed() would access hardware with
clocks potentially disabled.

Switch to pm_runtime_resume_and_get() which handles the usage-count
cleanup on failure, check the return value, and unwind the already
registered iommu device on error.

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
---
 drivers/iommu/arm/arm-smmu/qcom_iommu.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
index 71251aecc292..1d04f0a19124 100644
--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
@@ -861,13 +861,17 @@ static int qcom_iommu_device_probe(struct platform_device *pdev)
 	}
 
 	if (qcom_iommu->local_base) {
-		pm_runtime_get_sync(dev);
+		ret = pm_runtime_resume_and_get(dev);
+		if (ret)
+			goto err_iommu_unregister;
 		writel_relaxed(0xffffffff, qcom_iommu->local_base + SMMU_INTR_SEL_NS);
 		pm_runtime_put_sync(dev);
 	}
 
 	return 0;
 
+err_iommu_unregister:
+	iommu_device_unregister(&qcom_iommu->iommu);
 err_sysfs_remove:
 	iommu_device_sysfs_remove(&qcom_iommu->iommu);
 	return ret;
-- 
2.53.0



^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox