[PATCH v4 0/7] clk: add a driver for the ath79 PLL controller

From: Rosen Penev

Date: Sat Nov 14 2026 - 18:42:47 EST


The clocks of the Atheros/Qualcomm ath79 MIPS SoCs are set up by
arch/mips/ath79/clock.c, a CLK_OF_DECLARE driver that registers every
clock before the driver core is up. This series replaces it with a new
driver in drivers/clk.

Only the reference and CPU clocks are registered early, with
CLK_OF_DECLARE_DRIVER(), because the MIPS timer needs the CPU rate from
plat_time_init(). A platform driver bound to the same node registers the
DDR, AHB, MDIO, UART1 and PCIe clocks. Until it does, the early provider
returns -EPROBE_DEFER for them. clk-mt7621 uses the same scheme.

Patches 1 and 2 move the two remaining non-clock duties out of the arch
clock code, so that it only uses its own registers and the clk API: the
QCA956x timer interrupt workaround, and the reference clock that is
read from the bootstrap pins when the device tree has no rate. Patches 3
and 4 drop ATH79_CLK_END, which is not ABI, from the binding header, and
patch 5 adds the UART1 and PCIe PLL clock IDs. Patch 6 adds the new
driver, and patch 7 removes the old code.

Tested on a TP-Link Archer C7 v2 (QCA9558) with an LLVM build. The CPU,
DDR, AHB and reference rates (960, 800, 266.67 and 40 MHz) match those
of the old code. The serial console, both GMACs, the PCIe PLL with a
QCA9880 behind it, and the WMAC all work, and no devices are left
deferred. The debugfs clk_summary, consumers included, is the same as
with v2, and stays the same when the clock-frequency of the reference
clock node is removed. These results are from v3; v4 only changes the
QCA956x rate calculation, which the C7 doesn't use. The other SoCs are
not tested on hardware. For each SoC the rate calculation was compiled
in userspace together with the old code and fed 2 million random
register sets. The results are identical, except where the old code
overflowed 32 bits with register values that no real setup uses, and on
QCA956x, where v4 fixes the upper fractional part of the PLLs.

Changes in v4:
- Fix the upper fractional part of the QCA956x PLLs, which the old
code computed as (hfrac >> 13), always 0, and follow the formula in
the QCA9563 datasheet. NFRAC[17:5] is not zero at reset, so rates now
differ from the old code on QCA956x (review feedback). This part tested on
Archer C7 v4.

v3: https://lore.kernel.org/linux-clk/20261111215729.10683-1-rosenp@xxxxxxxxx/

Changes in v3:
- Register the reference clock read from the bootstrap pins as the
provider of the reference clock node instead of with clkdev, so that
its other consumers, such as the AR933x UART, find it and fw_devlink
doesn't hold the platform driver back when the device tree has no
rate. Drop the clk_get_sys() fallbacks (review feedback).
- Wait for the PCIe PLL update to finish after each write in unprepare
too (review feedback).
- Add the UART1 and PCIe PLL clock IDs in one patch (review feedback).
- Drop ATH79_CLK_END from the binding header instead of growing it, as
the number of clocks is not ABI, after moving the old clock code off
it (review feedback).

v2:https://lore.kernel.org/linux-clk/20261110013646.1582970-1-rosenp@xxxxxxxxx/

Changes in v2:
- Post the new driver as one patch, instead of moving
arch/mips/ath79/clock.c to drivers/clk and cleaning it up over six
patches (review feedback).
- Register only the reference and CPU clocks with CLK_OF_DECLARE, and
the others from a platform driver (review feedback).
- Describe the SoCs with match data, and read the CPU, DDR and AHB
selection of AR934x and later with one function.
- Keep mapping the AR934x SRIF block from its fixed address. It lies
inside the wireless MAC registers, which ath9k claims, so it can't be
a reg entry of the PLL node.
- Drop the clkdev registrations, which have no users.

Claude Code (Claude Opus 5.5) was used while preparing this series. It
wrote most of the new driver from the old one, together with the
userspace test of the rate calculation. I reviewed and tested every
change and take responsibility for it.


Rosen Penev (7):
MIPS: ath79: apply the QCA956x timer workaround in setup
MIPS: ath79: move the bootstrap reference clock to setup
MIPS: ath79: stop using ATH79_CLK_END
dt-bindings: clock: ath79: drop ATH79_CLK_END
dt-bindings: clock: ath79: add the UART1 and PCIe PLL clocks
clk: add a driver for the Atheros/Qualcomm ath79 PLL controller
MIPS: ath79: remove the old clock code

MAINTAINERS | 8 +
arch/mips/ath79/Makefile | 2 +-
arch/mips/ath79/clock.c | 673 ----------------------
arch/mips/ath79/setup.c | 107 ++++
drivers/clk/Kconfig | 12 +
drivers/clk/Makefile | 1 +
drivers/clk/clk-ath79.c | 782 ++++++++++++++++++++++++++
include/dt-bindings/clock/ath79-clk.h | 4 +-
8 files changed, 913 insertions(+), 676 deletions(-)
delete mode 100644 arch/mips/ath79/clock.c
create mode 100644 drivers/clk/clk-ath79.c


base-commit: 630059a5a632377b9b7b487baccde92b7ae1dd47
--
2.56.1