* [PATCH v16 0/9] clk: realtek: Add RTD1625 clock support
@ 2026-11-12 5:25 Yu-Chun Lin
2026-11-12 5:25 ` [PATCH v16 1/9] dt-bindings: clock: Add Realtek RTD1625 Clock & Reset Controller Yu-Chun Lin
` (8 more replies)
0 siblings, 9 replies; 16+ messages in thread
From: Yu-Chun Lin @ 2026-11-12 5:25 UTC (permalink / raw)
To: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou
Cc: linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, james.tai, cy.huang, stanley_chang,
eleanor.lin
Hello,
This patch series adds the clock controller support for Realtek's
RTD1625 SoC platform.
Because the reset controllers share the same register space with the
clock controllers on this platform, we utilize the Auxiliary Bus framework
to decouple them. The clock controllers act as the primary devices,
registering the reset controllers as auxiliary devices.
The series includes:
1. Device Tree Bindings:
- Add bindings for the Realtek RTD1625 Clock & Reset Controllers.
2. Clock Subsystem Infrastructure:
- Introduce a common probe, and add support for basic clocks including
PLLs, gate clocks, mux clocks, and MMC-tuned PLLs.
3. Clock Platform Drivers:
- Add the clock controller drivers for RTD1625-CRT and RTD1625-ISO.
- These drivers provide the clock sources and instantiate the
corresponding auxiliary reset devices.
Best regards,
Yu-Chun Lin
---
Changes in v16:
General:
- Split out the reset controller support into a separate series.
Patch 1 (dt-binding):
- Remove Krzysztof's reviewed-by tag.
- Add 'clock-name' property with a predefined enum list.
- Update 'clocks' property constraints.
- Move the reset ID header to the reset controller series.
Patch 3 (PLL):
- Remove Brian's reviewed-by tag.
- Introduce 'expected_parent_rate' validation in '.determine_rate()' and
'.set_rate()' to safely enforce the fixed input rate requirement.
- In determined_rate, replacing the floor/ceil algorithm with a closest-match
search within [min_rate, max_rate] boundaries.
- Improve comments for spinlock.
- Add '.is_enabled' callback to 'rtk_clk_pll_ro_ops'
Patch 4 (GATE):
- Remove Brian's reviewed-by tag.
- Replace 'CLK_HW_INIT' with 'CLK_HW_INIT_HW' and 'CLK_HW_INIT_FW_NAME' macros
to avoid relying on unstable internal CCF global names.
- Drop all unused NO_PARENT macro and 'rtk_clk_regmap_gate_ro_ops'.
Patch 5 (MUX):
- Remove Brian's reviewed-by tag.
- Replace 'CLK_HW_INIT_PARENTS' with 'CLK_HW_INIT_PARENTS_HW' to use '.parent_hws'
Patch 6 (MMC PLL):
- Remove Brian's reviewed-by tag.
- Move the MMC PLL structs and ops declarations out of clk-pll.h into a new
clk-regmap-pll-mmc.h.
- Add a separate 'struct rtk_clk_pll_mmc_phase' with its own to_clk_pll_mmc_phase().
- Merge prepare/unprepare/is_prepared into enable/disable/is_enabled, as
suggested: there is no sleeping operation.
- Introduce the 'rtk_clk_pll_mmc_div_cfg' table for the SSCPLL analog tuning.
- Introduce the 'rtk_clk_pll_mmc_rate' table.
- determine_rate() selects the closest entry within [min_rate, max_rate]
- set_rate() programs that entry only
- recalc_rate() matches all five raw register fields against the table. However,
only on a miss does it fall back to 'clk_pll_mmc_calc_rate()', which implements
the formula.
Patch 7 & 8 (CRT & ISO clock driver):
- Remove Brian's reviewed-by tag.
- Replace 'const char *' parent arrays with 'struct clk_hw *' arrays.
- Switch all gate, mux, and fixed-factor clock initializations to use '_HW' or
'_FW_NAME' macros.
- Use 'CLK_HW_INIT_FW_NAME' for regmap_pll initialization when referencing external
clocks, and add 'expected_parent_rate' to ensure a safe input rate.
- Refactor eMMC PLL initialization (decoupling phases and appending rate tables).
Patch 9 (DTS):
- Add 'clock-names = "osc27m"' to the 'cc' and 'iso_s_cc' clock controller nodes.
- Explicitly wire up internal parent clocks from the 'cc' controller to the 'ic'
clock controller, along with their corresponding 'clock-names'.
v15: https://lore.kernel.org/lkml/20261002074331.3066919-1-eleanor.lin@realtek.com/
v14: https://lore.kernel.org/lkml/20260901072446.2563145-1-eleanor.lin@realtek.com/
v13: https://lore.kernel.org/lkml/20260812020009.3480538-1-eleanor.lin@realtek.com/
v12: https://lore.kernel.org/lkml/20260804163807.1285869-1-eleanor.lin@realtek.com/
v11: https://lore.kernel.org/lkml/20260728142806.1954638-1-eleanor.lin@realtek.com/
v10: https://lore.kernel.org/lkml/20260713155630.3054636-1-eleanor.lin@realtek.com/
v9: https://lore.kernel.org/lkml/20260624112940.3475605-1-eleanor.lin@realtek.com/
v8: https://lore.kernel.org/lkml/20260610080824.255063-1-eleanor.lin@realtek.com/
v7: https://lore.kernel.org/lkml/20260508111641.3192177-1-eleanor.lin@realtek.com/
v6: https://lore.kernel.org/lkml/20260402073957.2742459-1-eleanor.lin@realtek.com/
v5: https://lore.kernel.org/lkml/20260324025332.3416977-1-eleanor.lin@realtek.com/
v4: https://lore.kernel.org/lkml/20260313081100.596224-1-eleanor.lin@realtek.com/
v3: https://lore.kernel.org/lkml/20260122110857.12995-1-eleanor.lin@realtek.com/
v2: https://lore.kernel.org/lkml/20260113112333.821-1-eleanor.lin@realtek.com/
v1: https://lore.kernel.org/lkml/20251229075313.27254-1-eleanor.lin@realtek.com/
Cheng-Yu Lee (7):
clk: realtek: Introduce common probe()
clk: realtek: Add support for phase locked loops (PLLs)
clk: realtek: Add support for gate clock
clk: realtek: Add support for mux clock
clk: realtek: Add support for MMC-tuned PLL clocks
clk: realtek: Add RTD1625-CRT clock controller driver
clk: realtek: Add RTD1625-ISO clock controller driver
Yu-Chun Lin (2):
dt-bindings: clock: Add Realtek RTD1625 Clock & Reset Controller
arm64: dts: realtek: Add clock support for RTD1625
.../bindings/clock/realtek,rtd1625-clk.yaml | 95 ++
MAINTAINERS | 7 +
arch/arm64/boot/dts/realtek/kent.dtsi | 41 +
drivers/clk/Kconfig | 1 +
drivers/clk/Makefile | 1 +
drivers/clk/realtek/Kconfig | 46 +
drivers/clk/realtek/Makefile | 12 +
drivers/clk/realtek/clk-regmap-gate.c | 59 ++
drivers/clk/realtek/clk-regmap-gate.h | 54 ++
drivers/clk/realtek/clk-regmap-mux.c | 40 +
drivers/clk/realtek/clk-regmap-mux.h | 42 +
drivers/clk/realtek/clk-regmap-pll-mmc.c | 457 +++++++++
drivers/clk/realtek/clk-regmap-pll-mmc.h | 66 ++
drivers/clk/realtek/clk-regmap-pll.c | 219 +++++
drivers/clk/realtek/clk-regmap-pll.h | 53 ++
drivers/clk/realtek/clk-rtd1625-crt.c | 878 ++++++++++++++++++
drivers/clk/realtek/clk-rtd1625-iso.c | 140 +++
drivers/clk/realtek/clk-rtk-common.c | 84 ++
drivers/clk/realtek/clk-rtk-common.h | 37 +
drivers/clk/realtek/freq_table.c | 63 ++
drivers/clk/realtek/freq_table.h | 24 +
.../dt-bindings/clock/realtek,rtd1625-clk.h | 166 ++++
22 files changed, 2585 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/realtek,rtd1625-clk.yaml
create mode 100644 drivers/clk/realtek/Kconfig
create mode 100644 drivers/clk/realtek/Makefile
create mode 100644 drivers/clk/realtek/clk-regmap-gate.c
create mode 100644 drivers/clk/realtek/clk-regmap-gate.h
create mode 100644 drivers/clk/realtek/clk-regmap-mux.c
create mode 100644 drivers/clk/realtek/clk-regmap-mux.h
create mode 100644 drivers/clk/realtek/clk-regmap-pll-mmc.c
create mode 100644 drivers/clk/realtek/clk-regmap-pll-mmc.h
create mode 100644 drivers/clk/realtek/clk-regmap-pll.c
create mode 100644 drivers/clk/realtek/clk-regmap-pll.h
create mode 100644 drivers/clk/realtek/clk-rtd1625-crt.c
create mode 100644 drivers/clk/realtek/clk-rtd1625-iso.c
create mode 100644 drivers/clk/realtek/clk-rtk-common.c
create mode 100644 drivers/clk/realtek/clk-rtk-common.h
create mode 100644 drivers/clk/realtek/freq_table.c
create mode 100644 drivers/clk/realtek/freq_table.h
create mode 100644 include/dt-bindings/clock/realtek,rtd1625-clk.h
--
2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v16 1/9] dt-bindings: clock: Add Realtek RTD1625 Clock & Reset Controller
2026-11-12 5:25 [PATCH v16 0/9] clk: realtek: Add RTD1625 clock support Yu-Chun Lin
@ 2026-11-12 5:25 ` Yu-Chun Lin
2026-11-12 9:23 ` Krzysztof Kozlowski
2026-11-12 5:25 ` [PATCH v16 2/9] clk: realtek: Introduce common probe() Yu-Chun Lin
` (7 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Yu-Chun Lin @ 2026-11-12 5:25 UTC (permalink / raw)
To: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou
Cc: linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, james.tai, cy.huang, stanley_chang,
eleanor.lin
Add DT binding schema for Realtek RTD1625 clock and reset controller
Co-developed-by: Cheng-Yu Lee <cylee12@realtek.com>
Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
Changes in v16:
- Remove Krzysztof's reviewed-by tag.
- Add 'clock-name' property with a predefined enum list.
- Update 'clocks' property constraints.
- Move the reset ID header to the reset controller series.
---
.../bindings/clock/realtek,rtd1625-clk.yaml | 95 ++++++++++
MAINTAINERS | 6 +
.../dt-bindings/clock/realtek,rtd1625-clk.h | 166 ++++++++++++++++++
3 files changed, 267 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/realtek,rtd1625-clk.yaml
create mode 100644 include/dt-bindings/clock/realtek,rtd1625-clk.h
diff --git a/Documentation/devicetree/bindings/clock/realtek,rtd1625-clk.yaml b/Documentation/devicetree/bindings/clock/realtek,rtd1625-clk.yaml
new file mode 100644
index 000000000000..31213e401111
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/realtek,rtd1625-clk.yaml
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/realtek,rtd1625-clk.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek RTD1625 Clock & Reset Controller
+
+maintainers:
+ - Cheng-Yu Lee <cylee12@realtek.com>
+ - Yu-Chun Lin <eleanor.lin@realtek.com>
+
+description:
+ The Realtek RTD1625 Clock Controller manages and distributes clock
+ signals to various controllers and implements a Reset Controller for the
+ SoC peripherals.
+
+properties:
+ compatible:
+ enum:
+ - realtek,rtd1625-crt-clk
+ - realtek,rtd1625-iso-clk
+ - realtek,rtd1625-iso-s-clk
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ minItems: 1
+ maxItems: 5
+
+ clock-names:
+ minItems: 1
+ maxItems: 5
+
+ "#clock-cells":
+ const: 1
+
+ "#reset-cells":
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - "#clock-cells"
+ - "#reset-cells"
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ const: realtek,rtd1625-iso-clk
+
+ then:
+ properties:
+ clocks:
+ items:
+ - description: External 27 MHz oscillator
+ - description: CRT SYS clock input
+ - description: CRT SYSH clock input
+ - description: CRT DDSA divide-by-four clock input
+ - description: CRT miscellaneous gate clock input
+
+ clock-names:
+ items:
+ - const: osc27m
+ - const: clk_sys
+ - const: clk_sysh
+ - const: clk_ddsa_div4
+ - const: clk_en_misc
+
+ else:
+ properties:
+ clocks:
+ items:
+ - description: External 27 MHz oscillator
+
+ clock-names:
+ items:
+ - const: osc27m
+
+additionalProperties: false
+
+examples:
+ - |
+ clock-controller@98000000 {
+ compatible = "realtek,rtd1625-crt-clk";
+ reg = <0x98000000 0x1000>;
+ clocks = <&osc27m>;
+ clock-names = "osc27m";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 93abbb315065..c51f9fc157c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23537,6 +23537,12 @@ S: Maintained
F: include/sound/rt*.h
F: sound/soc/codecs/rt*
+REALTEK CLOCK DRIVERS
+M: Cheng-Yu Lee <cylee12@realtek.com>
+M: Yu-Chun Lin <eleanor.lin@realtek.com>
+S: Supported
+F: include/dt-bindings/clock/realtek*
+
REALTEK OTTO WATCHDOG
M: Sander Vanheule <sander@svanheule.net>
L: linux-watchdog@vger.kernel.org
diff --git a/include/dt-bindings/clock/realtek,rtd1625-clk.h b/include/dt-bindings/clock/realtek,rtd1625-clk.h
new file mode 100644
index 000000000000..ea4e6bb77736
--- /dev/null
+++ b/include/dt-bindings/clock/realtek,rtd1625-clk.h
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2026 Realtek Semiconductor Corp.
+ */
+#ifndef __DT_BINDINGS_RTK_CLOCK_RTD1625_H
+#define __DT_BINDINGS_RTK_CLOCK_RTD1625_H
+
+#define RTD1625_CRT_CLK_EN_MISC 0
+#define RTD1625_CRT_CLK_EN_PCIE0 1
+#define RTD1625_CRT_CLK_EN_DIP 2
+#define RTD1625_CRT_CLK_EN_GSPI 3
+#define RTD1625_CRT_CLK_EN_ISO_MISC 5
+#define RTD1625_CRT_CLK_EN_SDS 6
+#define RTD1625_CRT_CLK_EN_HDMI 7
+#define RTD1625_CRT_CLK_EN_GPU 9
+#define RTD1625_CRT_CLK_EN_VE1 10
+#define RTD1625_CRT_CLK_EN_VE2 11
+#define RTD1625_CRT_CLK_EN_MD 18
+#define RTD1625_CRT_CLK_EN_TP 19
+#define RTD1625_CRT_CLK_EN_RCIC 20
+#define RTD1625_CRT_CLK_EN_NF 21
+#define RTD1625_CRT_CLK_EN_EMMC 22
+#define RTD1625_CRT_CLK_EN_SD 23
+#define RTD1625_CRT_CLK_EN_SDIO_IP 24
+#define RTD1625_CRT_CLK_EN_MIPI_CSI 25
+#define RTD1625_CRT_CLK_EN_EMMC_IP 26
+#define RTD1625_CRT_CLK_EN_SDIO 27
+#define RTD1625_CRT_CLK_EN_SD_IP 28
+#define RTD1625_CRT_CLK_EN_TPB 30
+#define RTD1625_CRT_CLK_EN_MISC_SC1 31
+#define RTD1625_CRT_CLK_EN_MISC_I2C_3 32
+#define RTD1625_CRT_CLK_EN_ACPU 33
+#define RTD1625_CRT_CLK_EN_JPEG 34
+#define RTD1625_CRT_CLK_EN_MISC_SC0 37
+#define RTD1625_CRT_CLK_EN_HDMIRX 45
+#define RTD1625_CRT_CLK_EN_HSE 46
+#define RTD1625_CRT_CLK_EN_FAN 49
+#define RTD1625_CRT_CLK_EN_SATA_WRAP_SYS 52
+#define RTD1625_CRT_CLK_EN_SATA_WRAP_SYSH 53
+#define RTD1625_CRT_CLK_EN_SATA_MAC_SYSH 54
+#define RTD1625_CRT_CLK_EN_R2RDSC 55
+#define RTD1625_CRT_CLK_EN_TPC 56
+#define RTD1625_CRT_CLK_EN_PCIE1 57
+#define RTD1625_CRT_CLK_EN_MISC_I2C_4 58
+#define RTD1625_CRT_CLK_EN_MISC_I2C_5 59
+#define RTD1625_CRT_CLK_EN_TSIO 60
+#define RTD1625_CRT_CLK_EN_VE4 61
+#define RTD1625_CRT_CLK_EN_EDP 62
+#define RTD1625_CRT_CLK_EN_TSIO_TRX 63
+#define RTD1625_CRT_CLK_EN_PCIE2 64
+#define RTD1625_CRT_CLK_EN_EARC 66
+#define RTD1625_CRT_CLK_EN_LITE 67
+#define RTD1625_CRT_CLK_EN_MIPI_DSI 68
+#define RTD1625_CRT_CLK_EN_NPUPP 69
+#define RTD1625_CRT_CLK_EN_NPU 70
+#define RTD1625_CRT_CLK_EN_AUCPU0 71
+#define RTD1625_CRT_CLK_EN_AUCPU1 72
+#define RTD1625_CRT_CLK_EN_NSRAM 73
+#define RTD1625_CRT_CLK_EN_HDMITOP 74
+#define RTD1625_CRT_CLK_EN_AUCPU_ISO_NPU 76
+#define RTD1625_CRT_CLK_EN_KEYLADDER 77
+#define RTD1625_CRT_CLK_EN_IFCP_KLM 78
+#define RTD1625_CRT_CLK_EN_IFCP 79
+#define RTD1625_CRT_CLK_EN_MDL_GENPW 80
+#define RTD1625_CRT_CLK_EN_MDL_CHIP 81
+#define RTD1625_CRT_CLK_EN_MDL_IP 82
+#define RTD1625_CRT_CLK_EN_MDLM2M 83
+#define RTD1625_CRT_CLK_EN_MDL_XTAL 84
+#define RTD1625_CRT_CLK_EN_TEST_MUX 85
+#define RTD1625_CRT_CLK_EN_DLA 86
+#define RTD1625_CRT_CLK_EN_TPCW 88
+#define RTD1625_CRT_CLK_EN_GPU_TS_SRC 89
+#define RTD1625_CRT_CLK_EN_VI 91
+#define RTD1625_CRT_CLK_EN_LVDS1 92
+#define RTD1625_CRT_CLK_EN_LVDS2 93
+#define RTD1625_CRT_CLK_EN_AUCPU 94
+#define RTD1625_CRT_CLK_EN_UR1 96
+#define RTD1625_CRT_CLK_EN_UR2 97
+#define RTD1625_CRT_CLK_EN_UR3 98
+#define RTD1625_CRT_CLK_EN_UR4 99
+#define RTD1625_CRT_CLK_EN_UR5 100
+#define RTD1625_CRT_CLK_EN_UR6 101
+#define RTD1625_CRT_CLK_EN_UR7 102
+#define RTD1625_CRT_CLK_EN_UR8 103
+#define RTD1625_CRT_CLK_EN_UR9 104
+#define RTD1625_CRT_CLK_EN_UR_TOP 105
+#define RTD1625_CRT_CLK_EN_MISC_I2C_7 110
+#define RTD1625_CRT_CLK_EN_MISC_I2C_6 111
+#define RTD1625_CRT_CLK_EN_SPI0 112
+#define RTD1625_CRT_CLK_EN_SPI1 113
+#define RTD1625_CRT_CLK_EN_SPI2 114
+#define RTD1625_CRT_CLK_EN_LSADC0 120
+#define RTD1625_CRT_CLK_EN_LSADC1 121
+#define RTD1625_CRT_CLK_EN_ISOMIS_DMA 122
+#define RTD1625_CRT_CLK_EN_DPTX 124
+#define RTD1625_CRT_CLK_EN_NPU_MIPI_CSI 125
+#define RTD1625_CRT_CLK_EN_EDPTX 126
+#define RTD1625_CRT_CLK_HIFI 128
+#define RTD1625_CRT_CLK_NPU_MIPI_CSI 129
+#define RTD1625_CRT_CLK_NPU 130
+#define RTD1625_CRT_CLK_NPU_SYSH 132
+#define RTD1625_CRT_CLK_HIFI_SCPU 133
+#define RTD1625_CRT_CLK_GPU 134
+#define RTD1625_CRT_CLK_GPU2D 135
+#define RTD1625_CRT_CLK_MIPI_DSI_PCLK 136
+#define RTD1625_CRT_CLK_VE1 137
+#define RTD1625_CRT_CLK_VE2 138
+#define RTD1625_CRT_CLK_VE4 139
+#define RTD1625_CRT_CLK_SYS 141
+#define RTD1625_CRT_CLK_SYSH 142
+#define RTD1625_CRT_PLL_SDIO_REF 145
+#define RTD1625_CRT_PLL_CR_REF 146
+#define RTD1625_CRT_PLL_EMMC_REF 147
+#define RTD1625_CRT_CLK_MIS_SC0 148
+#define RTD1625_CRT_CLK_MIS_SC1 149
+#define RTD1625_CRT_PLL_SCPU 150
+#define RTD1625_CRT_PLL_VE1 151
+#define RTD1625_CRT_PLL_DDSA 152
+#define RTD1625_CRT_PLL_PSAUDA1 153
+#define RTD1625_CRT_PLL_PSAUDA2 154
+#define RTD1625_CRT_PLL_BUS 155
+#define RTD1625_CRT_PLL_SDIO 156
+#define RTD1625_CRT_PLL_SDIO_VP0 157
+#define RTD1625_CRT_PLL_SDIO_VP1 158
+#define RTD1625_CRT_PLL_DCSB 159
+#define RTD1625_CRT_PLL_GPU 160
+#define RTD1625_CRT_PLL_NPU 161
+#define RTD1625_CRT_PLL_VE2 162
+#define RTD1625_CRT_PLL_HIFI 163
+#define RTD1625_CRT_PLL_SD 164
+#define RTD1625_CRT_PLL_SD_VP0 165
+#define RTD1625_CRT_PLL_SD_VP1 166
+#define RTD1625_CRT_PLL_EMMC 167
+#define RTD1625_CRT_PLL_EMMC_VP0 168
+#define RTD1625_CRT_PLL_EMMC_VP1 169
+#define RTD1625_CRT_PLL_ACPU 170
+#define RTD1625_CRT_CLK_DET 171
+#define RTD1625_CRT_PLL_VODMA 172
+#define RTD1625_CRT_CLK_DDSA_DIV4 173
+
+#define RTD1625_ISO_CLK_EN_USB_P4 0
+#define RTD1625_ISO_CLK_EN_USB_P3 1
+#define RTD1625_ISO_CLK_EN_MISC_CEC0 2
+#define RTD1625_ISO_CLK_EN_CBUSRX_SYS 3
+#define RTD1625_ISO_CLK_EN_CBUSTX_SYS 4
+#define RTD1625_ISO_CLK_EN_CBUS_SYS 5
+#define RTD1625_ISO_CLK_EN_CBUS_OSC 6
+#define RTD1625_ISO_CLK_EN_MISC_UR0 8
+#define RTD1625_ISO_CLK_EN_I2C0 9
+#define RTD1625_ISO_CLK_EN_I2C1 10
+#define RTD1625_ISO_CLK_EN_ETN_250M 11
+#define RTD1625_ISO_CLK_EN_ETN_SYS 12
+#define RTD1625_ISO_CLK_EN_USB_DRD 13
+#define RTD1625_ISO_CLK_EN_USB_HOST 14
+#define RTD1625_ISO_CLK_EN_USB_U3_HOST 15
+#define RTD1625_ISO_CLK_EN_USB 16
+#define RTD1625_ISO_CLK_EN_VTC 17
+#define RTD1625_ISO_CLK_EN_MISC_VFD 18
+
+#define RTD1625_ISO_S_CLK_EN_ISOM_MIS 0
+#define RTD1625_ISO_S_CLK_EN_ISOM_GPIOM 1
+#define RTD1625_ISO_S_CLK_EN_TIMER7 2
+#define RTD1625_ISO_S_CLK_EN_IRDA 3
+#define RTD1625_ISO_S_CLK_EN_UR10 4
+
+#endif /* __DT_BINDINGS_RTK_CLOCK_RTD1625_H */
--
2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v16 2/9] clk: realtek: Introduce common probe()
2026-11-12 5:25 [PATCH v16 0/9] clk: realtek: Add RTD1625 clock support Yu-Chun Lin
2026-11-12 5:25 ` [PATCH v16 1/9] dt-bindings: clock: Add Realtek RTD1625 Clock & Reset Controller Yu-Chun Lin
@ 2026-11-12 5:25 ` Yu-Chun Lin
2026-11-12 17:14 ` Brian Masney
2026-11-12 5:25 ` [PATCH v16 3/9] clk: realtek: Add support for phase locked loops (PLLs) Yu-Chun Lin
` (6 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Yu-Chun Lin @ 2026-11-12 5:25 UTC (permalink / raw)
To: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou
Cc: linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, james.tai, cy.huang, stanley_chang,
eleanor.lin, Brian Masney
From: Cheng-Yu Lee <cylee12@realtek.com>
Add rtk_clk_probe() to set up the shared regmap, register clock hardware,
and add the clock provider.
Additionally, if the "#reset-cells" property is present in the device tree,
it creates and registers an auxiliary device using the provided aux_name.
This allows the dedicated reset driver to bind to this device, enabling
both clock and reset drivers to share the same regmap.
Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
Reviewed-by: Brian Masney <bmasney@redhat.com>
---
MAINTAINERS | 1 +
drivers/clk/Kconfig | 1 +
drivers/clk/Makefile | 1 +
drivers/clk/realtek/Kconfig | 29 ++++++++++
drivers/clk/realtek/Makefile | 4 ++
drivers/clk/realtek/clk-rtk-common.c | 84 ++++++++++++++++++++++++++++
drivers/clk/realtek/clk-rtk-common.h | 37 ++++++++++++
7 files changed, 157 insertions(+)
create mode 100644 drivers/clk/realtek/Kconfig
create mode 100644 drivers/clk/realtek/Makefile
create mode 100644 drivers/clk/realtek/clk-rtk-common.c
create mode 100644 drivers/clk/realtek/clk-rtk-common.h
diff --git a/MAINTAINERS b/MAINTAINERS
index c51f9fc157c8..54873a33038b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23541,6 +23541,7 @@ REALTEK CLOCK DRIVERS
M: Cheng-Yu Lee <cylee12@realtek.com>
M: Yu-Chun Lin <eleanor.lin@realtek.com>
S: Supported
+F: drivers/clk/realtek/*
F: include/dt-bindings/clock/realtek*
REALTEK OTTO WATCHDOG
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 37a8e35d4178..eb9256459251 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -532,6 +532,7 @@ source "drivers/clk/nuvoton/Kconfig"
source "drivers/clk/pistachio/Kconfig"
source "drivers/clk/qcom/Kconfig"
source "drivers/clk/ralink/Kconfig"
+source "drivers/clk/realtek/Kconfig"
source "drivers/clk/renesas/Kconfig"
source "drivers/clk/rockchip/Kconfig"
source "drivers/clk/samsung/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 52d138d4ffc8..3930bf20667b 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -156,6 +156,7 @@ obj-$(CONFIG_COMMON_CLK_PISTACHIO) += pistachio/
obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/
obj-y += ralink/
+obj-$(CONFIG_COMMON_CLK_REALTEK) += realtek/
obj-y += renesas/
obj-$(CONFIG_COMMON_CLK_ROCKCHIP) += rockchip/
obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
diff --git a/drivers/clk/realtek/Kconfig b/drivers/clk/realtek/Kconfig
new file mode 100644
index 000000000000..e8deccf93f94
--- /dev/null
+++ b/drivers/clk/realtek/Kconfig
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config COMMON_CLK_REALTEK
+ tristate "Clock driver for Realtek SoCs"
+ depends on ARCH_REALTEK || COMPILE_TEST
+ default ARCH_REALTEK
+ help
+ Enable the common clock framework infrastructure for Realtek
+ system-on-chip platforms.
+
+ This provides the base support required by individual Realtek
+ clock controller drivers to expose clocks to peripheral devices.
+
+ If you have a Realtek-based platform, say Y.
+
+if COMMON_CLK_REALTEK
+
+config RTK_CLK_COMMON
+ tristate "Realtek Clock Common"
+ select AUXILIARY_BUS
+ select REGMAP_MMIO
+ help
+ Common helper code shared by Realtek clock controller drivers.
+
+ This provides utility functions and data structures used by
+ multiple Realtek clock implementations. It also provides the
+ infrastructure to spawn reset controllers via the auxiliary bus
+ where required.
+
+endif
diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
new file mode 100644
index 000000000000..13000ed4ba11
--- /dev/null
+++ b/drivers/clk/realtek/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_RTK_CLK_COMMON) += clk-rtk.o
+
+clk-rtk-y += clk-rtk-common.o
diff --git a/drivers/clk/realtek/clk-rtk-common.c b/drivers/clk/realtek/clk-rtk-common.c
new file mode 100644
index 000000000000..7df6d04bb95a
--- /dev/null
+++ b/drivers/clk/realtek/clk-rtk-common.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019-2026 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <cylee12@realtek.com>
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include "clk-rtk-common.h"
+
+static int rtk_reset_controller_register(struct device *dev, const char *aux_name,
+ struct regmap *map)
+{
+ struct auxiliary_device *adev;
+
+ if (!of_property_present(dev->of_node, "#reset-cells"))
+ return 0;
+
+ if (!aux_name) {
+ dev_err(dev, "DTS requires reset controller, but aux_name is missing\n");
+ return -EINVAL;
+ }
+
+ adev = devm_auxiliary_device_create(dev, aux_name, (void *)map);
+ if (!adev)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static const struct regmap_config rtk_clk_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+};
+
+int rtk_clk_probe(struct platform_device *pdev, const struct rtk_clk_desc *desc)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap;
+ void __iomem *base;
+ struct clk_hw *hw;
+ int i, ret;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ regmap = devm_regmap_init_mmio(dev, base, &rtk_clk_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ for (i = 0; i < desc->num_clks; i++)
+ desc->clks[i]->regmap = regmap;
+
+ for (i = 0; i < desc->clk_data->num; i++) {
+ hw = desc->clk_data->hws[i];
+ if (!hw)
+ continue;
+
+ ret = devm_clk_hw_register(dev, hw);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register hw of clk%d\n", i);
+ }
+
+ ret = rtk_reset_controller_register(dev, desc->aux_name, regmap);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register reset controller\n");
+
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+ desc->clk_data);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to add clock provider\n");
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(rtk_clk_probe, "CLK_REALTEK");
+
+MODULE_DESCRIPTION("Realtek clock infrastructure");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/realtek/clk-rtk-common.h b/drivers/clk/realtek/clk-rtk-common.h
new file mode 100644
index 000000000000..de3f23120b53
--- /dev/null
+++ b/drivers/clk/realtek/clk-rtk-common.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2016-2026 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <cylee12@realtek.com>
+ */
+
+#ifndef __CLK_REALTEK_COMMON_H
+#define __CLK_REALTEK_COMMON_H
+
+#include <linux/clk-provider.h>
+
+#define __rtk_clk_regmap_hw(_p) ((_p)->hw)
+
+struct device;
+struct platform_device;
+struct regmap;
+
+struct rtk_clk_regmap {
+ struct clk_hw hw;
+ struct regmap *regmap;
+};
+
+struct rtk_clk_desc {
+ struct clk_hw_onecell_data *clk_data;
+ struct rtk_clk_regmap **clks;
+ size_t num_clks;
+ char *aux_name;
+};
+
+static inline struct rtk_clk_regmap *to_rtk_clk_regmap(struct clk_hw *hw)
+{
+ return container_of(hw, struct rtk_clk_regmap, hw);
+}
+
+int rtk_clk_probe(struct platform_device *pdev, const struct rtk_clk_desc *desc);
+
+#endif /* __CLK_REALTEK_COMMON_H */
--
2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v16 3/9] clk: realtek: Add support for phase locked loops (PLLs)
2026-11-12 5:25 [PATCH v16 0/9] clk: realtek: Add RTD1625 clock support Yu-Chun Lin
2026-11-12 5:25 ` [PATCH v16 1/9] dt-bindings: clock: Add Realtek RTD1625 Clock & Reset Controller Yu-Chun Lin
2026-11-12 5:25 ` [PATCH v16 2/9] clk: realtek: Introduce common probe() Yu-Chun Lin
@ 2026-11-12 5:25 ` Yu-Chun Lin
2026-11-12 17:14 ` Brian Masney
2026-11-12 5:25 ` [PATCH v16 4/9] clk: realtek: Add support for gate clock Yu-Chun Lin
` (5 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Yu-Chun Lin @ 2026-11-12 5:25 UTC (permalink / raw)
To: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou
Cc: linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, james.tai, cy.huang, stanley_chang,
eleanor.lin
From: Cheng-Yu Lee <cylee12@realtek.com>
Provide a full set of PLL operations for programmable PLLs and a read-only
variant for fixed or hardware-managed PLLs.
Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
Changes in v16:
- Remove Brian's reviewed-by tag.
- Introduce 'expected_parent_rate' validation in '.determine_rate()' and
'.set_rate()' to safely enforce the fixed input rate requirement.
- In determined_rate, replacing the floor/ceil algorithm with a closest-match
search within [min_rate, max_rate] boundaries.
- Improve comments for spinlock.
- Add '.is_enabled' callback to 'rtk_clk_pll_ro_ops'
---
drivers/clk/realtek/Makefile | 2 +
drivers/clk/realtek/clk-regmap-pll.c | 219 +++++++++++++++++++++++++++
drivers/clk/realtek/clk-regmap-pll.h | 53 +++++++
drivers/clk/realtek/freq_table.c | 62 ++++++++
drivers/clk/realtek/freq_table.h | 24 +++
5 files changed, 360 insertions(+)
create mode 100644 drivers/clk/realtek/clk-regmap-pll.c
create mode 100644 drivers/clk/realtek/clk-regmap-pll.h
create mode 100644 drivers/clk/realtek/freq_table.c
create mode 100644 drivers/clk/realtek/freq_table.h
diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
index 13000ed4ba11..6fbe6e07b760 100644
--- a/drivers/clk/realtek/Makefile
+++ b/drivers/clk/realtek/Makefile
@@ -2,3 +2,5 @@
obj-$(CONFIG_RTK_CLK_COMMON) += clk-rtk.o
clk-rtk-y += clk-rtk-common.o
+clk-rtk-y += clk-regmap-pll.o
+clk-rtk-y += freq_table.o
diff --git a/drivers/clk/realtek/clk-regmap-pll.c b/drivers/clk/realtek/clk-regmap-pll.c
new file mode 100644
index 000000000000..e43e78a36647
--- /dev/null
+++ b/drivers/clk/realtek/clk-regmap-pll.c
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024-2026 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <cylee12@realtek.com>
+ */
+
+#include <linux/export.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+#include "clk-regmap-pll.h"
+
+#define TIMEOUT 500
+
+static inline struct rtk_clk_regmap_pll *to_rtk_clk_regmap_pll(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap *clkr = to_rtk_clk_regmap(hw);
+
+ return container_of(clkr, struct rtk_clk_regmap_pll, clkr);
+}
+
+static int wait_freq_ready(struct rtk_clk_regmap_pll *clkp)
+{
+ u32 pollval;
+
+ /*
+ * Optional register: return success if not provided.
+ */
+ if (!clkp->freq_ready_reg)
+ return 0;
+
+ return regmap_read_poll_timeout_atomic(clkp->clkr.regmap, clkp->freq_ready_reg, pollval,
+ (pollval & clkp->freq_ready_mask) == clkp->freq_ready_val, 1, TIMEOUT);
+}
+
+static bool is_power_on(struct rtk_clk_regmap_pll *clkp)
+{
+ u32 val;
+
+ /*
+ * If the PLL does not provide a power register, it is considered
+ * to be always powered.
+ */
+ if (!clkp->power_reg)
+ return true;
+
+ if (regmap_read(clkp->clkr.regmap, clkp->power_reg, &val))
+ return false;
+
+ return (val & clkp->power_mask) == clkp->power_val_on;
+}
+
+static void rtk_clk_regmap_pll_disable(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap_pll *clkp = to_rtk_clk_regmap_pll(hw);
+ unsigned long flags;
+
+ if (!clkp->seq_power_off)
+ return;
+
+ spin_lock_irqsave(&clkp->lock, flags);
+
+ regmap_multi_reg_write(clkp->clkr.regmap, clkp->seq_power_off,
+ clkp->num_seq_power_off);
+
+ spin_unlock_irqrestore(&clkp->lock, flags);
+}
+
+static int rtk_clk_regmap_pll_is_enabled(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap_pll *clkp = to_rtk_clk_regmap_pll(hw);
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&clkp->lock, flags);
+
+ ret = is_power_on(clkp);
+
+ spin_unlock_irqrestore(&clkp->lock, flags);
+
+ return ret;
+}
+
+static int rtk_clk_regmap_pll_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct rtk_clk_regmap_pll *clkp = to_rtk_clk_regmap_pll(hw);
+ const struct rtk_freq_table *ftblv = NULL;
+
+ if (clkp->expected_parent_rate &&
+ req->best_parent_rate != clkp->expected_parent_rate)
+ return -EINVAL;
+
+ ftblv = ftbl_find_closest_by_rate(clkp->freq_tbl, req->rate,
+ req->min_rate, req->max_rate);
+ if (!ftblv)
+ return -EINVAL;
+
+ req->rate = ftblv->rate;
+
+ return 0;
+}
+
+static unsigned long rtk_clk_regmap_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct rtk_clk_regmap_pll *clkp = to_rtk_clk_regmap_pll(hw);
+ const struct rtk_freq_table *fv;
+ unsigned long flags;
+ u32 freq_val;
+
+ spin_lock_irqsave(&clkp->lock, flags);
+
+ if (regmap_read(clkp->clkr.regmap, clkp->freq_reg, &freq_val)) {
+ spin_unlock_irqrestore(&clkp->lock, flags);
+ return 0;
+ }
+
+ freq_val &= clkp->freq_mask;
+
+ fv = ftbl_find_by_val_with_mask(clkp->freq_tbl, clkp->freq_mask,
+ freq_val);
+
+ spin_unlock_irqrestore(&clkp->lock, flags);
+
+ return fv ? fv->rate : 0;
+}
+
+static int rtk_clk_regmap_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct rtk_clk_regmap_pll *clkp = to_rtk_clk_regmap_pll(hw);
+ const struct rtk_freq_table *fv;
+ unsigned long flags;
+ int ret;
+
+ if (clkp->expected_parent_rate && parent_rate != clkp->expected_parent_rate)
+ return -EINVAL;
+
+ fv = ftbl_find_by_rate(clkp->freq_tbl, rate);
+ if (!fv || fv->rate != rate)
+ return -EINVAL;
+
+ spin_lock_irqsave(&clkp->lock, flags);
+
+ if (clkp->seq_pre_set_freq) {
+ ret = regmap_multi_reg_write(clkp->clkr.regmap, clkp->seq_pre_set_freq,
+ clkp->num_seq_pre_set_freq);
+ if (ret)
+ goto unlock;
+ }
+
+ ret = regmap_update_bits(clkp->clkr.regmap, clkp->freq_reg,
+ clkp->freq_mask, fv->val);
+ if (ret)
+ goto unlock;
+
+ if (clkp->seq_post_set_freq) {
+ ret = regmap_multi_reg_write(clkp->clkr.regmap, clkp->seq_post_set_freq,
+ clkp->num_seq_post_set_freq);
+ if (ret)
+ goto unlock;
+ }
+
+ if (is_power_on(clkp)) {
+ ret = wait_freq_ready(clkp);
+ if (ret)
+ goto unlock;
+ }
+
+unlock:
+ spin_unlock_irqrestore(&clkp->lock, flags);
+
+ return ret;
+}
+
+static int rtk_clk_regmap_pll_enable(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap_pll *clkp = to_rtk_clk_regmap_pll(hw);
+ unsigned long flags;
+ int ret = 0;
+
+ if (!clkp->seq_power_on)
+ return ret;
+
+ spin_lock_irqsave(&clkp->lock, flags);
+
+ if (is_power_on(clkp))
+ goto unlock;
+
+ ret = regmap_multi_reg_write(clkp->clkr.regmap, clkp->seq_power_on,
+ clkp->num_seq_power_on);
+ if (ret)
+ goto unlock;
+
+ ret = wait_freq_ready(clkp);
+ if (ret)
+ goto unlock;
+
+unlock:
+ spin_unlock_irqrestore(&clkp->lock, flags);
+
+ return ret;
+}
+
+const struct clk_ops rtk_clk_pll_ops = {
+ .enable = rtk_clk_regmap_pll_enable,
+ .disable = rtk_clk_regmap_pll_disable,
+ .is_enabled = rtk_clk_regmap_pll_is_enabled,
+ .recalc_rate = rtk_clk_regmap_pll_recalc_rate,
+ .determine_rate = rtk_clk_regmap_pll_determine_rate,
+ .set_rate = rtk_clk_regmap_pll_set_rate,
+};
+EXPORT_SYMBOL_NS_GPL(rtk_clk_pll_ops, "CLK_REALTEK");
+
+const struct clk_ops rtk_clk_pll_ro_ops = {
+ .is_enabled = rtk_clk_regmap_pll_is_enabled,
+ .recalc_rate = rtk_clk_regmap_pll_recalc_rate,
+};
+EXPORT_SYMBOL_NS_GPL(rtk_clk_pll_ro_ops, "CLK_REALTEK");
diff --git a/drivers/clk/realtek/clk-regmap-pll.h b/drivers/clk/realtek/clk-regmap-pll.h
new file mode 100644
index 000000000000..f6fac6b4ac90
--- /dev/null
+++ b/drivers/clk/realtek/clk-regmap-pll.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2017-2026 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <cylee12@realtek.com>
+ */
+
+#ifndef __CLK_REALTEK_CLK_PLL_H
+#define __CLK_REALTEK_CLK_PLL_H
+
+#include <linux/spinlock.h>
+#include "clk-rtk-common.h"
+#include "freq_table.h"
+
+struct reg_sequence;
+
+struct rtk_clk_regmap_pll {
+ struct rtk_clk_regmap clkr;
+ const struct reg_sequence *seq_power_on;
+ u32 num_seq_power_on;
+ const struct reg_sequence *seq_power_off;
+ u32 num_seq_power_off;
+ const struct reg_sequence *seq_pre_set_freq;
+ u32 num_seq_pre_set_freq;
+ const struct reg_sequence *seq_post_set_freq;
+ u32 num_seq_post_set_freq;
+ const struct rtk_freq_table *freq_tbl;
+ u32 freq_reg;
+ u32 freq_mask;
+ u32 freq_ready_mask;
+ u32 freq_ready_reg;
+ u32 freq_ready_val;
+ u32 power_reg;
+ u32 power_mask;
+ u32 power_val_on;
+
+ /* Expected input rate for the preset frequency table; zero disables check. */
+ unsigned long expected_parent_rate;
+
+ /*
+ * Serialize the multi-step register sequences in .set_rate() against
+ * .enable()/.disable(). CCF protects them with different locks
+ * (prepare_lock vs. enable_lock), and regmap only guarantees atomicity of
+ * individual register accesses.
+ */
+ spinlock_t lock;
+};
+
+#define __rtk_clk_regmap_pll_hw(_ptr) __rtk_clk_regmap_hw(&(_ptr)->clkr)
+
+extern const struct clk_ops rtk_clk_pll_ops;
+extern const struct clk_ops rtk_clk_pll_ro_ops;
+
+#endif /* __CLK_REALTEK_CLK_PLL_H */
diff --git a/drivers/clk/realtek/freq_table.c b/drivers/clk/realtek/freq_table.c
new file mode 100644
index 000000000000..0f977a3fc902
--- /dev/null
+++ b/drivers/clk/realtek/freq_table.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/types.h>
+#include "freq_table.h"
+
+#define IS_FREQ_TABLE_END(_f) ((_f)->rate == 0)
+
+const struct rtk_freq_table *ftbl_find_closest_by_rate(const struct rtk_freq_table *ftbl,
+ unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate)
+{
+ const struct rtk_freq_table *best = NULL;
+ unsigned long best_delta = ULONG_MAX;
+
+ for ( ; !IS_FREQ_TABLE_END(ftbl); ftbl++) {
+ unsigned long delta;
+
+ if (ftbl->rate < min_rate || ftbl->rate > max_rate)
+ continue;
+
+ delta = ftbl->rate >= rate ? ftbl->rate - rate : rate - ftbl->rate;
+ if (delta < best_delta) {
+ best_delta = delta;
+ best = ftbl;
+ }
+ }
+
+ return best;
+}
+
+const struct rtk_freq_table *ftbl_find_by_rate(const struct rtk_freq_table *ftbl,
+ unsigned long rate)
+{
+ const struct rtk_freq_table *best = NULL;
+ unsigned long best_rate = 0;
+
+ for (; !IS_FREQ_TABLE_END(ftbl); ftbl++) {
+ if (ftbl->rate == rate)
+ return ftbl;
+
+ if (ftbl->rate > rate)
+ continue;
+
+ if (ftbl->rate > best_rate) {
+ best_rate = ftbl->rate;
+ best = ftbl;
+ }
+ }
+
+ return best;
+}
+
+const struct rtk_freq_table *ftbl_find_by_val_with_mask(const struct rtk_freq_table *ftbl,
+ u32 mask, u32 value)
+{
+ for (; !IS_FREQ_TABLE_END(ftbl); ftbl++) {
+ if ((ftbl->val & mask) == (value & mask))
+ return ftbl;
+ }
+ return NULL;
+}
diff --git a/drivers/clk/realtek/freq_table.h b/drivers/clk/realtek/freq_table.h
new file mode 100644
index 000000000000..801f4882a891
--- /dev/null
+++ b/drivers/clk/realtek/freq_table.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __CLK_REALTEK_FREQ_TABLE_H
+#define __CLK_REALTEK_FREQ_TABLE_H
+
+struct rtk_freq_table {
+ u32 val;
+ unsigned long rate;
+};
+
+#define FREQ_TABLE_END \
+ { \
+ .rate = 0 \
+ }
+
+const struct rtk_freq_table *ftbl_find_closest_by_rate(const struct rtk_freq_table *ftbl,
+ unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate);
+const struct rtk_freq_table *ftbl_find_by_rate(const struct rtk_freq_table *ftbl,
+ unsigned long rate);
+const struct rtk_freq_table *
+ftbl_find_by_val_with_mask(const struct rtk_freq_table *ftbl, u32 mask, u32 value);
+
+#endif /* __CLK_REALTEK_FREQ_TABLE_H */
--
2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v16 4/9] clk: realtek: Add support for gate clock
2026-11-12 5:25 [PATCH v16 0/9] clk: realtek: Add RTD1625 clock support Yu-Chun Lin
` (2 preceding siblings ...)
2026-11-12 5:25 ` [PATCH v16 3/9] clk: realtek: Add support for phase locked loops (PLLs) Yu-Chun Lin
@ 2026-11-12 5:25 ` Yu-Chun Lin
2026-11-12 17:14 ` Brian Masney
2026-11-12 5:25 ` [PATCH v16 5/9] clk: realtek: Add support for mux clock Yu-Chun Lin
` (4 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Yu-Chun Lin @ 2026-11-12 5:25 UTC (permalink / raw)
To: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou
Cc: linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, james.tai, cy.huang, stanley_chang,
eleanor.lin
From: Cheng-Yu Lee <cylee12@realtek.com>
Introduce clk_regmap_gate_ops supporting enable, disable, and is_enabled
for standard regmap gate clocks. To accommodate hardware designs, the
enable and disable operations handle a 'write_en' flag, which asserts an
adjacent write-enable bit (bit_idx + 1) simultaneously when modifying the
gate bit.
Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
Changes in v16:
- Remove Brian's reviewed-by tag.
- Replace 'CLK_HW_INIT' with 'CLK_HW_INIT_HW' and 'CLK_HW_INIT_FW_NAME' macros
to avoid relying on unstable internal CCF global names.
- Drop all unused NO_PARENT macro and 'rtk_clk_regmap_gate_ro_ops'.
---
drivers/clk/realtek/Makefile | 1 +
drivers/clk/realtek/clk-regmap-gate.c | 59 +++++++++++++++++++++++++++
drivers/clk/realtek/clk-regmap-gate.h | 54 ++++++++++++++++++++++++
3 files changed, 114 insertions(+)
create mode 100644 drivers/clk/realtek/clk-regmap-gate.c
create mode 100644 drivers/clk/realtek/clk-regmap-gate.h
diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
index 6fbe6e07b760..9397d677f52d 100644
--- a/drivers/clk/realtek/Makefile
+++ b/drivers/clk/realtek/Makefile
@@ -2,5 +2,6 @@
obj-$(CONFIG_RTK_CLK_COMMON) += clk-rtk.o
clk-rtk-y += clk-rtk-common.o
+clk-rtk-y += clk-regmap-gate.o
clk-rtk-y += clk-regmap-pll.o
clk-rtk-y += freq_table.o
diff --git a/drivers/clk/realtek/clk-regmap-gate.c b/drivers/clk/realtek/clk-regmap-gate.c
new file mode 100644
index 000000000000..12539e11647c
--- /dev/null
+++ b/drivers/clk/realtek/clk-regmap-gate.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2017-2026 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <cylee12@realtek.com>
+ */
+
+#include <linux/bits.h>
+#include <linux/clk-provider.h>
+#include <linux/export.h>
+#include <linux/regmap.h>
+#include "clk-regmap-gate.h"
+
+static int rtk_clk_regmap_gate_update(struct clk_hw *hw, bool enable)
+{
+ struct rtk_clk_regmap_gate *clkg = to_rtk_clk_regmap_gate(hw);
+ unsigned int mask = BIT(clkg->bit_idx);
+ unsigned int val = enable ? mask : 0;
+
+ /*
+ * Hardware specific design: to modify the gate bit, the adjacent
+ * write-enable bit (bit_idx + 1) must be asserted simultaneously.
+ */
+ if (clkg->write_en) {
+ mask |= BIT(clkg->bit_idx + 1);
+ val |= BIT(clkg->bit_idx + 1);
+ }
+
+ return regmap_update_bits(clkg->clkr.regmap, clkg->gate_ofs, mask, val);
+}
+
+static int rtk_clk_regmap_gate_enable(struct clk_hw *hw)
+{
+ return rtk_clk_regmap_gate_update(hw, true);
+}
+
+static void rtk_clk_regmap_gate_disable(struct clk_hw *hw)
+{
+ rtk_clk_regmap_gate_update(hw, false);
+}
+
+static int rtk_clk_regmap_gate_is_enabled(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap_gate *clkg = to_rtk_clk_regmap_gate(hw);
+ int ret;
+ u32 val;
+
+ ret = regmap_read(clkg->clkr.regmap, clkg->gate_ofs, &val);
+ if (ret < 0)
+ return ret;
+
+ return !!(val & BIT(clkg->bit_idx));
+}
+
+const struct clk_ops rtk_clk_regmap_gate_ops = {
+ .enable = rtk_clk_regmap_gate_enable,
+ .disable = rtk_clk_regmap_gate_disable,
+ .is_enabled = rtk_clk_regmap_gate_is_enabled,
+};
+EXPORT_SYMBOL_NS_GPL(rtk_clk_regmap_gate_ops, "CLK_REALTEK");
diff --git a/drivers/clk/realtek/clk-regmap-gate.h b/drivers/clk/realtek/clk-regmap-gate.h
new file mode 100644
index 000000000000..4540e73ca72b
--- /dev/null
+++ b/drivers/clk/realtek/clk-regmap-gate.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2017-2026 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <cylee12@realtek.com>
+ */
+
+#ifndef __CLK_REALTEK_CLK_REGMAP_GATE_H
+#define __CLK_REALTEK_CLK_REGMAP_GATE_H
+
+#include "clk-rtk-common.h"
+
+struct rtk_clk_regmap_gate {
+ struct rtk_clk_regmap clkr;
+ unsigned int gate_ofs;
+ u8 bit_idx;
+ u32 write_en : 1;
+};
+
+#define __rtk_clk_regmap_gate_hw(_p) __rtk_clk_regmap_hw(&(_p)->clkr)
+
+#define __RTK_CLK_REGMAP_GATE_HW(_name, _parent, _ops, _flags, _ofs, _bit_idx, _write_en) \
+struct rtk_clk_regmap_gate _name = { \
+ .clkr.hw.init = CLK_HW_INIT_HW(#_name, _parent, _ops, _flags), \
+ .gate_ofs = _ofs, \
+ .bit_idx = _bit_idx, \
+ .write_en = _write_en, \
+}
+
+#define RTK_CLK_REGMAP_GATE_HW(_name, _parent, _flags, _ofs, _bit_idx, _write_en) \
+ __RTK_CLK_REGMAP_GATE_HW(_name, _parent, &rtk_clk_regmap_gate_ops, _flags, \
+ _ofs, _bit_idx, _write_en)
+
+#define __RTK_CLK_REGMAP_GATE_FW_NAME(_name, _parent, _ops, _flags, _ofs, _bit_idx, _write_en) \
+struct rtk_clk_regmap_gate _name = { \
+ .clkr.hw.init = CLK_HW_INIT_FW_NAME(#_name, _parent, _ops, _flags), \
+ .gate_ofs = _ofs, \
+ .bit_idx = _bit_idx, \
+ .write_en = _write_en, \
+}
+
+#define RTK_CLK_REGMAP_GATE_FW_NAME(_name, _parent, _flags, _ofs, _bit_idx, _write_en) \
+ __RTK_CLK_REGMAP_GATE_FW_NAME(_name, _parent, &rtk_clk_regmap_gate_ops, _flags, \
+ _ofs, _bit_idx, _write_en)
+
+static inline struct rtk_clk_regmap_gate *to_rtk_clk_regmap_gate(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap *clkr = to_rtk_clk_regmap(hw);
+
+ return container_of(clkr, struct rtk_clk_regmap_gate, clkr);
+}
+
+extern const struct clk_ops rtk_clk_regmap_gate_ops;
+
+#endif /* __CLK_REALTEK_CLK_REGMAP_GATE_H */
--
2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v16 5/9] clk: realtek: Add support for mux clock
2026-11-12 5:25 [PATCH v16 0/9] clk: realtek: Add RTD1625 clock support Yu-Chun Lin
` (3 preceding siblings ...)
2026-11-12 5:25 ` [PATCH v16 4/9] clk: realtek: Add support for gate clock Yu-Chun Lin
@ 2026-11-12 5:25 ` Yu-Chun Lin
2026-11-12 5:25 ` [PATCH v16 6/9] clk: realtek: Add support for MMC-tuned PLL clocks Yu-Chun Lin
` (3 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Yu-Chun Lin @ 2026-11-12 5:25 UTC (permalink / raw)
To: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou
Cc: linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, james.tai, cy.huang, stanley_chang,
eleanor.lin
From: Cheng-Yu Lee <cylee12@realtek.com>
Add a simple regmap-based clk_ops implementation for Realtek mux clocks.
The implementation supports parent selection and rate determination through
regmap-backed register access.
Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
Changes in v16:
- Remove Brian's reviewed-by tag.
- Replace 'CLK_HW_INIT_PARENTS' with 'CLK_HW_INIT_PARENTS_HW' to use
'.parent_hws'
---
drivers/clk/realtek/Makefile | 1 +
drivers/clk/realtek/clk-regmap-mux.c | 40 ++++++++++++++++++++++++++
drivers/clk/realtek/clk-regmap-mux.h | 42 ++++++++++++++++++++++++++++
3 files changed, 83 insertions(+)
create mode 100644 drivers/clk/realtek/clk-regmap-mux.c
create mode 100644 drivers/clk/realtek/clk-regmap-mux.h
diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
index 9397d677f52d..4be39e2dd5b4 100644
--- a/drivers/clk/realtek/Makefile
+++ b/drivers/clk/realtek/Makefile
@@ -3,5 +3,6 @@ obj-$(CONFIG_RTK_CLK_COMMON) += clk-rtk.o
clk-rtk-y += clk-rtk-common.o
clk-rtk-y += clk-regmap-gate.o
+clk-rtk-y += clk-regmap-mux.o
clk-rtk-y += clk-regmap-pll.o
clk-rtk-y += freq_table.o
diff --git a/drivers/clk/realtek/clk-regmap-mux.c b/drivers/clk/realtek/clk-regmap-mux.c
new file mode 100644
index 000000000000..ba86f314bb5e
--- /dev/null
+++ b/drivers/clk/realtek/clk-regmap-mux.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2017-2026 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <cylee12@realtek.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/export.h>
+#include <linux/regmap.h>
+#include "clk-regmap-mux.h"
+
+static u8 rtk_clk_regmap_mux_get_parent(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap_mux *clkm = to_rtk_clk_regmap_mux(hw);
+ u32 val;
+ int ret;
+
+ ret = regmap_read(clkm->clkr.regmap, clkm->mux_ofs, &val);
+ if (ret)
+ return 0xff;
+
+ val = (val >> clkm->shift) & clkm->mask;
+
+ return val;
+}
+
+static int rtk_clk_regmap_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct rtk_clk_regmap_mux *clkm = to_rtk_clk_regmap_mux(hw);
+
+ return regmap_update_bits(clkm->clkr.regmap, clkm->mux_ofs,
+ clkm->mask << clkm->shift, (u32)index << clkm->shift);
+}
+
+const struct clk_ops rtk_clk_regmap_mux_ops = {
+ .set_parent = rtk_clk_regmap_mux_set_parent,
+ .get_parent = rtk_clk_regmap_mux_get_parent,
+ .determine_rate = __clk_mux_determine_rate,
+};
+EXPORT_SYMBOL_NS_GPL(rtk_clk_regmap_mux_ops, "CLK_REALTEK");
diff --git a/drivers/clk/realtek/clk-regmap-mux.h b/drivers/clk/realtek/clk-regmap-mux.h
new file mode 100644
index 000000000000..1d86a7f42efd
--- /dev/null
+++ b/drivers/clk/realtek/clk-regmap-mux.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2017-2026 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <cylee12@realtek.com>
+ */
+
+#ifndef __CLK_REALTEK_CLK_REGMAP_MUX_H
+#define __CLK_REALTEK_CLK_REGMAP_MUX_H
+
+#include "clk-rtk-common.h"
+
+struct rtk_clk_regmap_mux {
+ struct rtk_clk_regmap clkr;
+ unsigned int mux_ofs;
+ unsigned int mask;
+ unsigned int shift;
+};
+
+#define __rtk_clk_regmap_mux_hw(_p) __rtk_clk_regmap_hw(&(_p)->clkr)
+
+#define __RTK_CLK_REGMAP_MUX_HW(_name, _parents, _ops, _flags, _ofs, _sft, _mask) \
+struct rtk_clk_regmap_mux _name = { \
+ .clkr.hw.init = CLK_HW_INIT_PARENTS_HW(#_name, _parents, _ops, _flags), \
+ .mux_ofs = _ofs, \
+ .shift = _sft, \
+ .mask = _mask, \
+}
+
+#define RTK_CLK_REGMAP_MUX_HW(_name, _parents, _flags, _ofs, _sft, _mask) \
+ __RTK_CLK_REGMAP_MUX_HW(_name, _parents, &rtk_clk_regmap_mux_ops, _flags, _ofs, \
+ _sft, _mask)
+
+static inline struct rtk_clk_regmap_mux *to_rtk_clk_regmap_mux(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap *clkr = to_rtk_clk_regmap(hw);
+
+ return container_of(clkr, struct rtk_clk_regmap_mux, clkr);
+}
+
+extern const struct clk_ops rtk_clk_regmap_mux_ops;
+
+#endif /* __CLK_REALTEK_CLK_REGMAP_MUX_H */
--
2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v16 6/9] clk: realtek: Add support for MMC-tuned PLL clocks
2026-11-12 5:25 [PATCH v16 0/9] clk: realtek: Add RTD1625 clock support Yu-Chun Lin
` (4 preceding siblings ...)
2026-11-12 5:25 ` [PATCH v16 5/9] clk: realtek: Add support for mux clock Yu-Chun Lin
@ 2026-11-12 5:25 ` Yu-Chun Lin
2026-11-12 17:14 ` Brian Masney
2026-11-12 5:25 ` [PATCH v16 7/9] clk: realtek: Add RTD1625-CRT clock controller driver Yu-Chun Lin
` (2 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Yu-Chun Lin @ 2026-11-12 5:25 UTC (permalink / raw)
To: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou
Cc: linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, james.tai, cy.huang, stanley_chang,
eleanor.lin
From: Cheng-Yu Lee <cylee12@realtek.com>
Add clk_pll_mmc_ops for enable/disable, rate control, and status operations
on MMC PLL clocks.
Also add clk_pll_mmc_phase_ops to support phase get/set operations.
Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
Co-developed-by: Jyan Chou <jyanchou@realtek.com>
Signed-off-by: Jyan Chou <jyanchou@realtek.com>
Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
Changes in v16:
- Remove Brian's reviewed-by tag.
- Move the MMC PLL structs and ops declarations out of clk-pll.h into a new
clk-regmap-pll-mmc.h.
- Add a separate 'struct rtk_clk_pll_mmc_phase' with its own to_clk_pll_mmc_phase().
- Merge prepare/unprepare/is_prepared into enable/disable/is_enabled, as
suggested: there is no sleeping operation.
- Introduce the 'rtk_clk_pll_mmc_div_cfg' table for the SSCPLL analog tuning.
- Introduce the 'rtk_clk_pll_mmc_rate' table.
- determine_rate() selects the closest entry within [min_rate, max_rate]
- set_rate() programs that entry only
- recalc_rate() matches all five raw register fields against the table. However,
only on a miss does it fall back to 'clk_pll_mmc_calc_rate()', which implements
the formula.
---
drivers/clk/realtek/Kconfig | 3 +
drivers/clk/realtek/Makefile | 2 +
drivers/clk/realtek/clk-regmap-pll-mmc.c | 457 +++++++++++++++++++++++
drivers/clk/realtek/clk-regmap-pll-mmc.h | 66 ++++
drivers/clk/realtek/freq_table.c | 1 +
5 files changed, 529 insertions(+)
create mode 100644 drivers/clk/realtek/clk-regmap-pll-mmc.c
create mode 100644 drivers/clk/realtek/clk-regmap-pll-mmc.h
diff --git a/drivers/clk/realtek/Kconfig b/drivers/clk/realtek/Kconfig
index e8deccf93f94..00ef9c5ba969 100644
--- a/drivers/clk/realtek/Kconfig
+++ b/drivers/clk/realtek/Kconfig
@@ -26,4 +26,7 @@ config RTK_CLK_COMMON
infrastructure to spawn reset controllers via the auxiliary bus
where required.
+config RTK_CLK_PLL_MMC
+ bool
+
endif
diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
index 4be39e2dd5b4..5fefe9bf901f 100644
--- a/drivers/clk/realtek/Makefile
+++ b/drivers/clk/realtek/Makefile
@@ -6,3 +6,5 @@ clk-rtk-y += clk-regmap-gate.o
clk-rtk-y += clk-regmap-mux.o
clk-rtk-y += clk-regmap-pll.o
clk-rtk-y += freq_table.o
+
+clk-rtk-$(CONFIG_RTK_CLK_PLL_MMC) += clk-regmap-pll-mmc.o
diff --git a/drivers/clk/realtek/clk-regmap-pll-mmc.c b/drivers/clk/realtek/clk-regmap-pll-mmc.c
new file mode 100644
index 000000000000..50df27ef8539
--- /dev/null
+++ b/drivers/clk/realtek/clk-regmap-pll-mmc.c
@@ -0,0 +1,457 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021-2026 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <cylee12@realtek.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/math64.h>
+#include <linux/regmap.h>
+#include "clk-regmap-pll-mmc.h"
+
+#define RTK_PLL_EMMC1_OFFSET 0x0
+#define RTK_PLL_EMMC2_OFFSET 0x4
+#define RTK_PLL_EMMC3_OFFSET 0x8
+#define RTK_PLL_EMMC4_OFFSET 0xc
+#define RTK_PLL_SSC_DIG_EMMC0_OFFSET 0x0
+#define RTK_PLL_SSC_DIG_EMMC3_OFFSET 0xc
+#define RTK_PLL_SSC_DIG_EMMC4_OFFSET 0x10
+
+#define RTK_PLL_PHRT0_MASK BIT(0)
+#define RTK_PLL_PHSEL_MASK GENMASK(4, 0)
+#define RTK_PLL_SSCPLL_RS_MASK GENMASK(12, 10)
+#define RTK_PLL_SSCPLL_ICP_MASK GENMASK(9, 5)
+#define RTK_PLL_SSC_DIV_EXT_F_MASK GENMASK(25, 13)
+#define RTK_PLL_PI_IBSELH_MASK GENMASK(28, 27)
+#define RTK_PLL_SSC_DIV_N_MASK GENMASK(23, 16)
+#define RTK_PLL_NCODE_SSC_EMMC_MASK GENMASK(20, 13)
+#define RTK_PLL_FCODE_SSC_EMMC_MASK GENMASK(12, 0)
+#define RTK_PLL_GRAN_EST_EM_MC_MASK GENMASK(20, 0)
+#define RTK_PLL_EN_SSC_EMMC_MASK BIT(0)
+#define RTK_PLL_SSC_DIG_EMMC0_EN_SSC BIT(1)
+#define RTK_PLL_FLAG_INITIAL_EMMC_MASK BIT(8)
+
+#define RTK_PLL_PHRT0_SHIFT 1
+
+#define CYCLE_DEGREES 360
+#define PHASE_STEPS 32
+#define PHASE_SCALE_FACTOR 1125
+
+static inline struct rtk_clk_regmap_pll_mmc *to_clk_pll_mmc(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap *clkr = to_rtk_clk_regmap(hw);
+
+ return container_of(clkr, struct rtk_clk_regmap_pll_mmc, clkr);
+}
+
+static inline struct rtk_clk_pll_mmc_phase *to_clk_pll_mmc_phase(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap *clkr = to_rtk_clk_regmap(hw);
+
+ return container_of(clkr, struct rtk_clk_pll_mmc_phase, clkr);
+}
+
+static inline int get_phrt0(struct rtk_clk_regmap_pll_mmc *clkm, u32 *val)
+{
+ u32 reg;
+ int ret;
+
+ ret = regmap_read(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC1_OFFSET, ®);
+ if (ret)
+ return ret;
+
+ *val = (reg >> RTK_PLL_PHRT0_SHIFT) & RTK_PLL_PHRT0_MASK;
+
+ return 0;
+}
+
+static inline int set_phrt0(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
+{
+ return regmap_update_bits(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC1_OFFSET,
+ RTK_PLL_PHRT0_MASK << RTK_PLL_PHRT0_SHIFT,
+ val << RTK_PLL_PHRT0_SHIFT);
+}
+
+static inline int clk_pll_emmc_set_sscpll_rs(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
+{
+ return regmap_update_bits(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC2_OFFSET,
+ RTK_PLL_SSCPLL_RS_MASK, FIELD_PREP(RTK_PLL_SSCPLL_RS_MASK, val));
+}
+
+static inline int clk_pll_emmc_set_sscpll_icp(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
+{
+ return regmap_update_bits(clkm->clkr.regmap,
+ clkm->pll_ofs + RTK_PLL_EMMC2_OFFSET,
+ RTK_PLL_SSCPLL_ICP_MASK,
+ FIELD_PREP(RTK_PLL_SSCPLL_ICP_MASK, val));
+}
+
+static inline int clk_pll_emmc_set_ssc_div_ext_f(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
+{
+ return regmap_update_bits(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC2_OFFSET,
+ RTK_PLL_SSC_DIV_EXT_F_MASK,
+ FIELD_PREP(RTK_PLL_SSC_DIV_EXT_F_MASK, val));
+}
+
+static inline int clk_pll_emmc_set_pi_ibselh(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
+{
+ return regmap_update_bits(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC2_OFFSET,
+ RTK_PLL_PI_IBSELH_MASK, FIELD_PREP(RTK_PLL_PI_IBSELH_MASK, val));
+}
+
+static inline int clk_pll_emmc_set_ssc_div_n(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
+{
+ return regmap_update_bits(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC3_OFFSET,
+ RTK_PLL_SSC_DIV_N_MASK, FIELD_PREP(RTK_PLL_SSC_DIV_N_MASK, val));
+}
+
+static inline int set_pow_ctl(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
+{
+ return regmap_write(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC4_OFFSET, val);
+}
+
+static inline int get_pow_ctl(struct rtk_clk_regmap_pll_mmc *clkm, u32 *val)
+{
+ u32 raw_val;
+ int ret;
+
+ ret = regmap_read(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC4_OFFSET, &raw_val);
+ if (ret)
+ return ret;
+
+ *val = raw_val;
+
+ return 0;
+}
+
+static int rtk_clk_regmap_pll_mmc_phase_set_phase(struct clk_hw *hw, int degrees)
+{
+ struct rtk_clk_pll_mmc_phase *clkm = to_clk_pll_mmc_phase(hw);
+ int ret;
+ u32 val;
+
+ val = DIV_ROUND_CLOSEST(degrees * 100, PHASE_SCALE_FACTOR);
+ ret = regmap_update_bits(clkm->clkr.regmap,
+ clkm->pll_mmc->pll_ofs + RTK_PLL_EMMC1_OFFSET,
+ RTK_PLL_PHSEL_MASK << clkm->shift, val << clkm->shift);
+ if (ret)
+ return ret;
+
+ usleep_range(10, 20);
+
+ return 0;
+}
+
+static int rtk_clk_regmap_pll_mmc_phase_get_phase(struct clk_hw *hw)
+{
+ struct rtk_clk_pll_mmc_phase *clkm = to_clk_pll_mmc_phase(hw);
+ unsigned int raw_val;
+ int ret;
+ u32 val;
+
+ ret = regmap_read(clkm->clkr.regmap, clkm->pll_mmc->pll_ofs + RTK_PLL_EMMC1_OFFSET,
+ &raw_val);
+ if (ret)
+ return ret;
+
+ val = (raw_val >> clkm->shift) & RTK_PLL_PHSEL_MASK;
+
+ return DIV_ROUND_CLOSEST(val * CYCLE_DEGREES, PHASE_STEPS);
+}
+
+const struct clk_ops rtk_clk_pll_mmc_phase_ops = {
+ .set_phase = rtk_clk_regmap_pll_mmc_phase_set_phase,
+ .get_phase = rtk_clk_regmap_pll_mmc_phase_get_phase,
+};
+EXPORT_SYMBOL_NS_GPL(rtk_clk_pll_mmc_phase_ops, "CLK_REALTEK");
+
+static int rtk_clk_regmap_pll_mmc_enable(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap_pll_mmc *clkm = to_clk_pll_mmc(hw);
+ int ret;
+
+ ret = set_pow_ctl(clkm, 7);
+ if (ret)
+ return ret;
+
+ ret = set_phrt0(clkm, 1);
+ if (ret)
+ return ret;
+
+ udelay(10);
+
+ return 0;
+}
+
+static void rtk_clk_regmap_pll_mmc_disable(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap_pll_mmc *clkm = to_clk_pll_mmc(hw);
+
+ set_phrt0(clkm, 0);
+ udelay(10);
+ set_pow_ctl(clkm, 0);
+}
+
+static int rtk_clk_regmap_pll_mmc_is_enabled(struct clk_hw *hw)
+{
+ struct rtk_clk_regmap_pll_mmc *clkm = to_clk_pll_mmc(hw);
+ u32 pow_val, phrt_val;
+ int ret;
+
+ ret = get_pow_ctl(clkm, &pow_val);
+ if (ret)
+ return 1;
+
+ ret = get_phrt0(clkm, &phrt_val);
+ if (ret)
+ return 1;
+
+ return (pow_val != 0x0) && (phrt_val == 0x1);
+}
+
+static unsigned long clk_pll_mmc_calc_rate(unsigned long parent_rate,
+ u32 div_n, u32 div_ext_f)
+{
+ u64 rate = (u64)parent_rate * (div_n + 2);
+
+ rate += (u64)parent_rate * div_ext_f / 8192;
+
+ return div64_u64(rate, 4);
+}
+
+static unsigned long rtk_clk_regmap_pll_mmc_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct rtk_clk_regmap_pll_mmc *clkm = to_clk_pll_mmc(hw);
+ u32 emmc2, emmc3, ssc3, ssc4, val, ext_f, ncode, fcode, gran_est;
+
+ if (regmap_read(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC2_OFFSET, &emmc2))
+ return 0;
+
+ if (regmap_read(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC3_OFFSET, &emmc3))
+ return 0;
+
+ if (regmap_read(clkm->clkr.regmap, clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC3_OFFSET, &ssc3))
+ return 0;
+
+ if (regmap_read(clkm->clkr.regmap, clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC4_OFFSET, &ssc4))
+ return 0;
+
+ val = FIELD_GET(RTK_PLL_SSC_DIV_N_MASK, emmc3);
+ ext_f = FIELD_GET(RTK_PLL_SSC_DIV_EXT_F_MASK, emmc2);
+ ncode = FIELD_GET(RTK_PLL_NCODE_SSC_EMMC_MASK, ssc3);
+ fcode = FIELD_GET(RTK_PLL_FCODE_SSC_EMMC_MASK, ssc3);
+ gran_est = FIELD_GET(RTK_PLL_GRAN_EST_EM_MC_MASK, ssc4);
+
+ for (unsigned int i = 0; clkm->rate_tbl && i < clkm->num_rate_tbl; i++) {
+ const struct rtk_clk_pll_mmc_rate *entry = &clkm->rate_tbl[i];
+
+ if (entry->ssc_div_n == val && entry->ssc_div_ext_f == ext_f &&
+ entry->ncode == ncode && entry->fcode == fcode &&
+ entry->gran_est == gran_est)
+ return entry->rate;
+ }
+
+ return clk_pll_mmc_calc_rate(parent_rate, val, ext_f);
+}
+
+static const struct rtk_clk_pll_mmc_rate *
+rtk_clk_pll_mmc_find_rate(const struct rtk_clk_regmap_pll_mmc *clkm, unsigned long rate)
+{
+ if (!clkm->rate_tbl || !clkm->num_rate_tbl)
+ return NULL;
+
+ for (unsigned int i = 0; i < clkm->num_rate_tbl; i++) {
+ if (clkm->rate_tbl[i].rate == rate)
+ return &clkm->rate_tbl[i];
+ }
+
+ return NULL;
+}
+
+static const struct rtk_clk_pll_mmc_rate *
+rtk_clk_pll_mmc_find_closest_rate(const struct rtk_clk_pll_mmc_rate *tbl, u32 num,
+ unsigned long rate, unsigned long min_rate,
+ unsigned long max_rate)
+{
+ const struct rtk_clk_pll_mmc_rate *best = NULL;
+ unsigned long best_delta = ~0UL;
+
+ for (unsigned int i = 0; i < num; i++) {
+ const struct rtk_clk_pll_mmc_rate *entry = &tbl[i];
+ unsigned long delta;
+
+ if (entry->rate < min_rate || entry->rate > max_rate)
+ continue;
+
+ delta = entry->rate >= rate ? entry->rate - rate : rate - entry->rate;
+ if (delta < best_delta) {
+ best = entry;
+ best_delta = delta;
+ }
+ }
+
+ return best;
+}
+
+static int rtk_clk_regmap_pll_mmc_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct rtk_clk_regmap_pll_mmc *clkm = to_clk_pll_mmc(hw);
+ const struct rtk_clk_pll_mmc_rate *entry;
+
+ if (!clkm->rate_tbl || !clkm->num_rate_tbl ||
+ req->min_rate > req->max_rate)
+ return -EINVAL;
+
+ entry = rtk_clk_pll_mmc_find_closest_rate(clkm->rate_tbl,
+ clkm->num_rate_tbl, req->rate,
+ req->min_rate, req->max_rate);
+ if (!entry)
+ return -EINVAL;
+
+ req->rate = entry->rate;
+
+ return 0;
+}
+
+static const struct rtk_clk_pll_mmc_div_cfg clk_pll_emmc_default_div_cfg[] = {
+ { 31, 46, 3, 3, 2 },
+ { 20, 30, 2, 3, 1 },
+ { 10, 19, 1, 2, 1 },
+ { 5, 9, 0, 2, 0 },
+};
+
+static const struct rtk_clk_pll_mmc_div_cfg *
+clk_pll_emmc_find_div_cfg(struct rtk_clk_regmap_pll_mmc *clkm, u32 div)
+{
+ const struct rtk_clk_pll_mmc_div_cfg *tbl = clkm->div_cfg;
+ u8 num = clkm->num_div_cfg;
+
+ if (!tbl) {
+ tbl = clk_pll_emmc_default_div_cfg;
+ num = ARRAY_SIZE(clk_pll_emmc_default_div_cfg);
+ }
+
+ for (unsigned int i = 0; i < num; i++) {
+ if (div >= tbl[i].div_min && div <= tbl[i].div_max)
+ return &tbl[i];
+ }
+
+ return NULL;
+}
+
+static int clk_pll_emmc_program_div_cfg(struct rtk_clk_regmap_pll_mmc *clkm, u32 div)
+{
+ const struct rtk_clk_pll_mmc_div_cfg *t = clk_pll_emmc_find_div_cfg(clkm, div);
+ int ret;
+
+ if (!t)
+ return -EINVAL;
+
+ ret = clk_pll_emmc_set_pi_ibselh(clkm, t->ibselh);
+ if (ret)
+ return ret;
+
+ ret = clk_pll_emmc_set_sscpll_rs(clkm, t->rs);
+ if (ret)
+ return ret;
+
+ return clk_pll_emmc_set_sscpll_icp(clkm, t->icp);
+}
+
+static int rtk_clk_regmap_pll_mmc_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct rtk_clk_regmap_pll_mmc *clkm = to_clk_pll_mmc(hw);
+ const struct rtk_clk_pll_mmc_rate *entry = rtk_clk_pll_mmc_find_rate(clkm, rate);
+ int ret;
+
+ if (!entry)
+ return -EINVAL;
+
+ ret = regmap_update_bits(clkm->clkr.regmap,
+ clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC0_OFFSET,
+ RTK_PLL_FLAG_INITIAL_EMMC_MASK,
+ FIELD_PREP(RTK_PLL_FLAG_INITIAL_EMMC_MASK, 0));
+ if (ret)
+ return ret;
+
+ ret = clk_pll_emmc_set_ssc_div_n(clkm, entry->ssc_div_n);
+ if (ret)
+ return ret;
+
+ ret = clk_pll_emmc_set_ssc_div_ext_f(clkm, entry->ssc_div_ext_f);
+ if (ret)
+ return ret;
+
+ ret = clk_pll_emmc_program_div_cfg(clkm, entry->ssc_div_n);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(clkm->clkr.regmap,
+ clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC3_OFFSET,
+ RTK_PLL_NCODE_SSC_EMMC_MASK,
+ FIELD_PREP(RTK_PLL_NCODE_SSC_EMMC_MASK, entry->ncode));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(clkm->clkr.regmap,
+ clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC3_OFFSET,
+ RTK_PLL_FCODE_SSC_EMMC_MASK,
+ FIELD_PREP(RTK_PLL_FCODE_SSC_EMMC_MASK, entry->fcode));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(clkm->clkr.regmap,
+ clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC4_OFFSET,
+ RTK_PLL_GRAN_EST_EM_MC_MASK,
+ FIELD_PREP(RTK_PLL_GRAN_EST_EM_MC_MASK, entry->gran_est));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(clkm->clkr.regmap,
+ clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC0_OFFSET,
+ RTK_PLL_SSC_DIG_EMMC0_EN_SSC,
+ FIELD_PREP(RTK_PLL_SSC_DIG_EMMC0_EN_SSC, 1));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(clkm->clkr.regmap,
+ clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC0_OFFSET,
+ RTK_PLL_EN_SSC_EMMC_MASK,
+ FIELD_PREP(RTK_PLL_EN_SSC_EMMC_MASK, 1));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(clkm->clkr.regmap,
+ clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC0_OFFSET,
+ RTK_PLL_EN_SSC_EMMC_MASK,
+ FIELD_PREP(RTK_PLL_EN_SSC_EMMC_MASK, 0));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(clkm->clkr.regmap,
+ clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC0_OFFSET,
+ RTK_PLL_FLAG_INITIAL_EMMC_MASK,
+ FIELD_PREP(RTK_PLL_FLAG_INITIAL_EMMC_MASK, 1));
+ if (ret)
+ return ret;
+
+ usleep_range(10, 20);
+
+ return 0;
+}
+
+const struct clk_ops rtk_clk_pll_mmc_ops = {
+ .enable = rtk_clk_regmap_pll_mmc_enable,
+ .disable = rtk_clk_regmap_pll_mmc_disable,
+ .is_enabled = rtk_clk_regmap_pll_mmc_is_enabled,
+ .recalc_rate = rtk_clk_regmap_pll_mmc_recalc_rate,
+ .determine_rate = rtk_clk_regmap_pll_mmc_determine_rate,
+ .set_rate = rtk_clk_regmap_pll_mmc_set_rate,
+};
+EXPORT_SYMBOL_NS_GPL(rtk_clk_pll_mmc_ops, "CLK_REALTEK");
diff --git a/drivers/clk/realtek/clk-regmap-pll-mmc.h b/drivers/clk/realtek/clk-regmap-pll-mmc.h
new file mode 100644
index 000000000000..c2e973f3df72
--- /dev/null
+++ b/drivers/clk/realtek/clk-regmap-pll-mmc.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2026 Realtek Semiconductor Corporation
+ */
+
+#ifndef __CLK_REALTEK_CLK_PLL_MMC_H
+#define __CLK_REALTEK_CLK_PLL_MMC_H
+
+#include "clk-rtk-common.h"
+
+/* SSCPLL charge-pump settings per divider range */
+struct rtk_clk_pll_mmc_div_cfg {
+ u16 div_min;
+ u16 div_max;
+ u8 ibselh;
+ u8 rs;
+ u8 icp;
+};
+
+/* Register settings for a specific eMMC PLL rate */
+struct rtk_clk_pll_mmc_rate {
+ unsigned long rate;
+ u32 ssc_div_n;
+ u32 ssc_div_ext_f;
+ u32 ncode;
+ u32 fcode;
+ u32 gran_est;
+};
+
+struct rtk_clk_regmap_pll_mmc {
+ struct rtk_clk_regmap clkr;
+ unsigned int pll_ofs;
+ unsigned int ssc_dig_ofs;
+
+ /*
+ * Optional per-SoC tuning table. When NULL, the driver's default table
+ * is used and num_div_cfg is ignored;
+ */
+ const struct rtk_clk_pll_mmc_div_cfg *div_cfg;
+ u32 num_div_cfg;
+
+ /*
+ * Supported operating points. Must be set: without a table
+ * ->determine_rate() and ->set_rate() return -EINVAL, while
+ * ->recalc_rate() falls back to the divider formula. There is no
+ * default table here because the register values are SoC-specific.
+ */
+ const struct rtk_clk_pll_mmc_rate *rate_tbl;
+ u32 num_rate_tbl;
+};
+
+#define __rtk_clk_regmap_pll_mmc_hw(_ptr) __rtk_clk_regmap_hw(&(_ptr)->clkr)
+
+extern const struct clk_ops rtk_clk_pll_mmc_ops;
+
+struct rtk_clk_pll_mmc_phase {
+ struct rtk_clk_regmap clkr;
+ struct rtk_clk_regmap_pll_mmc *pll_mmc;
+ u32 shift;
+};
+
+#define __rtk_clk_regmap_pll_mmc_phase_hw(_ptr) __rtk_clk_regmap_hw(&(_ptr)->clkr)
+
+extern const struct clk_ops rtk_clk_pll_mmc_phase_ops;
+
+#endif /* __CLK_REALTEK_CLK_PLL_MMC_H */
diff --git a/drivers/clk/realtek/freq_table.c b/drivers/clk/realtek/freq_table.c
index 0f977a3fc902..d0e015131e57 100644
--- a/drivers/clk/realtek/freq_table.c
+++ b/drivers/clk/realtek/freq_table.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/limits.h>
#include <linux/types.h>
#include "freq_table.h"
--
2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v16 7/9] clk: realtek: Add RTD1625-CRT clock controller driver
2026-11-12 5:25 [PATCH v16 0/9] clk: realtek: Add RTD1625 clock support Yu-Chun Lin
` (5 preceding siblings ...)
2026-11-12 5:25 ` [PATCH v16 6/9] clk: realtek: Add support for MMC-tuned PLL clocks Yu-Chun Lin
@ 2026-11-12 5:25 ` Yu-Chun Lin
2026-11-12 17:14 ` Brian Masney
2026-11-12 5:25 ` [PATCH v16 8/9] clk: realtek: Add RTD1625-ISO " Yu-Chun Lin
2026-11-12 5:25 ` [PATCH v16 9/9] arm64: dts: realtek: Add clock support for RTD1625 Yu-Chun Lin
8 siblings, 1 reply; 16+ messages in thread
From: Yu-Chun Lin @ 2026-11-12 5:25 UTC (permalink / raw)
To: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou
Cc: linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, james.tai, cy.huang, stanley_chang,
eleanor.lin
From: Cheng-Yu Lee <cylee12@realtek.com>
Add support for the CRT (Clock, Reset, and Test) domain clock controller
on the Realtek RTD1625 SoC. This driver provides essential clock sources
(including PLLs), gating, and multiplexing functionalities for the
platform's peripherals.
Because the reset controller shares the same register space with this
CRT clock controller, this driver also acts as the parent device and
registers the reset controller as an auxiliary device on the auxiliary
bus.
Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
Changes in v16:
- Remove Brian's reviewed-by tag.
- Replace 'const char *' parent arrays with 'struct clk_hw *' arrays.
- Switch all gate, mux, and fixed-factor clock initializations to use '_HW' macros.
- Use 'CLK_HW_INIT_FW_NAME' for regmap_pll initialization when referencing external
clocks, and add 'expected_parent_rate' to ensure a safe input rate.
- Refactor eMMC PLL initialization (decoupling phases and appending rate tables).
---
drivers/clk/realtek/Kconfig | 14 +
drivers/clk/realtek/Makefile | 1 +
drivers/clk/realtek/clk-rtd1625-crt.c | 878 ++++++++++++++++++++++++++
3 files changed, 893 insertions(+)
create mode 100644 drivers/clk/realtek/clk-rtd1625-crt.c
diff --git a/drivers/clk/realtek/Kconfig b/drivers/clk/realtek/Kconfig
index 00ef9c5ba969..043a6876a388 100644
--- a/drivers/clk/realtek/Kconfig
+++ b/drivers/clk/realtek/Kconfig
@@ -29,4 +29,18 @@ config RTK_CLK_COMMON
config RTK_CLK_PLL_MMC
bool
+config CLK_RTD1625
+ tristate "RTD1625 Clock Controller"
+ select RTK_CLK_COMMON
+ select RTK_CLK_PLL_MMC
+ help
+ Support for the clock controller on Realtek RTD1625 SoCs.
+
+ This driver provides clock sources, gating, multiplexing, and
+ (via an auxiliary device) reset control for peripherals on the
+ RTD1625 platform.
+
+ Say Y here if your system is based on the RTD1625 and you need
+ its peripheral devices to function.
+
endif
diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
index 5fefe9bf901f..dd4c667e9808 100644
--- a/drivers/clk/realtek/Makefile
+++ b/drivers/clk/realtek/Makefile
@@ -8,3 +8,4 @@ clk-rtk-y += clk-regmap-pll.o
clk-rtk-y += freq_table.o
clk-rtk-$(CONFIG_RTK_CLK_PLL_MMC) += clk-regmap-pll-mmc.o
+obj-$(CONFIG_CLK_RTD1625) += clk-rtd1625-crt.o
diff --git a/drivers/clk/realtek/clk-rtd1625-crt.c b/drivers/clk/realtek/clk-rtd1625-crt.c
new file mode 100644
index 000000000000..b0cccf5c7af2
--- /dev/null
+++ b/drivers/clk/realtek/clk-rtd1625-crt.c
@@ -0,0 +1,878 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2022-2026 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <cylee12@realtek.com>
+ */
+
+#include <dt-bindings/clock/realtek,rtd1625-clk.h>
+#include <linux/array_size.h>
+#include <linux/bits.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+#include "clk-regmap-gate.h"
+#include "clk-regmap-mux.h"
+#include "clk-regmap-pll.h"
+#include "clk-regmap-pll-mmc.h"
+
+#define RTD1625_CRT_CLK_MAX 174
+
+#define RTD1625_REG_PLL_ACPU1 0x10c
+#define RTD1625_REG_PLL_ACPU2 0x110
+#define RTD1625_REG_PLL_SSC_DIG_ACPU0 0x5c0
+#define RTD1625_REG_PLL_SSC_DIG_ACPU1 0x5c4
+#define RTD1625_REG_PLL_SSC_DIG_ACPU2 0x5c8
+#define RTD1625_REG_PLL_SSC_DIG_ACPU_DBG2 0x5dc
+
+#define RTD1625_REG_PLL_VE1_1 0x114
+#define RTD1625_REG_PLL_VE1_2 0x118
+#define RTD1625_REG_PLL_SSC_DIG_VE1_0 0x580
+#define RTD1625_REG_PLL_SSC_DIG_VE1_1 0x584
+#define RTD1625_REG_PLL_SSC_DIG_VE1_2 0x588
+#define RTD1625_REG_PLL_SSC_DIG_VE1_DBG2 0x59c
+
+#define RTD1625_REG_PLL_GPU1 0x1c0
+#define RTD1625_REG_PLL_GPU2 0x1c4
+#define RTD1625_REG_PLL_SSC_DIG_GPU0 0x5a0
+#define RTD1625_REG_PLL_SSC_DIG_GPU1 0x5a4
+#define RTD1625_REG_PLL_SSC_DIG_GPU2 0x5a8
+#define RTD1625_REG_PLL_SSC_DIG_GPU_DBG2 0x5bc
+
+#define RTD1625_REG_PLL_NPU1 0x1c8
+#define RTD1625_REG_PLL_NPU2 0x1cc
+#define RTD1625_REG_PLL_SSC_DIG_NPU0 0x800
+#define RTD1625_REG_PLL_SSC_DIG_NPU1 0x804
+#define RTD1625_REG_PLL_SSC_DIG_NPU2 0x808
+#define RTD1625_REG_PLL_SSC_DIG_NPU_DBG2 0x81c
+
+#define RTD1625_REG_PLL_VE2_1 0x1d0
+#define RTD1625_REG_PLL_VE2_2 0x1d4
+#define RTD1625_REG_PLL_SSC_DIG_VE2_0 0x5e0
+#define RTD1625_REG_PLL_SSC_DIG_VE2_1 0x5e4
+#define RTD1625_REG_PLL_SSC_DIG_VE2_2 0x5e8
+#define RTD1625_REG_PLL_SSC_DIG_VE2_DBG2 0x5fc
+
+#define RTD1625_REG_PLL_HIFI1 0x1d8
+#define RTD1625_REG_PLL_HIFI2 0x1dc
+#define RTD1625_REG_PLL_SSC_DIG_HIFI0 0x6e0
+#define RTD1625_REG_PLL_SSC_DIG_HIFI1 0x6e4
+#define RTD1625_REG_PLL_SSC_DIG_HIFI2 0x6e8
+#define RTD1625_REG_PLL_SSC_DIG_HIFI_DBG2 0x6fc
+
+#define RTD1625_REG_PLL_BUS1 0x524
+
+#define RTD1625_REG_PLL_VODMA1 0x260
+
+#define RTD1625_REG_PLL_SSC_DIG_DDSA1 0x564
+
+#define RTD1625_REG_PLL_SSC_DIG_DCSB1 0x544
+
+#define FREQ_NF_MASK 0x7ffff
+#define FREQ_NF(_r, _nf) {.rate = _r, .val = (_nf),}
+
+/* PLL VODMA: M (11:4) / N (13:12) / O (19:17) */
+#define FREQ_MNO_MASK 0x63ff0
+#define FREQ_MNO(_r, _m, _n, _o) { .rate = (_r), .val = ((_m) << 4) | \
+ ((_n) << 12) | ((_o) << 17), }
+
+static const struct rtk_freq_table acpu_tbl[] = {
+ FREQ_NF(513000000, 0x11000),
+ FREQ_TABLE_END
+};
+
+static const struct rtk_freq_table ve_tbl[] = {
+ FREQ_NF(553500000, 0x12800),
+ FREQ_NF(661500000, 0x16800),
+ FREQ_NF(688500000, 0x17800),
+ FREQ_TABLE_END
+};
+
+static const struct rtk_freq_table bus_tbl[] = {
+ FREQ_NF(513000000, 0x11000),
+ FREQ_NF(540000000, 0x12000),
+ FREQ_NF(553500000, 0x12800),
+ FREQ_TABLE_END
+};
+
+static const struct rtk_freq_table ddsa_tbl[] = {
+ FREQ_NF(432000000, 0xe000),
+ FREQ_TABLE_END
+};
+
+static const struct rtk_freq_table gpu_tbl[] = {
+ FREQ_NF(405000000, 0xd000),
+ FREQ_NF(540000000, 0x12000),
+ FREQ_NF(661500000, 0x16800),
+ FREQ_NF(729000000, 0x19000),
+ FREQ_NF(810000000, 0x1c000),
+ FREQ_NF(850500000, 0x1d800),
+ FREQ_TABLE_END
+};
+
+static const struct rtk_freq_table hifi_tbl[] = {
+ FREQ_NF(756000000, 0x1a000),
+ FREQ_NF(810000000, 0x1c000),
+ FREQ_TABLE_END
+};
+
+static const struct rtk_freq_table npu_tbl[] = {
+ FREQ_NF(661500000, 0x16800),
+ FREQ_NF(729000000, 0x19000),
+ FREQ_NF(810000000, 0x1c000),
+ FREQ_TABLE_END
+};
+
+static const struct reg_sequence pll_acpu_seq_power_on[] = {
+ {RTD1625_REG_PLL_ACPU2, 0x5},
+ {RTD1625_REG_PLL_ACPU2, 0x7},
+ {RTD1625_REG_PLL_ACPU1, 0x54000},
+ {RTD1625_REG_PLL_SSC_DIG_ACPU2, 0x1e1f8e},
+ {RTD1625_REG_PLL_SSC_DIG_ACPU0, 0x4},
+ {RTD1625_REG_PLL_SSC_DIG_ACPU0, 0x5, 200},
+ {RTD1625_REG_PLL_ACPU2, 0x3},
+};
+
+static const struct reg_sequence pll_acpu_seq_power_off[] = {
+ {RTD1625_REG_PLL_ACPU2, 0x4},
+};
+
+static const struct reg_sequence pll_acpu_seq_pre_set_freq[] = {
+ {RTD1625_REG_PLL_SSC_DIG_ACPU0, 0x4},
+};
+
+static const struct reg_sequence pll_acpu_seq_post_set_freq[] = {
+ {RTD1625_REG_PLL_SSC_DIG_ACPU0, 0x5},
+};
+
+static struct rtk_clk_regmap_pll pll_acpu = {
+ .clkr.hw.init = CLK_HW_INIT_FW_NAME("pll_acpu", "osc27m", &rtk_clk_pll_ops,
+ CLK_GET_RATE_NOCACHE),
+ .seq_power_on = pll_acpu_seq_power_on,
+ .num_seq_power_on = ARRAY_SIZE(pll_acpu_seq_power_on),
+ .seq_power_off = pll_acpu_seq_power_off,
+ .num_seq_power_off = ARRAY_SIZE(pll_acpu_seq_power_off),
+ .seq_pre_set_freq = pll_acpu_seq_pre_set_freq,
+ .num_seq_pre_set_freq = ARRAY_SIZE(pll_acpu_seq_pre_set_freq),
+ .seq_post_set_freq = pll_acpu_seq_post_set_freq,
+ .num_seq_post_set_freq = ARRAY_SIZE(pll_acpu_seq_post_set_freq),
+ .freq_reg = RTD1625_REG_PLL_SSC_DIG_ACPU1,
+ .freq_tbl = acpu_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .freq_ready_reg = RTD1625_REG_PLL_SSC_DIG_ACPU_DBG2,
+ .freq_ready_mask = BIT(20),
+ .freq_ready_val = BIT(20),
+ .power_reg = RTD1625_REG_PLL_ACPU2,
+ .power_mask = 0x7,
+ .power_val_on = 0x3,
+ .expected_parent_rate = 27000000,
+ .lock = __SPIN_LOCK_UNLOCKED(pll_acpu.lock),
+};
+
+static const struct reg_sequence pll_ve1_seq_power_on[] = {
+ {RTD1625_REG_PLL_VE1_2, 0x5},
+ {RTD1625_REG_PLL_VE1_2, 0x7},
+ {RTD1625_REG_PLL_VE1_1, 0x54000},
+ {RTD1625_REG_PLL_SSC_DIG_VE1_0, 0x4},
+ {RTD1625_REG_PLL_SSC_DIG_VE1_0, 0x5, 200},
+ {RTD1625_REG_PLL_VE1_2, 0x3},
+};
+
+static const struct reg_sequence pll_ve1_seq_power_off[] = {
+ {RTD1625_REG_PLL_VE1_2, 0x4},
+};
+
+static const struct reg_sequence pll_ve1_seq_pre_set_freq[] = {
+ {RTD1625_REG_PLL_SSC_DIG_VE1_0, 0x4},
+};
+
+static const struct reg_sequence pll_ve1_seq_post_set_freq[] = {
+ {RTD1625_REG_PLL_SSC_DIG_VE1_0, 0x5},
+};
+
+static struct rtk_clk_regmap_pll pll_ve1 = {
+ .clkr.hw.init = CLK_HW_INIT_FW_NAME("pll_ve1", "osc27m", &rtk_clk_pll_ops,
+ CLK_GET_RATE_NOCACHE),
+ .seq_power_on = pll_ve1_seq_power_on,
+ .num_seq_power_on = ARRAY_SIZE(pll_ve1_seq_power_on),
+ .seq_power_off = pll_ve1_seq_power_off,
+ .num_seq_power_off = ARRAY_SIZE(pll_ve1_seq_power_off),
+ .seq_pre_set_freq = pll_ve1_seq_pre_set_freq,
+ .num_seq_pre_set_freq = ARRAY_SIZE(pll_ve1_seq_pre_set_freq),
+ .seq_post_set_freq = pll_ve1_seq_post_set_freq,
+ .num_seq_post_set_freq = ARRAY_SIZE(pll_ve1_seq_post_set_freq),
+ .freq_reg = RTD1625_REG_PLL_SSC_DIG_VE1_1,
+ .freq_tbl = ve_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .freq_ready_reg = RTD1625_REG_PLL_SSC_DIG_VE1_DBG2,
+ .freq_ready_mask = BIT(20),
+ .freq_ready_val = BIT(20),
+ .power_reg = RTD1625_REG_PLL_VE1_2,
+ .power_mask = 0x7,
+ .power_val_on = 0x3,
+ .expected_parent_rate = 27000000,
+ .lock = __SPIN_LOCK_UNLOCKED(pll_ve1.lock),
+};
+
+static struct rtk_clk_regmap_pll pll_ddsa = {
+ .clkr.hw.init = CLK_HW_INIT_FW_NAME("pll_ddsa", "osc27m", &rtk_clk_pll_ro_ops,
+ CLK_GET_RATE_NOCACHE),
+ .freq_reg = RTD1625_REG_PLL_SSC_DIG_DDSA1,
+ .freq_tbl = ddsa_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .lock = __SPIN_LOCK_UNLOCKED(pll_ddsa.lock),
+};
+
+static CLK_FIXED_FACTOR_HW(clk_ddsa_div4, "clk_ddsa_div4",
+ &__rtk_clk_regmap_pll_hw(&pll_ddsa), 4, 1, 0);
+
+static struct rtk_clk_regmap_pll pll_bus = {
+ .clkr.hw.init = CLK_HW_INIT_FW_NAME("pll_bus", "osc27m", &rtk_clk_pll_ro_ops,
+ CLK_GET_RATE_NOCACHE),
+ .freq_reg = RTD1625_REG_PLL_BUS1,
+ .freq_tbl = bus_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .lock = __SPIN_LOCK_UNLOCKED(pll_bus.lock),
+};
+
+static CLK_FIXED_FACTOR_HW(clk_sys, "clk_sys", &__rtk_clk_regmap_pll_hw(&pll_bus), 2, 1, 0);
+
+static struct rtk_clk_regmap_pll pll_dcsb = {
+ .clkr.hw.init = CLK_HW_INIT_FW_NAME("pll_dcsb", "osc27m", &rtk_clk_pll_ro_ops,
+ CLK_GET_RATE_NOCACHE),
+ .freq_reg = RTD1625_REG_PLL_SSC_DIG_DCSB1,
+ .freq_tbl = bus_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .lock = __SPIN_LOCK_UNLOCKED(pll_dcsb.lock),
+};
+
+static CLK_FIXED_FACTOR_HW(clk_sysh, "clk_sysh", &__rtk_clk_regmap_pll_hw(&pll_dcsb), 1, 1, 0);
+
+/* PLL VODMA: read-only, frequency is set by boot code; M/N/O from register */
+static const struct rtk_freq_table pll_vodma_tbl[] = {
+ FREQ_MNO(607500000, 0x29, 0x1, 0x0), /* adjustment */
+ FREQ_MNO(634500000, 0x2b, 0x1, 0x0), /* default target */
+ FREQ_TABLE_END
+};
+
+static struct rtk_clk_regmap_pll pll_vodma = {
+ .clkr.hw.init = CLK_HW_INIT_FW_NAME("pll_vodma", "osc27m", &rtk_clk_pll_ro_ops,
+ CLK_GET_RATE_NOCACHE),
+ .freq_reg = RTD1625_REG_PLL_VODMA1,
+ .freq_tbl = pll_vodma_tbl,
+ .freq_mask = FREQ_MNO_MASK,
+ .lock = __SPIN_LOCK_UNLOCKED(pll_vodma.lock),
+};
+
+static const struct reg_sequence pll_gpu_seq_power_on[] = {
+ {RTD1625_REG_PLL_GPU2, 0x5},
+ {RTD1625_REG_PLL_GPU2, 0x7},
+ {RTD1625_REG_PLL_GPU1, 0x54000},
+ {RTD1625_REG_PLL_SSC_DIG_GPU0, 0x4},
+ {RTD1625_REG_PLL_SSC_DIG_GPU0, 0x5, 200},
+ {RTD1625_REG_PLL_GPU2, 0x3},
+};
+
+static const struct reg_sequence pll_gpu_seq_power_off[] = {
+ {RTD1625_REG_PLL_GPU2, 0x4},
+};
+
+static const struct reg_sequence pll_gpu_seq_pre_set_freq[] = {
+ {RTD1625_REG_PLL_SSC_DIG_GPU0, 0x4},
+};
+
+static const struct reg_sequence pll_gpu_seq_post_set_freq[] = {
+ {RTD1625_REG_PLL_SSC_DIG_GPU0, 0x5},
+};
+
+static struct rtk_clk_regmap_pll pll_gpu = {
+ .clkr.hw.init = CLK_HW_INIT_FW_NAME("pll_gpu", "osc27m", &rtk_clk_pll_ops,
+ CLK_GET_RATE_NOCACHE),
+ .seq_power_on = pll_gpu_seq_power_on,
+ .num_seq_power_on = ARRAY_SIZE(pll_gpu_seq_power_on),
+ .seq_power_off = pll_gpu_seq_power_off,
+ .num_seq_power_off = ARRAY_SIZE(pll_gpu_seq_power_off),
+ .seq_pre_set_freq = pll_gpu_seq_pre_set_freq,
+ .num_seq_pre_set_freq = ARRAY_SIZE(pll_gpu_seq_pre_set_freq),
+ .seq_post_set_freq = pll_gpu_seq_post_set_freq,
+ .num_seq_post_set_freq = ARRAY_SIZE(pll_gpu_seq_post_set_freq),
+ .freq_reg = RTD1625_REG_PLL_SSC_DIG_GPU1,
+ .freq_tbl = gpu_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .freq_ready_reg = RTD1625_REG_PLL_SSC_DIG_GPU_DBG2,
+ .freq_ready_mask = BIT(20),
+ .freq_ready_val = BIT(20),
+ .power_reg = RTD1625_REG_PLL_GPU2,
+ .power_mask = 0x7,
+ .power_val_on = 0x3,
+ .expected_parent_rate = 27000000,
+ .lock = __SPIN_LOCK_UNLOCKED(pll_gpu.lock),
+};
+
+static const struct reg_sequence pll_npu_seq_power_on[] = {
+ {RTD1625_REG_PLL_NPU2, 0x5},
+ {RTD1625_REG_PLL_NPU2, 0x7},
+ {RTD1625_REG_PLL_NPU1, 0x54000},
+ {RTD1625_REG_PLL_SSC_DIG_NPU0, 0x4},
+ {RTD1625_REG_PLL_SSC_DIG_NPU0, 0x5, 200},
+ {RTD1625_REG_PLL_NPU2, 0x3},
+};
+
+static const struct reg_sequence pll_npu_seq_power_off[] = {
+ {RTD1625_REG_PLL_NPU2, 0x4},
+ {RTD1625_REG_PLL_NPU1, 0x54010},
+};
+
+static const struct reg_sequence pll_npu_seq_pre_set_freq[] = {
+ {RTD1625_REG_PLL_SSC_DIG_NPU0, 0x4},
+};
+
+static const struct reg_sequence pll_npu_seq_post_set_freq[] = {
+ {RTD1625_REG_PLL_SSC_DIG_NPU0, 0x5},
+};
+
+static struct rtk_clk_regmap_pll pll_npu = {
+ .clkr.hw.init = CLK_HW_INIT_FW_NAME("pll_npu", "osc27m", &rtk_clk_pll_ops,
+ CLK_GET_RATE_NOCACHE),
+ .seq_power_on = pll_npu_seq_power_on,
+ .num_seq_power_on = ARRAY_SIZE(pll_npu_seq_power_on),
+ .seq_power_off = pll_npu_seq_power_off,
+ .num_seq_power_off = ARRAY_SIZE(pll_npu_seq_power_off),
+ .seq_pre_set_freq = pll_npu_seq_pre_set_freq,
+ .num_seq_pre_set_freq = ARRAY_SIZE(pll_npu_seq_pre_set_freq),
+ .seq_post_set_freq = pll_npu_seq_post_set_freq,
+ .num_seq_post_set_freq = ARRAY_SIZE(pll_npu_seq_post_set_freq),
+ .freq_reg = RTD1625_REG_PLL_SSC_DIG_NPU1,
+ .freq_tbl = npu_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .freq_ready_reg = RTD1625_REG_PLL_SSC_DIG_NPU_DBG2,
+ .freq_ready_mask = BIT(20),
+ .freq_ready_val = BIT(20),
+ .power_reg = RTD1625_REG_PLL_NPU2,
+ .power_mask = 0x7,
+ .power_val_on = 0x3,
+ .expected_parent_rate = 27000000,
+ .lock = __SPIN_LOCK_UNLOCKED(pll_npu.lock),
+};
+
+static CLK_FIXED_FACTOR_HW(clk_npu, "clk_npu", &__rtk_clk_regmap_pll_hw(&pll_npu), 1, 1,
+ CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HW(clk_npu_mipi_csi, "clk_npu_mipi_csi",
+ &__rtk_clk_regmap_pll_hw(&pll_npu), 1, 1, CLK_SET_RATE_PARENT);
+
+static const struct reg_sequence pll_ve2_seq_power_on[] = {
+ {RTD1625_REG_PLL_VE2_2, 0x5},
+ {RTD1625_REG_PLL_VE2_2, 0x7},
+ {RTD1625_REG_PLL_VE2_1, 0x54000},
+ {RTD1625_REG_PLL_SSC_DIG_VE2_0, 0x4},
+ {RTD1625_REG_PLL_SSC_DIG_VE2_0, 0x5, 200},
+ {RTD1625_REG_PLL_VE2_2, 0x3},
+};
+
+static const struct reg_sequence pll_ve2_seq_power_off[] = {
+ {RTD1625_REG_PLL_VE2_2, 0x4},
+};
+
+static const struct reg_sequence pll_ve2_seq_pre_set_freq[] = {
+ {RTD1625_REG_PLL_SSC_DIG_VE2_0, 0x4},
+};
+
+static const struct reg_sequence pll_ve2_seq_post_set_freq[] = {
+ {RTD1625_REG_PLL_SSC_DIG_VE2_0, 0x5},
+};
+
+static struct rtk_clk_regmap_pll pll_ve2 = {
+ .clkr.hw.init = CLK_HW_INIT_FW_NAME("pll_ve2", "osc27m", &rtk_clk_pll_ops,
+ CLK_GET_RATE_NOCACHE),
+ .seq_power_on = pll_ve2_seq_power_on,
+ .num_seq_power_on = ARRAY_SIZE(pll_ve2_seq_power_on),
+ .seq_power_off = pll_ve2_seq_power_off,
+ .num_seq_power_off = ARRAY_SIZE(pll_ve2_seq_power_off),
+ .seq_pre_set_freq = pll_ve2_seq_pre_set_freq,
+ .num_seq_pre_set_freq = ARRAY_SIZE(pll_ve2_seq_pre_set_freq),
+ .seq_post_set_freq = pll_ve2_seq_post_set_freq,
+ .num_seq_post_set_freq = ARRAY_SIZE(pll_ve2_seq_post_set_freq),
+ .freq_reg = RTD1625_REG_PLL_SSC_DIG_VE2_1,
+ .freq_tbl = ve_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .freq_ready_reg = RTD1625_REG_PLL_SSC_DIG_VE2_DBG2,
+ .freq_ready_mask = BIT(20),
+ .freq_ready_val = BIT(20),
+ .power_reg = RTD1625_REG_PLL_VE2_2,
+ .power_mask = 0x7,
+ .power_val_on = 0x3,
+ .expected_parent_rate = 27000000,
+ .lock = __SPIN_LOCK_UNLOCKED(pll_ve2.lock),
+};
+
+static const struct reg_sequence pll_hifi_seq_power_on[] = {
+ {RTD1625_REG_PLL_HIFI2, 0x5},
+ {RTD1625_REG_PLL_HIFI2, 0x7},
+ {RTD1625_REG_PLL_HIFI1, 0x54000},
+ {RTD1625_REG_PLL_SSC_DIG_HIFI0, 0x4},
+ {RTD1625_REG_PLL_SSC_DIG_HIFI0, 0x5, 200},
+ {RTD1625_REG_PLL_HIFI2, 0x3},
+};
+
+static const struct reg_sequence pll_hifi_seq_power_off[] = {
+ {RTD1625_REG_PLL_HIFI2, 0x4},
+};
+
+static const struct reg_sequence pll_hifi_seq_pre_set_freq[] = {
+ {RTD1625_REG_PLL_SSC_DIG_HIFI0, 0x4},
+};
+
+static const struct reg_sequence pll_hifi_seq_post_set_freq[] = {
+ {RTD1625_REG_PLL_SSC_DIG_HIFI0, 0x5},
+};
+
+static struct rtk_clk_regmap_pll pll_hifi = {
+ .clkr.hw.init = CLK_HW_INIT_FW_NAME("pll_hifi", "osc27m", &rtk_clk_pll_ops,
+ CLK_GET_RATE_NOCACHE),
+ .seq_power_on = pll_hifi_seq_power_on,
+ .num_seq_power_on = ARRAY_SIZE(pll_hifi_seq_power_on),
+ .seq_power_off = pll_hifi_seq_power_off,
+ .num_seq_power_off = ARRAY_SIZE(pll_hifi_seq_power_off),
+ .seq_pre_set_freq = pll_hifi_seq_pre_set_freq,
+ .num_seq_pre_set_freq = ARRAY_SIZE(pll_hifi_seq_pre_set_freq),
+ .seq_post_set_freq = pll_hifi_seq_post_set_freq,
+ .num_seq_post_set_freq = ARRAY_SIZE(pll_hifi_seq_post_set_freq),
+ .freq_reg = RTD1625_REG_PLL_SSC_DIG_HIFI1,
+ .freq_tbl = hifi_tbl,
+ .freq_mask = FREQ_NF_MASK,
+ .freq_ready_reg = RTD1625_REG_PLL_SSC_DIG_HIFI_DBG2,
+ .freq_ready_mask = BIT(20),
+ .freq_ready_val = BIT(20),
+ .power_reg = RTD1625_REG_PLL_HIFI2,
+ .power_mask = 0x7,
+ .power_val_on = 0x3,
+ .expected_parent_rate = 27000000,
+ .lock = __SPIN_LOCK_UNLOCKED(pll_hifi.lock),
+};
+
+/* The shared tune calculates to 196,999,969 Hz with a 27 MHz ref. */
+static const struct rtk_clk_pll_mmc_rate rtd1625_pll_emmc_rate_tbl[] = {
+ { .rate = 196999969, .ssc_div_n = 27,
+ .ssc_div_ext_f = 1517, .ncode = 27, .fcode = 321, .gran_est = 5985 },
+};
+
+static CLK_FIXED_FACTOR_FW_NAME(pll_emmc_ref, "pll_emmc_ref", "osc27m", 1, 1, 0);
+
+static struct rtk_clk_regmap_pll_mmc pll_emmc = {
+ .pll_ofs = 0x1f0,
+ .ssc_dig_ofs = 0x6b0,
+ .clkr.hw.init = CLK_HW_INIT_HW("pll_emmc", &pll_emmc_ref.hw, &rtk_clk_pll_mmc_ops, 0),
+ .rate_tbl = rtd1625_pll_emmc_rate_tbl,
+ .num_rate_tbl = ARRAY_SIZE(rtd1625_pll_emmc_rate_tbl),
+};
+
+static struct rtk_clk_pll_mmc_phase pll_emmc_vp0 = {
+ .clkr.hw.init = CLK_HW_INIT_HW("pll_emmc_vp0",
+ &__rtk_clk_regmap_pll_mmc_phase_hw(&pll_emmc),
+ &rtk_clk_pll_mmc_phase_ops, 0),
+ .pll_mmc = &pll_emmc,
+ .shift = 3,
+};
+
+static struct rtk_clk_pll_mmc_phase pll_emmc_vp1 = {
+ .clkr.hw.init = CLK_HW_INIT_HW("pll_emmc_vp1",
+ &__rtk_clk_regmap_pll_mmc_phase_hw(&pll_emmc),
+ &rtk_clk_pll_mmc_phase_ops, 0),
+ .pll_mmc = &pll_emmc,
+ .shift = 8,
+};
+
+static const struct clk_hw *clk_gpu_parents[] = { &__rtk_clk_regmap_pll_hw(&pll_gpu), &clk_sys.hw };
+static RTK_CLK_REGMAP_MUX_HW(clk_gpu, clk_gpu_parents,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 0x28, 12, 0x1);
+static const struct clk_hw *clk_ve_parents[] = { &__rtk_clk_regmap_pll_hw(&pll_vodma), &clk_sysh.hw,
+ &__rtk_clk_regmap_pll_hw(&pll_ve1),
+ &__rtk_clk_regmap_pll_hw(&pll_ve2) };
+static RTK_CLK_REGMAP_MUX_HW(clk_ve1, clk_ve_parents,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 0x4c, 0, 0x3);
+static RTK_CLK_REGMAP_MUX_HW(clk_ve2, clk_ve_parents,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 0x4c, 3, 0x3);
+static RTK_CLK_REGMAP_MUX_HW(clk_ve4, clk_ve_parents,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 0x4c, 6, 0x3);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_misc, &clk_sys.hw, CLK_IS_CRITICAL, 0x50, 0, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_pcie0, &clk_sys.hw, 0, 0x50, 2, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_gspi, &clk_sys.hw, 0, 0x50, 6, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_iso_misc, &clk_sys.hw, CLK_IS_CRITICAL, 0x50, 10, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_sds, &clk_sys.hw, 0, 0x50, 12, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_hdmi, &clk_sys.hw, 0, 0x50, 14, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_gpu, &__rtk_clk_regmap_mux_hw(&clk_gpu),
+ CLK_SET_RATE_PARENT, 0x50, 18, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ve1, &__rtk_clk_regmap_mux_hw(&clk_ve1),
+ CLK_SET_RATE_PARENT, 0x50, 20, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ve2, &__rtk_clk_regmap_mux_hw(&clk_ve2),
+ CLK_SET_RATE_PARENT, 0x50, 22, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_md, &clk_sys.hw, 0, 0x54, 4, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_tp, &clk_sys.hw, 0, 0x54, 6, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_rcic, &clk_sys.hw, 0, 0x54, 8, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_nf, &clk_sys.hw, 0, 0x54, 10, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_emmc, &clk_sys.hw, 0, 0x54, 12, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_sd, &clk_sys.hw, 0, 0x54, 14, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_sdio_ip, &clk_sys.hw, 0, 0x54, 16, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_mipi_csi, &clk_sysh.hw, 0, 0x54, 18, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_emmc_ip, &__rtk_clk_regmap_pll_mmc_hw(&pll_emmc),
+ CLK_SET_RATE_PARENT,
+ 0x54, 20, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_sdio, &clk_sys.hw, 0, 0x54, 22, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_sd_ip, &clk_sys.hw, 0, 0x54, 24, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_tpb, &clk_sys.hw, 0, 0x54, 28, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_misc_sc1, &__rtk_clk_regmap_gate_hw(&clk_en_misc),
+ 0, 0x54, 30, 1);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_misc_i2c_3, "osc27m", 0, 0x58, 0, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_jpeg, &clk_sysh.hw, 0, 0x58, 4, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_acpu, &__rtk_clk_regmap_pll_hw(&pll_acpu),
+ CLK_SET_RATE_PARENT, 0x58, 6, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_misc_sc0, &__rtk_clk_regmap_gate_hw(&clk_en_misc),
+ 0, 0x58, 10, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_hdmirx, &clk_sys.hw, 0, 0x58, 26, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_hse, &clk_sysh.hw, CLK_IS_CRITICAL, 0x58, 28, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_fan, &clk_sys.hw, 0, 0x5c, 2, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_sata_wrap_sys, &clk_sys.hw, 0, 0x5c, 8, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_sata_wrap_sysh, &clk_sysh.hw, 0, 0x5c, 10, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_sata_mac_sysh, &clk_sysh.hw, 0, 0x5c, 12, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_r2rdsc, &clk_sys.hw, 0, 0x5c, 14, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_pcie1, &clk_sys.hw, 0, 0x5c, 18, 1);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_misc_i2c_4, "osc27m", 0, 0x5c, 20, 1);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_misc_i2c_5, "osc27m", 0, 0x5c, 22, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_tsio, &clk_sys.hw, 0, 0x5c, 24, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ve4, &__rtk_clk_regmap_mux_hw(&clk_ve4),
+ CLK_SET_RATE_PARENT, 0x5c, 26, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_edp, &clk_sys.hw, 0, 0x5c, 28, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_tsio_trx, &clk_sys.hw, 0, 0x5c, 30, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_pcie2, &clk_sys.hw, 0, 0x8c, 0, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_earc, &clk_sys.hw, 0, 0x8c, 4, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_lite, &clk_sys.hw, 0, 0x8c, 6, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_mipi_dsi, &clk_sys.hw, 0, 0x8c, 8, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_npupp, &clk_sys.hw, 0, 0x8c, 10, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_npu, &clk_npu.hw, 0, 0x8c, 12, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_aucpu0, &__rtk_clk_regmap_pll_hw(&pll_hifi),
+ 0, 0x8c, 14, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_aucpu1, &__rtk_clk_regmap_pll_hw(&pll_hifi),
+ 0, 0x8c, 16, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_nsram, &clk_sys.hw, 0, 0x8c, 18, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_hdmitop, &clk_sys.hw, 0, 0x8c, 20, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_aucpu_iso_npu, &__rtk_clk_regmap_pll_hw(&pll_hifi),
+ 0, 0x8c, 24, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_keyladder, &clk_sys.hw, 0, 0x8c, 26, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ifcp_klm, &clk_sys.hw, 0, 0x8c, 28, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ifcp, &clk_sys.hw, 0, 0x8c, 30, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_mdl_genpw, &clk_sys.hw, 0, 0xb0, 0, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_mdl_chip, &clk_sys.hw, 0, 0xb0, 2, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_mdl_ip, &clk_sys.hw, 0, 0xb0, 4, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_mdlm2m, &clk_sys.hw, 0, 0xb0, 6, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_mdl_xtal, &clk_sys.hw, 0, 0xb0, 8, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_test_mux, &clk_sys.hw, 0, 0xb0, 10, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_dla, &clk_sysh.hw, 0, 0xb0, 12, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_tpcw, &clk_sys.hw, CLK_IS_CRITICAL, 0xb0, 16, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_gpu_ts_src, &clk_sys.hw, 0, 0xb0, 18, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_vi, &clk_sysh.hw, 0, 0xb0, 22, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_lvds1, &clk_sys.hw, 0, 0xb0, 24, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_lvds2, &clk_sys.hw, 0, 0xb0, 26, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_aucpu, &__rtk_clk_regmap_pll_hw(&pll_hifi),
+ 0, 0xb0, 28, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ur_top, &clk_sys.hw, CLK_IS_CRITICAL, 0x884, 18, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ur1, &__rtk_clk_regmap_gate_hw(&clk_en_ur_top),
+ 0, 0x884, 0, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ur2, &__rtk_clk_regmap_gate_hw(&clk_en_ur_top),
+ 0, 0x884, 2, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ur3, &__rtk_clk_regmap_gate_hw(&clk_en_ur_top),
+ 0, 0x884, 4, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ur4, &__rtk_clk_regmap_gate_hw(&clk_en_ur_top),
+ 0, 0x884, 6, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ur5, &__rtk_clk_regmap_gate_hw(&clk_en_ur_top),
+ 0, 0x884, 8, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ur6, &__rtk_clk_regmap_gate_hw(&clk_en_ur_top),
+ 0, 0x884, 10, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ur7, &__rtk_clk_regmap_gate_hw(&clk_en_ur_top),
+ 0, 0x884, 12, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ur8, &__rtk_clk_regmap_gate_hw(&clk_en_ur_top),
+ 0, 0x884, 14, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_ur9, &__rtk_clk_regmap_gate_hw(&clk_en_ur_top),
+ 0, 0x884, 16, 1);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_misc_i2c_7, "osc27m", 0, 0x884, 28, 1);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_misc_i2c_6, "osc27m", 0, 0x884, 30, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_spi0, &clk_sys.hw, 0, 0x894, 0, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_spi1, &clk_sys.hw, 0, 0x894, 2, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_spi2, &clk_sys.hw, 0, 0x894, 4, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_lsadc0, &clk_sys.hw, 0, 0x894, 16, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_lsadc1, &clk_sys.hw, 0, 0x894, 18, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_isomis_dma, &clk_sys.hw, 0, 0x894, 20, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_dptx, &clk_sys.hw, 0, 0x894, 24, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_npu_mipi_csi, &clk_npu_mipi_csi.hw, 0, 0x894, 26, 1);
+static RTK_CLK_REGMAP_GATE_HW(clk_en_edptx, &clk_sys.hw, 0, 0x894, 28, 1);
+
+static struct rtk_clk_regmap *rtd1625_crt_regmap_clks[] = {
+ &clk_en_misc.clkr,
+ &clk_en_pcie0.clkr,
+ &clk_en_gspi.clkr,
+ &clk_en_iso_misc.clkr,
+ &clk_en_sds.clkr,
+ &clk_en_hdmi.clkr,
+ &clk_en_gpu.clkr,
+ &clk_en_ve1.clkr,
+ &clk_en_ve2.clkr,
+ &clk_en_md.clkr,
+ &clk_en_tp.clkr,
+ &clk_en_rcic.clkr,
+ &clk_en_nf.clkr,
+ &clk_en_emmc.clkr,
+ &pll_emmc_vp0.clkr,
+ &pll_emmc_vp1.clkr,
+ &clk_en_sd.clkr,
+ &clk_en_sdio_ip.clkr,
+ &clk_en_mipi_csi.clkr,
+ &clk_en_emmc_ip.clkr,
+ &clk_en_sdio.clkr,
+ &clk_en_sd_ip.clkr,
+ &clk_en_tpb.clkr,
+ &clk_en_misc_sc1.clkr,
+ &clk_en_misc_i2c_3.clkr,
+ &clk_en_jpeg.clkr,
+ &clk_en_acpu.clkr,
+ &clk_en_misc_sc0.clkr,
+ &clk_en_hdmirx.clkr,
+ &clk_en_hse.clkr,
+ &clk_en_fan.clkr,
+ &clk_en_sata_wrap_sys.clkr,
+ &clk_en_sata_wrap_sysh.clkr,
+ &clk_en_sata_mac_sysh.clkr,
+ &clk_en_r2rdsc.clkr,
+ &clk_en_pcie1.clkr,
+ &clk_en_misc_i2c_4.clkr,
+ &clk_en_misc_i2c_5.clkr,
+ &clk_en_tsio.clkr,
+ &clk_en_ve4.clkr,
+ &clk_en_edp.clkr,
+ &clk_en_tsio_trx.clkr,
+ &clk_en_pcie2.clkr,
+ &clk_en_earc.clkr,
+ &clk_en_lite.clkr,
+ &clk_en_mipi_dsi.clkr,
+ &clk_en_npupp.clkr,
+ &clk_en_npu.clkr,
+ &clk_en_aucpu0.clkr,
+ &clk_en_aucpu1.clkr,
+ &clk_en_nsram.clkr,
+ &clk_en_hdmitop.clkr,
+ &clk_en_aucpu_iso_npu.clkr,
+ &clk_en_keyladder.clkr,
+ &clk_en_ifcp_klm.clkr,
+ &clk_en_ifcp.clkr,
+ &clk_en_mdl_genpw.clkr,
+ &clk_en_mdl_chip.clkr,
+ &clk_en_mdl_ip.clkr,
+ &clk_en_mdlm2m.clkr,
+ &clk_en_mdl_xtal.clkr,
+ &clk_en_test_mux.clkr,
+ &clk_en_dla.clkr,
+ &clk_en_tpcw.clkr,
+ &clk_en_gpu_ts_src.clkr,
+ &clk_en_vi.clkr,
+ &clk_en_lvds1.clkr,
+ &clk_en_lvds2.clkr,
+ &clk_en_aucpu.clkr,
+ &clk_en_ur1.clkr,
+ &clk_en_ur2.clkr,
+ &clk_en_ur3.clkr,
+ &clk_en_ur4.clkr,
+ &clk_en_ur5.clkr,
+ &clk_en_ur6.clkr,
+ &clk_en_ur7.clkr,
+ &clk_en_ur8.clkr,
+ &clk_en_ur9.clkr,
+ &clk_en_ur_top.clkr,
+ &clk_en_misc_i2c_7.clkr,
+ &clk_en_misc_i2c_6.clkr,
+ &clk_en_spi0.clkr,
+ &clk_en_spi1.clkr,
+ &clk_en_spi2.clkr,
+ &clk_en_lsadc0.clkr,
+ &clk_en_lsadc1.clkr,
+ &clk_en_isomis_dma.clkr,
+ &clk_en_dptx.clkr,
+ &clk_en_npu_mipi_csi.clkr,
+ &clk_en_edptx.clkr,
+ &clk_gpu.clkr,
+ &clk_ve1.clkr,
+ &clk_ve2.clkr,
+ &clk_ve4.clkr,
+ &pll_ve1.clkr,
+ &pll_ddsa.clkr,
+ &pll_bus.clkr,
+ &pll_dcsb.clkr,
+ &pll_gpu.clkr,
+ &pll_npu.clkr,
+ &pll_ve2.clkr,
+ &pll_hifi.clkr,
+ &pll_emmc.clkr,
+ &pll_vodma.clkr,
+ &pll_acpu.clkr,
+};
+
+static struct clk_hw_onecell_data rtd1625_crt_hw_data = {
+ .num = RTD1625_CRT_CLK_MAX,
+ .hws = {
+ [RTD1625_CRT_CLK_EN_MISC] = &__rtk_clk_regmap_gate_hw(&clk_en_misc),
+ [RTD1625_CRT_CLK_EN_PCIE0] = &__rtk_clk_regmap_gate_hw(&clk_en_pcie0),
+ [RTD1625_CRT_CLK_EN_GSPI] = &__rtk_clk_regmap_gate_hw(&clk_en_gspi),
+ [RTD1625_CRT_CLK_EN_ISO_MISC] = &__rtk_clk_regmap_gate_hw(&clk_en_iso_misc),
+ [RTD1625_CRT_CLK_EN_SDS] = &__rtk_clk_regmap_gate_hw(&clk_en_sds),
+ [RTD1625_CRT_CLK_EN_HDMI] = &__rtk_clk_regmap_gate_hw(&clk_en_hdmi),
+ [RTD1625_CRT_CLK_EN_GPU] = &__rtk_clk_regmap_gate_hw(&clk_en_gpu),
+ [RTD1625_CRT_CLK_EN_VE1] = &__rtk_clk_regmap_gate_hw(&clk_en_ve1),
+ [RTD1625_CRT_CLK_EN_VE2] = &__rtk_clk_regmap_gate_hw(&clk_en_ve2),
+ [RTD1625_CRT_CLK_EN_MD] = &__rtk_clk_regmap_gate_hw(&clk_en_md),
+ [RTD1625_CRT_CLK_EN_TP] = &__rtk_clk_regmap_gate_hw(&clk_en_tp),
+ [RTD1625_CRT_CLK_EN_RCIC] = &__rtk_clk_regmap_gate_hw(&clk_en_rcic),
+ [RTD1625_CRT_CLK_EN_NF] = &__rtk_clk_regmap_gate_hw(&clk_en_nf),
+ [RTD1625_CRT_CLK_EN_EMMC] = &__rtk_clk_regmap_gate_hw(&clk_en_emmc),
+ [RTD1625_CRT_CLK_EN_SD] = &__rtk_clk_regmap_gate_hw(&clk_en_sd),
+ [RTD1625_CRT_CLK_EN_SDIO_IP] = &__rtk_clk_regmap_gate_hw(&clk_en_sdio_ip),
+ [RTD1625_CRT_CLK_EN_MIPI_CSI] = &__rtk_clk_regmap_gate_hw(&clk_en_mipi_csi),
+ [RTD1625_CRT_CLK_EN_EMMC_IP] = &__rtk_clk_regmap_gate_hw(&clk_en_emmc_ip),
+ [RTD1625_CRT_CLK_EN_SDIO] = &__rtk_clk_regmap_gate_hw(&clk_en_sdio),
+ [RTD1625_CRT_CLK_EN_SD_IP] = &__rtk_clk_regmap_gate_hw(&clk_en_sd_ip),
+ [RTD1625_CRT_CLK_EN_TPB] = &__rtk_clk_regmap_gate_hw(&clk_en_tpb),
+ [RTD1625_CRT_CLK_EN_MISC_SC1] = &__rtk_clk_regmap_gate_hw(&clk_en_misc_sc1),
+ [RTD1625_CRT_CLK_EN_MISC_I2C_3] = &__rtk_clk_regmap_gate_hw(&clk_en_misc_i2c_3),
+ [RTD1625_CRT_CLK_EN_ACPU] = &__rtk_clk_regmap_gate_hw(&clk_en_acpu),
+ [RTD1625_CRT_CLK_EN_JPEG] = &__rtk_clk_regmap_gate_hw(&clk_en_jpeg),
+ [RTD1625_CRT_CLK_EN_MISC_SC0] = &__rtk_clk_regmap_gate_hw(&clk_en_misc_sc0),
+ [RTD1625_CRT_CLK_EN_HDMIRX] = &__rtk_clk_regmap_gate_hw(&clk_en_hdmirx),
+ [RTD1625_CRT_CLK_EN_HSE] = &__rtk_clk_regmap_gate_hw(&clk_en_hse),
+ [RTD1625_CRT_CLK_EN_FAN] = &__rtk_clk_regmap_gate_hw(&clk_en_fan),
+ [RTD1625_CRT_CLK_EN_SATA_WRAP_SYS] =
+ &__rtk_clk_regmap_gate_hw(&clk_en_sata_wrap_sys),
+ [RTD1625_CRT_CLK_EN_SATA_WRAP_SYSH] =
+ &__rtk_clk_regmap_gate_hw(&clk_en_sata_wrap_sysh),
+ [RTD1625_CRT_CLK_EN_SATA_MAC_SYSH] =
+ &__rtk_clk_regmap_gate_hw(&clk_en_sata_mac_sysh),
+ [RTD1625_CRT_CLK_EN_R2RDSC] = &__rtk_clk_regmap_gate_hw(&clk_en_r2rdsc),
+ [RTD1625_CRT_CLK_EN_PCIE1] = &__rtk_clk_regmap_gate_hw(&clk_en_pcie1),
+ [RTD1625_CRT_CLK_EN_MISC_I2C_4] = &__rtk_clk_regmap_gate_hw(&clk_en_misc_i2c_4),
+ [RTD1625_CRT_CLK_EN_MISC_I2C_5] = &__rtk_clk_regmap_gate_hw(&clk_en_misc_i2c_5),
+ [RTD1625_CRT_CLK_EN_TSIO] = &__rtk_clk_regmap_gate_hw(&clk_en_tsio),
+ [RTD1625_CRT_CLK_EN_VE4] = &__rtk_clk_regmap_gate_hw(&clk_en_ve4),
+ [RTD1625_CRT_CLK_EN_EDP] = &__rtk_clk_regmap_gate_hw(&clk_en_edp),
+ [RTD1625_CRT_CLK_EN_TSIO_TRX] = &__rtk_clk_regmap_gate_hw(&clk_en_tsio_trx),
+ [RTD1625_CRT_CLK_EN_PCIE2] = &__rtk_clk_regmap_gate_hw(&clk_en_pcie2),
+ [RTD1625_CRT_CLK_EN_EARC] = &__rtk_clk_regmap_gate_hw(&clk_en_earc),
+ [RTD1625_CRT_CLK_EN_LITE] = &__rtk_clk_regmap_gate_hw(&clk_en_lite),
+ [RTD1625_CRT_CLK_EN_MIPI_DSI] = &__rtk_clk_regmap_gate_hw(&clk_en_mipi_dsi),
+ [RTD1625_CRT_CLK_EN_NPUPP] = &__rtk_clk_regmap_gate_hw(&clk_en_npupp),
+ [RTD1625_CRT_CLK_EN_NPU] = &__rtk_clk_regmap_gate_hw(&clk_en_npu),
+ [RTD1625_CRT_CLK_EN_AUCPU0] = &__rtk_clk_regmap_gate_hw(&clk_en_aucpu0),
+ [RTD1625_CRT_CLK_EN_AUCPU1] = &__rtk_clk_regmap_gate_hw(&clk_en_aucpu1),
+ [RTD1625_CRT_CLK_EN_NSRAM] = &__rtk_clk_regmap_gate_hw(&clk_en_nsram),
+ [RTD1625_CRT_CLK_EN_HDMITOP] = &__rtk_clk_regmap_gate_hw(&clk_en_hdmitop),
+ [RTD1625_CRT_CLK_EN_AUCPU_ISO_NPU] =
+ &__rtk_clk_regmap_gate_hw(&clk_en_aucpu_iso_npu),
+ [RTD1625_CRT_CLK_EN_KEYLADDER] = &__rtk_clk_regmap_gate_hw(&clk_en_keyladder),
+ [RTD1625_CRT_CLK_EN_IFCP_KLM] = &__rtk_clk_regmap_gate_hw(&clk_en_ifcp_klm),
+ [RTD1625_CRT_CLK_EN_IFCP] = &__rtk_clk_regmap_gate_hw(&clk_en_ifcp),
+ [RTD1625_CRT_CLK_EN_MDL_GENPW] = &__rtk_clk_regmap_gate_hw(&clk_en_mdl_genpw),
+ [RTD1625_CRT_CLK_EN_MDL_CHIP] = &__rtk_clk_regmap_gate_hw(&clk_en_mdl_chip),
+ [RTD1625_CRT_CLK_EN_MDL_IP] = &__rtk_clk_regmap_gate_hw(&clk_en_mdl_ip),
+ [RTD1625_CRT_CLK_EN_MDLM2M] = &__rtk_clk_regmap_gate_hw(&clk_en_mdlm2m),
+ [RTD1625_CRT_CLK_EN_MDL_XTAL] = &__rtk_clk_regmap_gate_hw(&clk_en_mdl_xtal),
+ [RTD1625_CRT_CLK_EN_TEST_MUX] = &__rtk_clk_regmap_gate_hw(&clk_en_test_mux),
+ [RTD1625_CRT_CLK_EN_DLA] = &__rtk_clk_regmap_gate_hw(&clk_en_dla),
+ [RTD1625_CRT_CLK_EN_TPCW] = &__rtk_clk_regmap_gate_hw(&clk_en_tpcw),
+ [RTD1625_CRT_CLK_EN_GPU_TS_SRC] = &__rtk_clk_regmap_gate_hw(&clk_en_gpu_ts_src),
+ [RTD1625_CRT_CLK_EN_VI] = &__rtk_clk_regmap_gate_hw(&clk_en_vi),
+ [RTD1625_CRT_CLK_EN_LVDS1] = &__rtk_clk_regmap_gate_hw(&clk_en_lvds1),
+ [RTD1625_CRT_CLK_EN_LVDS2] = &__rtk_clk_regmap_gate_hw(&clk_en_lvds2),
+ [RTD1625_CRT_CLK_EN_AUCPU] = &__rtk_clk_regmap_gate_hw(&clk_en_aucpu),
+ [RTD1625_CRT_CLK_EN_UR1] = &__rtk_clk_regmap_gate_hw(&clk_en_ur1),
+ [RTD1625_CRT_CLK_EN_UR2] = &__rtk_clk_regmap_gate_hw(&clk_en_ur2),
+ [RTD1625_CRT_CLK_EN_UR3] = &__rtk_clk_regmap_gate_hw(&clk_en_ur3),
+ [RTD1625_CRT_CLK_EN_UR4] = &__rtk_clk_regmap_gate_hw(&clk_en_ur4),
+ [RTD1625_CRT_CLK_EN_UR5] = &__rtk_clk_regmap_gate_hw(&clk_en_ur5),
+ [RTD1625_CRT_CLK_EN_UR6] = &__rtk_clk_regmap_gate_hw(&clk_en_ur6),
+ [RTD1625_CRT_CLK_EN_UR7] = &__rtk_clk_regmap_gate_hw(&clk_en_ur7),
+ [RTD1625_CRT_CLK_EN_UR8] = &__rtk_clk_regmap_gate_hw(&clk_en_ur8),
+ [RTD1625_CRT_CLK_EN_UR9] = &__rtk_clk_regmap_gate_hw(&clk_en_ur9),
+ [RTD1625_CRT_CLK_EN_UR_TOP] = &__rtk_clk_regmap_gate_hw(&clk_en_ur_top),
+ [RTD1625_CRT_CLK_EN_MISC_I2C_7] = &__rtk_clk_regmap_gate_hw(&clk_en_misc_i2c_7),
+ [RTD1625_CRT_CLK_EN_MISC_I2C_6] = &__rtk_clk_regmap_gate_hw(&clk_en_misc_i2c_6),
+ [RTD1625_CRT_CLK_EN_SPI0] = &__rtk_clk_regmap_gate_hw(&clk_en_spi0),
+ [RTD1625_CRT_CLK_EN_SPI1] = &__rtk_clk_regmap_gate_hw(&clk_en_spi1),
+ [RTD1625_CRT_CLK_EN_SPI2] = &__rtk_clk_regmap_gate_hw(&clk_en_spi2),
+ [RTD1625_CRT_CLK_EN_LSADC0] = &__rtk_clk_regmap_gate_hw(&clk_en_lsadc0),
+ [RTD1625_CRT_CLK_EN_LSADC1] = &__rtk_clk_regmap_gate_hw(&clk_en_lsadc1),
+ [RTD1625_CRT_CLK_EN_ISOMIS_DMA] = &__rtk_clk_regmap_gate_hw(&clk_en_isomis_dma),
+ [RTD1625_CRT_CLK_EN_DPTX] = &__rtk_clk_regmap_gate_hw(&clk_en_dptx),
+ [RTD1625_CRT_CLK_EN_NPU_MIPI_CSI] =
+ &__rtk_clk_regmap_gate_hw(&clk_en_npu_mipi_csi),
+ [RTD1625_CRT_CLK_EN_EDPTX] = &__rtk_clk_regmap_gate_hw(&clk_en_edptx),
+ [RTD1625_CRT_CLK_GPU] = &__rtk_clk_regmap_mux_hw(&clk_gpu),
+ [RTD1625_CRT_CLK_VE1] = &__rtk_clk_regmap_mux_hw(&clk_ve1),
+ [RTD1625_CRT_CLK_VE2] = &__rtk_clk_regmap_mux_hw(&clk_ve2),
+ [RTD1625_CRT_CLK_VE4] = &__rtk_clk_regmap_mux_hw(&clk_ve4),
+ [RTD1625_CRT_PLL_VE1] = &__rtk_clk_regmap_pll_hw(&pll_ve1),
+ [RTD1625_CRT_PLL_DDSA] = &__rtk_clk_regmap_pll_hw(&pll_ddsa),
+ [RTD1625_CRT_CLK_DDSA_DIV4] = &clk_ddsa_div4.hw,
+ [RTD1625_CRT_PLL_BUS] = &__rtk_clk_regmap_pll_hw(&pll_bus),
+ [RTD1625_CRT_CLK_SYS] = &clk_sys.hw,
+ [RTD1625_CRT_PLL_DCSB] = &__rtk_clk_regmap_pll_hw(&pll_dcsb),
+ [RTD1625_CRT_CLK_SYSH] = &clk_sysh.hw,
+ [RTD1625_CRT_PLL_GPU] = &__rtk_clk_regmap_pll_hw(&pll_gpu),
+ [RTD1625_CRT_PLL_NPU] = &__rtk_clk_regmap_pll_hw(&pll_npu),
+ [RTD1625_CRT_PLL_VE2] = &__rtk_clk_regmap_pll_hw(&pll_ve2),
+ [RTD1625_CRT_PLL_HIFI] = &__rtk_clk_regmap_pll_hw(&pll_hifi),
+ [RTD1625_CRT_PLL_EMMC_REF] = &pll_emmc_ref.hw,
+ [RTD1625_CRT_PLL_EMMC] = &__rtk_clk_regmap_pll_mmc_hw(&pll_emmc),
+ [RTD1625_CRT_PLL_EMMC_VP0] =
+ &__rtk_clk_regmap_pll_mmc_phase_hw(&pll_emmc_vp0),
+ [RTD1625_CRT_PLL_EMMC_VP1] =
+ &__rtk_clk_regmap_pll_mmc_phase_hw(&pll_emmc_vp1),
+ [RTD1625_CRT_PLL_ACPU] = &__rtk_clk_regmap_pll_hw(&pll_acpu),
+ [RTD1625_CRT_CLK_NPU] = &clk_npu.hw,
+ [RTD1625_CRT_CLK_NPU_MIPI_CSI] = &clk_npu_mipi_csi.hw,
+ [RTD1625_CRT_PLL_VODMA] = &__rtk_clk_regmap_pll_hw(&pll_vodma),
+ },
+};
+
+static const struct rtk_clk_desc rtd1625_crt_desc = {
+ .clk_data = &rtd1625_crt_hw_data,
+ .clks = rtd1625_crt_regmap_clks,
+ .num_clks = ARRAY_SIZE(rtd1625_crt_regmap_clks),
+ .aux_name = "rtd1625_crt_rst",
+};
+
+static int rtd1625_crt_probe(struct platform_device *pdev)
+{
+ const struct rtk_clk_desc *desc;
+
+ desc = device_get_match_data(&pdev->dev);
+ if (!desc)
+ return -EINVAL;
+
+ return rtk_clk_probe(pdev, desc);
+}
+
+static const struct of_device_id rtd1625_crt_match[] = {
+ { .compatible = "realtek,rtd1625-crt-clk", .data = &rtd1625_crt_desc, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rtd1625_crt_match);
+
+static struct platform_driver rtd1625_crt_driver = {
+ .probe = rtd1625_crt_probe,
+ .driver = {
+ .name = "rtk-rtd1625-crt-clk",
+ .of_match_table = rtd1625_crt_match,
+ },
+};
+
+module_platform_driver(rtd1625_crt_driver)
+
+MODULE_DESCRIPTION("Realtek RTD1625 CRT Clock Controller Driver");
+MODULE_AUTHOR("Cheng-Yu Lee <cylee12@realtek.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("CLK_REALTEK");
--
2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v16 8/9] clk: realtek: Add RTD1625-ISO clock controller driver
2026-11-12 5:25 [PATCH v16 0/9] clk: realtek: Add RTD1625 clock support Yu-Chun Lin
` (6 preceding siblings ...)
2026-11-12 5:25 ` [PATCH v16 7/9] clk: realtek: Add RTD1625-CRT clock controller driver Yu-Chun Lin
@ 2026-11-12 5:25 ` Yu-Chun Lin
2026-11-12 5:25 ` [PATCH v16 9/9] arm64: dts: realtek: Add clock support for RTD1625 Yu-Chun Lin
8 siblings, 0 replies; 16+ messages in thread
From: Yu-Chun Lin @ 2026-11-12 5:25 UTC (permalink / raw)
To: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou
Cc: linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, james.tai, cy.huang, stanley_chang,
eleanor.lin
From: Cheng-Yu Lee <cylee12@realtek.com>
Add support for the ISO (Isolation) domain clock controller on the Realtek
RTD1625 SoC. This controller manages clocks in the always-on power domain,
ensuring essential services remain functional even when the main system
power is gated.
Because the reset controller shares the same register space with this ISO
clock controller, this driver also acts as the parent device and registers
the reset controller as an auxiliary device on the auxiliary bus.
Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
Changes in v16:
- Remove Brian's reviewed-by tag.
- Switch all gate clock initializations to use '_FW_NAME' macros.
---
drivers/clk/realtek/Makefile | 1 +
drivers/clk/realtek/clk-rtd1625-iso.c | 140 ++++++++++++++++++++++++++
2 files changed, 141 insertions(+)
create mode 100644 drivers/clk/realtek/clk-rtd1625-iso.c
diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
index dd4c667e9808..04990a44c88a 100644
--- a/drivers/clk/realtek/Makefile
+++ b/drivers/clk/realtek/Makefile
@@ -9,3 +9,4 @@ clk-rtk-y += freq_table.o
clk-rtk-$(CONFIG_RTK_CLK_PLL_MMC) += clk-regmap-pll-mmc.o
obj-$(CONFIG_CLK_RTD1625) += clk-rtd1625-crt.o
+obj-$(CONFIG_CLK_RTD1625) += clk-rtd1625-iso.o
diff --git a/drivers/clk/realtek/clk-rtd1625-iso.c b/drivers/clk/realtek/clk-rtd1625-iso.c
new file mode 100644
index 000000000000..f7fd346ea964
--- /dev/null
+++ b/drivers/clk/realtek/clk-rtd1625-iso.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024-2026 Realtek Semiconductor Corporation
+ * Author: Cheng-Yu Lee <cylee12@realtek.com>
+ */
+
+#include <dt-bindings/clock/realtek,rtd1625-clk.h>
+#include <linux/array_size.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include "clk-regmap-gate.h"
+
+#define RTD1625_ISO_CLK_MAX 19
+#define RTD1625_ISO_S_CLK_MAX 5
+
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_usb_p4, "clk_sys", 0, 0x4, 0, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_usb_p3, "clk_sys", 0, 0x4, 1, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_misc_cec0, "clk_en_misc", 0, 0x4, 2, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_cbusrx_sys, "clk_sys", 0, 0x4, 3, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_cbustx_sys, "clk_sys", 0, 0x4, 4, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_cbus_sys, "clk_sys", 0, 0x4, 5, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_cbus_osc, "osc27m", 0, 0x4, 6, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_i2c0, "clk_ddsa_div4", 0, 0x4, 9, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_i2c1, "osc27m", 0, 0x4, 10, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_etn_250m, "clk_sys", 0, 0x4, 11, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_etn_sys, "clk_sys", 0, 0x4, 12, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_usb_drd, "clk_sys", 0, 0x4, 13, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_usb_host, "clk_sys", 0, 0x4, 14, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_usb_u3_host, "clk_sys", 0, 0x4, 15, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_usb, "clk_sys", 0, 0x4, 16, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_vtc, "osc27m", 0, 0x4, 17, 0);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_misc_vfd, "clk_en_misc", 0, 0x4, 18, 0);
+
+static struct rtk_clk_regmap *rtd1625_iso_clk_regmap_list[] = {
+ &clk_en_usb_p4.clkr,
+ &clk_en_usb_p3.clkr,
+ &clk_en_misc_cec0.clkr,
+ &clk_en_cbusrx_sys.clkr,
+ &clk_en_cbustx_sys.clkr,
+ &clk_en_cbus_sys.clkr,
+ &clk_en_cbus_osc.clkr,
+ &clk_en_i2c0.clkr,
+ &clk_en_i2c1.clkr,
+ &clk_en_etn_250m.clkr,
+ &clk_en_etn_sys.clkr,
+ &clk_en_usb_drd.clkr,
+ &clk_en_usb_host.clkr,
+ &clk_en_usb_u3_host.clkr,
+ &clk_en_usb.clkr,
+ &clk_en_vtc.clkr,
+ &clk_en_misc_vfd.clkr,
+};
+
+static struct clk_hw_onecell_data rtd1625_iso_clk_data = {
+ .num = RTD1625_ISO_CLK_MAX,
+ .hws = {
+ [RTD1625_ISO_CLK_EN_USB_P4] = &__rtk_clk_regmap_gate_hw(&clk_en_usb_p4),
+ [RTD1625_ISO_CLK_EN_USB_P3] = &__rtk_clk_regmap_gate_hw(&clk_en_usb_p3),
+ [RTD1625_ISO_CLK_EN_MISC_CEC0] = &__rtk_clk_regmap_gate_hw(&clk_en_misc_cec0),
+ [RTD1625_ISO_CLK_EN_CBUSRX_SYS] = &__rtk_clk_regmap_gate_hw(&clk_en_cbusrx_sys),
+ [RTD1625_ISO_CLK_EN_CBUSTX_SYS] = &__rtk_clk_regmap_gate_hw(&clk_en_cbustx_sys),
+ [RTD1625_ISO_CLK_EN_CBUS_SYS] = &__rtk_clk_regmap_gate_hw(&clk_en_cbus_sys),
+ [RTD1625_ISO_CLK_EN_CBUS_OSC] = &__rtk_clk_regmap_gate_hw(&clk_en_cbus_osc),
+ [RTD1625_ISO_CLK_EN_I2C0] = &__rtk_clk_regmap_gate_hw(&clk_en_i2c0),
+ [RTD1625_ISO_CLK_EN_I2C1] = &__rtk_clk_regmap_gate_hw(&clk_en_i2c1),
+ [RTD1625_ISO_CLK_EN_ETN_250M] = &__rtk_clk_regmap_gate_hw(&clk_en_etn_250m),
+ [RTD1625_ISO_CLK_EN_ETN_SYS] = &__rtk_clk_regmap_gate_hw(&clk_en_etn_sys),
+ [RTD1625_ISO_CLK_EN_USB_DRD] = &__rtk_clk_regmap_gate_hw(&clk_en_usb_drd),
+ [RTD1625_ISO_CLK_EN_USB_HOST] = &__rtk_clk_regmap_gate_hw(&clk_en_usb_host),
+ [RTD1625_ISO_CLK_EN_USB_U3_HOST] = &__rtk_clk_regmap_gate_hw(&clk_en_usb_u3_host),
+ [RTD1625_ISO_CLK_EN_USB] = &__rtk_clk_regmap_gate_hw(&clk_en_usb),
+ [RTD1625_ISO_CLK_EN_VTC] = &__rtk_clk_regmap_gate_hw(&clk_en_vtc),
+ [RTD1625_ISO_CLK_EN_MISC_VFD] = &__rtk_clk_regmap_gate_hw(&clk_en_misc_vfd),
+ },
+};
+
+static const struct rtk_clk_desc rtd1625_iso_desc = {
+ .clk_data = &rtd1625_iso_clk_data,
+ .clks = rtd1625_iso_clk_regmap_list,
+ .num_clks = ARRAY_SIZE(rtd1625_iso_clk_regmap_list),
+ .aux_name = "rtd1625_iso_rst",
+};
+
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_irda, "osc27m", 0, 0x4, 6, 1);
+static RTK_CLK_REGMAP_GATE_FW_NAME(clk_en_ur10, "osc27m", 0, 0x4, 8, 1);
+
+static struct rtk_clk_regmap *rtd1625_iso_s_clk_regmap_list[] = {
+ &clk_en_irda.clkr,
+ &clk_en_ur10.clkr,
+};
+
+static struct clk_hw_onecell_data rtd1625_iso_s_clk_data = {
+ .num = RTD1625_ISO_S_CLK_MAX,
+ .hws = {
+ [RTD1625_ISO_S_CLK_EN_IRDA] = &__rtk_clk_regmap_gate_hw(&clk_en_irda),
+ [RTD1625_ISO_S_CLK_EN_UR10] = &__rtk_clk_regmap_gate_hw(&clk_en_ur10),
+ },
+};
+
+static const struct rtk_clk_desc rtd1625_iso_s_desc = {
+ .clk_data = &rtd1625_iso_s_clk_data,
+ .clks = rtd1625_iso_s_clk_regmap_list,
+ .num_clks = ARRAY_SIZE(rtd1625_iso_s_clk_regmap_list),
+ .aux_name = "rtd1625_iso_s_rst",
+};
+
+static int rtd1625_iso_probe(struct platform_device *pdev)
+{
+ const struct rtk_clk_desc *desc;
+
+ desc = device_get_match_data(&pdev->dev);
+ if (!desc)
+ return -EINVAL;
+
+ return rtk_clk_probe(pdev, desc);
+}
+
+static const struct of_device_id rtd1625_iso_match[] = {
+ { .compatible = "realtek,rtd1625-iso-clk", .data = &rtd1625_iso_desc },
+ { .compatible = "realtek,rtd1625-iso-s-clk", .data = &rtd1625_iso_s_desc },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rtd1625_iso_match);
+
+static struct platform_driver rtd1625_iso_driver = {
+ .probe = rtd1625_iso_probe,
+ .driver = {
+ .name = "rtk-rtd1625-iso-clk",
+ .of_match_table = rtd1625_iso_match,
+ .suppress_bind_attrs = true,
+ },
+};
+
+module_platform_driver(rtd1625_iso_driver);
+
+MODULE_DESCRIPTION("Realtek RTD1625 ISO Clock Controller Driver");
+MODULE_AUTHOR("Cheng-Yu Lee <cylee12@realtek.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("CLK_REALTEK");
--
2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v16 9/9] arm64: dts: realtek: Add clock support for RTD1625
2026-11-12 5:25 [PATCH v16 0/9] clk: realtek: Add RTD1625 clock support Yu-Chun Lin
` (7 preceding siblings ...)
2026-11-12 5:25 ` [PATCH v16 8/9] clk: realtek: Add RTD1625-ISO " Yu-Chun Lin
@ 2026-11-12 5:25 ` Yu-Chun Lin
8 siblings, 0 replies; 16+ messages in thread
From: Yu-Chun Lin @ 2026-11-12 5:25 UTC (permalink / raw)
To: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou
Cc: linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, james.tai, cy.huang, stanley_chang,
eleanor.lin
Add the clock controller nodes and osc27m fixed clock for the
Realtek RTD1625 SoC.
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
Changes in v16:
- Add 'clock-names = "osc27m"' to the 'cc' and 'iso_s_cc' clock controller nodes.
- Explicitly wire up internal parent clocks from the 'cc' controller to the 'ic'
clock controller, along with their corresponding 'clock-names'.
---
arch/arm64/boot/dts/realtek/kent.dtsi | 41 +++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/arch/arm64/boot/dts/realtek/kent.dtsi b/arch/arm64/boot/dts/realtek/kent.dtsi
index df0d5ee3b1b9..fdb2bc2b3c79 100644
--- a/arch/arm64/boot/dts/realtek/kent.dtsi
+++ b/arch/arm64/boot/dts/realtek/kent.dtsi
@@ -5,6 +5,7 @@
* Copyright (c) 2024 Realtek Semiconductor Corp.
*/
+#include <dt-bindings/clock/realtek,rtd1625-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
@@ -26,6 +27,15 @@ timer {
<GIC_PPI 12 IRQ_TYPE_LEVEL_HIGH>;
};
+ clocks {
+ osc27m: osc {
+ compatible = "fixed-clock";
+ clock-frequency = <27000000>;
+ clock-output-names = "osc27m";
+ #clock-cells = <0>;
+ };
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -141,6 +151,28 @@ rbus: bus@98000000 {
#address-cells = <1>;
#size-cells = <1>;
+ cc: clock-controller@0 {
+ compatible = "realtek,rtd1625-crt-clk";
+ reg = <0x0 0x900>;
+ clocks = <&osc27m>;
+ clock-names = "osc27m";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ ic: clock-controller@7088 {
+ compatible = "realtek,rtd1625-iso-clk";
+ reg = <0x7088 0x8>;
+ clocks = <&osc27m>, <&cc RTD1625_CRT_CLK_SYS>,
+ <&cc RTD1625_CRT_CLK_SYSH>,
+ <&cc RTD1625_CRT_CLK_DDSA_DIV4>,
+ <&cc RTD1625_CRT_CLK_EN_MISC>;
+ clock-names = "osc27m", "clk_sys", "clk_sysh", "clk_ddsa_div4",
+ "clk_en_misc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
uart0: serial@7800 {
compatible = "snps,dw-apb-uart";
reg = <0x7800 0x100>;
@@ -205,6 +237,15 @@ isom_pinctrl: pinctrl@146200 {
reg = <0x146200 0x34>;
};
+ iso_s_cc: clock-controller@146310 {
+ compatible = "realtek,rtd1625-iso-s-clk";
+ reg = <0x146310 0x8>;
+ clocks = <&osc27m>;
+ clock-names = "osc27m";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
ve4_pinctrl: pinctrl@14e000 {
compatible = "realtek,rtd1625-ve4-pinctrl";
reg = <0x14e000 0x84>;
--
2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v16 1/9] dt-bindings: clock: Add Realtek RTD1625 Clock & Reset Controller
2026-11-12 5:25 ` [PATCH v16 1/9] dt-bindings: clock: Add Realtek RTD1625 Clock & Reset Controller Yu-Chun Lin
@ 2026-11-12 9:23 ` Krzysztof Kozlowski
0 siblings, 0 replies; 16+ messages in thread
From: Krzysztof Kozlowski @ 2026-11-12 9:23 UTC (permalink / raw)
To: Yu-Chun Lin
Cc: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou, linux-clk, devicetree, linux-kernel,
linux-arm-kernel, linux-realtek-soc, james.tai, cy.huang,
stanley_chang
On Thu, Nov 12, 2026 at 01:25:36PM +0800, Yu-Chun Lin wrote:
> + then:
> + properties:
> + clocks:
> + items:
> + - description: External 27 MHz oscillator
> + - description: CRT SYS clock input
> + - description: CRT SYSH clock input
> + - description: CRT DDSA divide-by-four clock input
> + - description: CRT miscellaneous gate clock input
> +
> + clock-names:
> + items:
> + - const: osc27m
> + - const: clk_sys
> + - const: clk_sysh
> + - const: clk_ddsa_div4
> + - const: clk_en_misc
Put the list in the top level with minItems: 1, then here you only set
minItems: 5 or maxItems: 1.
> +
> + else:
> + properties:
> + clocks:
> + items:
> + - description: External 27 MHz oscillator
> +
> + clock-names:
> + items:
> + - const: osc27m
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v16 2/9] clk: realtek: Introduce common probe()
2026-11-12 5:25 ` [PATCH v16 2/9] clk: realtek: Introduce common probe() Yu-Chun Lin
@ 2026-11-12 17:14 ` Brian Masney
0 siblings, 0 replies; 16+ messages in thread
From: Brian Masney @ 2026-11-12 17:14 UTC (permalink / raw)
To: Yu-Chun Lin
Cc: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou, linux-clk, devicetree, linux-kernel,
linux-arm-kernel, linux-realtek-soc, james.tai, cy.huang,
stanley_chang, Brian Masney, Brian Masney
> Add rtk_clk_probe() to set up the shared regmap, register clock hardware,
> and add the clock provider.
>
> Additionally, if the "#reset-cells" property is present in the device tree,
> it creates and registers an auxiliary device using the provided aux_name.
> This allows the dedicated reset driver to bind to this device, enabling
> both clock and reset drivers to share the same regmap.
>
> Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
> Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> Reviewed-by: Brian Masney <bmasney@redhat.com>
> ---
> MAINTAINERS | 1 +
> drivers/clk/Kconfig | 1 +
> drivers/clk/Makefile | 1 +
> drivers/clk/realtek/Kconfig | 29 ++++++++++
> drivers/clk/realtek/Makefile | 4 ++
> drivers/clk/realtek/clk-rtk-common.c | 84 ++++++++++++++++++++++++++++
> drivers/clk/realtek/clk-rtk-common.h | 37 ++++++++++++
> 7 files changed, 157 insertions(+)
> create mode 100644 drivers/clk/realtek/Kconfig
> create mode 100644 drivers/clk/realtek/Makefile
> create mode 100644 drivers/clk/realtek/clk-rtk-common.c
> create mode 100644 drivers/clk/realtek/clk-rtk-common.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c51f9fc157c8..54873a33038b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -23541,6 +23541,7 @@ REALTEK CLOCK DRIVERS
> M: Cheng-Yu Lee <cylee12@realtek.com>
> M: Yu-Chun Lin <eleanor.lin@realtek.com>
> S: Supported
> +F: drivers/clk/realtek/*
> F: include/dt-bindings/clock/realtek*
>
> REALTEK OTTO WATCHDOG
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 37a8e35d4178..eb9256459251 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -532,6 +532,7 @@ source "drivers/clk/nuvoton/Kconfig"
> source "drivers/clk/pistachio/Kconfig"
> source "drivers/clk/qcom/Kconfig"
> source "drivers/clk/ralink/Kconfig"
> +source "drivers/clk/realtek/Kconfig"
> source "drivers/clk/renesas/Kconfig"
> source "drivers/clk/rockchip/Kconfig"
> source "drivers/clk/samsung/Kconfig"
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 52d138d4ffc8..3930bf20667b 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -156,6 +156,7 @@ obj-$(CONFIG_COMMON_CLK_PISTACHIO) += pistachio/
> obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
> obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/
> obj-y += ralink/
> +obj-$(CONFIG_COMMON_CLK_REALTEK) += realtek/
> obj-y += renesas/
> obj-$(CONFIG_COMMON_CLK_ROCKCHIP) += rockchip/
> obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
> diff --git a/drivers/clk/realtek/Kconfig b/drivers/clk/realtek/Kconfig
> new file mode 100644
> index 000000000000..e8deccf93f94
> --- /dev/null
> +++ b/drivers/clk/realtek/Kconfig
> @@ -0,0 +1,29 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config COMMON_CLK_REALTEK
> + tristate "Clock driver for Realtek SoCs"
> + depends on ARCH_REALTEK || COMPILE_TEST
> + default ARCH_REALTEK
> + help
> + Enable the common clock framework infrastructure for Realtek
> + system-on-chip platforms.
> +
> + This provides the base support required by individual Realtek
> + clock controller drivers to expose clocks to peripheral devices.
> +
> + If you have a Realtek-based platform, say Y.
> +
> +if COMMON_CLK_REALTEK
> +
> +config RTK_CLK_COMMON
> + tristate "Realtek Clock Common"
> + select AUXILIARY_BUS
> + select REGMAP_MMIO
> + help
> + Common helper code shared by Realtek clock controller drivers.
> +
> + This provides utility functions and data structures used by
> + multiple Realtek clock implementations. It also provides the
> + infrastructure to spawn reset controllers via the auxiliary bus
> + where required.
Drop the prompt text because this isn't meant to be user selectable.
> +
> +endif
> diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
> new file mode 100644
> index 000000000000..13000ed4ba11
> --- /dev/null
> +++ b/drivers/clk/realtek/Makefile
> @@ -0,0 +1,4 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-$(CONFIG_RTK_CLK_COMMON) += clk-rtk.o
> +
> +clk-rtk-y += clk-rtk-common.o
> diff --git a/drivers/clk/realtek/clk-rtk-common.c b/drivers/clk/realtek/clk-rtk-common.c
> new file mode 100644
> index 000000000000..7df6d04bb95a
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-rtk-common.c
> @@ -0,0 +1,84 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2019-2026 Realtek Semiconductor Corporation
> + * Author: Cheng-Yu Lee <cylee12@realtek.com>
> + */
> +
> +#include <linux/auxiliary_bus.h>
> +#include <linux/device.h>
> +#include <linux/export.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include "clk-rtk-common.h"
> +
> +static int rtk_reset_controller_register(struct device *dev, const char *aux_name,
> + struct regmap *map)
> +{
> + struct auxiliary_device *adev;
> +
> + if (!of_property_present(dev->of_node, "#reset-cells"))
> + return 0;
> +
> + if (!aux_name) {
> + dev_err(dev, "DTS requires reset controller, but aux_name is missing\n");
> + return -EINVAL;
> + }
> +
> + adev = devm_auxiliary_device_create(dev, aux_name, (void *)map);
> + if (!adev)
> + return -ENOMEM;
> +
> + return 0;
> +}
> +
> +static const struct regmap_config rtk_clk_regmap_config = {
> + .reg_bits = 32,
> + .reg_stride = 4,
> + .val_bits = 32,
> +};
> +
> +int rtk_clk_probe(struct platform_device *pdev, const struct rtk_clk_desc *desc)
> +{
> + struct device *dev = &pdev->dev;
> + struct regmap *regmap;
> + void __iomem *base;
> + struct clk_hw *hw;
> + int i, ret;
> +
> + base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
> +
> + regmap = devm_regmap_init_mmio(dev, base, &rtk_clk_regmap_config);
> + if (IS_ERR(regmap))
> + return PTR_ERR(regmap);
> +
> + for (i = 0; i < desc->num_clks; i++)
> + desc->clks[i]->regmap = regmap;
> +
> + for (i = 0; i < desc->clk_data->num; i++) {
> + hw = desc->clk_data->hws[i];
> + if (!hw)
> + continue;
> +
> + ret = devm_clk_hw_register(dev, hw);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to register hw of clk%d\n", i);
> + }
> +
> + ret = rtk_reset_controller_register(dev, desc->aux_name, regmap);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to register reset controller\n");
> +
> + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
> + desc->clk_data);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to add clock provider\n");
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_NS_GPL(rtk_clk_probe, "CLK_REALTEK");
> +
> +MODULE_DESCRIPTION("Realtek clock infrastructure");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/clk/realtek/clk-rtk-common.h b/drivers/clk/realtek/clk-rtk-common.h
> new file mode 100644
> index 000000000000..de3f23120b53
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-rtk-common.h
> @@ -0,0 +1,37 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2016-2026 Realtek Semiconductor Corporation
> + * Author: Cheng-Yu Lee <cylee12@realtek.com>
> + */
> +
> +#ifndef __CLK_REALTEK_COMMON_H
> +#define __CLK_REALTEK_COMMON_H
> +
> +#include <linux/clk-provider.h>
> +
> +#define __rtk_clk_regmap_hw(_p) ((_p)->hw)
> +
> +struct device;
> +struct platform_device;
> +struct regmap;
> +
> +struct rtk_clk_regmap {
> + struct clk_hw hw;
> + struct regmap *regmap;
> +};
> +
> +struct rtk_clk_desc {
> + struct clk_hw_onecell_data *clk_data;
> + struct rtk_clk_regmap **clks;
> + size_t num_clks;
> + char *aux_name;
Can this be const?
Brian
--
Brian Masney <masneyb@kernel.org>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v16 3/9] clk: realtek: Add support for phase locked loops (PLLs)
2026-11-12 5:25 ` [PATCH v16 3/9] clk: realtek: Add support for phase locked loops (PLLs) Yu-Chun Lin
@ 2026-11-12 17:14 ` Brian Masney
0 siblings, 0 replies; 16+ messages in thread
From: Brian Masney @ 2026-11-12 17:14 UTC (permalink / raw)
To: Yu-Chun Lin
Cc: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou, linux-clk, devicetree, linux-kernel,
linux-arm-kernel, linux-realtek-soc, james.tai, cy.huang,
stanley_chang, Brian Masney
> Provide a full set of PLL operations for programmable PLLs and a read-only
> variant for fixed or hardware-managed PLLs.
>
> Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
> Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> ---
> Changes in v16:
> - Remove Brian's reviewed-by tag.
> - Introduce 'expected_parent_rate' validation in '.determine_rate()' and
> '.set_rate()' to safely enforce the fixed input rate requirement.
> - In determined_rate, replacing the floor/ceil algorithm with a closest-match
> search within [min_rate, max_rate] boundaries.
> - Improve comments for spinlock.
> - Add '.is_enabled' callback to 'rtk_clk_pll_ro_ops'
> ---
> drivers/clk/realtek/Makefile | 2 +
> drivers/clk/realtek/clk-regmap-pll.c | 219 +++++++++++++++++++++++++++
> drivers/clk/realtek/clk-regmap-pll.h | 53 +++++++
> drivers/clk/realtek/freq_table.c | 62 ++++++++
> drivers/clk/realtek/freq_table.h | 24 +++
> 5 files changed, 360 insertions(+)
> create mode 100644 drivers/clk/realtek/clk-regmap-pll.c
> create mode 100644 drivers/clk/realtek/clk-regmap-pll.h
> create mode 100644 drivers/clk/realtek/freq_table.c
> create mode 100644 drivers/clk/realtek/freq_table.h
>
> diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
> index 13000ed4ba11..6fbe6e07b760 100644
> --- a/drivers/clk/realtek/Makefile
> +++ b/drivers/clk/realtek/Makefile
> @@ -2,3 +2,5 @@
> obj-$(CONFIG_RTK_CLK_COMMON) += clk-rtk.o
>
> clk-rtk-y += clk-rtk-common.o
> +clk-rtk-y += clk-regmap-pll.o
> +clk-rtk-y += freq_table.o
> diff --git a/drivers/clk/realtek/clk-regmap-pll.c b/drivers/clk/realtek/clk-regmap-pll.c
> new file mode 100644
> index 000000000000..e43e78a36647
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-regmap-pll.c
> @@ -0,0 +1,219 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2024-2026 Realtek Semiconductor Corporation
> + * Author: Cheng-Yu Lee <cylee12@realtek.com>
> + */
> +
> +#include <linux/export.h>
> +#include <linux/regmap.h>
> +#include <linux/spinlock.h>
> +#include "clk-regmap-pll.h"
> +
> +#define TIMEOUT 500
> +
> +static inline struct rtk_clk_regmap_pll *to_rtk_clk_regmap_pll(struct clk_hw *hw)
> +{
> + struct rtk_clk_regmap *clkr = to_rtk_clk_regmap(hw);
> +
> + return container_of(clkr, struct rtk_clk_regmap_pll, clkr);
> +}
> +
> +static int wait_freq_ready(struct rtk_clk_regmap_pll *clkp)
> +{
> + u32 pollval;
> +
> + /*
> + * Optional register: return success if not provided.
> + */
> + if (!clkp->freq_ready_reg)
> + return 0;
> +
> + return regmap_read_poll_timeout_atomic(clkp->clkr.regmap, clkp->freq_ready_reg, pollval,
> + (pollval & clkp->freq_ready_mask) == clkp->freq_ready_val, 1, TIMEOUT);
> +}
> +
> +static bool is_power_on(struct rtk_clk_regmap_pll *clkp)
> +{
> + u32 val;
> +
> + /*
> + * If the PLL does not provide a power register, it is considered
> + * to be always powered.
> + */
> + if (!clkp->power_reg)
> + return true;
> +
> + if (regmap_read(clkp->clkr.regmap, clkp->power_reg, &val))
> + return false;
> +
> + return (val & clkp->power_mask) == clkp->power_val_on;
> +}
> +
> +static void rtk_clk_regmap_pll_disable(struct clk_hw *hw)
> +{
> + struct rtk_clk_regmap_pll *clkp = to_rtk_clk_regmap_pll(hw);
> + unsigned long flags;
> +
> + if (!clkp->seq_power_off)
> + return;
> +
> + spin_lock_irqsave(&clkp->lock, flags);
> +
> + regmap_multi_reg_write(clkp->clkr.regmap, clkp->seq_power_off,
> + clkp->num_seq_power_off);
> +
> + spin_unlock_irqrestore(&clkp->lock, flags);
> +}
> +
> +static int rtk_clk_regmap_pll_is_enabled(struct clk_hw *hw)
> +{
> + struct rtk_clk_regmap_pll *clkp = to_rtk_clk_regmap_pll(hw);
> + unsigned long flags;
> + int ret;
> +
> + spin_lock_irqsave(&clkp->lock, flags);
> +
> + ret = is_power_on(clkp);
> +
> + spin_unlock_irqrestore(&clkp->lock, flags);
> +
> + return ret;
> +}
> +
> +static int rtk_clk_regmap_pll_determine_rate(struct clk_hw *hw,
> + struct clk_rate_request *req)
> +{
> + struct rtk_clk_regmap_pll *clkp = to_rtk_clk_regmap_pll(hw);
> + const struct rtk_freq_table *ftblv = NULL;
> +
> + if (clkp->expected_parent_rate &&
> + req->best_parent_rate != clkp->expected_parent_rate)
> + return -EINVAL;
> +
> + ftblv = ftbl_find_closest_by_rate(clkp->freq_tbl, req->rate,
> + req->min_rate, req->max_rate);
> + if (!ftblv)
> + return -EINVAL;
> +
> + req->rate = ftblv->rate;
> +
> + return 0;
> +}
> +
> +static unsigned long rtk_clk_regmap_pll_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct rtk_clk_regmap_pll *clkp = to_rtk_clk_regmap_pll(hw);
> + const struct rtk_freq_table *fv;
> + unsigned long flags;
> + u32 freq_val;
> +
> + spin_lock_irqsave(&clkp->lock, flags);
> +
> + if (regmap_read(clkp->clkr.regmap, clkp->freq_reg, &freq_val)) {
> + spin_unlock_irqrestore(&clkp->lock, flags);
> + return 0;
> + }
> +
> + freq_val &= clkp->freq_mask;
ftbl_find_by_val_with_mask() performs the mask operation as well, so
this is redundant. Just pick one way.
> +
> + fv = ftbl_find_by_val_with_mask(clkp->freq_tbl, clkp->freq_mask,
> + freq_val);
> +
> + spin_unlock_irqrestore(&clkp->lock, flags);
> +
> + return fv ? fv->rate : 0;
> +}
> +
> +static int rtk_clk_regmap_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + struct rtk_clk_regmap_pll *clkp = to_rtk_clk_regmap_pll(hw);
> + const struct rtk_freq_table *fv;
> + unsigned long flags;
> + int ret;
> +
> + if (clkp->expected_parent_rate && parent_rate != clkp->expected_parent_rate)
> + return -EINVAL;
> +
> + fv = ftbl_find_by_rate(clkp->freq_tbl, rate);
> + if (!fv || fv->rate != rate)
> + return -EINVAL;
> +
> + spin_lock_irqsave(&clkp->lock, flags);
> +
> + if (clkp->seq_pre_set_freq) {
> + ret = regmap_multi_reg_write(clkp->clkr.regmap, clkp->seq_pre_set_freq,
> + clkp->num_seq_pre_set_freq);
> + if (ret)
> + goto unlock;
> + }
> +
> + ret = regmap_update_bits(clkp->clkr.regmap, clkp->freq_reg,
> + clkp->freq_mask, fv->val);
> + if (ret)
> + goto unlock;
> +
> + if (clkp->seq_post_set_freq) {
> + ret = regmap_multi_reg_write(clkp->clkr.regmap, clkp->seq_post_set_freq,
> + clkp->num_seq_post_set_freq);
> + if (ret)
> + goto unlock;
> + }
> +
> + if (is_power_on(clkp)) {
> + ret = wait_freq_ready(clkp);
> + if (ret)
> + goto unlock;
> + }
> +
> +unlock:
> + spin_unlock_irqrestore(&clkp->lock, flags);
> +
> + return ret;
> +}
> +
> +static int rtk_clk_regmap_pll_enable(struct clk_hw *hw)
> +{
> + struct rtk_clk_regmap_pll *clkp = to_rtk_clk_regmap_pll(hw);
> + unsigned long flags;
> + int ret = 0;
> +
> + if (!clkp->seq_power_on)
> + return ret;
> +
> + spin_lock_irqsave(&clkp->lock, flags);
> +
> + if (is_power_on(clkp))
> + goto unlock;
> +
> + ret = regmap_multi_reg_write(clkp->clkr.regmap, clkp->seq_power_on,
> + clkp->num_seq_power_on);
> + if (ret)
> + goto unlock;
> +
> + ret = wait_freq_ready(clkp);
This can wait up to 500 us with interrupts disabled. Should this move to
a prepare lock instead with a mutex?
> + if (ret)
> + goto unlock;
> +
> +unlock:
> + spin_unlock_irqrestore(&clkp->lock, flags);
> +
> + return ret;
+}
> +
> +const struct clk_ops rtk_clk_pll_ops = {
> + .enable = rtk_clk_regmap_pll_enable,
> + .disable = rtk_clk_regmap_pll_disable,
> + .is_enabled = rtk_clk_regmap_pll_is_enabled,
> + .recalc_rate = rtk_clk_regmap_pll_recalc_rate,
> + .determine_rate = rtk_clk_regmap_pll_determine_rate,
> + .set_rate = rtk_clk_regmap_pll_set_rate,
> +};
> +EXPORT_SYMBOL_NS_GPL(rtk_clk_pll_ops, "CLK_REALTEK");
> +
> +const struct clk_ops rtk_clk_pll_ro_ops = {
> + .is_enabled = rtk_clk_regmap_pll_is_enabled,
> + .recalc_rate = rtk_clk_regmap_pll_recalc_rate,
> +};
> +EXPORT_SYMBOL_NS_GPL(rtk_clk_pll_ro_ops, "CLK_REALTEK");
> diff --git a/drivers/clk/realtek/clk-regmap-pll.h b/drivers/clk/realtek/clk-regmap-pll.h
> new file mode 100644
> index 000000000000..f6fac6b4ac90
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-regmap-pll.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2017-2026 Realtek Semiconductor Corporation
> + * Author: Cheng-Yu Lee <cylee12@realtek.com>
> + */
> +
> +#ifndef __CLK_REALTEK_CLK_PLL_H
> +#define __CLK_REALTEK_CLK_PLL_H
> +
> +#include <linux/spinlock.h>
> +#include "clk-rtk-common.h"
> +#include "freq_table.h"
> +
> +struct reg_sequence;
> +
> +struct rtk_clk_regmap_pll {
> + struct rtk_clk_regmap clkr;
> + const struct reg_sequence *seq_power_on;
> + u32 num_seq_power_on;
> + const struct reg_sequence *seq_power_off;
> + u32 num_seq_power_off;
> + const struct reg_sequence *seq_pre_set_freq;
> + u32 num_seq_pre_set_freq;
> + const struct reg_sequence *seq_post_set_freq;
> + u32 num_seq_post_set_freq;
> + const struct rtk_freq_table *freq_tbl;
> + u32 freq_reg;
> + u32 freq_mask;
> + u32 freq_ready_mask;
> + u32 freq_ready_reg;
> + u32 freq_ready_val;
> + u32 power_reg;
> + u32 power_mask;
> + u32 power_val_on;
> +
> + /* Expected input rate for the preset frequency table; zero disables check. */
> + unsigned long expected_parent_rate;
> +
> + /*
> + * Serialize the multi-step register sequences in .set_rate() against
> + * .enable()/.disable(). CCF protects them with different locks
> + * (prepare_lock vs. enable_lock), and regmap only guarantees atomicity of
> + * individual register accesses.
> + */
> + spinlock_t lock;
> +};
> +
> +#define __rtk_clk_regmap_pll_hw(_ptr) __rtk_clk_regmap_hw(&(_ptr)->clkr)
> +
> +extern const struct clk_ops rtk_clk_pll_ops;
> +extern const struct clk_ops rtk_clk_pll_ro_ops;
> +
> +#endif /* __CLK_REALTEK_CLK_PLL_H */
> diff --git a/drivers/clk/realtek/freq_table.c b/drivers/clk/realtek/freq_table.c
> new file mode 100644
> index 000000000000..0f977a3fc902
> --- /dev/null
> +++ b/drivers/clk/realtek/freq_table.c
> @@ -0,0 +1,62 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +#include <linux/types.h>
> +#include "freq_table.h"
> +
> +#define IS_FREQ_TABLE_END(_f) ((_f)->rate == 0)
> +
> +const struct rtk_freq_table *ftbl_find_closest_by_rate(const struct rtk_freq_table *ftbl,
> + unsigned long rate,
> + unsigned long min_rate,
> + unsigned long max_rate)
> +{
> + const struct rtk_freq_table *best = NULL;
> + unsigned long best_delta = ULONG_MAX;
From sashiko: #include <linux/limits.h> for ULONG_MAX.
There's some other sashiko feedback on these files and I'm not going to
duplicate that.
Brian
--
Brian Masney <masneyb@kernel.org>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v16 4/9] clk: realtek: Add support for gate clock
2026-11-12 5:25 ` [PATCH v16 4/9] clk: realtek: Add support for gate clock Yu-Chun Lin
@ 2026-11-12 17:14 ` Brian Masney
0 siblings, 0 replies; 16+ messages in thread
From: Brian Masney @ 2026-11-12 17:14 UTC (permalink / raw)
To: Yu-Chun Lin
Cc: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou, linux-clk, devicetree, linux-kernel,
linux-arm-kernel, linux-realtek-soc, james.tai, cy.huang,
stanley_chang, Brian Masney
> Introduce clk_regmap_gate_ops supporting enable, disable, and is_enabled
> for standard regmap gate clocks. To accommodate hardware designs, the
> enable and disable operations handle a 'write_en' flag, which asserts an
> adjacent write-enable bit (bit_idx + 1) simultaneously when modifying the
> gate bit.
>
> Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
> Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> ---
> Changes in v16:
> - Remove Brian's reviewed-by tag.
> - Replace 'CLK_HW_INIT' with 'CLK_HW_INIT_HW' and 'CLK_HW_INIT_FW_NAME' macros
> to avoid relying on unstable internal CCF global names.
> - Drop all unused NO_PARENT macro and 'rtk_clk_regmap_gate_ro_ops'.
> ---
> drivers/clk/realtek/Makefile | 1 +
> drivers/clk/realtek/clk-regmap-gate.c | 59 +++++++++++++++++++++++++++
> drivers/clk/realtek/clk-regmap-gate.h | 54 ++++++++++++++++++++++++
> 3 files changed, 114 insertions(+)
> create mode 100644 drivers/clk/realtek/clk-regmap-gate.c
> create mode 100644 drivers/clk/realtek/clk-regmap-gate.h
>
> diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
> index 6fbe6e07b760..9397d677f52d 100644
> --- a/drivers/clk/realtek/Makefile
> +++ b/drivers/clk/realtek/Makefile
> @@ -2,5 +2,6 @@
> obj-$(CONFIG_RTK_CLK_COMMON) += clk-rtk.o
>
> clk-rtk-y += clk-rtk-common.o
> +clk-rtk-y += clk-regmap-gate.o
> clk-rtk-y += clk-regmap-pll.o
> clk-rtk-y += freq_table.o
> diff --git a/drivers/clk/realtek/clk-regmap-gate.c b/drivers/clk/realtek/clk-regmap-gate.c
> new file mode 100644
> index 000000000000..12539e11647c
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-regmap-gate.c
> @@ -0,0 +1,59 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2017-2026 Realtek Semiconductor Corporation
> + * Author: Cheng-Yu Lee <cylee12@realtek.com>
> + */
> +
> +#include <linux/bits.h>
> +#include <linux/clk-provider.h>
> +#include <linux/export.h>
> +#include <linux/regmap.h>
> +#include "clk-regmap-gate.h"
> +
> +static int rtk_clk_regmap_gate_update(struct clk_hw *hw, bool enable)
> +{
> + struct rtk_clk_regmap_gate *clkg = to_rtk_clk_regmap_gate(hw);
> + unsigned int mask = BIT(clkg->bit_idx);
> + unsigned int val = enable ? mask : 0;
> +
> + /*
> + * Hardware specific design: to modify the gate bit, the adjacent
> + * write-enable bit (bit_idx + 1) must be asserted simultaneously.
> + */
> + if (clkg->write_en) {
> + mask |= BIT(clkg->bit_idx + 1);
> + val |= BIT(clkg->bit_idx + 1);
> + }
> +
> + return regmap_update_bits(clkg->clkr.regmap, clkg->gate_ofs, mask, val);
> +}
> +
> +static int rtk_clk_regmap_gate_enable(struct clk_hw *hw)
> +{
> + return rtk_clk_regmap_gate_update(hw, true);
> +}
> +
> +static void rtk_clk_regmap_gate_disable(struct clk_hw *hw)
> +{
> + rtk_clk_regmap_gate_update(hw, false);
> +}
> +
> +static int rtk_clk_regmap_gate_is_enabled(struct clk_hw *hw)
> +{
> + struct rtk_clk_regmap_gate *clkg = to_rtk_clk_regmap_gate(hw);
> + int ret;
> + u32 val;
> +
> + ret = regmap_read(clkg->clkr.regmap, clkg->gate_ofs, &val);
> + if (ret < 0)
> + return ret;
This becomes a bool in clk_core_is_enabled(). Either return 0 or 1.
Brian
--
Brian Masney <masneyb@kernel.org>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v16 6/9] clk: realtek: Add support for MMC-tuned PLL clocks
2026-11-12 5:25 ` [PATCH v16 6/9] clk: realtek: Add support for MMC-tuned PLL clocks Yu-Chun Lin
@ 2026-11-12 17:14 ` Brian Masney
0 siblings, 0 replies; 16+ messages in thread
From: Brian Masney @ 2026-11-12 17:14 UTC (permalink / raw)
To: Yu-Chun Lin
Cc: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou, linux-clk, devicetree, linux-kernel,
linux-arm-kernel, linux-realtek-soc, james.tai, cy.huang,
stanley_chang, Brian Masney
> Add clk_pll_mmc_ops for enable/disable, rate control, and status operations
> on MMC PLL clocks.
>
> Also add clk_pll_mmc_phase_ops to support phase get/set operations.
>
> Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
> Co-developed-by: Jyan Chou <jyanchou@realtek.com>
> Signed-off-by: Jyan Chou <jyanchou@realtek.com>
> Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> ---
> Changes in v16:
> - Remove Brian's reviewed-by tag.
> - Move the MMC PLL structs and ops declarations out of clk-pll.h into a new
> clk-regmap-pll-mmc.h.
> - Add a separate 'struct rtk_clk_pll_mmc_phase' with its own to_clk_pll_mmc_phase().
> - Merge prepare/unprepare/is_prepared into enable/disable/is_enabled, as
> suggested: there is no sleeping operation.
> - Introduce the 'rtk_clk_pll_mmc_div_cfg' table for the SSCPLL analog tuning.
> - Introduce the 'rtk_clk_pll_mmc_rate' table.
> - determine_rate() selects the closest entry within [min_rate, max_rate]
> - set_rate() programs that entry only
> - recalc_rate() matches all five raw register fields against the table. However,
> only on a miss does it fall back to 'clk_pll_mmc_calc_rate()', which implements
> the formula.
> ---
> drivers/clk/realtek/Kconfig | 3 +
> drivers/clk/realtek/Makefile | 2 +
> drivers/clk/realtek/clk-regmap-pll-mmc.c | 457 +++++++++++++++++++++++
> drivers/clk/realtek/clk-regmap-pll-mmc.h | 66 ++++
> drivers/clk/realtek/freq_table.c | 1 +
> 5 files changed, 529 insertions(+)
> create mode 100644 drivers/clk/realtek/clk-regmap-pll-mmc.c
> create mode 100644 drivers/clk/realtek/clk-regmap-pll-mmc.h
>
> diff --git a/drivers/clk/realtek/Kconfig b/drivers/clk/realtek/Kconfig
> index e8deccf93f94..00ef9c5ba969 100644
> --- a/drivers/clk/realtek/Kconfig
> +++ b/drivers/clk/realtek/Kconfig
> @@ -26,4 +26,7 @@ config RTK_CLK_COMMON
> infrastructure to spawn reset controllers via the auxiliary bus
> where required.
>
> +config RTK_CLK_PLL_MMC
> + bool
> +
> endif
> diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
> index 4be39e2dd5b4..5fefe9bf901f 100644
> --- a/drivers/clk/realtek/Makefile
> +++ b/drivers/clk/realtek/Makefile
> @@ -6,3 +6,5 @@ clk-rtk-y += clk-regmap-gate.o
> clk-rtk-y += clk-regmap-mux.o
> clk-rtk-y += clk-regmap-pll.o
> clk-rtk-y += freq_table.o
> +
> +clk-rtk-$(CONFIG_RTK_CLK_PLL_MMC) += clk-regmap-pll-mmc.o
> diff --git a/drivers/clk/realtek/clk-regmap-pll-mmc.c b/drivers/clk/realtek/clk-regmap-pll-mmc.c
> new file mode 100644
> index 000000000000..50df27ef8539
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-regmap-pll-mmc.c
> @@ -0,0 +1,457 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2021-2026 Realtek Semiconductor Corporation
> + * Author: Cheng-Yu Lee <cylee12@realtek.com>
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +#include <linux/delay.h>
> +#include <linux/export.h>
> +#include <linux/math64.h>
> +#include <linux/regmap.h>
> +#include "clk-regmap-pll-mmc.h"
> +
> +#define RTK_PLL_EMMC1_OFFSET 0x0
> +#define RTK_PLL_EMMC2_OFFSET 0x4
> +#define RTK_PLL_EMMC3_OFFSET 0x8
> +#define RTK_PLL_EMMC4_OFFSET 0xc
> +#define RTK_PLL_SSC_DIG_EMMC0_OFFSET 0x0
> +#define RTK_PLL_SSC_DIG_EMMC3_OFFSET 0xc
> +#define RTK_PLL_SSC_DIG_EMMC4_OFFSET 0x10
> +
> +#define RTK_PLL_PHRT0_MASK BIT(0)
> +#define RTK_PLL_PHSEL_MASK GENMASK(4, 0)
> +#define RTK_PLL_SSCPLL_RS_MASK GENMASK(12, 10)
> +#define RTK_PLL_SSCPLL_ICP_MASK GENMASK(9, 5)
> +#define RTK_PLL_SSC_DIV_EXT_F_MASK GENMASK(25, 13)
> +#define RTK_PLL_PI_IBSELH_MASK GENMASK(28, 27)
> +#define RTK_PLL_SSC_DIV_N_MASK GENMASK(23, 16)
> +#define RTK_PLL_NCODE_SSC_EMMC_MASK GENMASK(20, 13)
> +#define RTK_PLL_FCODE_SSC_EMMC_MASK GENMASK(12, 0)
> +#define RTK_PLL_GRAN_EST_EM_MC_MASK GENMASK(20, 0)
> +#define RTK_PLL_EN_SSC_EMMC_MASK BIT(0)
> +#define RTK_PLL_SSC_DIG_EMMC0_EN_SSC BIT(1)
> +#define RTK_PLL_FLAG_INITIAL_EMMC_MASK BIT(8)
> +
> +#define RTK_PLL_PHRT0_SHIFT 1
> +
> +#define CYCLE_DEGREES 360
> +#define PHASE_STEPS 32
> +#define PHASE_SCALE_FACTOR 1125
> +
> +static inline struct rtk_clk_regmap_pll_mmc *to_clk_pll_mmc(struct clk_hw *hw)
> +{
> + struct rtk_clk_regmap *clkr = to_rtk_clk_regmap(hw);
> +
> + return container_of(clkr, struct rtk_clk_regmap_pll_mmc, clkr);
> +}
> +
> +static inline struct rtk_clk_pll_mmc_phase *to_clk_pll_mmc_phase(struct clk_hw *hw)
> +{
> + struct rtk_clk_regmap *clkr = to_rtk_clk_regmap(hw);
> +
> + return container_of(clkr, struct rtk_clk_pll_mmc_phase, clkr);
> +}
> +
> +static inline int get_phrt0(struct rtk_clk_regmap_pll_mmc *clkm, u32 *val)
> +{
> + u32 reg;
> + int ret;
> +
> + ret = regmap_read(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC1_OFFSET, ®);
> + if (ret)
> + return ret;
> +
> + *val = (reg >> RTK_PLL_PHRT0_SHIFT) & RTK_PLL_PHRT0_MASK;
> +
> + return 0;
> +}
> +
> +static inline int set_phrt0(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
> +{
> + return regmap_update_bits(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC1_OFFSET,
> + RTK_PLL_PHRT0_MASK << RTK_PLL_PHRT0_SHIFT,
> + val << RTK_PLL_PHRT0_SHIFT);
> +}
> +
> +static inline int clk_pll_emmc_set_sscpll_rs(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
> +{
> + return regmap_update_bits(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC2_OFFSET,
> + RTK_PLL_SSCPLL_RS_MASK, FIELD_PREP(RTK_PLL_SSCPLL_RS_MASK, val));
> +}
> +
> +static inline int clk_pll_emmc_set_sscpll_icp(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
> +{
> + return regmap_update_bits(clkm->clkr.regmap,
> + clkm->pll_ofs + RTK_PLL_EMMC2_OFFSET,
> + RTK_PLL_SSCPLL_ICP_MASK,
> + FIELD_PREP(RTK_PLL_SSCPLL_ICP_MASK, val));
> +}
> +
> +static inline int clk_pll_emmc_set_ssc_div_ext_f(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
> +{
> + return regmap_update_bits(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC2_OFFSET,
> + RTK_PLL_SSC_DIV_EXT_F_MASK,
> + FIELD_PREP(RTK_PLL_SSC_DIV_EXT_F_MASK, val));
> +}
> +
> +static inline int clk_pll_emmc_set_pi_ibselh(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
> +{
> + return regmap_update_bits(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC2_OFFSET,
> + RTK_PLL_PI_IBSELH_MASK, FIELD_PREP(RTK_PLL_PI_IBSELH_MASK, val));
> +}
> +
> +static inline int clk_pll_emmc_set_ssc_div_n(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
> +{
> + return regmap_update_bits(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC3_OFFSET,
> + RTK_PLL_SSC_DIV_N_MASK, FIELD_PREP(RTK_PLL_SSC_DIV_N_MASK, val));
> +}
> +
> +static inline int set_pow_ctl(struct rtk_clk_regmap_pll_mmc *clkm, u32 val)
> +{
> + return regmap_write(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC4_OFFSET, val);
> +}
> +
> +static inline int get_pow_ctl(struct rtk_clk_regmap_pll_mmc *clkm, u32 *val)
> +{
> + u32 raw_val;
> + int ret;
> +
> + ret = regmap_read(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC4_OFFSET, &raw_val);
> + if (ret)
> + return ret;
> +
> + *val = raw_val;
> +
> + return 0;
> +}
> +
> +static int rtk_clk_regmap_pll_mmc_phase_set_phase(struct clk_hw *hw, int degrees)
> +{
> + struct rtk_clk_pll_mmc_phase *clkm = to_clk_pll_mmc_phase(hw);
> + int ret;
> + u32 val;
> +
> + val = DIV_ROUND_CLOSEST(degrees * 100, PHASE_SCALE_FACTOR);
> + ret = regmap_update_bits(clkm->clkr.regmap,
> + clkm->pll_mmc->pll_ofs + RTK_PLL_EMMC1_OFFSET,
> + RTK_PLL_PHSEL_MASK << clkm->shift, val << clkm->shift);
> + if (ret)
> + return ret;
> +
> + usleep_range(10, 20);
> +
> + return 0;
> +}
> +
> +static int rtk_clk_regmap_pll_mmc_phase_get_phase(struct clk_hw *hw)
> +{
> + struct rtk_clk_pll_mmc_phase *clkm = to_clk_pll_mmc_phase(hw);
> + unsigned int raw_val;
> + int ret;
> + u32 val;
> +
> + ret = regmap_read(clkm->clkr.regmap, clkm->pll_mmc->pll_ofs + RTK_PLL_EMMC1_OFFSET,
> + &raw_val);
> + if (ret)
> + return ret;
> +
> + val = (raw_val >> clkm->shift) & RTK_PLL_PHSEL_MASK;
> +
> + return DIV_ROUND_CLOSEST(val * CYCLE_DEGREES, PHASE_STEPS);
> +}
> +
> +const struct clk_ops rtk_clk_pll_mmc_phase_ops = {
> + .set_phase = rtk_clk_regmap_pll_mmc_phase_set_phase,
> + .get_phase = rtk_clk_regmap_pll_mmc_phase_get_phase,
> +};
> +EXPORT_SYMBOL_NS_GPL(rtk_clk_pll_mmc_phase_ops, "CLK_REALTEK");
> +
> +static int rtk_clk_regmap_pll_mmc_enable(struct clk_hw *hw)
> +{
> + struct rtk_clk_regmap_pll_mmc *clkm = to_clk_pll_mmc(hw);
> + int ret;
> +
> + ret = set_pow_ctl(clkm, 7);
> + if (ret)
> + return ret;
> +
> + ret = set_phrt0(clkm, 1);
> + if (ret)
> + return ret;
> +
> + udelay(10);
> +
> + return 0;
> +}
> +
> +static void rtk_clk_regmap_pll_mmc_disable(struct clk_hw *hw)
> +{
> + struct rtk_clk_regmap_pll_mmc *clkm = to_clk_pll_mmc(hw);
> +
> + set_phrt0(clkm, 0);
> + udelay(10);
> + set_pow_ctl(clkm, 0);
> +}
> +
> +static int rtk_clk_regmap_pll_mmc_is_enabled(struct clk_hw *hw)
> +{
> + struct rtk_clk_regmap_pll_mmc *clkm = to_clk_pll_mmc(hw);
> + u32 pow_val, phrt_val;
> + int ret;
> +
> + ret = get_pow_ctl(clkm, &pow_val);
> + if (ret)
> + return 1;
> +
> + ret = get_phrt0(clkm, &phrt_val);
> + if (ret)
> + return 1;
> +
> + return (pow_val != 0x0) && (phrt_val == 0x1);
> +}
> +
> +static unsigned long clk_pll_mmc_calc_rate(unsigned long parent_rate,
> + u32 div_n, u32 div_ext_f)
> +{
> + u64 rate = (u64)parent_rate * (div_n + 2);
> +
> + rate += (u64)parent_rate * div_ext_f / 8192;
> +
> + return div64_u64(rate, 4);
> +}
> +
> +static unsigned long rtk_clk_regmap_pll_mmc_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct rtk_clk_regmap_pll_mmc *clkm = to_clk_pll_mmc(hw);
> + u32 emmc2, emmc3, ssc3, ssc4, val, ext_f, ncode, fcode, gran_est;
> +
> + if (regmap_read(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC2_OFFSET, &emmc2))
> + return 0;
> +
> + if (regmap_read(clkm->clkr.regmap, clkm->pll_ofs + RTK_PLL_EMMC3_OFFSET, &emmc3))
> + return 0;
> +
> + if (regmap_read(clkm->clkr.regmap, clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC3_OFFSET, &ssc3))
> + return 0;
> +
> + if (regmap_read(clkm->clkr.regmap, clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC4_OFFSET, &ssc4))
> + return 0;
> +
> + val = FIELD_GET(RTK_PLL_SSC_DIV_N_MASK, emmc3);
> + ext_f = FIELD_GET(RTK_PLL_SSC_DIV_EXT_F_MASK, emmc2);
> + ncode = FIELD_GET(RTK_PLL_NCODE_SSC_EMMC_MASK, ssc3);
> + fcode = FIELD_GET(RTK_PLL_FCODE_SSC_EMMC_MASK, ssc3);
> + gran_est = FIELD_GET(RTK_PLL_GRAN_EST_EM_MC_MASK, ssc4);
> +
> + for (unsigned int i = 0; clkm->rate_tbl && i < clkm->num_rate_tbl; i++) {
> + const struct rtk_clk_pll_mmc_rate *entry = &clkm->rate_tbl[i];
> +
> + if (entry->ssc_div_n == val && entry->ssc_div_ext_f == ext_f &&
> + entry->ncode == ncode && entry->fcode == fcode &&
> + entry->gran_est == gran_est)
> + return entry->rate;
> + }
> +
> + return clk_pll_mmc_calc_rate(parent_rate, val, ext_f);
> +}
> +
> +static const struct rtk_clk_pll_mmc_rate *
> +rtk_clk_pll_mmc_find_rate(const struct rtk_clk_regmap_pll_mmc *clkm, unsigned long rate)
> +{
> + if (!clkm->rate_tbl || !clkm->num_rate_tbl)
> + return NULL;
> +
> + for (unsigned int i = 0; i < clkm->num_rate_tbl; i++) {
> + if (clkm->rate_tbl[i].rate == rate)
> + return &clkm->rate_tbl[i];
> + }
> +
> + return NULL;
> +}
> +
> +static const struct rtk_clk_pll_mmc_rate *
> +rtk_clk_pll_mmc_find_closest_rate(const struct rtk_clk_pll_mmc_rate *tbl, u32 num,
> + unsigned long rate, unsigned long min_rate,
> + unsigned long max_rate)
> +{
> + const struct rtk_clk_pll_mmc_rate *best = NULL;
> + unsigned long best_delta = ~0UL;
> +
> + for (unsigned int i = 0; i < num; i++) {
> + const struct rtk_clk_pll_mmc_rate *entry = &tbl[i];
> + unsigned long delta;
> +
> + if (entry->rate < min_rate || entry->rate > max_rate)
> + continue;
> +
> + delta = entry->rate >= rate ? entry->rate - rate : rate - entry->rate;
> + if (delta < best_delta) {
> + best = entry;
> + best_delta = delta;
> + }
> + }
> +
> + return best;
> +}
This duplicates the functionality in ftbl_find_closest_by_rate() from
patch 3.
> +
> +static int rtk_clk_regmap_pll_mmc_determine_rate(struct clk_hw *hw,
> + struct clk_rate_request *req)
> +{
> + struct rtk_clk_regmap_pll_mmc *clkm = to_clk_pll_mmc(hw);
> + const struct rtk_clk_pll_mmc_rate *entry;
> +
> + if (!clkm->rate_tbl || !clkm->num_rate_tbl ||
> + req->min_rate > req->max_rate)
clk_core_check_boundaries() already checks the min/max rate.
> + return -EINVAL;
> +
> + entry = rtk_clk_pll_mmc_find_closest_rate(clkm->rate_tbl,
> + clkm->num_rate_tbl, req->rate,
> + req->min_rate, req->max_rate);
> + if (!entry)
> + return -EINVAL;
> +
> + req->rate = entry->rate;
> +
> + return 0;
> +}
> +
> +static const struct rtk_clk_pll_mmc_div_cfg clk_pll_emmc_default_div_cfg[] = {
> + { 31, 46, 3, 3, 2 },
> + { 20, 30, 2, 3, 1 },
> + { 10, 19, 1, 2, 1 },
> + { 5, 9, 0, 2, 0 },
> +};
> +
> +static const struct rtk_clk_pll_mmc_div_cfg *
> +clk_pll_emmc_find_div_cfg(struct rtk_clk_regmap_pll_mmc *clkm, u32 div)
> +{
> + const struct rtk_clk_pll_mmc_div_cfg *tbl = clkm->div_cfg;
> + u8 num = clkm->num_div_cfg;
This is a u32 in struct rtk_clk_regmap_pll_mmc.
> +
> + if (!tbl) {
> + tbl = clk_pll_emmc_default_div_cfg;
> + num = ARRAY_SIZE(clk_pll_emmc_default_div_cfg);
> + }
> +
> + for (unsigned int i = 0; i < num; i++) {
> + if (div >= tbl[i].div_min && div <= tbl[i].div_max)
> + return &tbl[i];
> + }
> +
> + return NULL;
> +}
> +
> +static int clk_pll_emmc_program_div_cfg(struct rtk_clk_regmap_pll_mmc *clkm, u32 div)
> +{
> + const struct rtk_clk_pll_mmc_div_cfg *t = clk_pll_emmc_find_div_cfg(clkm, div);
> + int ret;
> +
> + if (!t)
> + return -EINVAL;
> +
> + ret = clk_pll_emmc_set_pi_ibselh(clkm, t->ibselh);
> + if (ret)
> + return ret;
> +
> + ret = clk_pll_emmc_set_sscpll_rs(clkm, t->rs);
> + if (ret)
> + return ret;
> +
> + return clk_pll_emmc_set_sscpll_icp(clkm, t->icp);
> +}
> +
> +static int rtk_clk_regmap_pll_mmc_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + struct rtk_clk_regmap_pll_mmc *clkm = to_clk_pll_mmc(hw);
> + const struct rtk_clk_pll_mmc_rate *entry = rtk_clk_pll_mmc_find_rate(clkm, rate);
> + int ret;
> +
> + if (!entry)
> + return -EINVAL;
> +
> + ret = regmap_update_bits(clkm->clkr.regmap,
> + clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC0_OFFSET,
> + RTK_PLL_FLAG_INITIAL_EMMC_MASK,
> + FIELD_PREP(RTK_PLL_FLAG_INITIAL_EMMC_MASK, 0));
> + if (ret)
> + return ret;
> +
> + ret = clk_pll_emmc_set_ssc_div_n(clkm, entry->ssc_div_n);
> + if (ret)
> + return ret;
> +
> + ret = clk_pll_emmc_set_ssc_div_ext_f(clkm, entry->ssc_div_ext_f);
> + if (ret)
> + return ret;
> +
> + ret = clk_pll_emmc_program_div_cfg(clkm, entry->ssc_div_n);
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(clkm->clkr.regmap,
> + clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC3_OFFSET,
> + RTK_PLL_NCODE_SSC_EMMC_MASK,
> + FIELD_PREP(RTK_PLL_NCODE_SSC_EMMC_MASK, entry->ncode));
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(clkm->clkr.regmap,
> + clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC3_OFFSET,
> + RTK_PLL_FCODE_SSC_EMMC_MASK,
> + FIELD_PREP(RTK_PLL_FCODE_SSC_EMMC_MASK, entry->fcode));
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(clkm->clkr.regmap,
> + clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC4_OFFSET,
> + RTK_PLL_GRAN_EST_EM_MC_MASK,
> + FIELD_PREP(RTK_PLL_GRAN_EST_EM_MC_MASK, entry->gran_est));
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(clkm->clkr.regmap,
> + clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC0_OFFSET,
> + RTK_PLL_SSC_DIG_EMMC0_EN_SSC,
> + FIELD_PREP(RTK_PLL_SSC_DIG_EMMC0_EN_SSC, 1));
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(clkm->clkr.regmap,
> + clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC0_OFFSET,
> + RTK_PLL_EN_SSC_EMMC_MASK,
> + FIELD_PREP(RTK_PLL_EN_SSC_EMMC_MASK, 1));
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(clkm->clkr.regmap,
> + clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC0_OFFSET,
> + RTK_PLL_EN_SSC_EMMC_MASK,
> + FIELD_PREP(RTK_PLL_EN_SSC_EMMC_MASK, 0));
EN_SSC_EMMC is set and then immediately cleared. If this is intentional
then put a comment here to be sure it's intentional.
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(clkm->clkr.regmap,
> + clkm->ssc_dig_ofs + RTK_PLL_SSC_DIG_EMMC0_OFFSET,
> + RTK_PLL_FLAG_INITIAL_EMMC_MASK,
> + FIELD_PREP(RTK_PLL_FLAG_INITIAL_EMMC_MASK, 1));
> + if (ret)
> + return ret;
> +
> + usleep_range(10, 20);
> +
> + return 0;
> +}
> +
> +const struct clk_ops rtk_clk_pll_mmc_ops = {
> + .enable = rtk_clk_regmap_pll_mmc_enable,
> + .disable = rtk_clk_regmap_pll_mmc_disable,
> + .is_enabled = rtk_clk_regmap_pll_mmc_is_enabled,
> + .recalc_rate = rtk_clk_regmap_pll_mmc_recalc_rate,
> + .determine_rate = rtk_clk_regmap_pll_mmc_determine_rate,
> + .set_rate = rtk_clk_regmap_pll_mmc_set_rate,
> +};
> +EXPORT_SYMBOL_NS_GPL(rtk_clk_pll_mmc_ops, "CLK_REALTEK");
> diff --git a/drivers/clk/realtek/clk-regmap-pll-mmc.h b/drivers/clk/realtek/clk-regmap-pll-mmc.h
> new file mode 100644
> index 000000000000..c2e973f3df72
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-regmap-pll-mmc.h
> @@ -0,0 +1,66 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2026 Realtek Semiconductor Corporation
> + */
> +
> +#ifndef __CLK_REALTEK_CLK_PLL_MMC_H
> +#define __CLK_REALTEK_CLK_PLL_MMC_H
> +
> +#include "clk-rtk-common.h"
> +
> +/* SSCPLL charge-pump settings per divider range */
> +struct rtk_clk_pll_mmc_div_cfg {
> + u16 div_min;
> + u16 div_max;
> + u8 ibselh;
> + u8 rs;
> + u8 icp;
> +};
> +
> +/* Register settings for a specific eMMC PLL rate */
> +struct rtk_clk_pll_mmc_rate {
> + unsigned long rate;
> + u32 ssc_div_n;
> + u32 ssc_div_ext_f;
> + u32 ncode;
> + u32 fcode;
> + u32 gran_est;
> +};
> +
> +struct rtk_clk_regmap_pll_mmc {
> + struct rtk_clk_regmap clkr;
> + unsigned int pll_ofs;
> + unsigned int ssc_dig_ofs;
> +
> + /*
> + * Optional per-SoC tuning table. When NULL, the driver's default table
> + * is used and num_div_cfg is ignored;
Replace ; at end with .
Brian
--
Brian Masney <masneyb@kernel.org>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v16 7/9] clk: realtek: Add RTD1625-CRT clock controller driver
2026-11-12 5:25 ` [PATCH v16 7/9] clk: realtek: Add RTD1625-CRT clock controller driver Yu-Chun Lin
@ 2026-11-12 17:14 ` Brian Masney
0 siblings, 0 replies; 16+ messages in thread
From: Brian Masney @ 2026-11-12 17:14 UTC (permalink / raw)
To: Yu-Chun Lin
Cc: sboyd, bmasney+clk, jbrunet+clk, robh, krzk+dt, conor+dt,
cylee12, afaerber, jyanchou, linux-clk, devicetree, linux-kernel,
linux-arm-kernel, linux-realtek-soc, james.tai, cy.huang,
stanley_chang, Brian Masney
> Add support for the CRT (Clock, Reset, and Test) domain clock controller
> on the Realtek RTD1625 SoC. This driver provides essential clock sources
> (including PLLs), gating, and multiplexing functionalities for the
> platform's peripherals.
>
> Because the reset controller shares the same register space with this
> CRT clock controller, this driver also acts as the parent device and
> registers the reset controller as an auxiliary device on the auxiliary
> bus.
>
> Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
> Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> ---
> Changes in v16:
> - Remove Brian's reviewed-by tag.
> - Replace 'const char *' parent arrays with 'struct clk_hw *' arrays.
> - Switch all gate, mux, and fixed-factor clock initializations to use '_HW' macros.
> - Use 'CLK_HW_INIT_FW_NAME' for regmap_pll initialization when referencing external
> clocks, and add 'expected_parent_rate' to ensure a safe input rate.
> - Refactor eMMC PLL initialization (decoupling phases and appending rate tables).
> ---
> +static int rtd1625_crt_probe(struct platform_device *pdev)
> +{
> + const struct rtk_clk_desc *desc;
> +
> + desc = device_get_match_data(&pdev->dev);
> + if (!desc)
> + return -EINVAL;
> +
> + return rtk_clk_probe(pdev, desc);
> +}
> +
> +static const struct of_device_id rtd1625_crt_match[] = {
> + { .compatible = "realtek,rtd1625-crt-clk", .data = &rtd1625_crt_desc, },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, rtd1625_crt_match);
> +
> +static struct platform_driver rtd1625_crt_driver = {
> + .probe = rtd1625_crt_probe,
> + .driver = {
> + .name = "rtk-rtd1625-crt-clk",
> + .of_match_table = rtd1625_crt_match,
> + },
Should .suppress_bind_attrs = true similar to what you have in patch 8?
Brian
--
Brian Masney <masneyb@kernel.org>
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2026-11-12 17:15 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-12 5:25 [PATCH v16 0/9] clk: realtek: Add RTD1625 clock support Yu-Chun Lin
2026-11-12 5:25 ` [PATCH v16 1/9] dt-bindings: clock: Add Realtek RTD1625 Clock & Reset Controller Yu-Chun Lin
2026-11-12 9:23 ` Krzysztof Kozlowski
2026-11-12 5:25 ` [PATCH v16 2/9] clk: realtek: Introduce common probe() Yu-Chun Lin
2026-11-12 17:14 ` Brian Masney
2026-11-12 5:25 ` [PATCH v16 3/9] clk: realtek: Add support for phase locked loops (PLLs) Yu-Chun Lin
2026-11-12 17:14 ` Brian Masney
2026-11-12 5:25 ` [PATCH v16 4/9] clk: realtek: Add support for gate clock Yu-Chun Lin
2026-11-12 17:14 ` Brian Masney
2026-11-12 5:25 ` [PATCH v16 5/9] clk: realtek: Add support for mux clock Yu-Chun Lin
2026-11-12 5:25 ` [PATCH v16 6/9] clk: realtek: Add support for MMC-tuned PLL clocks Yu-Chun Lin
2026-11-12 17:14 ` Brian Masney
2026-11-12 5:25 ` [PATCH v16 7/9] clk: realtek: Add RTD1625-CRT clock controller driver Yu-Chun Lin
2026-11-12 17:14 ` Brian Masney
2026-11-12 5:25 ` [PATCH v16 8/9] clk: realtek: Add RTD1625-ISO " Yu-Chun Lin
2026-11-12 5:25 ` [PATCH v16 9/9] arm64: dts: realtek: Add clock support for RTD1625 Yu-Chun Lin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®