* [PATCH 05/15] dt-bindings: clock: mediatek: Add MT8189 clocks
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
Edward-JW Yang, Richard Cochran
Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>
Add dt schema and IDs for the clocks of MediaTek MT8189 SoC.
The MT8189 clock IP provide clock control for main system
(apmixedsys, topcksys and vlpcksys) and subsys (eg. peri, scp,
ufs...).
Also, add compatible for frequency hopping and spread spectrum clock
functionality and reset controller header file for MT8189 UFS reset
controller support.
Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
.../bindings/clock/mediatek,mt8186-clock.yaml | 28 ++
.../bindings/clock/mediatek,mt8186-fhctl.yaml | 1 +
.../bindings/clock/mediatek,mt8186-sys-clock.yaml | 10 +
include/dt-bindings/clock/mediatek,mt8189-clk.h | 433 +++++++++++++++++++++
include/dt-bindings/reset/mediatek,mt8189-resets.h | 17 +
5 files changed, 489 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/mediatek,mt8186-clock.yaml b/Documentation/devicetree/bindings/clock/mediatek,mt8186-clock.yaml
index 84e602c7d326..e30ed16f321d 100644
--- a/Documentation/devicetree/bindings/clock/mediatek,mt8186-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/mediatek,mt8186-clock.yaml
@@ -58,6 +58,19 @@ properties:
- mediatek,mt8188-vencsys
- mediatek,mt8188-wpesys
- mediatek,mt8188-wpesys-vpp0
+ - mediatek,mt8189-dbg-ao
+ - mediatek,mt8189-dem
+ - mediatek,mt8189-dvfsrc-top
+ - mediatek,mt8189-iic-wrap-e
+ - mediatek,mt8189-iic-wrap-en
+ - mediatek,mt8189-iic-wrap-s
+ - mediatek,mt8189-iic-wrap-ws
+ - mediatek,mt8189-scp-clk
+ - mediatek,mt8189-scp-i2c-clk
+ - mediatek,mt8189-ufscfg-ao
+ - mediatek,mt8189-ufscfg-pdn
+ - mediatek,mt8189-vlpcfg
+ - mediatek,mt8189-vlpcfg-ao
- mediatek,mt8192-camsys
- mediatek,mt8192-camsys_rawa
- mediatek,mt8192-camsys_rawb
@@ -145,6 +158,19 @@ allOf:
- mediatek,mt8188-vencsys
- mediatek,mt8188-wpesys
- mediatek,mt8188-wpesys-vpp0
+ - mediatek,mt8189-dbg-ao
+ - mediatek,mt8189-dem
+ - mediatek,mt8189-dvfsrc-top
+ - mediatek,mt8189-iic-wrap-e
+ - mediatek,mt8189-iic-wrap-en
+ - mediatek,mt8189-iic-wrap-s
+ - mediatek,mt8189-iic-wrap-ws
+ - mediatek,mt8189-scp-clk
+ - mediatek,mt8189-scp-i2c-clk
+ - mediatek,mt8189-ufscfg-ao
+ - mediatek,mt8189-ufscfg-pdn
+ - mediatek,mt8189-vlpcfg
+ - mediatek,mt8189-vlpcfg-ao
then:
required:
- '#clock-cells'
@@ -163,6 +189,8 @@ allOf:
- mediatek,mt8188-imgsys1-dip-nr
- mediatek,mt8188-imgsys1-dip-top
- mediatek,mt8188-ipesys
+ - mediatek,mt8189-ufscfg-ao
+ - mediatek,mt8189-ufscfg-pdn
then:
required:
- '#reset-cells'
diff --git a/Documentation/devicetree/bindings/clock/mediatek,mt8186-fhctl.yaml b/Documentation/devicetree/bindings/clock/mediatek,mt8186-fhctl.yaml
index d00327d12e1e..824e3b2bd6c0 100644
--- a/Documentation/devicetree/bindings/clock/mediatek,mt8186-fhctl.yaml
+++ b/Documentation/devicetree/bindings/clock/mediatek,mt8186-fhctl.yaml
@@ -20,6 +20,7 @@ properties:
- mediatek,mt6795-fhctl
- mediatek,mt8173-fhctl
- mediatek,mt8186-fhctl
+ - mediatek,mt8189-fhctl
- mediatek,mt8192-fhctl
- mediatek,mt8195-fhctl
diff --git a/Documentation/devicetree/bindings/clock/mediatek,mt8186-sys-clock.yaml b/Documentation/devicetree/bindings/clock/mediatek,mt8186-sys-clock.yaml
index c4288b91e6b6..35094ed68548 100644
--- a/Documentation/devicetree/bindings/clock/mediatek,mt8186-sys-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/mediatek,mt8186-sys-clock.yaml
@@ -35,6 +35,11 @@ properties:
- mediatek,mt8188-infracfg-ao
- mediatek,mt8188-pericfg-ao
- mediatek,mt8188-topckgen
+ - mediatek,mt8189-apmixedsys
+ - mediatek,mt8189-infra-ao
+ - mediatek,mt8189-peri-ao
+ - mediatek,mt8189-topckgen
+ - mediatek,mt8189-vlpckgen
- mediatek,mt8192-apmixedsys
- mediatek,mt8192-infracfg
- mediatek,mt8192-pericfg
@@ -68,6 +73,11 @@ allOf:
- mediatek,mt8188-infracfg-ao
- mediatek,mt8188-pericfg-ao
- mediatek,mt8188-topckgen
+ - mediatek,mt8189-apmixedsys
+ - mediatek,mt8189-infra-ao
+ - mediatek,mt8189-peri-ao
+ - mediatek,mt8189-topckgen
+ - mediatek,mt8189-vlpckgen
then:
required:
- '#clock-cells'
diff --git a/include/dt-bindings/clock/mediatek,mt8189-clk.h b/include/dt-bindings/clock/mediatek,mt8189-clk.h
new file mode 100644
index 000000000000..ca433f969698
--- /dev/null
+++ b/include/dt-bindings/clock/mediatek,mt8189-clk.h
@@ -0,0 +1,433 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ * Qiqi Wang <qiqi.wang@mediatek.com>
+ * Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ * Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8189_H
+#define _DT_BINDINGS_CLK_MT8189_H
+
+/* TOPCKGEN */
+#define CLK_TOP_AXI_SEL 0
+#define CLK_TOP_AXI_PERI_SEL 1
+#define CLK_TOP_AXI_U_SEL 2
+#define CLK_TOP_BUS_AXIMEM_SEL 3
+#define CLK_TOP_DISP0_SEL 4
+#define CLK_TOP_MMINFRA_SEL 5
+#define CLK_TOP_UART_SEL 6
+#define CLK_TOP_SPI0_SEL 7
+#define CLK_TOP_SPI1_SEL 8
+#define CLK_TOP_SPI2_SEL 9
+#define CLK_TOP_SPI3_SEL 10
+#define CLK_TOP_SPI4_SEL 11
+#define CLK_TOP_SPI5_SEL 12
+#define CLK_TOP_MSDC_MACRO_0P_SEL 13
+#define CLK_TOP_MSDC50_0_HCLK_SEL 14
+#define CLK_TOP_MSDC50_0_SEL 15
+#define CLK_TOP_AES_MSDCFDE_SEL 16
+#define CLK_TOP_MSDC_MACRO_1P_SEL 17
+#define CLK_TOP_MSDC30_1_SEL 18
+#define CLK_TOP_MSDC30_1_HCLK_SEL 19
+#define CLK_TOP_MSDC_MACRO_2P_SEL 20
+#define CLK_TOP_MSDC30_2_SEL 21
+#define CLK_TOP_MSDC30_2_HCLK_SEL 22
+#define CLK_TOP_AUD_INTBUS_SEL 23
+#define CLK_TOP_ATB_SEL 24
+#define CLK_TOP_DISP_PWM_SEL 25
+#define CLK_TOP_USB_TOP_P0_SEL 26
+#define CLK_TOP_USB_XHCI_P0_SEL 27
+#define CLK_TOP_USB_TOP_P1_SEL 28
+#define CLK_TOP_USB_XHCI_P1_SEL 29
+#define CLK_TOP_USB_TOP_P2_SEL 30
+#define CLK_TOP_USB_XHCI_P2_SEL 31
+#define CLK_TOP_USB_TOP_P3_SEL 32
+#define CLK_TOP_USB_XHCI_P3_SEL 33
+#define CLK_TOP_USB_TOP_P4_SEL 34
+#define CLK_TOP_USB_XHCI_P4_SEL 35
+#define CLK_TOP_I2C_SEL 36
+#define CLK_TOP_SENINF_SEL 37
+#define CLK_TOP_SENINF1_SEL 38
+#define CLK_TOP_AUD_ENGEN1_SEL 39
+#define CLK_TOP_AUD_ENGEN2_SEL 40
+#define CLK_TOP_AES_UFSFDE_SEL 41
+#define CLK_TOP_U_SEL 42
+#define CLK_TOP_U_MBIST_SEL 43
+#define CLK_TOP_AUD_1_SEL 44
+#define CLK_TOP_AUD_2_SEL 45
+#define CLK_TOP_VENC_SEL 46
+#define CLK_TOP_VDEC_SEL 47
+#define CLK_TOP_PWM_SEL 48
+#define CLK_TOP_AUDIO_H_SEL 49
+#define CLK_TOP_MCUPM_SEL 50
+#define CLK_TOP_MEM_SUB_SEL 51
+#define CLK_TOP_MEM_SUB_PERI_SEL 52
+#define CLK_TOP_MEM_SUB_U_SEL 53
+#define CLK_TOP_EMI_N_SEL 54
+#define CLK_TOP_DSI_OCC_SEL 55
+#define CLK_TOP_AP2CONN_HOST_SEL 56
+#define CLK_TOP_IMG1_SEL 57
+#define CLK_TOP_IPE_SEL 58
+#define CLK_TOP_CAM_SEL 59
+#define CLK_TOP_CAMTM_SEL 60
+#define CLK_TOP_DSP_SEL 61
+#define CLK_TOP_SR_PKA_SEL 62
+#define CLK_TOP_DXCC_SEL 63
+#define CLK_TOP_MFG_REF_SEL 64
+#define CLK_TOP_MDP0_SEL 65
+#define CLK_TOP_DP_SEL 66
+#define CLK_TOP_EDP_SEL 67
+#define CLK_TOP_EDP_FAVT_SEL 68
+#define CLK_TOP_ETH_250M_SEL 69
+#define CLK_TOP_ETH_62P4M_PTP_SEL 70
+#define CLK_TOP_ETH_50M_RMII_SEL 71
+#define CLK_TOP_SFLASH_SEL 72
+#define CLK_TOP_GCPU_SEL 73
+#define CLK_TOP_MAC_TL_SEL 74
+#define CLK_TOP_VDSTX_DG_CTS_SEL 75
+#define CLK_TOP_PLL_DPIX_SEL 76
+#define CLK_TOP_ECC_SEL 77
+#define CLK_TOP_APLL_I2SIN0_MCK_SEL 78
+#define CLK_TOP_APLL_I2SIN1_MCK_SEL 79
+#define CLK_TOP_APLL_I2SIN2_MCK_SEL 80
+#define CLK_TOP_APLL_I2SIN3_MCK_SEL 81
+#define CLK_TOP_APLL_I2SIN4_MCK_SEL 82
+#define CLK_TOP_APLL_I2SIN6_MCK_SEL 83
+#define CLK_TOP_APLL_I2SOUT0_MCK_SEL 84
+#define CLK_TOP_APLL_I2SOUT1_MCK_SEL 85
+#define CLK_TOP_APLL_I2SOUT2_MCK_SEL 86
+#define CLK_TOP_APLL_I2SOUT3_MCK_SEL 87
+#define CLK_TOP_APLL_I2SOUT4_MCK_SEL 88
+#define CLK_TOP_APLL_I2SOUT6_MCK_SEL 89
+#define CLK_TOP_APLL_FMI2S_MCK_SEL 90
+#define CLK_TOP_APLL_TDMOUT_MCK_SEL 91
+#define CLK_TOP_MFG_SEL_MFGPLL 92
+#define CLK_TOP_APLL12_CK_DIV_I2SIN0 93
+#define CLK_TOP_APLL12_CK_DIV_I2SIN1 94
+#define CLK_TOP_APLL12_CK_DIV_I2SOUT0 95
+#define CLK_TOP_APLL12_CK_DIV_I2SOUT1 96
+#define CLK_TOP_APLL12_CK_DIV_FMI2S 97
+#define CLK_TOP_APLL12_CK_DIV_TDMOUT_M 98
+#define CLK_TOP_APLL12_CK_DIV_TDMOUT_B 99
+#define CLK_TOP_MAINPLL_D3 100
+#define CLK_TOP_MAINPLL_D4 101
+#define CLK_TOP_MAINPLL_D4_D2 102
+#define CLK_TOP_MAINPLL_D4_D4 103
+#define CLK_TOP_MAINPLL_D4_D8 104
+#define CLK_TOP_MAINPLL_D5 105
+#define CLK_TOP_MAINPLL_D5_D2 106
+#define CLK_TOP_MAINPLL_D5_D4 107
+#define CLK_TOP_MAINPLL_D5_D8 108
+#define CLK_TOP_MAINPLL_D6 109
+#define CLK_TOP_MAINPLL_D6_D2 110
+#define CLK_TOP_MAINPLL_D6_D4 111
+#define CLK_TOP_MAINPLL_D6_D8 112
+#define CLK_TOP_MAINPLL_D7 113
+#define CLK_TOP_MAINPLL_D7_D2 114
+#define CLK_TOP_MAINPLL_D7_D4 115
+#define CLK_TOP_MAINPLL_D7_D8 116
+#define CLK_TOP_MAINPLL_D9 117
+#define CLK_TOP_UNIVPLL_D2 118
+#define CLK_TOP_UNIVPLL_D3 119
+#define CLK_TOP_UNIVPLL_D4 120
+#define CLK_TOP_UNIVPLL_D4_D2 121
+#define CLK_TOP_UNIVPLL_D4_D4 122
+#define CLK_TOP_UNIVPLL_D4_D8 123
+#define CLK_TOP_UNIVPLL_D5 124
+#define CLK_TOP_UNIVPLL_D5_D2 125
+#define CLK_TOP_UNIVPLL_D5_D4 126
+#define CLK_TOP_UNIVPLL_D6 127
+#define CLK_TOP_UNIVPLL_D6_D2 128
+#define CLK_TOP_UNIVPLL_D6_D4 129
+#define CLK_TOP_UNIVPLL_D6_D8 130
+#define CLK_TOP_UNIVPLL_D6_D16 131
+#define CLK_TOP_UNIVPLL_D7 132
+#define CLK_TOP_UNIVPLL_D7_D2 133
+#define CLK_TOP_UNIVPLL_D7_D3 134
+#define CLK_TOP_LVDSTX_DG_CTS 135
+#define CLK_TOP_UNIVPLL_192M 136
+#define CLK_TOP_UNIVPLL_192M_D2 137
+#define CLK_TOP_UNIVPLL_192M_D4 138
+#define CLK_TOP_UNIVPLL_192M_D8 139
+#define CLK_TOP_UNIVPLL_192M_D10 140
+#define CLK_TOP_UNIVPLL_192M_D16 141
+#define CLK_TOP_UNIVPLL_192M_D32 142
+#define CLK_TOP_APLL1_D2 143
+#define CLK_TOP_APLL1_D4 144
+#define CLK_TOP_APLL1_D8 145
+#define CLK_TOP_APLL1_D3 146
+#define CLK_TOP_APLL2_D2 147
+#define CLK_TOP_APLL2_D4 148
+#define CLK_TOP_APLL2_D8 149
+#define CLK_TOP_APLL2_D3 150
+#define CLK_TOP_MMPLL_D4 151
+#define CLK_TOP_MMPLL_D4_D2 152
+#define CLK_TOP_MMPLL_D4_D4 153
+#define CLK_TOP_VPLL_DPIX 154
+#define CLK_TOP_MMPLL_D5 155
+#define CLK_TOP_MMPLL_D5_D2 156
+#define CLK_TOP_MMPLL_D5_D4 157
+#define CLK_TOP_MMPLL_D6 158
+#define CLK_TOP_MMPLL_D6_D2 159
+#define CLK_TOP_MMPLL_D7 160
+#define CLK_TOP_MMPLL_D9 161
+#define CLK_TOP_TVDPLL1_D2 162
+#define CLK_TOP_TVDPLL1_D4 163
+#define CLK_TOP_TVDPLL1_D8 164
+#define CLK_TOP_TVDPLL1_D16 165
+#define CLK_TOP_TVDPLL2_D2 166
+#define CLK_TOP_TVDPLL2_D4 167
+#define CLK_TOP_TVDPLL2_D8 168
+#define CLK_TOP_TVDPLL2_D16 169
+#define CLK_TOP_ETHPLL_D2 170
+#define CLK_TOP_ETHPLL_D8 171
+#define CLK_TOP_ETHPLL_D10 172
+#define CLK_TOP_MSDCPLL_D2 173
+#define CLK_TOP_UFSPLL_D2 174
+#define CLK_TOP_F26M_CK_D2 175
+#define CLK_TOP_OSC_D2 176
+#define CLK_TOP_OSC_D4 177
+#define CLK_TOP_OSC_D8 178
+#define CLK_TOP_OSC_D16 179
+#define CLK_TOP_OSC_D3 180
+#define CLK_TOP_OSC_D7 181
+#define CLK_TOP_OSC_D10 182
+#define CLK_TOP_OSC_D20 183
+#define CLK_TOP_FMCNT_P0_EN 184
+#define CLK_TOP_FMCNT_P1_EN 185
+#define CLK_TOP_FMCNT_P2_EN 186
+#define CLK_TOP_FMCNT_P3_EN 187
+#define CLK_TOP_FMCNT_P4_EN 188
+#define CLK_TOP_USB_F26M_CK_EN 189
+#define CLK_TOP_SSPXTP_F26M_CK_EN 190
+#define CLK_TOP_USB2_PHY_RF_P0_EN 191
+#define CLK_TOP_USB2_PHY_RF_P1_EN 192
+#define CLK_TOP_USB2_PHY_RF_P2_EN 193
+#define CLK_TOP_USB2_PHY_RF_P3_EN 194
+#define CLK_TOP_USB2_PHY_RF_P4_EN 195
+#define CLK_TOP_USB2_26M_CK_P0_EN 196
+#define CLK_TOP_USB2_26M_CK_P1_EN 197
+#define CLK_TOP_USB2_26M_CK_P2_EN 198
+#define CLK_TOP_USB2_26M_CK_P3_EN 199
+#define CLK_TOP_USB2_26M_CK_P4_EN 200
+#define CLK_TOP_F26M_CK_EN 201
+#define CLK_TOP_AP2CON_EN 202
+#define CLK_TOP_EINT_N_EN 203
+#define CLK_TOP_TOPCKGEN_FMIPI_CSI_UP26M_CK_EN 204
+#define CLK_TOP_EINT_E_EN 205
+#define CLK_TOP_EINT_W_EN 206
+#define CLK_TOP_EINT_S_EN 207
+
+/* INFRACFG_AO */
+#define CLK_IFRAO_CQ_DMA_FPC 0
+#define CLK_IFRAO_DEBUGSYS 1
+#define CLK_IFRAO_DBG_TRACE 2
+#define CLK_IFRAO_CQ_DMA 3
+
+/* APMIXEDSYS */
+#define CLK_APMIXED_ARMPLL_LL 0
+#define CLK_APMIXED_ARMPLL_BL 1
+#define CLK_APMIXED_CCIPLL 2
+#define CLK_APMIXED_MAINPLL 3
+#define CLK_APMIXED_UNIVPLL 4
+#define CLK_APMIXED_MMPLL 5
+#define CLK_APMIXED_MFGPLL 6
+#define CLK_APMIXED_APLL1 7
+#define CLK_APMIXED_APLL2 8
+#define CLK_APMIXED_EMIPLL 9
+#define CLK_APMIXED_APUPLL2 10
+#define CLK_APMIXED_APUPLL 11
+#define CLK_APMIXED_TVDPLL1 12
+#define CLK_APMIXED_TVDPLL2 13
+#define CLK_APMIXED_ETHPLL 14
+#define CLK_APMIXED_MSDCPLL 15
+#define CLK_APMIXED_UFSPLL 16
+
+/* PERICFG_AO */
+#define CLK_PERAO_UART0 0
+#define CLK_PERAO_UART1 1
+#define CLK_PERAO_UART2 2
+#define CLK_PERAO_UART3 3
+#define CLK_PERAO_PWM_H 4
+#define CLK_PERAO_PWM_B 5
+#define CLK_PERAO_PWM_FB1 6
+#define CLK_PERAO_PWM_FB2 7
+#define CLK_PERAO_PWM_FB3 8
+#define CLK_PERAO_PWM_FB4 9
+#define CLK_PERAO_DISP_PWM0 10
+#define CLK_PERAO_DISP_PWM1 11
+#define CLK_PERAO_SPI0_B 12
+#define CLK_PERAO_SPI1_B 13
+#define CLK_PERAO_SPI2_B 14
+#define CLK_PERAO_SPI3_B 15
+#define CLK_PERAO_SPI4_B 16
+#define CLK_PERAO_SPI5_B 17
+#define CLK_PERAO_SPI0_H 18
+#define CLK_PERAO_SPI1_H 19
+#define CLK_PERAO_SPI2_H 20
+#define CLK_PERAO_SPI3_H 21
+#define CLK_PERAO_SPI4_H 22
+#define CLK_PERAO_SPI5_H 23
+#define CLK_PERAO_AXI 24
+#define CLK_PERAO_AHB_APB 25
+#define CLK_PERAO_TL 26
+#define CLK_PERAO_REF 27
+#define CLK_PERAO_I2C 28
+#define CLK_PERAO_DMA_B 29
+#define CLK_PERAO_SSUSB0_REF 30
+#define CLK_PERAO_SSUSB0_FRMCNT 31
+#define CLK_PERAO_SSUSB0_SYS 32
+#define CLK_PERAO_SSUSB0_XHCI 33
+#define CLK_PERAO_SSUSB0_F 34
+#define CLK_PERAO_SSUSB0_H 35
+#define CLK_PERAO_SSUSB1_REF 36
+#define CLK_PERAO_SSUSB1_FRMCNT 37
+#define CLK_PERAO_SSUSB1_SYS 38
+#define CLK_PERAO_SSUSB1_XHCI 39
+#define CLK_PERAO_SSUSB1_F 40
+#define CLK_PERAO_SSUSB1_H 41
+#define CLK_PERAO_SSUSB2_REF 42
+#define CLK_PERAO_SSUSB2_FRMCNT 43
+#define CLK_PERAO_SSUSB2_SYS 44
+#define CLK_PERAO_SSUSB2_XHCI 45
+#define CLK_PERAO_SSUSB2_F 46
+#define CLK_PERAO_SSUSB2_H 47
+#define CLK_PERAO_SSUSB3_REF 48
+#define CLK_PERAO_SSUSB3_FRMCNT 49
+#define CLK_PERAO_SSUSB3_SYS 50
+#define CLK_PERAO_SSUSB3_XHCI 51
+#define CLK_PERAO_SSUSB3_F 52
+#define CLK_PERAO_SSUSB3_H 53
+#define CLK_PERAO_SSUSB4_REF 54
+#define CLK_PERAO_SSUSB4_FRMCNT 55
+#define CLK_PERAO_SSUSB4_SYS 56
+#define CLK_PERAO_SSUSB4_XHCI 57
+#define CLK_PERAO_SSUSB4_F 58
+#define CLK_PERAO_SSUSB4_H 59
+#define CLK_PERAO_MSDC0 60
+#define CLK_PERAO_MSDC0_H 61
+#define CLK_PERAO_MSDC0_FAES 62
+#define CLK_PERAO_MSDC0_MST_F 63
+#define CLK_PERAO_MSDC0_SLV_H 64
+#define CLK_PERAO_MSDC1 65
+#define CLK_PERAO_MSDC1_H 66
+#define CLK_PERAO_MSDC1_MST_F 67
+#define CLK_PERAO_MSDC1_SLV_H 68
+#define CLK_PERAO_MSDC2 69
+#define CLK_PERAO_MSDC2_H 70
+#define CLK_PERAO_MSDC2_MST_F 71
+#define CLK_PERAO_MSDC2_SLV_H 72
+#define CLK_PERAO_SFLASH 73
+#define CLK_PERAO_SFLASH_F 74
+#define CLK_PERAO_SFLASH_H 75
+#define CLK_PERAO_SFLASH_P 76
+#define CLK_PERAO_AUDIO0 77
+#define CLK_PERAO_AUDIO1 78
+#define CLK_PERAO_AUDIO2 79
+#define CLK_PERAO_AUXADC_26M 80
+
+/* UFSCFG_AO_REG */
+#define CLK_UFSCFG_AO_REG_UNIPRO_TX_SYM 0
+#define CLK_UFSCFG_AO_REG_UNIPRO_RX_SYM0 1
+#define CLK_UFSCFG_AO_REG_UNIPRO_RX_SYM1 2
+#define CLK_UFSCFG_AO_REG_UNIPRO_SYS 3
+#define CLK_UFSCFG_AO_REG_U_SAP_CFG 4
+#define CLK_UFSCFG_AO_REG_U_PHY_TOP_AHB_S_BUS 5
+
+/* UFSCFG_PDN_REG */
+#define CLK_UFSCFG_REG_UFSHCI_UFS 0
+#define CLK_UFSCFG_REG_UFSHCI_AES 1
+#define CLK_UFSCFG_REG_UFSHCI_U_AHB 2
+#define CLK_UFSCFG_REG_UFSHCI_U_AXI 3
+
+/* IMP_IIC_WRAP_WS */
+#define CLK_IMPWS_I2C2 0
+
+/* IMP_IIC_WRAP_E */
+#define CLK_IMPE_I2C0 0
+#define CLK_IMPE_I2C1 1
+
+/* IMP_IIC_WRAP_S */
+#define CLK_IMPS_I2C3 0
+#define CLK_IMPS_I2C4 1
+#define CLK_IMPS_I2C5 2
+#define CLK_IMPS_I2C6 3
+
+/* IMP_IIC_WRAP_EN */
+#define CLK_IMPEN_I2C7 0
+#define CLK_IMPEN_I2C8 1
+
+/* VLPCFG_REG */
+#define CLK_VLPCFG_REG_SCP 0
+#define CLK_VLPCFG_REG_RG_R_APXGPT_26M 1
+#define CLK_VLPCFG_REG_DPMSRCK_TEST 2
+#define CLK_VLPCFG_REG_RG_DPMSRRTC_TEST 3
+#define CLK_VLPCFG_REG_DPMSRULP_TEST 4
+#define CLK_VLPCFG_REG_SPMI_P_MST 5
+#define CLK_VLPCFG_REG_SPMI_P_MST_32K 6
+#define CLK_VLPCFG_REG_PMIF_SPMI_P_SYS 7
+#define CLK_VLPCFG_REG_PMIF_SPMI_P_TMR 8
+#define CLK_VLPCFG_REG_PMIF_SPMI_M_SYS 9
+#define CLK_VLPCFG_REG_PMIF_SPMI_M_TMR 10
+#define CLK_VLPCFG_REG_DVFSRC 11
+#define CLK_VLPCFG_REG_PWM_VLP 12
+#define CLK_VLPCFG_REG_SRCK 13
+#define CLK_VLPCFG_REG_SSPM_F26M 14
+#define CLK_VLPCFG_REG_SSPM_F32K 15
+#define CLK_VLPCFG_REG_SSPM_ULPOSC 16
+#define CLK_VLPCFG_REG_VLP_32K_COM 17
+#define CLK_VLPCFG_REG_VLP_26M_COM 18
+
+/* VLP_CKSYS */
+#define CLK_VLP_CK_SCP_SEL 0
+#define CLK_VLP_CK_PWRAP_ULPOSC_SEL 1
+#define CLK_VLP_CK_SPMI_P_MST_SEL 2
+#define CLK_VLP_CK_DVFSRC_SEL 3
+#define CLK_VLP_CK_PWM_VLP_SEL 4
+#define CLK_VLP_CK_AXI_VLP_SEL 5
+#define CLK_VLP_CK_SYSTIMER_26M_SEL 6
+#define CLK_VLP_CK_SSPM_SEL 7
+#define CLK_VLP_CK_SSPM_F26M_SEL 8
+#define CLK_VLP_CK_SRCK_SEL 9
+#define CLK_VLP_CK_SCP_SPI_SEL 10
+#define CLK_VLP_CK_SCP_IIC_SEL 11
+#define CLK_VLP_CK_SCP_SPI_HIGH_SPD_SEL 12
+#define CLK_VLP_CK_SCP_IIC_HIGH_SPD_SEL 13
+#define CLK_VLP_CK_SSPM_ULPOSC_SEL 14
+#define CLK_VLP_CK_APXGPT_26M_SEL 15
+#define CLK_VLP_CK_VADSP_SEL 16
+#define CLK_VLP_CK_VADSP_VOWPLL_SEL 17
+#define CLK_VLP_CK_VADSP_UARTHUB_BCLK_SEL 18
+#define CLK_VLP_CK_CAMTG0_SEL 19
+#define CLK_VLP_CK_CAMTG1_SEL 20
+#define CLK_VLP_CK_CAMTG2_SEL 21
+#define CLK_VLP_CK_AUD_ADC_SEL 22
+#define CLK_VLP_CK_KP_IRQ_GEN_SEL 23
+#define CLK_VLP_CK_VADSYS_VLP_26M_EN 24
+#define CLK_VLP_CK_FMIPI_CSI_UP26M_CK_EN 25
+
+/* SCP_IIC */
+#define CLK_SCP_IIC_I2C0_W1S 0
+#define CLK_SCP_IIC_I2C1_W1S 1
+
+/* SCP */
+#define CLK_SCP_SET_SPI0 0
+#define CLK_SCP_SET_SPI1 1
+
+/* VLPCFG_AO_REG */
+#define CLK_VLPCFG_AO_APEINT_RX 0
+
+/* DVFSRC_TOP */
+#define CLK_DVFSRC_TOP_DVFSRC_EN 0
+
+/* DBGAO */
+#define CLK_DBGAO_ATB_EN 0
+
+/* DEM */
+#define CLK_DEM_ATB_EN 0
+#define CLK_DEM_BUSCLK_EN 1
+#define CLK_DEM_SYSCLK_EN 2
+
+#endif /* _DT_BINDINGS_CLK_MT8189_H */
diff --git a/include/dt-bindings/reset/mediatek,mt8189-resets.h b/include/dt-bindings/reset/mediatek,mt8189-resets.h
new file mode 100644
index 000000000000..0f31984374be
--- /dev/null
+++ b/include/dt-bindings/reset/mediatek,mt8189-resets.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2026 Collabora Ltd.
+ * Author: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8189
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8189
+
+/* UFS resets */
+#define MT8189_UFSAO_RST_UFS_MPHY 0
+
+#define MT8189_UFSPDN_RST_UFS_UNIPRO 0
+#define MT8189_UFSPDN_RST_UFS_CRYPTO 1
+#define MT8189_UFSPDN_RST_UFS_HCI 2
+
+#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8189 */
--
2.54.0
^ permalink raw reply related
* [PATCH 06/15] clk: mediatek: Add MT8189 apmixedsys clock support
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
Edward-JW Yang, Richard Cochran
Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>
Add support for the MT8189 apmixedsys clock controller, which provides
PLLs generated from SoC 26m.
Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
drivers/clk/mediatek/Kconfig | 13 ++
drivers/clk/mediatek/Makefile | 1 +
drivers/clk/mediatek/clk-mt8189-apmixedsys.c | 196 +++++++++++++++++++++++++++
3 files changed, 210 insertions(+)
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 2c09fd729bab..f67dfb6cd019 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -815,6 +815,19 @@ config COMMON_CLK_MT8188_WPESYS
help
This driver supports MediaTek MT8188 Warp Engine clocks.
+config COMMON_CLK_MT8189
+ tristate "Clock driver for MediaTek MT8189"
+ depends on ARM64 || COMPILE_TEST
+ select COMMON_CLK_MEDIATEK
+ select COMMON_CLK_MEDIATEK_FHCTL
+ default ARCH_MEDIATEK
+ help
+ Enable this option to support the clock management for MediaTek MT8189 SoC. This
+ includes handling of all primary clock functions and features specific to the MT8189
+ platform. Enabling this driver ensures that the system's clock functionality aligns
+ with the MediaTek MT8189 hardware capabilities, providing efficient management of
+ clock speeds and power consumption.
+
config COMMON_CLK_MT8192
tristate "Clock driver for MediaTek MT8192"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index d8736a060dbd..66577ccb9b93 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -123,6 +123,7 @@ obj-$(CONFIG_COMMON_CLK_MT8188_VDOSYS) += clk-mt8188-vdo0.o clk-mt8188-vdo1.o
obj-$(CONFIG_COMMON_CLK_MT8188_VENCSYS) += clk-mt8188-venc.o
obj-$(CONFIG_COMMON_CLK_MT8188_VPPSYS) += clk-mt8188-vpp0.o clk-mt8188-vpp1.o
obj-$(CONFIG_COMMON_CLK_MT8188_WPESYS) += clk-mt8188-wpe.o
+obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o
obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8189-apmixedsys.c b/drivers/clk/mediatek/clk-mt8189-apmixedsys.c
new file mode 100644
index 000000000000..0657a50c30d9
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8189-apmixedsys.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ * Qiqi Wang <qiqi.wang@mediatek.com>
+ * Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ * Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "clk-fhctl.h"
+#include "clk-mtk.h"
+#include "clk-pll.h"
+
+#include <dt-bindings/clock/mediatek,mt8189-clk.h>
+
+#define MT8189_PLL_FMAX (3800UL * MHZ)
+#define MT8189_PLL_FMIN (1500UL * MHZ)
+#define MT8189_PLLEN_OFS 0x70
+#define MT8189_INTEGER_BITS 8
+
+#define PLL_SETCLR(_id, _name, _reg, _en_setclr_bit, \
+ _rstb_setclr_bit, _flags, _pd_reg, \
+ _pd_shift, _tuner_reg, _tuner_en_reg, \
+ _tuner_en_bit, _pcw_reg, _pcw_shift, \
+ _pcwbits) { \
+ .id = _id, \
+ .name = _name, \
+ .en_reg = MT8189_PLLEN_OFS, \
+ .reg = _reg, \
+ .pll_en_bit = _en_setclr_bit, \
+ .rst_bar_mask = BIT(_rstb_setclr_bit), \
+ .flags = _flags, \
+ .fmax = MT8189_PLL_FMAX, \
+ .fmin = MT8189_PLL_FMIN, \
+ .pd_reg = _pd_reg, \
+ .pd_shift = _pd_shift, \
+ .tuner_reg = _tuner_reg, \
+ .tuner_en_reg = _tuner_en_reg, \
+ .tuner_en_bit = _tuner_en_bit, \
+ .pcw_reg = _pcw_reg, \
+ .pcw_shift = _pcw_shift, \
+ .pcwbits = _pcwbits, \
+ .pcwibits = MT8189_INTEGER_BITS, \
+ }
+
+static const struct mtk_pll_data apmixed_plls[] = {
+ PLL_SETCLR(CLK_APMIXED_ARMPLL_LL, "armpll-ll", 0x204, 18,
+ 0, PLL_AO, 0x208, 24, 0, 0, 0, 0x208, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_ARMPLL_BL, "armpll-bl", 0x214, 17,
+ 0, PLL_AO, 0x218, 24, 0, 0, 0, 0x218, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_CCIPLL, "ccipll", 0x224, 16,
+ 0, PLL_AO, 0x228, 24, 0, 0, 0, 0x228, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_MAINPLL, "mainpll", 0x304, 15,
+ 23, HAVE_RST_BAR | PLL_AO,
+ 0x308, 24, 0, 0, 0, 0x308, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_UNIVPLL, "univpll", 0x314, 14,
+ 23, HAVE_RST_BAR, 0x318, 24, 0, 0, 0, 0x318, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_MMPLL, "mmpll", 0x324, 13,
+ 23, HAVE_RST_BAR, 0x328, 24, 0, 0, 0, 0x328, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_MFGPLL, "mfgpll", 0x504, 7,
+ 0, 0, 0x508, 24, 0, 0, 0, 0x508, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_APLL1, "apll1", 0x404, 11,
+ 0, 0, 0x408, 24, 0x040, 0x00c, 0, 0x40c, 0, 32),
+ PLL_SETCLR(CLK_APMIXED_APLL2, "apll2", 0x418, 10,
+ 0, 0, 0x41c, 24, 0x044, 0x00c, 1, 0x420, 0, 32),
+ PLL_SETCLR(CLK_APMIXED_EMIPLL, "emipll", 0x334, 12,
+ 0, PLL_AO, 0x338, 24, 0, 0, 0, 0x338, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_APUPLL2, "apupll2", 0x614, 2,
+ 0, 0, 0x618, 24, 0, 0, 0, 0x618, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_APUPLL, "apupll", 0x604, 3,
+ 0, 0, 0x608, 24, 0, 0, 0, 0x608, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_TVDPLL1, "tvdpll1", 0x42c, 9,
+ 0, 0, 0x430, 24, 0, 0, 0, 0x430, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_TVDPLL2, "tvdpll2", 0x43c, 8,
+ 0, 0, 0x440, 24, 0, 0, 0, 0x440, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_ETHPLL, "ethpll", 0x514, 6,
+ 0, 0, 0x518, 24, 0, 0, 0, 0x518, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_MSDCPLL, "msdcpll", 0x524, 5,
+ 0, 0, 0x528, 24, 0, 0, 0, 0x528, 0, 22),
+ PLL_SETCLR(CLK_APMIXED_UFSPLL, "ufspll", 0x534, 4,
+ 0, 0, 0x538, 24, 0, 0, 0, 0x538, 0, 22),
+};
+
+#define FH(_pllid, _fhid, _offset) { \
+ .data = { \
+ .pll_id = _pllid, \
+ .fh_id = _fhid, \
+ .fh_ver = FHCTL_PLLFH_V2, \
+ .fhx_offset = _offset, \
+ .dds_mask = GENMASK(21, 0), \
+ .slope0_value = 0x6003c97, \
+ .slope1_value = 0x6003c97, \
+ .sfstrx_en = BIT(2), \
+ .frddsx_en = BIT(1), \
+ .fhctlx_en = BIT(0), \
+ .tgl_org = BIT(31), \
+ .dvfs_tri = BIT(31), \
+ .pcwchg = BIT(31), \
+ .dt_val = 0x0, \
+ .df_val = 0x9, \
+ .updnlmt_shft = 16, \
+ .msk_frddsx_dys = GENMASK(23, 20), \
+ .msk_frddsx_dts = GENMASK(19, 16), \
+ }, \
+ }
+
+static struct mtk_pllfh_data pllfhs[] = {
+ FH(CLK_APMIXED_ARMPLL_LL, 0, 0x003C),
+ FH(CLK_APMIXED_ARMPLL_BL, 1, 0x0050),
+ FH(CLK_APMIXED_CCIPLL, 2, 0x0064),
+ FH(CLK_APMIXED_MAINPLL, 3, 0x0078),
+ FH(CLK_APMIXED_MMPLL, 4, 0x008C),
+ FH(CLK_APMIXED_MFGPLL, 5, 0x00A0),
+ FH(CLK_APMIXED_EMIPLL, 6, 0x00B4),
+ FH(CLK_APMIXED_TVDPLL1, 7, 0x00C8),
+ FH(CLK_APMIXED_TVDPLL2, 8, 0x00DC),
+ FH(CLK_APMIXED_MSDCPLL, 9, 0x00F0),
+ FH(CLK_APMIXED_UFSPLL, 10, 0x0104),
+ FH(CLK_APMIXED_APUPLL, 11, 0x0118),
+ FH(CLK_APMIXED_APUPLL2, 12, 0x012c),
+};
+
+static const struct of_device_id of_match_clk_mt8189_apmixed[] = {
+ { .compatible = "mediatek,mt8189-apmixedsys" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_clk_mt8189_apmixed);
+
+static int clk_mt8189_apmixed_probe(struct platform_device *pdev)
+{
+ int r;
+ struct clk_hw_onecell_data *clk_data;
+ struct device_node *node = pdev->dev.of_node;
+ const u8 *fhctl_node = "mediatek,mt8189-fhctl";
+
+ clk_data = mtk_alloc_clk_data(ARRAY_SIZE(apmixed_plls));
+ if (!clk_data)
+ return -ENOMEM;
+
+ fhctl_parse_dt(fhctl_node, pllfhs, ARRAY_SIZE(pllfhs));
+
+ r = mtk_clk_register_pllfhs(&pdev->dev, apmixed_plls, ARRAY_SIZE(apmixed_plls),
+ pllfhs, ARRAY_SIZE(pllfhs), clk_data);
+ if (r)
+ goto free_apmixed_data;
+
+ r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+ if (r)
+ goto unregister_plls;
+
+ platform_set_drvdata(pdev, clk_data);
+
+ return 0;
+
+unregister_plls:
+ mtk_clk_unregister_pllfhs(apmixed_plls, ARRAY_SIZE(apmixed_plls), pllfhs,
+ ARRAY_SIZE(pllfhs), clk_data);
+free_apmixed_data:
+ mtk_free_clk_data(clk_data);
+ return r;
+}
+
+static void clk_mt8189_apmixed_remove(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
+
+ of_clk_del_provider(node);
+ mtk_clk_unregister_pllfhs(apmixed_plls, ARRAY_SIZE(apmixed_plls), pllfhs,
+ ARRAY_SIZE(pllfhs), clk_data);
+ mtk_free_clk_data(clk_data);
+}
+
+static struct platform_driver clk_mt8189_apmixed_drv = {
+ .probe = clk_mt8189_apmixed_probe,
+ .remove = clk_mt8189_apmixed_remove,
+ .driver = {
+ .name = "clk-mt8189-apmixed",
+ .of_match_table = of_match_clk_mt8189_apmixed,
+ },
+};
+module_platform_driver(clk_mt8189_apmixed_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8189 apmixed clocks driver");
+MODULE_LICENSE("GPL");
--
2.54.0
^ permalink raw reply related
* [PATCH 07/15] clk: mediatek: Add MT8189 topckgen clock support
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
Edward-JW Yang, Richard Cochran
Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>
Add support for the MT8189 topckgen clock controller, which provides
muxes and dividers for clock selection in other IP blocks.
Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
drivers/clk/mediatek/Makefile | 2 +-
drivers/clk/mediatek/clk-mt8189-topckgen.c | 1024 ++++++++++++++++++++++++++++
2 files changed, 1025 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 66577ccb9b93..9d3d2983bfb2 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -123,7 +123,7 @@ obj-$(CONFIG_COMMON_CLK_MT8188_VDOSYS) += clk-mt8188-vdo0.o clk-mt8188-vdo1.o
obj-$(CONFIG_COMMON_CLK_MT8188_VENCSYS) += clk-mt8188-venc.o
obj-$(CONFIG_COMMON_CLK_MT8188_VPPSYS) += clk-mt8188-vpp0.o clk-mt8188-vpp1.o
obj-$(CONFIG_COMMON_CLK_MT8188_WPESYS) += clk-mt8188-wpe.o
-obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o
+obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o clk-mt8189-topckgen.o
obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8189-topckgen.c b/drivers/clk/mediatek/clk-mt8189-topckgen.c
new file mode 100644
index 000000000000..62d292f5b8b8
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8189-topckgen.c
@@ -0,0 +1,1024 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ * Qiqi Wang <qiqi.wang@mediatek.com>
+ * Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ * Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+#include "clk-mux.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mediatek,mt8189-clk.h>
+
+static DEFINE_SPINLOCK(mt8189_clk_lock);
+
+static const struct mtk_fixed_factor top_divs[] = {
+ FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3),
+ FACTOR(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4),
+ FACTOR(CLK_TOP_MAINPLL_D4_D2, "mainpll_d4_d2", "mainpll", 1, 8),
+ FACTOR(CLK_TOP_MAINPLL_D4_D4, "mainpll_d4_d4", "mainpll", 1, 16),
+ FACTOR(CLK_TOP_MAINPLL_D4_D8, "mainpll_d4_d8", "mainpll", 43, 1375),
+ FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5),
+ FACTOR(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll", 1, 10),
+ FACTOR(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll", 1, 20),
+ FACTOR(CLK_TOP_MAINPLL_D5_D8, "mainpll_d5_d8", "mainpll", 1, 40),
+ FACTOR(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6),
+ FACTOR(CLK_TOP_MAINPLL_D6_D2, "mainpll_d6_d2", "mainpll", 1, 12),
+ FACTOR(CLK_TOP_MAINPLL_D6_D4, "mainpll_d6_d4", "mainpll", 1, 24),
+ FACTOR(CLK_TOP_MAINPLL_D6_D8, "mainpll_d6_d8", "mainpll", 1, 48),
+ FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7),
+ FACTOR(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll", 1, 14),
+ FACTOR(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll", 1, 28),
+ FACTOR(CLK_TOP_MAINPLL_D7_D8, "mainpll_d7_d8", "mainpll", 1, 56),
+ FACTOR(CLK_TOP_MAINPLL_D9, "mainpll_d9", "mainpll", 1, 9),
+ FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+ FACTOR(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL_D4_D2, "univpll_d4_d2", "univpll", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL_D4_D4, "univpll_d4_d4", "univpll", 1, 16),
+ FACTOR(CLK_TOP_UNIVPLL_D4_D8, "univpll_d4_d8", "univpll", 1, 32),
+ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+ FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll", 1, 10),
+ FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll", 1, 20),
+ FACTOR(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6),
+ FACTOR(CLK_TOP_UNIVPLL_D6_D2, "univpll_d6_d2", "univpll", 1, 12),
+ FACTOR(CLK_TOP_UNIVPLL_D6_D4, "univpll_d6_d4", "univpll", 1, 24),
+ FACTOR(CLK_TOP_UNIVPLL_D6_D8, "univpll_d6_d8", "univpll", 1, 48),
+ FACTOR(CLK_TOP_UNIVPLL_D6_D16, "univpll_d6_d16", "univpll", 1, 96),
+ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+ FACTOR(CLK_TOP_UNIVPLL_D7_D2, "univpll_d7_d2", "univpll", 1, 14),
+ FACTOR(CLK_TOP_UNIVPLL_D7_D3, "univpll_d7_d3", "univpll", 1, 21),
+ FACTOR(CLK_TOP_LVDSTX_DG_CTS, "lvdstx_dg_cts", "univpll", 1, 21),
+ FACTOR(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univpll", 1, 13),
+ FACTOR(CLK_TOP_UNIVPLL_192M_D2, "univpll_192m_d2", "univpll", 1, 26),
+ FACTOR(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll", 1, 52),
+ FACTOR(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll", 1, 104),
+ FACTOR(CLK_TOP_UNIVPLL_192M_D10, "univpll_192m_d10", "univpll", 1, 130),
+ FACTOR(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll", 1, 208),
+ FACTOR(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll", 1, 416),
+ FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1, 2),
+ FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, 4),
+ FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1", 1, 8),
+ FACTOR(CLK_TOP_APLL1_D3, "apll1_d3", "apll1", 1, 3),
+ FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2),
+ FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4),
+ FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2", 1, 8),
+ FACTOR(CLK_TOP_APLL2_D3, "apll2_d3", "apll2", 1, 3),
+ FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1, 4),
+ FACTOR(CLK_TOP_MMPLL_D4_D2, "mmpll_d4_d2", "mmpll", 1, 8),
+ FACTOR(CLK_TOP_MMPLL_D4_D4, "mmpll_d4_d4", "mmpll", 1, 16),
+ FACTOR(CLK_TOP_VPLL_DPIX, "vpll_dpix", "mmpll", 1, 16),
+ FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
+ FACTOR(CLK_TOP_MMPLL_D5_D2, "mmpll_d5_d2", "mmpll", 1, 10),
+ FACTOR(CLK_TOP_MMPLL_D5_D4, "mmpll_d5_d4", "mmpll", 1, 20),
+ FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll", 1, 6),
+ FACTOR(CLK_TOP_MMPLL_D6_D2, "mmpll_d6_d2", "mmpll", 1, 12),
+ FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
+ FACTOR(CLK_TOP_MMPLL_D9, "mmpll_d9", "mmpll", 1, 9),
+ FACTOR(CLK_TOP_TVDPLL1_D2, "tvdpll1_d2", "tvdpll1", 1, 2),
+ FACTOR(CLK_TOP_TVDPLL1_D4, "tvdpll1_d4", "tvdpll1", 1, 4),
+ FACTOR(CLK_TOP_TVDPLL1_D8, "tvdpll1_d8", "tvdpll1", 1, 8),
+ FACTOR(CLK_TOP_TVDPLL1_D16, "tvdpll1_d16", "tvdpll1", 92, 1473),
+ FACTOR(CLK_TOP_TVDPLL2_D2, "tvdpll2_d2", "tvdpll2", 1, 2),
+ FACTOR(CLK_TOP_TVDPLL2_D4, "tvdpll2_d4", "tvdpll2", 1, 4),
+ FACTOR(CLK_TOP_TVDPLL2_D8, "tvdpll2_d8", "tvdpll2", 1, 8),
+ FACTOR(CLK_TOP_TVDPLL2_D16, "tvdpll2_d16", "tvdpll2", 92, 1473),
+ FACTOR(CLK_TOP_ETHPLL_D2, "ethpll_d2", "ethpll", 1, 2),
+ FACTOR(CLK_TOP_ETHPLL_D8, "ethpll_d8", "ethpll", 1, 8),
+ FACTOR(CLK_TOP_ETHPLL_D10, "ethpll_d10", "ethpll", 1, 10),
+ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+ FACTOR(CLK_TOP_UFSPLL_D2, "ufspll_d2", "ufspll", 1, 2),
+ FACTOR(CLK_TOP_F26M_CK_D2, "f26m_d2", "clk26m", 1, 2),
+ FACTOR(CLK_TOP_OSC_D2, "osc_d2", "ulposc", 1, 2),
+ FACTOR(CLK_TOP_OSC_D4, "osc_d4", "ulposc", 1, 4),
+ FACTOR(CLK_TOP_OSC_D8, "osc_d8", "ulposc", 1, 8),
+ FACTOR(CLK_TOP_OSC_D16, "osc_d16", "ulposc", 61, 973),
+ FACTOR(CLK_TOP_OSC_D3, "osc_d3", "ulposc", 1, 3),
+ FACTOR(CLK_TOP_OSC_D7, "osc_d7", "ulposc", 1, 7),
+ FACTOR(CLK_TOP_OSC_D10, "osc_d10", "ulposc", 1, 10),
+ FACTOR(CLK_TOP_OSC_D20, "osc_d20", "ulposc", 1, 20),
+};
+
+static const char * const ap2conn_host_parents[] = {
+ "clk26m",
+ "mainpll_d7_d4"
+};
+
+static const char * const apll_m_parents[] = {
+ "aud_1_sel",
+ "aud_2_sel"
+};
+
+static const char * const aud_1_parents[] = {
+ "clk26m",
+ "apll1"
+};
+
+static const char * const aud_2_parents[] = {
+ "clk26m",
+ "apll2"
+};
+
+static const char * const mfg_sel_mfgpll_parents[] = {
+ "mfg_ref_sel",
+ "mfgpll"
+};
+
+static const char * const pwm_parents[] = {
+ "clk26m",
+ "univpll_d4_d8"
+};
+
+static const char * const snps_eth_250m_parents[] = {
+ "clk26m",
+ "ethpll_d2"
+};
+
+static const char * const snps_eth_50m_rmii_parents[] = {
+ "clk26m",
+ "ethpll_d10"
+};
+
+static const char * const uart_parents[] = {
+ "clk26m",
+ "univpll_d6_d8"
+};
+
+static const char * const atb_parents[] = {
+ "clk26m",
+ "mainpll_d4_d2",
+ "mainpll_d5_d2"
+};
+
+static const char * const aud_intbus_parents[] = {
+ "clk26m",
+ "mainpll_d4_d4",
+ "mainpll_d7_d4"
+};
+
+static const char * const msdc5hclk_parents[] = {
+ "clk26m",
+ "mainpll_d4_d2",
+ "mainpll_d6_d2"
+};
+
+static const char * const pcie_mac_tl_parents[] = {
+ "clk26m",
+ "mainpll_d4_d4",
+ "univpll_d5_d4"
+};
+
+static const char * const pll_dpix_parents[] = {
+ "clk26m",
+ "vpll_dpix",
+ "mmpll_d4_d4"
+};
+
+static const char * const usb_parents[] = {
+ "clk26m",
+ "univpll_d5_d4",
+ "univpll_d6_d4"
+};
+
+static const char * const vdstx_dg_cts_parents[] = {
+ "clk26m",
+ "lvdstx_dg_cts",
+ "univpll_d7_d3"
+};
+
+static const char * const audio_h_parents[] = {
+ "clk26m",
+ "univpll_d7_d2",
+ "apll1",
+ "apll2"
+};
+
+static const char * const aud_engen1_parents[] = {
+ "clk26m",
+ "apll1_d2",
+ "apll1_d4",
+ "apll1_d8"
+};
+
+static const char * const aud_engen2_parents[] = {
+ "clk26m",
+ "apll2_d2",
+ "apll2_d4",
+ "apll2_d8"
+};
+
+static const char * const axi_peri_parents[] = {
+ "clk26m",
+ "mainpll_d4_d4",
+ "mainpll_d7_d2",
+ "osc_d4"
+};
+
+static const char * const axi_u_parents[] = {
+ "clk26m",
+ "mainpll_d4_d8",
+ "mainpll_d7_d4",
+ "osc_d8"
+};
+
+static const char * const camtm_parents[] = {
+ "clk26m",
+ "osc_d2",
+ "univpll_d6_d2",
+ "univpll_d6_d4"
+};
+
+static const char * const dsi_occ_parents[] = {
+ "clk26m",
+ "univpll_d6_d2",
+ "univpll_d5_d2",
+ "univpll_d4_d2"
+};
+
+static const char * const dxcc_parents[] = {
+ "clk26m",
+ "mainpll_d4_d8",
+ "mainpll_d4_d4",
+ "mainpll_d4_d2"
+};
+
+static const char * const i2c_parents[] = {
+ "clk26m",
+ "mainpll_d4_d8",
+ "univpll_d5_d4",
+ "mainpll_d4_d4"
+};
+
+static const char * const mcupm_parents[] = {
+ "clk26m",
+ "univpll_d6_d2",
+ "mainpll_d5_d2",
+ "mainpll_d6_d2"
+};
+
+static const char * const mfg_ref_parents[] = {
+ "clk26m",
+ "mainpll_d6_d2",
+ "mainpll_d6",
+ "mainpll_d5_d2"
+};
+
+static const char * const msdc30_h_parents[] = {
+ "clk26m",
+ "msdcpll_d2",
+ "mainpll_d4_d4",
+ "mainpll_d6_d4"
+};
+
+static const char * const msdc_macro_p_parents[] = {
+ "clk26m",
+ "msdcpll",
+ "mmpll_d5_d4",
+ "univpll_d4_d2"
+};
+
+static const char * const snps_eth_62p4m_ptp_parents[] = {
+ "clk26m",
+ "ethpll_d8",
+ "apll1_d3",
+ "apll2_d3"
+};
+
+static const char * const ufs_mbist_parents[] = {
+ "clk26m",
+ "mainpll_d4_d2",
+ "univpll_d4_d2",
+ "ufspll_d2"
+};
+
+static const char * const aes_msdcfde_parents[] = {
+ "clk26m",
+ "mainpll_d4_d2",
+ "mainpll_d6",
+ "mainpll_d4_d4",
+ "msdcpll"
+};
+
+static const char * const bus_aximem_parents[] = {
+ "clk26m",
+ "mainpll_d7_d2",
+ "mainpll_d5_d2",
+ "mainpll_d4_d2",
+ "mainpll_d6"
+};
+
+static const char * const dp_parents[] = {
+ "clk26m",
+ "tvdpll1_d16",
+ "tvdpll1_d8",
+ "tvdpll1_d4",
+ "tvdpll1_d2"
+};
+
+static const char * const msdc30_parents[] = {
+ "clk26m",
+ "univpll_d6_d2",
+ "mainpll_d6_d2",
+ "mainpll_d7_d2",
+ "msdcpll_d2"
+};
+
+static const char * const ecc_parents[] = {
+ "clk26m",
+ "univpll_d6_d2",
+ "univpll_d4_d2",
+ "univpll_d6",
+ "mainpll_d4",
+ "univpll_d4"
+};
+
+static const char * const emi_n_parents[] = {
+ "clk26m",
+ "osc_d2",
+ "mainpll_d9",
+ "mainpll_d6",
+ "mainpll_d5",
+ "emipll"
+};
+
+static const char * const sr_pka_parents[] = {
+ "clk26m",
+ "mainpll_d4_d4",
+ "mainpll_d4_d2",
+ "mainpll_d7",
+ "mainpll_d6",
+ "mainpll_d5"
+};
+
+static const char * const aes_ufsfde_parents[] = {
+ "clk26m",
+ "mainpll_d4",
+ "mainpll_d4_d2",
+ "mainpll_d6",
+ "mainpll_d4_d4",
+ "univpll_d4_d2",
+ "univpll_d6"
+};
+
+static const char * const axi_parents[] = {
+ "clk26m",
+ "mainpll_d4_d4",
+ "mainpll_d7_d2",
+ "mainpll_d4_d2",
+ "mainpll_d5_d2",
+ "mainpll_d6_d2",
+ "osc_d4"
+};
+
+static const char * const disp_pwm_parents[] = {
+ "clk26m",
+ "univpll_d6_d4",
+ "osc_d2",
+ "osc_d4",
+ "osc_d16",
+ "univpll_d5_d4",
+ "mainpll_d4_d4"
+};
+
+static const char * const edp_parents[] = {
+ "clk26m",
+ "tvdpll2_d16",
+ "tvdpll2_d8",
+ "tvdpll2_d4",
+ "tvdpll2_d2"
+};
+
+static const char * const gcpu_parents[] = {
+ "clk26m",
+ "mainpll_d6",
+ "mainpll_d4_d2",
+ "univpll_d4_d2",
+ "univpll_d5_d2",
+ "univpll_d5_d4",
+ "univpll_d6"
+};
+
+static const char * const msdc50_0_parents[] = {
+ "clk26m",
+ "msdcpll",
+ "msdcpll_d2",
+ "mainpll_d6_d2",
+ "mainpll_d4_d4",
+ "mainpll_d6",
+ "univpll_d4_d4"
+};
+
+static const char * const ufs_parents[] = {
+ "clk26m",
+ "mainpll_d4_d8",
+ "mainpll_d4_d4",
+ "mainpll_d5_d2",
+ "mainpll_d6_d2",
+ "univpll_d6_d2",
+ "msdcpll_d2"
+};
+
+static const char * const dsp_parents[] = {
+ "clk26m",
+ "osc_d4",
+ "osc_d3",
+ "osc_d2",
+ "univpll_d7_d2",
+ "univpll_d6_d2",
+ "mainpll_d6",
+ "univpll_d5"
+};
+
+static const char * const mem_sub_peri_u_parents[] = {
+ "clk26m",
+ "univpll_d4_d4",
+ "mainpll_d5_d2",
+ "mainpll_d4_d2",
+ "mainpll_d6",
+ "mainpll_d5",
+ "univpll_d5",
+ "mainpll_d4"
+};
+
+static const char * const seninf_parents[] = {
+ "clk26m",
+ "osc_d2",
+ "univpll_d6_d2",
+ "mainpll_d4_d2",
+ "univpll_d4_d2",
+ "mmpll_d7",
+ "univpll_d6",
+ "univpll_d5"
+};
+
+static const char * const sflash_parents[] = {
+ "clk26m",
+ "mainpll_d7_d8",
+ "univpll_d6_d8",
+ "mainpll_d7_d4",
+ "mainpll_d6_d4",
+ "univpll_d6_d4",
+ "univpll_d7_d3",
+ "univpll_d5_d4"
+};
+
+static const char * const spi_parents[] = {
+ "clk26m",
+ "univpll_d6_d2",
+ "univpll_192m",
+ "mainpll_d6_d2",
+ "univpll_d4_d4",
+ "mainpll_d4_d4",
+ "univpll_d5_d4",
+ "univpll_d6_d4"
+};
+
+static const char * const img1_parents[] = {
+ "clk26m",
+ "univpll_d4",
+ "mmpll_d5",
+ "mmpll_d6",
+ "univpll_d6",
+ "mmpll_d7",
+ "mmpll_d4_d2",
+ "univpll_d4_d2",
+ "mainpll_d4_d2",
+ "mmpll_d6_d2",
+ "mmpll_d5_d2"
+};
+
+static const char * const ipe_parents[] = {
+ "clk26m",
+ "univpll_d4",
+ "mainpll_d4",
+ "mmpll_d6",
+ "univpll_d6",
+ "mainpll_d6",
+ "mmpll_d4_d2",
+ "univpll_d4_d2",
+ "mainpll_d4_d2",
+ "mmpll_d6_d2",
+ "mmpll_d5_d2"
+};
+
+static const char * const mem_sub_parents[] = {
+ "clk26m",
+ "univpll_d4_d4",
+ "mainpll_d6_d2",
+ "mainpll_d5_d2",
+ "mainpll_d4_d2",
+ "mainpll_d6",
+ "mmpll_d7",
+ "mainpll_d5",
+ "univpll_d5",
+ "mainpll_d4",
+ "univpll_d4"
+};
+
+static const char * const cam_parents[] = {
+ "clk26m",
+ "mainpll_d4",
+ "mmpll_d4",
+ "univpll_d4",
+ "univpll_d5",
+ "mmpll_d7",
+ "mmpll_d6",
+ "univpll_d6",
+ "univpll_d4_d2",
+ "mmpll_d9",
+ "mainpll_d4_d2",
+ "osc_d2"
+};
+
+static const char * const mmsys_parents[] = {
+ "clk26m",
+ "mainpll_d5_d2",
+ "univpll_d5_d2",
+ "mainpll_d4_d2",
+ "univpll_d4_d2",
+ "mainpll_d6",
+ "univpll_d6",
+ "mmpll_d6",
+ "tvdpll1",
+ "tvdpll2",
+ "univpll_d4",
+ "mmpll_d4"
+};
+
+static const char * const mminfra_parents[] = {
+ "clk26m",
+ "osc_d2",
+ "mainpll_d5_d2",
+ "mmpll_d6_d2",
+ "mainpll_d4_d2",
+ "mmpll_d4_d2",
+ "mainpll_d6",
+ "mmpll_d7",
+ "univpll_d6",
+ "mainpll_d5",
+ "mmpll_d6",
+ "univpll_d5",
+ "mainpll_d4",
+ "univpll_d4",
+ "mmpll_d4",
+ "emipll"
+};
+
+static const char * const vdec_parents[] = {
+ "clk26m",
+ "univpll_192m_d2",
+ "univpll_d5_d4",
+ "mainpll_d5",
+ "mainpll_d5_d2",
+ "mmpll_d6_d2",
+ "univpll_d5_d2",
+ "mainpll_d4_d2",
+ "univpll_d4_d2",
+ "univpll_d7",
+ "mmpll_d7",
+ "mmpll_d6",
+ "univpll_d6",
+ "mainpll_d4",
+ "univpll_d4",
+ "mmpll_d5_d2"
+};
+
+static const char * const venc_parents[] = {
+ "clk26m",
+ "mmpll_d4_d2",
+ "mainpll_d6",
+ "univpll_d4_d2",
+ "mainpll_d4_d2",
+ "univpll_d6",
+ "mmpll_d6",
+ "mainpll_d5_d2",
+ "mainpll_d6_d2",
+ "mmpll_d9",
+ "mmpll_d4",
+ "mainpll_d4",
+ "univpll_d4",
+ "univpll_d5",
+ "univpll_d5_d2",
+ "mainpll_d5"
+};
+
+static const struct mtk_mux top_muxes[] = {
+ /* CLK_CFG_0 */
+ MUX_CLR_SET_UPD(CLK_TOP_AXI_SEL, "axi_sel",
+ axi_parents, 0x010, 0x014, 0x018, 0, 3, 0x04, 0),
+ MUX_CLR_SET_UPD(CLK_TOP_AXI_PERI_SEL, "axi_peri_sel",
+ axi_peri_parents, 0x010, 0x014, 0x018,
+ 8, 2, 0x04, 1),
+ MUX_CLR_SET_UPD(CLK_TOP_AXI_U_SEL, "axi_u_sel",
+ axi_u_parents, 0x010, 0x014, 0x018,
+ 16, 2, 0x04, 2),
+ MUX_CLR_SET_UPD(CLK_TOP_BUS_AXIMEM_SEL, "bus_aximem_sel",
+ bus_aximem_parents, 0x010, 0x014, 0x018,
+ 24, 3, 0x04, 3),
+ /* CLK_CFG_1 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP0_SEL, "disp0_sel",
+ mmsys_parents, 0x020, 0x024, 0x028,
+ 0, 4, 7, 0x04, 4),
+ MUX_CLR_SET_UPD(CLK_TOP_MMINFRA_SEL, "mminfra_sel",
+ mminfra_parents, 0x020, 0x024, 0x028,
+ 8, 4, 0x04, 5),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel",
+ uart_parents, 0x020, 0x024, 0x028,
+ 16, 1, 23, 0x04, 6),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI0_SEL, "spi0_sel",
+ spi_parents, 0x020, 0x024, 0x028,
+ 24, 3, 31, 0x04, 7),
+ /* CLK_CFG_2 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI1_SEL, "spi1_sel",
+ spi_parents, 0x030, 0x034, 0x038,
+ 0, 3, 7, 0x04, 8),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI2_SEL, "spi2_sel",
+ spi_parents, 0x030, 0x034, 0x038,
+ 8, 3, 15, 0x04, 9),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI3_SEL, "spi3_sel",
+ spi_parents, 0x030, 0x034, 0x038,
+ 16, 3, 23, 0x04, 10),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI4_SEL, "spi4_sel",
+ spi_parents, 0x030, 0x034, 0x038,
+ 24, 3, 31, 0x04, 11),
+ /* CLK_CFG_3 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI5_SEL, "spi5_sel",
+ spi_parents, 0x040, 0x044, 0x048,
+ 0, 3, 7, 0x04, 12),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC_MACRO_0P_SEL, "msdc_macro_0p_sel",
+ msdc_macro_p_parents, 0x040, 0x044, 0x048,
+ 8, 2, 15, 0x04, 13),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc5hclk_sel",
+ msdc5hclk_parents, 0x040, 0x044, 0x048,
+ 16, 2, 23, 0x04, 14),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel",
+ msdc50_0_parents, 0x040, 0x044, 0x048,
+ 24, 3, 31, 0x04, 15),
+ /* CLK_CFG_4 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_MSDCFDE_SEL, "aes_msdcfde_sel",
+ aes_msdcfde_parents, 0x050, 0x054, 0x058,
+ 0, 3, 7, 0x04, 16),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC_MACRO_1P_SEL, "msdc_macro_1p_sel",
+ msdc_macro_p_parents, 0x050, 0x054, 0x058,
+ 8, 2, 15, 0x04, 17),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel",
+ msdc30_parents, 0x050, 0x054, 0x058,
+ 16, 3, 23, 0x04, 18),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_HCLK_SEL, "msdc30_1_h_sel",
+ msdc30_h_parents, 0x050, 0x054, 0x058,
+ 24, 2, 31, 0x04, 19),
+ /* CLK_CFG_5 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC_MACRO_2P_SEL, "msdc_macro_2p_sel",
+ msdc_macro_p_parents, 0x060, 0x064, 0x068,
+ 0, 2, 7, 0x04, 20),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel",
+ msdc30_parents, 0x060, 0x064, 0x068,
+ 8, 3, 15, 0x04, 21),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2_HCLK_SEL, "msdc30_2_h_sel",
+ msdc30_h_parents, 0x060, 0x064, 0x068,
+ 16, 2, 23, 0x04, 22),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel",
+ aud_intbus_parents, 0x060, 0x064, 0x068,
+ 24, 2, 31, 0x04, 23),
+ /* CLK_CFG_6 */
+ MUX_CLR_SET_UPD(CLK_TOP_ATB_SEL, "atb_sel",
+ atb_parents, 0x070, 0x074, 0x078, 0, 2, 0x04, 24),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_PWM_SEL, "disp_pwm_sel",
+ disp_pwm_parents, 0x070, 0x074, 0x078,
+ 8, 3, 15, 0x04, 25),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_P0_SEL, "usb_p0_sel",
+ usb_parents, 0x070, 0x074, 0x078,
+ 16, 2, 23, 0x04, 26),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P0_SEL, "ssusb_xhci_p0_sel",
+ usb_parents, 0x070, 0x074, 0x078,
+ 24, 2, 31, 0x04, 27),
+ /* CLK_CFG_7 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_P1_SEL, "usb_p1_sel",
+ usb_parents, 0x080, 0x084, 0x088,
+ 0, 2, 7, 0x04, 28),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P1_SEL, "ssusb_xhci_p1_sel",
+ usb_parents, 0x080, 0x084, 0x088,
+ 8, 2, 15, 0x04, 29),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_P2_SEL, "usb_p2_sel",
+ usb_parents, 0x080, 0x084, 0x088,
+ 16, 2, 23, 0x04, 30),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P2_SEL, "ssusb_xhci_p2_sel",
+ usb_parents, 0x080, 0x084, 0x088,
+ 24, 2, 31, 0x08, 0),
+ /* CLK_CFG_8 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_P3_SEL, "usb_p3_sel",
+ usb_parents, 0x090, 0x094, 0x098,
+ 0, 2, 7, 0x08, 1),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P3_SEL, "ssusb_xhci_p3_sel",
+ usb_parents, 0x090, 0x094, 0x098,
+ 8, 2, 15, 0x08, 2),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_P4_SEL, "usb_p4_sel",
+ usb_parents, 0x090, 0x094, 0x098,
+ 16, 2, 23, 0x08, 3),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P4_SEL, "ssusb_xhci_p4_sel",
+ usb_parents, 0x090, 0x094, 0x098,
+ 24, 2, 31, 0x08, 4),
+ /* CLK_CFG_9 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel",
+ i2c_parents, 0x0a0, 0x0a4, 0x0a8,
+ 0, 2, 7, 0x08, 5),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF_SEL, "seninf_sel",
+ seninf_parents, 0x0a0, 0x0a4, 0x0a8,
+ 8, 3, 15, 0x08, 6),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF1_SEL, "seninf1_sel",
+ seninf_parents, 0x0a0, 0x0a4, 0x0a8,
+ 16, 3, 23, 0x08, 7),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN1_SEL, "aud_engen1_sel",
+ aud_engen1_parents, 0x0a0, 0x0a4, 0x0a8,
+ 24, 2, 31, 0x08, 8),
+ /* CLK_CFG_10 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN2_SEL, "aud_engen2_sel",
+ aud_engen2_parents, 0x0b0, 0x0b4, 0x0b8,
+ 0, 2, 7, 0x08, 9),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_UFSFDE_SEL, "aes_ufsfde_sel",
+ aes_ufsfde_parents, 0x0b0, 0x0b4, 0x0b8,
+ 8, 3, 15, 0x08, 10),
+ MUX_CLR_SET_UPD(CLK_TOP_U_SEL, "ufs_sel",
+ ufs_parents, 0x0b0, 0x0b4, 0x0b8,
+ 16, 3, 0x08, 11),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_U_MBIST_SEL, "ufs_mbist_sel",
+ ufs_mbist_parents, 0x0b0, 0x0b4, 0x0b8,
+ 24, 2, 31, 0x08, 12),
+ /* CLK_CFG_11 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_1_SEL, "aud_1_sel",
+ aud_1_parents, 0x0c0, 0x0c4, 0x0c8,
+ 0, 1, 7, 0x08, 13),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_2_SEL, "aud_2_sel",
+ aud_2_parents, 0x0c0, 0x0c4, 0x0c8,
+ 8, 1, 15, 0x08, 14),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_VENC_SEL, "venc_sel",
+ venc_parents, 0x0c0, 0x0c4, 0x0c8,
+ 16, 4, 23, 0x08, 15),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_VDEC_SEL, "vdec_sel",
+ vdec_parents, 0x0c0, 0x0c4, 0x0c8,
+ 24, 4, 31, 0x08, 16),
+ /* CLK_CFG_12 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel",
+ pwm_parents, 0x0d0, 0x0d4, 0x0d8,
+ 0, 1, 7, 0x08, 17),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_H_SEL, "audio_h_sel",
+ audio_h_parents, 0x0d0, 0x0d4, 0x0d8,
+ 8, 2, 15, 0x08, 18),
+ MUX_CLR_SET_UPD(CLK_TOP_MCUPM_SEL, "mcupm_sel",
+ mcupm_parents, 0x0d0, 0x0d4, 0x0d8,
+ 16, 2, 0x08, 19),
+ MUX_CLR_SET_UPD(CLK_TOP_MEM_SUB_SEL, "mem_sub_sel",
+ mem_sub_parents, 0x0d0, 0x0d4, 0x0d8,
+ 24, 4, 0x08, 20),
+ /* CLK_CFG_13 */
+ MUX_CLR_SET_UPD(CLK_TOP_MEM_SUB_PERI_SEL, "mem_sub_peri_sel",
+ mem_sub_peri_u_parents, 0x0e0, 0x0e4, 0x0e8,
+ 0, 3, 0x08, 21),
+ MUX_CLR_SET_UPD(CLK_TOP_MEM_SUB_U_SEL, "mem_sub_u_sel",
+ mem_sub_peri_u_parents, 0x0e0, 0x0e4, 0x0e8,
+ 8, 3, 0x08, 22),
+ MUX_CLR_SET_UPD(CLK_TOP_EMI_N_SEL, "emi_n_sel",
+ emi_n_parents, 0x0e0, 0x0e4, 0x0e8,
+ 16, 3, 0x08, 23),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DSI_OCC_SEL, "dsi_occ_sel",
+ dsi_occ_parents, 0x0e0, 0x0e4, 0x0e8,
+ 24, 2, 31, 0x08, 24),
+ /* CLK_CFG_14 */
+ MUX_CLR_SET_UPD(CLK_TOP_AP2CONN_HOST_SEL, "ap2conn_host_sel",
+ ap2conn_host_parents, 0x0f0, 0x0f4, 0x0f8,
+ 0, 1, 0x08, 25),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_IMG1_SEL, "img1_sel",
+ img1_parents, 0x0f0, 0x0f4, 0x0f8,
+ 8, 4, 15, 0x08, 26),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_IPE_SEL, "ipe_sel",
+ ipe_parents, 0x0f0, 0x0f4, 0x0f8,
+ 16, 4, 23, 0x08, 27),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_CAM_SEL, "cam_sel",
+ cam_parents, 0x0f0, 0x0f4, 0x0f8,
+ 24, 4, 31, 0x08, 28),
+ /* CLK_CFG_15 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM_SEL, "camtm_sel",
+ camtm_parents, 0x100, 0x104, 0x108,
+ 0, 2, 7, 0x08, 29),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP_SEL, "dsp_sel",
+ dsp_parents, 0x100, 0x104, 0x108,
+ 8, 3, 15, 0x08, 30),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SR_PKA_SEL, "sr_pka_sel",
+ sr_pka_parents, 0x100, 0x104, 0x108,
+ 16, 3, 23, 0x0c, 0),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DXCC_SEL, "dxcc_sel",
+ dxcc_parents, 0x100, 0x104, 0x108,
+ 24, 2, 31, 0x0c, 1),
+ /* CLK_CFG_16 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG_REF_SEL, "mfg_ref_sel",
+ mfg_ref_parents, 0x110, 0x114, 0x118,
+ 0, 2, 7, 0x0c, 2),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MDP0_SEL, "mdp0_sel",
+ mmsys_parents, 0x110, 0x114, 0x118,
+ 8, 4, 15, 0x0c, 3),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_DP_SEL, "dp_sel",
+ dp_parents, 0x110, 0x114, 0x118,
+ 16, 3, 23, 0x0c, 4),
+ MUX_CLR_SET_UPD(CLK_TOP_EDP_SEL, "edp_sel",
+ edp_parents, 0x110, 0x114, 0x118,
+ 24, 3, 0x0c, 5),
+ /* CLK_CFG_17 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_EDP_FAVT_SEL, "edp_favt_sel",
+ edp_parents, 0x180, 0x184, 0x188,
+ 0, 3, 7, 0x0c, 6),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_250M_SEL, "snps_eth_250m_sel",
+ snps_eth_250m_parents, 0x180, 0x184, 0x188,
+ 8, 1, 15, 0x0c, 7),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_62P4M_PTP_SEL,
+ "snps_eth_62p4m_ptp_sel",
+ snps_eth_62p4m_ptp_parents,
+ 0x180, 0x184, 0x188, 16, 2, 23, 0x0c, 8),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_50M_RMII_SEL,
+ "snps_eth_50m_rmii_sel",
+ snps_eth_50m_rmii_parents,
+ 0x180, 0x184, 0x188, 24, 1, 31, 0x0c, 9),
+ /* CLK_CFG_18 */
+ MUX_CLR_SET_UPD(CLK_TOP_SFLASH_SEL, "sflash_sel",
+ sflash_parents, 0x190, 0x194, 0x198,
+ 0, 3, 0x0c, 10),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_GCPU_SEL, "gcpu_sel",
+ gcpu_parents, 0x190, 0x194, 0x198,
+ 8, 3, 15, 0x0c, 11),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_MAC_TL_SEL, "pcie_mac_tl_sel",
+ pcie_mac_tl_parents, 0x190, 0x194, 0x198,
+ 16, 2, 23, 0x0c, 12),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_VDSTX_DG_CTS_SEL, "vdstx_dg_cts_sel",
+ vdstx_dg_cts_parents, 0x190, 0x194, 0x198,
+ 24, 2, 31, 0x0c, 13),
+ /* CLK_CFG_19 */
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_PLL_DPIX_SEL, "pll_dpix_sel",
+ pll_dpix_parents, 0x240, 0x244, 0x248,
+ 0, 2, 7, 0x0c, 14),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_ECC_SEL, "ecc_sel",
+ ecc_parents, 0x240, 0x244, 0x248,
+ 8, 3, 15, 0x0c, 15),
+ /* CLK_MISC_CFG_3 */
+ GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MFG_SEL_MFGPLL, "mfg_sel_mfgpll",
+ mfg_sel_mfgpll_parents,
+ 0x510, 0x514, 0x0518, 16, 1, 0, -1, -1,
+ CLK_SET_RATE_PARENT,
+ mtk_mux_clr_set_upd_ops)
+};
+
+static const struct mtk_composite top_composites[] = {
+ /* CLK_AUDDIV_0 */
+ MUX(CLK_TOP_APLL_I2SIN0_MCK_SEL, "apll_i2sin0_m_sel",
+ apll_m_parents, 0x0320, 16, 1),
+ MUX(CLK_TOP_APLL_I2SIN1_MCK_SEL, "apll_i2sin1_m_sel",
+ apll_m_parents, 0x0320, 17, 1),
+ MUX(CLK_TOP_APLL_I2SIN2_MCK_SEL, "apll_i2sin2_m_sel",
+ apll_m_parents, 0x0320, 18, 1),
+ MUX(CLK_TOP_APLL_I2SIN3_MCK_SEL, "apll_i2sin3_m_sel",
+ apll_m_parents, 0x0320, 19, 1),
+ MUX(CLK_TOP_APLL_I2SIN4_MCK_SEL, "apll_i2sin4_m_sel",
+ apll_m_parents, 0x0320, 20, 1),
+ MUX(CLK_TOP_APLL_I2SIN6_MCK_SEL, "apll_i2sin6_m_sel",
+ apll_m_parents, 0x0320, 21, 1),
+ MUX(CLK_TOP_APLL_I2SOUT0_MCK_SEL, "apll_i2sout0_m_sel",
+ apll_m_parents, 0x0320, 22, 1),
+ MUX(CLK_TOP_APLL_I2SOUT1_MCK_SEL, "apll_i2sout1_m_sel",
+ apll_m_parents, 0x0320, 23, 1),
+ MUX(CLK_TOP_APLL_I2SOUT2_MCK_SEL, "apll_i2sout2_m_sel",
+ apll_m_parents, 0x0320, 24, 1),
+ MUX(CLK_TOP_APLL_I2SOUT3_MCK_SEL, "apll_i2sout3_m_sel",
+ apll_m_parents, 0x0320, 25, 1),
+ MUX(CLK_TOP_APLL_I2SOUT4_MCK_SEL, "apll_i2sout4_m_sel",
+ apll_m_parents, 0x0320, 26, 1),
+ MUX(CLK_TOP_APLL_I2SOUT6_MCK_SEL, "apll_i2sout6_m_sel",
+ apll_m_parents, 0x0320, 27, 1),
+ MUX(CLK_TOP_APLL_FMI2S_MCK_SEL, "apll_fmi2s_m_sel",
+ apll_m_parents, 0x0320, 28, 1),
+ MUX(CLK_TOP_APLL_TDMOUT_MCK_SEL, "apll_tdmout_m_sel",
+ apll_m_parents, 0x0320, 29, 1),
+ /* CLK_AUDDIV_2 */
+ DIV_GATE(CLK_TOP_APLL12_CK_DIV_I2SIN0, "apll12_div_i2sin0",
+ "apll_i2sin0_m_sel", 0x0320, 0, 0x0328, 8, 0),
+ DIV_GATE(CLK_TOP_APLL12_CK_DIV_I2SIN1, "apll12_div_i2sin1",
+ "apll_i2sin1_m_sel", 0x0320, 1, 0x0328, 8, 8),
+ /* CLK_AUDDIV_3 */
+ DIV_GATE(CLK_TOP_APLL12_CK_DIV_I2SOUT0, "apll12_div_i2sout0",
+ "apll_i2sout0_m_sel", 0x0320, 6, 0x0334, 8, 16),
+ DIV_GATE(CLK_TOP_APLL12_CK_DIV_I2SOUT1, "apll12_div_i2sout1",
+ "apll_i2sout1_m_sel", 0x0320, 7, 0x0334, 8, 24),
+ /* CLK_AUDDIV_5 */
+ DIV_GATE(CLK_TOP_APLL12_CK_DIV_FMI2S, "apll12_div_fmi2s",
+ "apll_fmi2s_m_sel", 0x0320, 12, 0x033c, 8, 0),
+ DIV_GATE(CLK_TOP_APLL12_CK_DIV_TDMOUT_M, "apll12_div_tdmout_m",
+ "apll_tdmout_m_sel", 0x0320, 13, 0x033c, 8, 8),
+ DIV_GATE(CLK_TOP_APLL12_CK_DIV_TDMOUT_B, "apll12_div_tdmout_b",
+ "apll12_div_tdmout_m", 0x0320, 14, 0x033c, 8, 16),
+};
+
+static const struct mtk_gate_regs top_cg_regs = {
+ .set_ofs = 0x514,
+ .clr_ofs = 0x518,
+ .sta_ofs = 0x510,
+};
+
+#define GATE_TOP_FLAGS(_id, _name, _parent, _shift, _flag) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &top_cg_regs, \
+ .shift = _shift, \
+ .flags = _flag, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+#define GATE_TOP(_id, _name, _parent, _shift) \
+ GATE_TOP_FLAGS(_id, _name, _parent, _shift, 0)
+
+static const struct mtk_gate top_clks[] = {
+ GATE_TOP_FLAGS(CLK_TOP_FMCNT_P0_EN, "fmcnt_p0_en", "univpll_192m_d4", 0, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_FMCNT_P1_EN, "fmcnt_p1_en", "univpll_192m_d4", 1, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_FMCNT_P2_EN, "fmcnt_p2_en", "univpll_192m_d4", 2, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_FMCNT_P3_EN, "fmcnt_p3_en", "univpll_192m_d4", 3, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_FMCNT_P4_EN, "fmcnt_p4_en", "univpll_192m_d4", 4, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_USB_F26M_CK_EN, "ssusb_f26m", "clk26m", 5, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_SSPXTP_F26M_CK_EN, "sspxtp_f26m", "clk26m", 6, CLK_IS_CRITICAL),
+ GATE_TOP(CLK_TOP_USB2_PHY_RF_P0_EN, "usb2_phy_rf_p0_en", "ssusb_f26m", 7),
+ GATE_TOP(CLK_TOP_USB2_PHY_RF_P1_EN, "usb2_phy_rf_p1_en", "ssusb_f26m", 10),
+ GATE_TOP(CLK_TOP_USB2_PHY_RF_P2_EN, "usb2_phy_rf_p2_en", "ssusb_f26m", 11),
+ GATE_TOP(CLK_TOP_USB2_PHY_RF_P3_EN, "usb2_phy_rf_p3_en", "ssusb_f26m", 12),
+ GATE_TOP(CLK_TOP_USB2_PHY_RF_P4_EN, "usb2_phy_rf_p4_en", "ssusb_f26m", 13),
+ GATE_TOP_FLAGS(CLK_TOP_USB2_26M_CK_P0_EN, "usb2_26m_p0_en", "ssusb_f26m", 14, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_USB2_26M_CK_P1_EN, "usb2_26m_p1_en", "ssusb_f26m", 15, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_USB2_26M_CK_P2_EN, "usb2_26m_p2_en", "ssusb_f26m", 18, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_USB2_26M_CK_P3_EN, "usb2_26m_p3_en", "ssusb_f26m", 19, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_USB2_26M_CK_P4_EN, "usb2_26m_p4_en", "ssusb_f26m", 20, CLK_IS_CRITICAL),
+ GATE_TOP(CLK_TOP_F26M_CK_EN, "pcie_f26m", "sspxtp_f26m", 21),
+ GATE_TOP_FLAGS(CLK_TOP_AP2CON_EN, "ap2con", "clk26m", 24, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_EINT_N_EN, "eint_n", "clk26m", 25, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_TOPCKGEN_FMIPI_CSI_UP26M_CK_EN,
+ "fmipi_csi_up26m", "osc_d10", 26, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_EINT_E_EN, "eint_e", "clk26m", 28, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_EINT_W_EN, "eint_w", "clk26m", 30, CLK_IS_CRITICAL),
+ GATE_TOP_FLAGS(CLK_TOP_EINT_S_EN, "eint_s", "clk26m", 31, CLK_IS_CRITICAL),
+};
+
+/* Register mux notifier for MFG mux */
+static int clk_mt8189_reg_mfg_mux_notifier(struct device *dev,
+ struct clk *clk)
+{
+ struct mtk_mux_nb *mfg_mux_nb;
+
+ mfg_mux_nb = devm_kzalloc(dev, sizeof(*mfg_mux_nb), GFP_KERNEL);
+ if (!mfg_mux_nb)
+ return -ENOMEM;
+
+ mfg_mux_nb->ops = &mtk_mux_clr_set_upd_ops;
+ mfg_mux_nb->bypass_index = 0; /* Bypass to CLK_TOP_MFG_REF_SEL */
+
+ return devm_mtk_clk_mux_notifier_register(dev, clk, mfg_mux_nb);
+}
+
+static const struct mtk_clk_desc topck_desc = {
+ .factor_clks = top_divs,
+ .num_factor_clks = ARRAY_SIZE(top_divs),
+ .mux_clks = top_muxes,
+ .num_mux_clks = ARRAY_SIZE(top_muxes),
+ .composite_clks = top_composites,
+ .num_composite_clks = ARRAY_SIZE(top_composites),
+ .clks = top_clks,
+ .num_clks = ARRAY_SIZE(top_clks),
+ .clk_notifier_func = clk_mt8189_reg_mfg_mux_notifier,
+ .mfg_clk_idx = CLK_TOP_MFG_SEL_MFGPLL,
+ .clk_lock = &mt8189_clk_lock,
+};
+
+static const struct of_device_id of_match_clk_mt8189_topck[] = {
+ { .compatible = "mediatek,mt8189-topckgen", .data = &topck_desc },
+ { /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8189_topck_drv = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt8189-topck",
+ .of_match_table = of_match_clk_mt8189_topck,
+ },
+};
+module_platform_driver(clk_mt8189_topck_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8189 topckgen clocks driver");
+MODULE_LICENSE("GPL");
--
2.54.0
^ permalink raw reply related
* [PATCH 08/15] clk: mediatek: Add MT8189 vlpckgen clock support
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
Edward-JW Yang, Richard Cochran
Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>
Add support for the MT8189 vlpckgen clock controller, which provides
muxes and dividers for clock selection in vlp domain for other IP blocks.
Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
drivers/clk/mediatek/Makefile | 3 +-
drivers/clk/mediatek/clk-mt8189-vlpckgen.c | 284 +++++++++++++++++++++++++++++
2 files changed, 286 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 9d3d2983bfb2..3b25df9e7b50 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -123,7 +123,8 @@ obj-$(CONFIG_COMMON_CLK_MT8188_VDOSYS) += clk-mt8188-vdo0.o clk-mt8188-vdo1.o
obj-$(CONFIG_COMMON_CLK_MT8188_VENCSYS) += clk-mt8188-venc.o
obj-$(CONFIG_COMMON_CLK_MT8188_VPPSYS) += clk-mt8188-vpp0.o clk-mt8188-vpp1.o
obj-$(CONFIG_COMMON_CLK_MT8188_WPESYS) += clk-mt8188-wpe.o
-obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o clk-mt8189-topckgen.o
+obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o clk-mt8189-topckgen.o \
+ clk-mt8189-vlpckgen.o
obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8189-vlpckgen.c b/drivers/clk/mediatek/clk-mt8189-vlpckgen.c
new file mode 100644
index 000000000000..39ca051b9ef8
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8189-vlpckgen.c
@@ -0,0 +1,284 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ * Qiqi Wang <qiqi.wang@mediatek.com>
+ * Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ * Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+#include "clk-mux.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mediatek,mt8189-clk.h>
+
+static DEFINE_SPINLOCK(mt8189_vlpclk_lock);
+
+static const char * const vlp_26m_oscd10_parents[] = {
+ "clk26m",
+ "osc_d10"
+};
+
+static const char * const vlp_vadsp_vowpll_parents[] = {
+ "clk26m",
+ "vowpll"
+};
+
+static const char * const vlp_sspm_ulposc_parents[] = {
+ "ulposc",
+ "univpll_d5_d2",
+ "osc_d10"
+};
+
+static const char * const vlp_aud_adc_parents[] = {
+ "clk26m",
+ "vowpll",
+ "aud_adc_ext",
+ "osc_d10"
+};
+
+static const char * const vlp_scp_iic_spi_parents[] = {
+ "clk26m",
+ "mainpll_d5_d4",
+ "mainpll_d7_d2",
+ "osc_d10"
+};
+
+static const char * const vlp_vadsp_uarthub_b_parents[] = {
+ "clk26m",
+ "osc_d10",
+ "univpll_d6_d4",
+ "univpll_d6_d2"
+};
+
+static const char * const vlp_axi_kp_parents[] = {
+ "clk26m",
+ "osc_d10",
+ "osc_d2",
+ "mainpll_d7_d4",
+ "mainpll_d7_d2"
+};
+
+static const char * const vlp_sspm_parents[] = {
+ "clk26m",
+ "osc_d10",
+ "mainpll_d5_d2",
+ "ulposc",
+ "mainpll_d6"
+};
+
+static const char * const vlp_pwm_vlp_parents[] = {
+ "clk26m",
+ "osc_d4",
+ "clk32k",
+ "osc_d10",
+ "mainpll_d4_d8"
+};
+
+static const char * const vlp_pwrap_ulposc_parents[] = {
+ "clk26m",
+ "osc_d10",
+ "osc_d7",
+ "osc_d8",
+ "osc_d16",
+ "mainpll_d7_d8"
+};
+
+static const char * const vlp_vadsp_parents[] = {
+ "clk26m",
+ "osc_d20",
+ "osc_d10",
+ "osc_d2",
+ "ulposc",
+ "mainpll_d4_d2"
+};
+
+static const char * const vlp_scp_parents[] = {
+ "clk26m",
+ "univpll_d4",
+ "univpll_d3",
+ "mainpll_d3",
+ "univpll_d6",
+ "apll1",
+ "mainpll_d4",
+ "mainpll_d6",
+ "mainpll_d7",
+ "osc_d10"
+};
+
+static const char * const vlp_spmi_p_parents[] = {
+ "clk26m",
+ "f26m_d2",
+ "osc_d8",
+ "osc_d10",
+ "osc_d16",
+ "osc_d7",
+ "clk32k",
+ "mainpll_d7_d8",
+ "mainpll_d6_d8",
+ "mainpll_d5_d8"
+};
+
+static const char * const vlp_camtg_parents[] = {
+ "clk26m",
+ "univpll_192m_d8",
+ "univpll_d6_d8",
+ "univpll_192m_d4",
+ "osc_d16",
+ "osc_d20",
+ "osc_d10",
+ "univpll_d6_d16",
+ "tvdpll1_d16",
+ "f26m_d2",
+ "univpll_192m_d10",
+ "univpll_192m_d16",
+ "univpll_192m_d32"
+};
+
+static const struct mtk_mux vlp_ck_muxes[] = {
+ /* VLP_CLK_CFG_0 */
+ MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_SCP_SEL, "vlp_scp_sel",
+ vlp_scp_parents, 0x008, 0x00c, 0x010,
+ 0, 4, 7, 0x04, 0),
+ MUX_CLR_SET_UPD(CLK_VLP_CK_PWRAP_ULPOSC_SEL, "vlp_pwrap_ulposc_sel",
+ vlp_pwrap_ulposc_parents, 0x008, 0x00c, 0x010,
+ 8, 3, 0x04, 1),
+ MUX_CLR_SET_UPD(CLK_VLP_CK_SPMI_P_MST_SEL, "vlp_spmi_p_sel",
+ vlp_spmi_p_parents, 0x008, 0x00c, 0x010,
+ 16, 4, 0x04, 2),
+ MUX_CLR_SET_UPD(CLK_VLP_CK_DVFSRC_SEL, "vlp_dvfsrc_sel",
+ vlp_26m_oscd10_parents, 0x008, 0x00c, 0x010,
+ 24, 1, 0x04, 3),
+ /* VLP_CLK_CFG_1 */
+ MUX_CLR_SET_UPD(CLK_VLP_CK_PWM_VLP_SEL, "vlp_pwm_vlp_sel",
+ vlp_pwm_vlp_parents, 0x014, 0x018, 0x01c,
+ 0, 3, 0x04, 4),
+ MUX_CLR_SET_UPD(CLK_VLP_CK_AXI_VLP_SEL, "vlp_axi_vlp_sel",
+ vlp_axi_kp_parents, 0x014, 0x018, 0x01c,
+ 8, 3, 0x04, 5),
+ MUX_CLR_SET_UPD(CLK_VLP_CK_SYSTIMER_26M_SEL, "vlp_timer_26m_sel",
+ vlp_26m_oscd10_parents, 0x014, 0x018, 0x01c,
+ 16, 1, 0x04, 6),
+ MUX_CLR_SET_UPD(CLK_VLP_CK_SSPM_SEL, "vlp_sspm_sel",
+ vlp_sspm_parents, 0x014, 0x018, 0x01c,
+ 24, 3, 0x04, 7),
+ /* VLP_CLK_CFG_2 */
+ MUX_CLR_SET_UPD(CLK_VLP_CK_SSPM_F26M_SEL, "vlp_sspm_f26m_sel",
+ vlp_26m_oscd10_parents, 0x020, 0x024, 0x028,
+ 0, 1, 0x04, 8),
+ MUX_CLR_SET_UPD(CLK_VLP_CK_SRCK_SEL, "vlp_srck_sel",
+ vlp_26m_oscd10_parents, 0x020, 0x024, 0x028,
+ 8, 1, 0x04, 9),
+ MUX_CLR_SET_UPD(CLK_VLP_CK_SCP_SPI_SEL, "vlp_scp_spi_sel",
+ vlp_scp_iic_spi_parents, 0x020, 0x024, 0x028,
+ 16, 2, 0x04, 10),
+ MUX_CLR_SET_UPD(CLK_VLP_CK_SCP_IIC_SEL, "vlp_scp_iic_sel",
+ vlp_scp_iic_spi_parents, 0x020, 0x024, 0x028,
+ 24, 2, 0x04, 11),
+ /* VLP_CLK_CFG_3 */
+ MUX_CLR_SET_UPD(CLK_VLP_CK_SCP_SPI_HIGH_SPD_SEL,
+ "vlp_scp_spi_hs_sel",
+ vlp_scp_iic_spi_parents, 0x02c, 0x030, 0x034,
+ 0, 2, 0x04, 12),
+ MUX_CLR_SET_UPD(CLK_VLP_CK_SCP_IIC_HIGH_SPD_SEL,
+ "vlp_scp_iic_hs_sel",
+ vlp_scp_iic_spi_parents, 0x02c, 0x030, 0x034,
+ 8, 2, 0x04, 13),
+ MUX_CLR_SET_UPD(CLK_VLP_CK_SSPM_ULPOSC_SEL, "vlp_sspm_ulposc_sel",
+ vlp_sspm_ulposc_parents, 0x02c, 0x030, 0x034,
+ 16, 2, 0x04, 14),
+ MUX_CLR_SET_UPD(CLK_VLP_CK_APXGPT_26M_SEL, "vlp_apxgpt_26m_sel",
+ vlp_26m_oscd10_parents, 0x02c, 0x030, 0x034,
+ 24, 1, 0x04, 15),
+ /* VLP_CLK_CFG_4 */
+ MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_VADSP_SEL, "vlp_vadsp_sel",
+ vlp_vadsp_parents, 0x038, 0x03c, 0x040,
+ 0, 3, 7, 0x04, 16),
+ MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_VADSP_VOWPLL_SEL,
+ "vlp_vadsp_vowpll_sel",
+ vlp_vadsp_vowpll_parents, 0x038, 0x03c, 0x040,
+ 8, 1, 15, 0x04, 17),
+ MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_VADSP_UARTHUB_BCLK_SEL,
+ "vlp_vadsp_uarthub_b_sel",
+ vlp_vadsp_uarthub_b_parents,
+ 0x038, 0x03c, 0x040, 16, 2, 23, 0x04, 18),
+ MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_CAMTG0_SEL, "vlp_camtg0_sel",
+ vlp_camtg_parents, 0x038, 0x03c, 0x040,
+ 24, 4, 31, 0x04, 19),
+ /* VLP_CLK_CFG_5 */
+ MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_CAMTG1_SEL, "vlp_camtg1_sel",
+ vlp_camtg_parents, 0x044, 0x048, 0x04c,
+ 0, 4, 7, 0x04, 20),
+ MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_CAMTG2_SEL, "vlp_camtg2_sel",
+ vlp_camtg_parents, 0x044, 0x048, 0x04c,
+ 8, 4, 15, 0x04, 21),
+ MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_AUD_ADC_SEL, "vlp_aud_adc_sel",
+ vlp_aud_adc_parents, 0x044, 0x048, 0x04c,
+ 16, 2, 23, 0x04, 22),
+ MUX_GATE_CLR_SET_UPD(CLK_VLP_CK_KP_IRQ_GEN_SEL, "vlp_kp_irq_sel",
+ vlp_axi_kp_parents, 0x044, 0x048, 0x04c,
+ 24, 3, 31, 0x04, 23),
+};
+
+static const struct mtk_gate_regs vlp_ck_cg_regs = {
+ .set_ofs = 0x1f4,
+ .clr_ofs = 0x1f8,
+ .sta_ofs = 0x1f0,
+};
+
+#define GATE_VLP_CK_FLAGS(_id, _name, _parent, _shift, _flag) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &vlp_ck_cg_regs, \
+ .shift = _shift, \
+ .flags = _flag, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+#define GATE_VLP_CK(_id, _name, _parent, _shift) \
+ GATE_VLP_CK_FLAGS(_id, _name, _parent, _shift, 0)
+
+static const struct mtk_gate vlp_ck_clks[] = {
+ GATE_VLP_CK(CLK_VLP_CK_VADSYS_VLP_26M_EN, "vlp_vadsys_vlp_26m", "clk26m", 1),
+ GATE_VLP_CK_FLAGS(CLK_VLP_CK_FMIPI_CSI_UP26M_CK_EN, "vlp_fmipi_csi_up26m",
+ "fmipi_csi_up26m", 11, CLK_IS_CRITICAL),
+};
+
+static const struct mtk_clk_desc vlpck_desc = {
+ .mux_clks = vlp_ck_muxes,
+ .num_mux_clks = ARRAY_SIZE(vlp_ck_muxes),
+ .clks = vlp_ck_clks,
+ .num_clks = ARRAY_SIZE(vlp_ck_clks),
+ .clk_lock = &mt8189_vlpclk_lock,
+};
+
+static const struct of_device_id of_match_clk_mt8189_vlpck[] = {
+ { .compatible = "mediatek,mt8189-vlpckgen", .data = &vlpck_desc },
+ { /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8189_vlpck_drv = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt8189-vlpck",
+ .of_match_table = of_match_clk_mt8189_vlpck,
+ },
+};
+module_platform_driver(clk_mt8189_vlpck_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8189 vlpckgen clocks driver");
+MODULE_LICENSE("GPL");
--
2.54.0
^ permalink raw reply related
* [PATCH 09/15] clk: mediatek: Add MT8189 vlpcfg clock support
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
Edward-JW Yang, Richard Cochran
Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>
Add support for the MT8189 vlpcfg clock controller,
which provides clock gate control for vlp domain IPs.
Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
drivers/clk/mediatek/Makefile | 2 +-
drivers/clk/mediatek/clk-mt8189-vlpcfg.c | 115 +++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 3b25df9e7b50..d9279b237b7b 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -124,7 +124,7 @@ obj-$(CONFIG_COMMON_CLK_MT8188_VENCSYS) += clk-mt8188-venc.o
obj-$(CONFIG_COMMON_CLK_MT8188_VPPSYS) += clk-mt8188-vpp0.o clk-mt8188-vpp1.o
obj-$(CONFIG_COMMON_CLK_MT8188_WPESYS) += clk-mt8188-wpe.o
obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o clk-mt8189-topckgen.o \
- clk-mt8189-vlpckgen.o
+ clk-mt8189-vlpckgen.o clk-mt8189-vlpcfg.o
obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8189-vlpcfg.c b/drivers/clk/mediatek/clk-mt8189-vlpcfg.c
new file mode 100644
index 000000000000..81e2d44bd320
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8189-vlpcfg.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ * Qiqi Wang <qiqi.wang@mediatek.com>
+ * Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ * Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mediatek,mt8189-clk.h>
+
+static const struct mtk_gate_regs vlpcfg_ao_reg_cg_regs = {
+ .set_ofs = 0x0,
+ .clr_ofs = 0x0,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_VLPCFG_AO_REG(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &vlpcfg_ao_reg_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr)
+
+static const struct mtk_gate vlpcfg_ao_reg_clks[] = {
+ GATE_VLPCFG_AO_REG(CLK_VLPCFG_AO_APEINT_RX, "vlpcfg_ao_apeint_rx", "clk26m", 8),
+};
+
+static const struct mtk_clk_desc vlpcfg_ao_reg_mcd = {
+ .clks = vlpcfg_ao_reg_clks,
+ .num_clks = ARRAY_SIZE(vlpcfg_ao_reg_clks),
+};
+
+static const struct mtk_gate_regs vlpcfg_reg_cg_regs = {
+ .set_ofs = 0x4,
+ .clr_ofs = 0x4,
+ .sta_ofs = 0x4,
+};
+
+#define GATE_VLPCFG_REG_FLAGS(_id, _name, _parent, _shift, _flags) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &vlpcfg_reg_cg_regs, _shift, \
+ &mtk_clk_gate_ops_no_setclr_inv, _flags)
+
+#define GATE_VLPCFG_REG(_id, _name, _parent, _shift) \
+ GATE_VLPCFG_REG_FLAGS(_id, _name, _parent, _shift, 0)
+
+static const struct mtk_gate vlpcfg_reg_clks[] = {
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SCP, "vlpcfg_scp",
+ "vlp_scp_sel", 28, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_RG_R_APXGPT_26M, "vlpcfg_r_apxgpt_26m",
+ "clk26m", 24, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_DPMSRCK_TEST, "vlpcfg_dpmsrck_test",
+ "clk26m", 23, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_RG_DPMSRRTC_TEST, "vlpcfg_dpmsrrtc_test",
+ "clk32k", 22, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_DPMSRULP_TEST, "vlpcfg_dpmsrulp_test",
+ "osc_d10", 21, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SPMI_P_MST, "vlpcfg_spmi_p",
+ "vlp_spmi_p_sel", 20, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SPMI_P_MST_32K, "vlpcfg_spmi_p_32k",
+ "clk32k", 18, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_PMIF_SPMI_P_SYS, "vlpcfg_pmif_spmi_p_sys",
+ "vlp_pwrap_ulposc_sel", 13, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_PMIF_SPMI_P_TMR, "vlpcfg_pmif_spmi_p_tmr",
+ "vlp_pwrap_ulposc_sel", 12, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG(CLK_VLPCFG_REG_PMIF_SPMI_M_SYS, "vlpcfg_pmif_spmi_m_sys",
+ "vlp_pwrap_ulposc_sel", 11),
+ GATE_VLPCFG_REG(CLK_VLPCFG_REG_PMIF_SPMI_M_TMR, "vlpcfg_pmif_spmi_m_tmr",
+ "vlp_pwrap_ulposc_sel", 10),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_DVFSRC, "vlpcfg_dvfsrc",
+ "vlp_dvfsrc_sel", 9, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_PWM_VLP, "vlpcfg_pwm_vlp",
+ "vlp_pwm_vlp_sel", 8, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SRCK, "vlpcfg_srck",
+ "vlp_srck_sel", 7, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SSPM_F26M, "vlpcfg_sspm_f26m",
+ "vlp_sspm_f26m_sel", 4, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SSPM_F32K, "vlpcfg_sspm_f32k",
+ "clk32k", 3, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SSPM_ULPOSC, "vlpcfg_sspm_ulposc",
+ "vlp_sspm_ulposc_sel", 2, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_VLP_32K_COM, "vlpcfg_vlp_32k_com",
+ "clk32k", 1, CLK_IS_CRITICAL),
+ GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_VLP_26M_COM, "vlpcfg_vlp_26m_com",
+ "clk26m", 0, CLK_IS_CRITICAL),
+};
+
+static const struct mtk_clk_desc vlpcfg_reg_mcd = {
+ .clks = vlpcfg_reg_clks,
+ .num_clks = ARRAY_SIZE(vlpcfg_reg_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8189_vlpcfg[] = {
+ { .compatible = "mediatek,mt8189-vlpcfg", .data = &vlpcfg_reg_mcd },
+ { .compatible = "mediatek,mt8189-vlpcfg-ao", .data = &vlpcfg_ao_reg_mcd },
+ { /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8189_vlpcfg_drv = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt8189-vlpcfg",
+ .of_match_table = of_match_clk_mt8189_vlpcfg,
+ },
+};
+module_platform_driver(clk_mt8189_vlpcfg_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8189 vlpcfg clocks driver");
+MODULE_LICENSE("GPL");
--
2.54.0
^ permalink raw reply related
* [PATCH 10/15] clk: mediatek: Add MT8189 bus clock support
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
Edward-JW Yang, Richard Cochran
Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>
Add support for the MT8189 bus clock controller,
which provides clock gate control for infra/peri IPs
(such as spi, uart, msdc, flashif ...).
Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
drivers/clk/mediatek/Kconfig | 11 ++
drivers/clk/mediatek/Makefile | 1 +
drivers/clk/mediatek/clk-mt8189-bus.c | 200 ++++++++++++++++++++++++++++++++++
3 files changed, 212 insertions(+)
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index f67dfb6cd019..8eba45f05968 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -828,6 +828,17 @@ config COMMON_CLK_MT8189
with the MediaTek MT8189 hardware capabilities, providing efficient management of
clock speeds and power consumption.
+config COMMON_CLK_MT8189_BUS
+ tristate "Clock driver for MediaTek MT8189 bus"
+ depends on COMMON_CLK_MT8189
+ default COMMON_CLK_MT8189
+ help
+ Enable this configuration option to support the clock framework for
+ MediaTek MT8189 SoC bus clocks. It includes the necessary clock
+ management for bus-related peripherals and interconnects within the
+ MT8189 chipset, ensuring that all bus-related components receive the
+ correct clock signals for optimal performance.
+
config COMMON_CLK_MT8192
tristate "Clock driver for MediaTek MT8192"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index d9279b237b7b..aabfb42cb1b2 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -125,6 +125,7 @@ obj-$(CONFIG_COMMON_CLK_MT8188_VPPSYS) += clk-mt8188-vpp0.o clk-mt8188-vpp1.o
obj-$(CONFIG_COMMON_CLK_MT8188_WPESYS) += clk-mt8188-wpe.o
obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o clk-mt8189-topckgen.o \
clk-mt8189-vlpckgen.o clk-mt8189-vlpcfg.o
+obj-$(CONFIG_COMMON_CLK_MT8189_BUS) += clk-mt8189-bus.o
obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8189-bus.c b/drivers/clk/mediatek/clk-mt8189-bus.c
new file mode 100644
index 000000000000..494f25e85d11
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8189-bus.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ * Qiqi Wang <qiqi.wang@mediatek.com>
+ * Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ * Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mediatek,mt8189-clk.h>
+
+static const struct mtk_gate_regs ifrao0_cg_regs = {
+ .set_ofs = 0x80,
+ .clr_ofs = 0x84,
+ .sta_ofs = 0x90,
+};
+
+static const struct mtk_gate_regs ifrao1_cg_regs = {
+ .set_ofs = 0x88,
+ .clr_ofs = 0x8c,
+ .sta_ofs = 0x94,
+};
+
+static const struct mtk_gate_regs ifrao2_cg_regs = {
+ .set_ofs = 0xa4,
+ .clr_ofs = 0xa8,
+ .sta_ofs = 0xac,
+};
+
+#define GATE_IFRAO0(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &ifrao0_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+#define GATE_IFRAO1(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &ifrao1_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+#define GATE_IFRAO2(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &ifrao2_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate ifrao_clks[] = {
+ /* IFRAO0 */
+ GATE_IFRAO0(CLK_IFRAO_CQ_DMA_FPC, "ifrao_dma", "ap2con", 28),
+ /* IFRAO1 */
+ GATE_IFRAO1(CLK_IFRAO_DEBUGSYS, "ifrao_debugsys", "axi_sel", 24),
+ GATE_IFRAO1(CLK_IFRAO_DBG_TRACE, "ifrao_dbg_trace", "axi_sel", 29),
+ /* IFRAO2 */
+ GATE_IFRAO2(CLK_IFRAO_CQ_DMA, "ifrao_cq_dma", "axi_sel", 27),
+};
+
+static const struct mtk_clk_desc ifrao_mcd = {
+ .clks = ifrao_clks,
+ .num_clks = ARRAY_SIZE(ifrao_clks),
+};
+
+static const struct mtk_gate_regs perao0_cg_regs = {
+ .set_ofs = 0x24,
+ .clr_ofs = 0x28,
+ .sta_ofs = 0x10,
+};
+
+static const struct mtk_gate_regs perao1_cg_regs = {
+ .set_ofs = 0x2c,
+ .clr_ofs = 0x30,
+ .sta_ofs = 0x14,
+};
+
+static const struct mtk_gate_regs perao2_cg_regs = {
+ .set_ofs = 0x34,
+ .clr_ofs = 0x38,
+ .sta_ofs = 0x18,
+};
+
+#define GATE_PERAO0(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &perao0_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+#define GATE_PERAO1(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &perao1_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+#define GATE_PERAO2(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &perao2_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate perao_clks[] = {
+ /* PERAO0 */
+ GATE_PERAO0(CLK_PERAO_UART0, "perao_uart0", "uart_sel", 0),
+ GATE_PERAO0(CLK_PERAO_UART1, "perao_uart1", "uart_sel", 1),
+ GATE_PERAO0(CLK_PERAO_UART2, "perao_uart2", "uart_sel", 2),
+ GATE_PERAO0(CLK_PERAO_UART3, "perao_uart3", "uart_sel", 3),
+ GATE_PERAO0(CLK_PERAO_PWM_H, "perao_pwm_h", "axi_peri_sel", 4),
+ GATE_PERAO0(CLK_PERAO_PWM_B, "perao_pwm_b", "pwm_sel", 5),
+ GATE_PERAO0(CLK_PERAO_PWM_FB1, "perao_pwm_fb1", "pwm_sel", 6),
+ GATE_PERAO0(CLK_PERAO_PWM_FB2, "perao_pwm_fb2", "pwm_sel", 7),
+ GATE_PERAO0(CLK_PERAO_PWM_FB3, "perao_pwm_fb3", "pwm_sel", 8),
+ GATE_PERAO0(CLK_PERAO_PWM_FB4, "perao_pwm_fb4", "pwm_sel", 9),
+ GATE_PERAO0(CLK_PERAO_DISP_PWM0, "perao_disp_pwm0", "disp_pwm_sel", 10),
+ GATE_PERAO0(CLK_PERAO_DISP_PWM1, "perao_disp_pwm1", "disp_pwm_sel", 11),
+ GATE_PERAO0(CLK_PERAO_SPI0_B, "perao_spi0_b", "spi0_sel", 12),
+ GATE_PERAO0(CLK_PERAO_SPI1_B, "perao_spi1_b", "spi1_sel", 13),
+ GATE_PERAO0(CLK_PERAO_SPI2_B, "perao_spi2_b", "spi2_sel", 14),
+ GATE_PERAO0(CLK_PERAO_SPI3_B, "perao_spi3_b", "spi3_sel", 15),
+ GATE_PERAO0(CLK_PERAO_SPI4_B, "perao_spi4_b", "spi4_sel", 16),
+ GATE_PERAO0(CLK_PERAO_SPI5_B, "perao_spi5_b", "spi5_sel", 17),
+ GATE_PERAO0(CLK_PERAO_SPI0_H, "perao_spi0_h", "axi_peri_sel", 18),
+ GATE_PERAO0(CLK_PERAO_SPI1_H, "perao_spi1_h", "axi_peri_sel", 19),
+ GATE_PERAO0(CLK_PERAO_SPI2_H, "perao_spi2_h", "axi_peri_sel", 20),
+ GATE_PERAO0(CLK_PERAO_SPI3_H, "perao_spi3_h", "axi_peri_sel", 21),
+ GATE_PERAO0(CLK_PERAO_SPI4_H, "perao_spi4_h", "axi_peri_sel", 22),
+ GATE_PERAO0(CLK_PERAO_SPI5_H, "perao_spi5_h", "axi_peri_sel", 23),
+ GATE_PERAO0(CLK_PERAO_AXI, "perao_axi", "mem_sub_peri_sel", 24),
+ GATE_PERAO0(CLK_PERAO_AHB_APB, "perao_ahb_apb", "axi_peri_sel", 25),
+ GATE_PERAO0(CLK_PERAO_TL, "perao_tl", "pcie_mac_tl_sel", 26),
+ GATE_PERAO0(CLK_PERAO_REF, "perao_ref", "pcie_f26m", 27),
+ GATE_PERAO0(CLK_PERAO_I2C, "perao_i2c", "axi_peri_sel", 28),
+ GATE_PERAO0(CLK_PERAO_DMA_B, "perao_dma_b", "axi_peri_sel", 29),
+ /* PERAO1 */
+ GATE_PERAO1(CLK_PERAO_SSUSB0_REF, "perao_ssusb0_ref", "usb2_26m_p0_en", 1),
+ GATE_PERAO1(CLK_PERAO_SSUSB0_FRMCNT, "perao_ssusb0_frmcnt", "fmcnt_p0_en", 2),
+ GATE_PERAO1(CLK_PERAO_SSUSB0_SYS, "perao_ssusb0_sys", "usb_p0_sel", 4),
+ GATE_PERAO1(CLK_PERAO_SSUSB0_XHCI, "perao_ssusb0_xhci", "ssusb_xhci_p0_sel", 5),
+ GATE_PERAO1(CLK_PERAO_SSUSB0_F, "perao_ssusb0_f", "axi_peri_sel", 6),
+ GATE_PERAO1(CLK_PERAO_SSUSB0_H, "perao_ssusb0_h", "axi_peri_sel", 7),
+ GATE_PERAO1(CLK_PERAO_SSUSB1_REF, "perao_ssusb1_ref", "usb2_26m_p1_en", 8),
+ GATE_PERAO1(CLK_PERAO_SSUSB1_FRMCNT, "perao_ssusb1_frmcnt", "fmcnt_p1_en", 9),
+ GATE_PERAO1(CLK_PERAO_SSUSB1_SYS, "perao_ssusb1_sys", "usb_p1_sel", 11),
+ GATE_PERAO1(CLK_PERAO_SSUSB1_XHCI, "perao_ssusb1_xhci", "ssusb_xhci_p1_sel", 12),
+ GATE_PERAO1(CLK_PERAO_SSUSB1_F, "perao_ssusb1_f", "axi_peri_sel", 13),
+ GATE_PERAO1(CLK_PERAO_SSUSB1_H, "perao_ssusb1_h", "axi_peri_sel", 14),
+ GATE_PERAO1(CLK_PERAO_SSUSB2_REF, "perao_ssusb2_ref", "usb2_26m_p2_en", 15),
+ GATE_PERAO1(CLK_PERAO_SSUSB2_FRMCNT, "perao_ssusb2_frmcnt", "fmcnt_p2_en", 16),
+ GATE_PERAO1(CLK_PERAO_SSUSB2_SYS, "perao_ssusb2_sys", "usb_p2_sel", 18),
+ GATE_PERAO1(CLK_PERAO_SSUSB2_XHCI, "perao_ssusb2_xhci", "ssusb_xhci_p2_sel", 19),
+ GATE_PERAO1(CLK_PERAO_SSUSB2_F, "perao_ssusb2_f", "axi_peri_sel", 20),
+ GATE_PERAO1(CLK_PERAO_SSUSB2_H, "perao_ssusb2_h", "axi_peri_sel", 21),
+ GATE_PERAO1(CLK_PERAO_SSUSB3_REF, "perao_ssusb3_ref", "usb2_26m_p3_en", 23),
+ GATE_PERAO1(CLK_PERAO_SSUSB3_FRMCNT, "perao_ssusb3_frmcnt", "fmcnt_p3_en", 24),
+ GATE_PERAO1(CLK_PERAO_SSUSB3_SYS, "perao_ssusb3_sys", "usb_p3_sel", 26),
+ GATE_PERAO1(CLK_PERAO_SSUSB3_XHCI, "perao_ssusb3_xhci", "ssusb_xhci_p3_sel", 27),
+ GATE_PERAO1(CLK_PERAO_SSUSB3_F, "perao_ssusb3_f", "axi_peri_sel", 28),
+ GATE_PERAO1(CLK_PERAO_SSUSB3_H, "perao_ssusb3_h", "axi_peri_sel", 29),
+ /* PERAO2 */
+ GATE_PERAO2(CLK_PERAO_SSUSB4_REF, "perao_ssusb4_ref", "usb2_26m_p4_en", 0),
+ GATE_PERAO2(CLK_PERAO_SSUSB4_FRMCNT, "perao_ssusb4_frmcnt", "fmcnt_p4_en", 1),
+ GATE_PERAO2(CLK_PERAO_SSUSB4_SYS, "perao_ssusb4_sys", "usb_p4_sel", 3),
+ GATE_PERAO2(CLK_PERAO_SSUSB4_XHCI, "perao_ssusb4_xhci", "ssusb_xhci_p4_sel", 4),
+ GATE_PERAO2(CLK_PERAO_SSUSB4_F, "perao_ssusb4_f", "axi_peri_sel", 5),
+ GATE_PERAO2(CLK_PERAO_SSUSB4_H, "perao_ssusb4_h", "axi_peri_sel", 6),
+ GATE_PERAO2(CLK_PERAO_MSDC0, "perao_msdc0", "msdc50_0_sel", 7),
+ GATE_PERAO2(CLK_PERAO_MSDC0_H, "perao_msdc0_h", "msdc5hclk_sel", 8),
+ GATE_PERAO2(CLK_PERAO_MSDC0_FAES, "perao_msdc0_faes", "aes_msdcfde_sel", 9),
+ GATE_PERAO2(CLK_PERAO_MSDC0_MST_F, "perao_msdc0_mst_f", "axi_peri_sel", 10),
+ GATE_PERAO2(CLK_PERAO_MSDC0_SLV_H, "perao_msdc0_slv_h", "axi_peri_sel", 11),
+ GATE_PERAO2(CLK_PERAO_MSDC1, "perao_msdc1", "msdc30_1_sel", 12),
+ GATE_PERAO2(CLK_PERAO_MSDC1_H, "perao_msdc1_h", "msdc30_1_h_sel", 13),
+ GATE_PERAO2(CLK_PERAO_MSDC1_MST_F, "perao_msdc1_mst_f", "axi_peri_sel", 14),
+ GATE_PERAO2(CLK_PERAO_MSDC1_SLV_H, "perao_msdc1_slv_h", "axi_peri_sel", 15),
+ GATE_PERAO2(CLK_PERAO_MSDC2, "perao_msdc2", "msdc30_2_sel", 16),
+ GATE_PERAO2(CLK_PERAO_MSDC2_H, "perao_msdc2_h", "msdc30_2_h_sel", 17),
+ GATE_PERAO2(CLK_PERAO_MSDC2_MST_F, "perao_msdc2_mst_f", "axi_peri_sel", 18),
+ GATE_PERAO2(CLK_PERAO_MSDC2_SLV_H, "perao_msdc2_slv_h", "axi_peri_sel", 19),
+ GATE_PERAO2(CLK_PERAO_SFLASH, "perao_sflash", "sflash_sel", 20),
+ GATE_PERAO2(CLK_PERAO_SFLASH_F, "perao_sflash_f", "axi_peri_sel", 21),
+ GATE_PERAO2(CLK_PERAO_SFLASH_H, "perao_sflash_h", "axi_peri_sel", 22),
+ GATE_PERAO2(CLK_PERAO_SFLASH_P, "perao_sflash_p", "axi_peri_sel", 23),
+ GATE_PERAO2(CLK_PERAO_AUDIO0, "perao_audio0", "axi_peri_sel", 24),
+ GATE_PERAO2(CLK_PERAO_AUDIO1, "perao_audio1", "axi_peri_sel", 25),
+ GATE_PERAO2(CLK_PERAO_AUDIO2, "perao_audio2", "aud_intbus_sel", 26),
+ GATE_PERAO2(CLK_PERAO_AUXADC_26M, "perao_auxadc_26m", "clk26m", 27),
+};
+
+static const struct mtk_clk_desc perao_mcd = {
+ .clks = perao_clks,
+ .num_clks = ARRAY_SIZE(perao_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8189_bus[] = {
+ { .compatible = "mediatek,mt8189-infra-ao", .data = &ifrao_mcd },
+ { .compatible = "mediatek,mt8189-peri-ao", .data = &perao_mcd },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_clk_mt8189_bus);
+
+static struct platform_driver clk_mt8189_bus_drv = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt8189-bus",
+ .of_match_table = of_match_clk_mt8189_bus,
+ },
+};
+module_platform_driver(clk_mt8189_bus_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8189 bus/peripheral clocks driver");
+MODULE_LICENSE("GPL");
--
2.54.0
^ permalink raw reply related
* [PATCH 11/15] clk: mediatek: Add MT8189 dbgao clock support
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
Edward-JW Yang, Richard Cochran
Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>
Add support for the MT8189 dbgao clock controller,
which provides clock gate control for debug-system.
Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
drivers/clk/mediatek/Kconfig | 10 ++++
drivers/clk/mediatek/Makefile | 1 +
drivers/clk/mediatek/clk-mt8189-dbgao.c | 98 +++++++++++++++++++++++++++++++++
3 files changed, 109 insertions(+)
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 8eba45f05968..635b0109ec07 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -839,6 +839,16 @@ config COMMON_CLK_MT8189_BUS
MT8189 chipset, ensuring that all bus-related components receive the
correct clock signals for optimal performance.
+config COMMON_CLK_MT8189_DBGAO
+ tristate "Clock driver for MediaTek MT8189 debug ao"
+ depends on COMMON_CLK_MT8189
+ default COMMON_CLK_MT8189
+ help
+ Enable this to support the clock management for the debug function
+ on MediaTek MT8189 SoCs. This includes enabling and disabling
+ vcore debug system clocks. If you want to control its clocks, say Y or M
+ to include this driver in your kernel build.
+
config COMMON_CLK_MT8192
tristate "Clock driver for MediaTek MT8192"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index aabfb42cb1b2..6ab6df7ebf2a 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -126,6 +126,7 @@ obj-$(CONFIG_COMMON_CLK_MT8188_WPESYS) += clk-mt8188-wpe.o
obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o clk-mt8189-topckgen.o \
clk-mt8189-vlpckgen.o clk-mt8189-vlpcfg.o
obj-$(CONFIG_COMMON_CLK_MT8189_BUS) += clk-mt8189-bus.o
+obj-$(CONFIG_COMMON_CLK_MT8189_DBGAO) += clk-mt8189-dbgao.o
obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8189-dbgao.c b/drivers/clk/mediatek/clk-mt8189-dbgao.c
new file mode 100644
index 000000000000..40307bdc93eb
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8189-dbgao.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ * Qiqi Wang <qiqi.wang@mediatek.com>
+ * Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ * Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mediatek,mt8189-clk.h>
+
+static const struct mtk_gate_regs dbgao_cg_regs = {
+ .set_ofs = 0x70,
+ .clr_ofs = 0x70,
+ .sta_ofs = 0x70,
+};
+
+#define GATE_DBGAO(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &dbgao_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv)
+
+static const struct mtk_gate dbgao_clks[] = {
+ GATE_DBGAO(CLK_DBGAO_ATB_EN, "dbgao_atb_en", "atb_sel", 0),
+};
+
+static const struct mtk_clk_desc dbgao_mcd = {
+ .clks = dbgao_clks,
+ .num_clks = ARRAY_SIZE(dbgao_clks),
+};
+
+static const struct mtk_gate_regs dem0_cg_regs = {
+ .set_ofs = 0x2c,
+ .clr_ofs = 0x2c,
+ .sta_ofs = 0x2c,
+};
+
+static const struct mtk_gate_regs dem1_cg_regs = {
+ .set_ofs = 0x30,
+ .clr_ofs = 0x30,
+ .sta_ofs = 0x30,
+};
+
+static const struct mtk_gate_regs dem2_cg_regs = {
+ .set_ofs = 0x70,
+ .clr_ofs = 0x70,
+ .sta_ofs = 0x70,
+};
+
+#define GATE_DEM0(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &dem0_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv)
+
+#define GATE_DEM1(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &dem1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv)
+
+#define GATE_DEM2(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &dem2_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv)
+
+static const struct mtk_gate dem_clks[] = {
+ /* DEM0 */
+ GATE_DEM0(CLK_DEM_BUSCLK_EN, "dem_busclk_en", "axi_sel", 0),
+ /* DEM1 */
+ GATE_DEM1(CLK_DEM_SYSCLK_EN, "dem_sysclk_en", "axi_sel", 0),
+ /* DEM2 */
+ GATE_DEM2(CLK_DEM_ATB_EN, "dem_atb_en", "atb_sel", 0),
+};
+
+static const struct mtk_clk_desc dem_mcd = {
+ .clks = dem_clks,
+ .num_clks = ARRAY_SIZE(dem_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8189_dbgao[] = {
+ { .compatible = "mediatek,mt8189-dbg-ao", .data = &dbgao_mcd },
+ { .compatible = "mediatek,mt8189-dem", .data = &dem_mcd },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_clk_mt8189_dbgao);
+
+static struct platform_driver clk_mt8189_dbgao_drv = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt8189-dbgao",
+ .of_match_table = of_match_clk_mt8189_dbgao,
+ },
+};
+module_platform_driver(clk_mt8189_dbgao_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8189 dbgao system clocks driver");
+MODULE_LICENSE("GPL");
--
2.54.0
^ permalink raw reply related
* [PATCH 12/15] clk: mediatek: Add MT8189 dvfsrc clock support
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
Edward-JW Yang, Richard Cochran
Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>
Add support for the MT8189 dvfsrc clock controller,
which provides clock gate control for dram dvfs.
Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
drivers/clk/mediatek/Kconfig | 10 ++++++
drivers/clk/mediatek/Makefile | 1 +
drivers/clk/mediatek/clk-mt8189-dvfsrc.c | 58 ++++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+)
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 635b0109ec07..245d3b83b5d3 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -849,6 +849,16 @@ config COMMON_CLK_MT8189_DBGAO
vcore debug system clocks. If you want to control its clocks, say Y or M
to include this driver in your kernel build.
+config COMMON_CLK_MT8189_DVFSRC
+ tristate "Clock driver for MediaTek MT8189 dvfsrc"
+ depends on COMMON_CLK_MT8189
+ default COMMON_CLK_MT8189
+ help
+ Enable this to support the clock management for the dvfsrc
+ on MediaTek MT8189 SoCs. This includes enabling and disabling
+ vcore dvfs clocks. If you want to control its clocks, say Y or M
+ to include this driver in your kernel build.
+
config COMMON_CLK_MT8192
tristate "Clock driver for MediaTek MT8192"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 6ab6df7ebf2a..4dbfc9ac83ba 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -127,6 +127,7 @@ obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o clk-mt8189-topckgen.o
clk-mt8189-vlpckgen.o clk-mt8189-vlpcfg.o
obj-$(CONFIG_COMMON_CLK_MT8189_BUS) += clk-mt8189-bus.o
obj-$(CONFIG_COMMON_CLK_MT8189_DBGAO) += clk-mt8189-dbgao.o
+obj-$(CONFIG_COMMON_CLK_MT8189_DVFSRC) += clk-mt8189-dvfsrc.o
obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8189-dvfsrc.c b/drivers/clk/mediatek/clk-mt8189-dvfsrc.c
new file mode 100644
index 000000000000..37b81dc0b882
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8189-dvfsrc.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ * Qiqi Wang <qiqi.wang@mediatek.com>
+ * Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ * Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mediatek,mt8189-clk.h>
+
+static const struct mtk_gate_regs dvfsrc_top_cg_regs = {
+ .set_ofs = 0x0,
+ .clr_ofs = 0x0,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_DVFSRC_TOP_FLAGS(_id, _name, _parent, _shift, _flags) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &dvfsrc_top_cg_regs, _shift, \
+ &mtk_clk_gate_ops_no_setclr_inv, _flags)
+
+static const struct mtk_gate dvfsrc_top_clks[] = {
+ GATE_DVFSRC_TOP_FLAGS(CLK_DVFSRC_TOP_DVFSRC_EN, "dvfsrc_dvfsrc_en",
+ "clk26m", 0, CLK_IS_CRITICAL),
+};
+
+static const struct mtk_clk_desc dvfsrc_top_mcd = {
+ .clks = dvfsrc_top_clks,
+ .num_clks = ARRAY_SIZE(dvfsrc_top_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8189_dvfsrc[] = {
+ { .compatible = "mediatek,mt8189-dvfsrc-top", .data = &dvfsrc_top_mcd },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_clk_mt8189_dvfsrc);
+
+static struct platform_driver clk_mt8189_dvfsrc_drv = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt8189-dvfsrc",
+ .of_match_table = of_match_clk_mt8189_dvfsrc,
+ },
+};
+module_platform_driver(clk_mt8189_dvfsrc_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8189 dvfsrc clocks driver");
+MODULE_LICENSE("GPL");
--
2.54.0
^ permalink raw reply related
* [PATCH 13/15] clk: mediatek: Add MT8189 i2c clock support
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
Edward-JW Yang, Richard Cochran
Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>
Add support for the MT8189 i2c clock controller,
which provides clock gate control for i2c.
Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
drivers/clk/mediatek/Kconfig | 13 ++++
drivers/clk/mediatek/Makefile | 1 +
drivers/clk/mediatek/clk-mt8189-iic.c | 122 ++++++++++++++++++++++++++++++++++
3 files changed, 136 insertions(+)
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 245d3b83b5d3..bba631138b07 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -859,6 +859,19 @@ config COMMON_CLK_MT8189_DVFSRC
vcore dvfs clocks. If you want to control its clocks, say Y or M
to include this driver in your kernel build.
+config COMMON_CLK_MT8189_IIC
+ tristate "Clock driver for MediaTek MT8189 iic"
+ depends on COMMON_CLK_MT8189
+ default COMMON_CLK_MT8189
+ help
+ Enable this option to support the clock framework for MediaTek MT8189
+ integrated circuits (iic). This driver is responsible for managing
+ clock sources, dividers, and gates specifically designed for MT8189
+ SoCs. Enabling this driver ensures that the system can correctly
+ manage clock frequencies and power for various components within
+ the MT8189 chipset, improving the overall performance and power
+ efficiency of the device.
+
config COMMON_CLK_MT8192
tristate "Clock driver for MediaTek MT8192"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 4dbfc9ac83ba..bfc075023d9b 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -128,6 +128,7 @@ obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o clk-mt8189-topckgen.o
obj-$(CONFIG_COMMON_CLK_MT8189_BUS) += clk-mt8189-bus.o
obj-$(CONFIG_COMMON_CLK_MT8189_DBGAO) += clk-mt8189-dbgao.o
obj-$(CONFIG_COMMON_CLK_MT8189_DVFSRC) += clk-mt8189-dvfsrc.o
+obj-$(CONFIG_COMMON_CLK_MT8189_IIC) += clk-mt8189-iic.o
obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8189-iic.c b/drivers/clk/mediatek/clk-mt8189-iic.c
new file mode 100644
index 000000000000..80a01706791a
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8189-iic.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ * Qiqi Wang <qiqi.wang@mediatek.com>
+ * Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ * Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mediatek,mt8189-clk.h>
+
+static const struct mtk_gate_regs impe_cg_regs = {
+ .set_ofs = 0x8,
+ .clr_ofs = 0x4,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_IMPE(_id, _name, _parent, _shift) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &impe_cg_regs, _shift, \
+ &mtk_clk_gate_ops_setclr, CLK_OPS_PARENT_ENABLE)
+
+static const struct mtk_gate impe_clks[] = {
+ GATE_IMPE(CLK_IMPE_I2C0, "impe_i2c0", "i2c_sel", 0),
+ GATE_IMPE(CLK_IMPE_I2C1, "impe_i2c1", "i2c_sel", 1),
+};
+
+static const struct mtk_clk_desc impe_mcd = {
+ .clks = impe_clks,
+ .num_clks = ARRAY_SIZE(impe_clks),
+};
+
+static const struct mtk_gate_regs impen_cg_regs = {
+ .set_ofs = 0x8,
+ .clr_ofs = 0x4,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_IMPEN(_id, _name, _parent, _shift) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &impen_cg_regs, _shift, \
+ &mtk_clk_gate_ops_setclr, CLK_OPS_PARENT_ENABLE)
+
+static const struct mtk_gate impen_clks[] = {
+ GATE_IMPEN(CLK_IMPEN_I2C7, "impen_i2c7", "i2c_sel", 0),
+ GATE_IMPEN(CLK_IMPEN_I2C8, "impen_i2c8", "i2c_sel", 1),
+};
+
+static const struct mtk_clk_desc impen_mcd = {
+ .clks = impen_clks,
+ .num_clks = ARRAY_SIZE(impen_clks),
+};
+
+static const struct mtk_gate_regs imps_cg_regs = {
+ .set_ofs = 0x8,
+ .clr_ofs = 0x4,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_IMPS(_id, _name, _parent, _shift) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &imps_cg_regs, _shift, \
+ &mtk_clk_gate_ops_setclr, CLK_OPS_PARENT_ENABLE)
+
+static const struct mtk_gate imps_clks[] = {
+ GATE_IMPS(CLK_IMPS_I2C3, "imps_i2c3", "i2c_sel", 0),
+ GATE_IMPS(CLK_IMPS_I2C4, "imps_i2c4", "i2c_sel", 1),
+ GATE_IMPS(CLK_IMPS_I2C5, "imps_i2c5", "i2c_sel", 2),
+ GATE_IMPS(CLK_IMPS_I2C6, "imps_i2c6", "i2c_sel", 3),
+};
+
+static const struct mtk_clk_desc imps_mcd = {
+ .clks = imps_clks,
+ .num_clks = ARRAY_SIZE(imps_clks),
+};
+
+static const struct mtk_gate_regs impws_cg_regs = {
+ .set_ofs = 0x8,
+ .clr_ofs = 0x4,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_IMPWS(_id, _name, _parent, _shift) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &impws_cg_regs, _shift, \
+ &mtk_clk_gate_ops_setclr, CLK_OPS_PARENT_ENABLE)
+
+static const struct mtk_gate impws_clks[] = {
+ GATE_IMPWS(CLK_IMPWS_I2C2, "impws_i2c2", "i2c_sel", 0),
+};
+
+static const struct mtk_clk_desc impws_mcd = {
+ .clks = impws_clks,
+ .num_clks = ARRAY_SIZE(impws_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8189_iic[] = {
+ { .compatible = "mediatek,mt8189-iic-wrap-e", .data = &impe_mcd },
+ { .compatible = "mediatek,mt8189-iic-wrap-en", .data = &impen_mcd },
+ { .compatible = "mediatek,mt8189-iic-wrap-s", .data = &imps_mcd },
+ { .compatible = "mediatek,mt8189-iic-wrap-ws", .data = &impws_mcd },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_clk_mt8189_iic);
+
+static struct platform_driver clk_mt8189_iic_drv = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt8189-iic",
+ .of_match_table = of_match_clk_mt8189_iic,
+ },
+};
+module_platform_driver(clk_mt8189_iic_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8189 iic clocks driver");
+MODULE_LICENSE("GPL");
--
2.54.0
^ permalink raw reply related
* [PATCH 14/15] clk: mediatek: Add MT8189 scp clock support
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
Edward-JW Yang, Richard Cochran
Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>
Add support for the MT8189 scp clock controller,
which provides clock gate control for System Control Processor.
Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
drivers/clk/mediatek/Kconfig | 10 +++++
drivers/clk/mediatek/Makefile | 1 +
drivers/clk/mediatek/clk-mt8189-scp.c | 77 +++++++++++++++++++++++++++++++++++
3 files changed, 88 insertions(+)
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index bba631138b07..919a916f1f4f 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -872,6 +872,16 @@ config COMMON_CLK_MT8189_IIC
the MT8189 chipset, improving the overall performance and power
efficiency of the device.
+config COMMON_CLK_MT8189_SCP
+ tristate "Clock driver for MediaTek MT8189 scp"
+ depends on COMMON_CLK_MT8189
+ default COMMON_CLK_MT8189
+ help
+ Enable this to support the clock framework for the System Control
+ Processor (SCP) in the MediaTek MT8189 SoC. This includes clock
+ management for SCP-related features, ensuring proper clock
+ distribution and gating for power efficiency and functionality.
+
config COMMON_CLK_MT8192
tristate "Clock driver for MediaTek MT8192"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index bfc075023d9b..a3a93a16b369 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -129,6 +129,7 @@ obj-$(CONFIG_COMMON_CLK_MT8189_BUS) += clk-mt8189-bus.o
obj-$(CONFIG_COMMON_CLK_MT8189_DBGAO) += clk-mt8189-dbgao.o
obj-$(CONFIG_COMMON_CLK_MT8189_DVFSRC) += clk-mt8189-dvfsrc.o
obj-$(CONFIG_COMMON_CLK_MT8189_IIC) += clk-mt8189-iic.o
+obj-$(CONFIG_COMMON_CLK_MT8189_SCP) += clk-mt8189-scp.o
obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8189-scp.c b/drivers/clk/mediatek/clk-mt8189-scp.c
new file mode 100644
index 000000000000..75197cd98b52
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8189-scp.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ * Qiqi Wang <qiqi.wang@mediatek.com>
+ * Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ * Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mediatek,mt8189-clk.h>
+
+static const struct mtk_gate_regs scp_cg_regs = {
+ .set_ofs = 0x4,
+ .clr_ofs = 0x8,
+ .sta_ofs = 0x4,
+};
+
+#define GATE_SCP(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &scp_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
+
+static const struct mtk_gate scp_clks[] = {
+ GATE_SCP(CLK_SCP_SET_SPI0, "scp_set_spi0", "clk26m", 0),
+ GATE_SCP(CLK_SCP_SET_SPI1, "scp_set_spi1", "clk26m", 1),
+};
+
+static const struct mtk_clk_desc scp_mcd = {
+ .clks = scp_clks,
+ .num_clks = ARRAY_SIZE(scp_clks),
+};
+
+static const struct mtk_gate_regs scp_iic_cg_regs = {
+ .set_ofs = 0x8,
+ .clr_ofs = 0x4,
+ .sta_ofs = 0x0,
+};
+
+#define GATE_SCP_IIC(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &scp_iic_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
+
+static const struct mtk_gate scp_iic_clks[] = {
+ GATE_SCP_IIC(CLK_SCP_IIC_I2C0_W1S, "scp_iic_i2c0_w1s", "vlp_scp_iic_sel", 0),
+ GATE_SCP_IIC(CLK_SCP_IIC_I2C1_W1S, "scp_iic_i2c1_w1s", "vlp_scp_iic_sel", 1),
+};
+
+static const struct mtk_clk_desc scp_iic_mcd = {
+ .clks = scp_iic_clks,
+ .num_clks = ARRAY_SIZE(scp_iic_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8189_scp[] = {
+ { .compatible = "mediatek,mt8189-scp-clk", .data = &scp_mcd },
+ { .compatible = "mediatek,mt8189-scp-i2c-clk", .data = &scp_iic_mcd },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_clk_mt8189_scp);
+
+static struct platform_driver clk_mt8189_scp_drv = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt8189-scp",
+ .of_match_table = of_match_clk_mt8189_scp,
+ },
+};
+module_platform_driver(clk_mt8189_scp_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8189 scp clocks driver");
+MODULE_LICENSE("GPL");
--
2.54.0
^ permalink raw reply related
* [PATCH 15/15] clk: mediatek: Add MT8189 ufs clock support
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
Edward-JW Yang, Richard Cochran
Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>
Add support for the MT8189 ufs clock controller,
which provides clock gate control for Universal Flash Storage.
Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
drivers/clk/mediatek/Kconfig | 12 +++
drivers/clk/mediatek/Makefile | 1 +
drivers/clk/mediatek/clk-mt8189-ufs.c | 133 ++++++++++++++++++++++++++++++++++
3 files changed, 146 insertions(+)
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 919a916f1f4f..34a270a377cc 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -882,6 +882,18 @@ config COMMON_CLK_MT8189_SCP
management for SCP-related features, ensuring proper clock
distribution and gating for power efficiency and functionality.
+config COMMON_CLK_MT8189_UFS
+ tristate "Clock driver for MediaTek MT8189 ufs"
+ depends on COMMON_CLK_MT8189
+ default COMMON_CLK_MT8189
+ help
+ Enable this to support the clock management for the Universal Flash
+ Storage (UFS) interface on MediaTek MT8189 SoCs. This includes
+ clock sources, dividers, and gates that are specific to the UFS
+ feature of the MT8189 platform. It is recommended to enable this
+ option if the system includes a UFS device that relies on the MT8189
+ SoC for clock management.
+
config COMMON_CLK_MT8192
tristate "Clock driver for MediaTek MT8192"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index a3a93a16b369..1aa9f4265225 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -130,6 +130,7 @@ obj-$(CONFIG_COMMON_CLK_MT8189_DBGAO) += clk-mt8189-dbgao.o
obj-$(CONFIG_COMMON_CLK_MT8189_DVFSRC) += clk-mt8189-dvfsrc.o
obj-$(CONFIG_COMMON_CLK_MT8189_IIC) += clk-mt8189-iic.o
obj-$(CONFIG_COMMON_CLK_MT8189_SCP) += clk-mt8189-scp.o
+obj-$(CONFIG_COMMON_CLK_MT8189_UFS) += clk-mt8189-ufs.o
obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8189-ufs.c b/drivers/clk/mediatek/clk-mt8189-ufs.c
new file mode 100644
index 000000000000..85afab04420f
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8189-ufs.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ * Qiqi Wang <qiqi.wang@mediatek.com>
+ * Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ * Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mediatek,mt8189-clk.h>
+#include <dt-bindings/reset/mediatek,mt8189-resets.h>
+
+#define MT8189_UFSCFG_AO_RST0_SET_OFFSET 0x48
+#define MT8189_UFSCFG_PDN_RST0_SET_OFFSET 0x48
+
+static const struct mtk_gate_regs ufscfg_ao_reg_cg_regs = {
+ .set_ofs = 0x8,
+ .clr_ofs = 0xc,
+ .sta_ofs = 0x4,
+};
+
+#define GATE_UFSCFG_AO_REG(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &ufscfg_ao_reg_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate ufscfg_ao_reg_clks[] = {
+ GATE_UFSCFG_AO_REG(CLK_UFSCFG_AO_REG_UNIPRO_TX_SYM,
+ "ufscfg_ao_unipro_tx_sym", "clk26m", 1),
+ GATE_UFSCFG_AO_REG(CLK_UFSCFG_AO_REG_UNIPRO_RX_SYM0,
+ "ufscfg_ao_unipro_rx_sym0", "clk26m", 2),
+ GATE_UFSCFG_AO_REG(CLK_UFSCFG_AO_REG_UNIPRO_RX_SYM1,
+ "ufscfg_ao_unipro_rx_sym1", "clk26m", 3),
+ GATE_UFSCFG_AO_REG(CLK_UFSCFG_AO_REG_UNIPRO_SYS,
+ "ufscfg_ao_unipro_sys", "ufs_sel", 4),
+ GATE_UFSCFG_AO_REG(CLK_UFSCFG_AO_REG_U_SAP_CFG,
+ "ufscfg_ao_u_sap_cfg", "clk26m", 5),
+ GATE_UFSCFG_AO_REG(CLK_UFSCFG_AO_REG_U_PHY_TOP_AHB_S_BUS,
+ "ufscfg_ao_u_phy_ahb_s_bus", "axi_u_sel", 6),
+};
+
+static u16 ufscfg_ao_rst_ofs[] = {
+ MT8189_UFSCFG_AO_RST0_SET_OFFSET,
+};
+
+static u16 ufscfg_ao_rst_idx_map[] = {
+ [MT8189_UFSAO_RST_UFS_MPHY] = 8,
+};
+
+static const struct mtk_clk_rst_desc ufscfg_ao_rst_desc = {
+ .version = MTK_RST_SET_CLR,
+ .rst_bank_ofs = ufscfg_ao_rst_ofs,
+ .rst_bank_nr = ARRAY_SIZE(ufscfg_ao_rst_ofs),
+ .rst_idx_map = ufscfg_ao_rst_idx_map,
+ .rst_idx_map_nr = ARRAY_SIZE(ufscfg_ao_rst_idx_map),
+};
+
+static const struct mtk_clk_desc ufscfg_ao_reg_mcd = {
+ .clks = ufscfg_ao_reg_clks,
+ .num_clks = ARRAY_SIZE(ufscfg_ao_reg_clks),
+ .rst_desc = &ufscfg_ao_rst_desc,
+};
+
+static const struct mtk_gate_regs ufscfg_pdn_reg_cg_regs = {
+ .set_ofs = 0x8,
+ .clr_ofs = 0xc,
+ .sta_ofs = 0x4,
+};
+
+#define GATE_UFSCFG_PDN_REG(_id, _name, _parent, _shift) \
+ GATE_MTK(_id, _name, _parent, &ufscfg_pdn_reg_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate ufscfg_pdn_reg_clks[] = {
+ GATE_UFSCFG_PDN_REG(CLK_UFSCFG_REG_UFSHCI_UFS,
+ "ufscfg_ufshci_ufs", "ufs_sel", 0),
+ GATE_UFSCFG_PDN_REG(CLK_UFSCFG_REG_UFSHCI_AES,
+ "ufscfg_ufshci_aes", "aes_ufsfde_sel", 1),
+ GATE_UFSCFG_PDN_REG(CLK_UFSCFG_REG_UFSHCI_U_AHB,
+ "ufscfg_ufshci_u_ahb", "axi_u_sel", 3),
+ GATE_UFSCFG_PDN_REG(CLK_UFSCFG_REG_UFSHCI_U_AXI,
+ "ufscfg_ufshci_u_axi", "mem_sub_u_sel", 5),
+};
+
+static u16 ufscfg_pdn_rst_ofs[] = {
+ MT8189_UFSCFG_PDN_RST0_SET_OFFSET,
+};
+
+static u16 ufscfg_pdn_rst_idx_map[] = {
+ [MT8189_UFSPDN_RST_UFS_UNIPRO] = 0,
+ [MT8189_UFSPDN_RST_UFS_CRYPTO] = 1,
+ [MT8189_UFSPDN_RST_UFS_HCI] = 2,
+};
+
+static const struct mtk_clk_rst_desc ufscfg_pdn_rst_desc = {
+ .version = MTK_RST_SET_CLR,
+ .rst_bank_ofs = ufscfg_pdn_rst_ofs,
+ .rst_bank_nr = ARRAY_SIZE(ufscfg_pdn_rst_ofs),
+ .rst_idx_map = ufscfg_pdn_rst_idx_map,
+ .rst_idx_map_nr = ARRAY_SIZE(ufscfg_pdn_rst_idx_map),
+};
+
+static const struct mtk_clk_desc ufscfg_pdn_reg_mcd = {
+ .clks = ufscfg_pdn_reg_clks,
+ .num_clks = ARRAY_SIZE(ufscfg_pdn_reg_clks),
+ .rst_desc = &ufscfg_pdn_rst_desc,
+};
+
+static const struct of_device_id of_match_clk_mt8189_ufs[] = {
+ { .compatible = "mediatek,mt8189-ufscfg-ao", .data = &ufscfg_ao_reg_mcd },
+ { .compatible = "mediatek,mt8189-ufscfg-pdn", .data = &ufscfg_pdn_reg_mcd },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match_clk_mt8189_ufs);
+
+static struct platform_driver clk_mt8189_ufs_drv = {
+ .probe = mtk_clk_simple_probe,
+ .remove = mtk_clk_simple_remove,
+ .driver = {
+ .name = "clk-mt8189-ufs",
+ .of_match_table = of_match_clk_mt8189_ufs,
+ },
+};
+module_platform_driver(clk_mt8189_ufs_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8189 ufs clocks driver");
+MODULE_LICENSE("GPL");
--
2.54.0
^ permalink raw reply related
* Re: [PATCH net-next V4 3/6] devlink: Parse eswitch mode boot defaults
From: Mark Bloch @ 2026-07-01 13:14 UTC (permalink / raw)
To: Jiri Pirko
Cc: Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Andrew Lunn,
Jonathan Corbet, Shuah Khan, netdev, linux-rdma, linux-doc
In-Reply-To: <akTencQhKSanuFeW@FV6GYCPJ69>
On 01/07/2026 12:38, Jiri Pirko wrote:
> Mon, Jun 29, 2026 at 08:20:58PM +0200, mbloch@nvidia.com wrote:
>> Add devlink_eswitch_mode= kernel command line parsing for a default
>> eswitch mode.
>>
>> The supported syntax selects either all devlink handles or one explicit
>> comma-separated handle list:
>>
>> devlink_eswitch_mode=*=<mode>
>>
>> devlink_eswitch_mode=<handle>[,<handle>...]=<mode>
>>
>> where <mode> is one of legacy, switchdev or switchdev_inactive. All
>> selected handles receive the same mode. Assigning different modes to
>> different handle lists in the same parameter value is not supported.
>>
>> Store the parsed selector and mode in devlink core so the default can be
>> applied by a downstream patch.
>>
>> Document the devlink_eswitch_mode= syntax and duplicate handle handling.
>>
>> Signed-off-by: Mark Bloch <mbloch@nvidia.com>
>> ---
>> .../admin-guide/kernel-parameters.txt | 25 ++
>> .../networking/devlink/devlink-defaults.rst | 78 ++++++
>> Documentation/networking/devlink/index.rst | 1 +
>> net/devlink/core.c | 227 ++++++++++++++++++
>> 4 files changed, 331 insertions(+)
>> create mode 100644 Documentation/networking/devlink/devlink-defaults.rst
>>
>> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
>> index b5493a7f8f22..117300dd589c 100644
>> --- a/Documentation/admin-guide/kernel-parameters.txt
>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>> @@ -1249,6 +1249,31 @@ Kernel parameters
>> dell_smm_hwmon.fan_max=
>> [HW] Maximum configurable fan speed.
>>
>> + devlink_eswitch_mode=
>> + [NET]
>> + Format:
>> + <selector>=<mode>
>> +
>> + <selector>:
>> + * | <handle>[,<handle>...]
>> +
>> + <handle>:
>> + <bus-name>/<dev-name>
>> +
>> + Configure default devlink eswitch mode for matching
>> + devlink instances during device initialization.
>> +
>> + <mode>:
>> + legacy | switchdev | switchdev_inactive
>> +
>> + Examples:
>> + devlink_eswitch_mode=*=switchdev
>> + devlink_eswitch_mode=pci/0000:08:00.0=switchdev
>> + devlink_eswitch_mode=pci/0000:08:00.0,pci/0000:09:00.1=switchdev_inactive
>> +
>> + See Documentation/networking/devlink/devlink-defaults.rst
>> + for the full syntax.
>> +
>> dfltcc= [HW,S390]
>> Format: { on | off | def_only | inf_only | always }
>> on: s390 zlib hardware support for compression on
>> diff --git a/Documentation/networking/devlink/devlink-defaults.rst b/Documentation/networking/devlink/devlink-defaults.rst
>> new file mode 100644
>> index 000000000000..380c9e99210e
>> --- /dev/null
>> +++ b/Documentation/networking/devlink/devlink-defaults.rst
>> @@ -0,0 +1,78 @@
>> +.. SPDX-License-Identifier: GPL-2.0
>> +
>> +==============================
>> +Devlink Eswitch Mode Defaults
>> +==============================
>> +
>> +Devlink eswitch mode defaults allow the eswitch mode to be provided on the
>> +kernel command line and applied to matching devlink instances during device
>> +initialization.
>> +
>> +The devlink device is selected by its devlink handle. For PCI devices this is
>> +the same handle shown by ``devlink dev show``, for example
>> +``pci/0000:08:00.0``.
>> +
>> +Kernel command line syntax
>> +==========================
>> +
>> +Defaults are specified with the ``devlink_eswitch_mode=`` kernel command line
>> +parameter.
>> +
>> +The general syntax is::
>> +
>> + devlink_eswitch_mode=<selector>=<mode>
>> +
>> +``<selector>`` is either ``*`` or one or more devlink handles::
>> +
>> + * | <bus-name>/<dev-name>[,<bus-name>/<dev-name>...]
>> +
>> +``*`` applies the mode to every devlink instance. All handles in the same
>> +selector receive the same eswitch mode.
>> +
>> +``<mode>`` is one of ``legacy``, ``switchdev`` or ``switchdev_inactive``.
>> +
>> +Syntax rules
>> +------------
>> +
>> +The following syntax rules apply:
>> +
>> +* Specify the default in one ``devlink_eswitch_mode=`` parameter. Repeated
>> + ``devlink_eswitch_mode=`` parameters are not accumulated.
>> +* The ``devlink_eswitch_mode=`` value is limited by the kernel command line
>> + size.
>> +* Whitespace is not allowed within the parameter value.
>> +* ``<selector>`` must be either ``*`` or a handle list. ``*`` cannot be
>> + combined with explicit handles.
>> +* ``<bus-name>`` and ``<dev-name>`` must not be empty.
>> +* ``<dev-name>`` may contain ``:``. This allows PCI names such as
>> + ``0000:08:00.0``.
>> +* Handles must not contain whitespace, ``*``, ``=`` or more than one ``/``.
>> +* A comma separates handles.
>> +* Comma-separated default assignments are not supported.
>> +* Duplicate handles are rejected and the devlink eswitch mode default is
>> + ignored.
>> +
>> +The eswitch mode default corresponds to the userspace command::
>> +
>> + devlink dev eswitch set <handle> mode <value>
>> +
>> +
>> +Examples
>> +========
>> +
>> +Set all devlink instances to switchdev mode::
>> +
>> + devlink_eswitch_mode=*=switchdev
>> +
>> +Set one PCI devlink instance to switchdev mode::
>> +
>> + devlink_eswitch_mode=pci/0000:08:00.0=switchdev
>> +
>> +Set two PCI devlink instances to switchdev inactive mode::
>> +
>> + devlink_eswitch_mode=pci/0000:08:00.0,pci/0000:09:00.1=switchdev_inactive
>> +
>> +The following is invalid because comma-separated default assignments are not
>> +supported::
>> +
>> + devlink_eswitch_mode=pci/0000:08:00.0=switchdev,pci/0000:09:00.0=switchdev_inactive
>
> Interesting. I would think that this is something user may want to set
> for some usecases, no?
sorry, totally missed some comments.
Wanted to keep this as simple as possible right now (the inital version was
too complex), we can always add it in the future.
>
>
>> diff --git a/Documentation/networking/devlink/index.rst b/Documentation/networking/devlink/index.rst
>> index 32f70879ddd0..93f09cb18c44 100644
>> --- a/Documentation/networking/devlink/index.rst
>> +++ b/Documentation/networking/devlink/index.rst
>> @@ -56,6 +56,7 @@ general.
>> :maxdepth: 1
>>
>> devlink-dpipe
>> + devlink-defaults
>> devlink-eswitch-attr
>> devlink-flash
>> devlink-health
>> diff --git a/net/devlink/core.c b/net/devlink/core.c
>
> Wanna have this in a separate file perhaps? "default.c"?
Okay.
Mark
>
>
>> index fe9f6a0a67d5..5126509a9c4e 100644
>> --- a/net/devlink/core.c
>> +++ b/net/devlink/core.c
>> @@ -4,6 +4,10 @@
>> * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
>> */
>>
>> +#include <linux/init.h>
>> +#include <linux/list.h>
>> +#include <linux/slab.h>
>> +#include <linux/string.h>
>> #include <net/genetlink.h>
>> #define CREATE_TRACE_POINTS
>> #include <trace/events/devlink.h>
>> @@ -16,6 +20,193 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_trap_report);
>>
>> DEFINE_XARRAY_FLAGS(devlinks, XA_FLAGS_ALLOC);
>>
>> +static char *devlink_default_esw_mode_param;
>> +static bool devlink_default_esw_mode_match_all;
>> +static enum devlink_eswitch_mode devlink_default_esw_mode;
>> +static LIST_HEAD(devlink_default_esw_mode_nodes);
>> +
>> +struct devlink_default_esw_mode_node {
>> + struct list_head list;
>> + char *bus_name;
>> + char *dev_name;
>> +};
>> +
>> +static int __init
>> +devlink_default_esw_mode_to_value(const char *str,
>> + enum devlink_eswitch_mode *mode)
>> +{
>> + if (!strcmp(str, "legacy")) {
>> + *mode = DEVLINK_ESWITCH_MODE_LEGACY;
>> + return 0;
>> + }
>> + if (!strcmp(str, "switchdev")) {
>> + *mode = DEVLINK_ESWITCH_MODE_SWITCHDEV;
>> + return 0;
>> + }
>> + if (!strcmp(str, "switchdev_inactive")) {
>> + *mode = DEVLINK_ESWITCH_MODE_SWITCHDEV_INACTIVE;
>> + return 0;
>> + }
>> +
>> + return -EINVAL;
>> +}
>> +
>> +static int __init
>> +devlink_default_esw_mode_handle_parse(char *handle, char **bus_name,
>> + char **dev_name)
>> +{
>> + char *slash;
>> + char *p;
>> +
>> + if (!*handle)
>> + return -EINVAL;
>> +
>> + for (p = handle; *p; p++) {
>> + if (*p == '*' || *p == '=')
>> + return -EINVAL;
>> + }
>> +
>> + slash = strchr(handle, '/');
>> + if (!slash || slash == handle || !slash[1])
>> + return -EINVAL;
>> + if (strchr(slash + 1, '/'))
>> + return -EINVAL;
>> +
>> + *slash = '\0';
>> +
>> + *bus_name = handle;
>> + *dev_name = slash + 1;
>> + return 0;
>> +}
>> +
>> +static struct devlink_default_esw_mode_node *
>> +devlink_default_esw_mode_node_find(const char *bus_name, const char *dev_name)
>> +{
>> + struct devlink_default_esw_mode_node *node;
>> +
>> + list_for_each_entry(node, &devlink_default_esw_mode_nodes, list) {
>> + if (!strcmp(node->bus_name, bus_name) &&
>> + !strcmp(node->dev_name, dev_name))
>> + return node;
>> + }
>> +
>> + return NULL;
>> +}
>> +
>> +static int __init
>> +devlink_default_esw_mode_node_add(const char *bus_name, const char *dev_name)
>> +{
>> + struct devlink_default_esw_mode_node *node;
>> +
>> + if (devlink_default_esw_mode_node_find(bus_name, dev_name))
>> + return -EEXIST;
>> +
>> + node = kzalloc_obj(*node);
>> + if (!node)
>> + return -ENOMEM;
>> +
>> + INIT_LIST_HEAD(&node->list);
>> + node->bus_name = kstrdup(bus_name, GFP_KERNEL);
>> + node->dev_name = kstrdup(dev_name, GFP_KERNEL);
>> + if (!node->bus_name || !node->dev_name) {
>> + kfree(node->bus_name);
>> + kfree(node->dev_name);
>> + kfree(node);
>> + return -ENOMEM;
>> + }
>> +
>> + list_add_tail(&node->list, &devlink_default_esw_mode_nodes);
>> + return 0;
>> +}
>> +
>> +static int __init devlink_default_esw_mode_handles_parse(char *handles)
>> +{
>> + char *handle;
>> + int err;
>> +
>> + if (!strcmp(handles, "*")) {
>> + devlink_default_esw_mode_match_all = true;
>> + return 0;
>> + }
>> +
>> + while ((handle = strsep(&handles, ",")) != NULL) {
>> + char *bus_name;
>> + char *dev_name;
>> +
>> + err = devlink_default_esw_mode_handle_parse(handle, &bus_name,
>> + &dev_name);
>> + if (err)
>> + return err;
>> +
>> + err = devlink_default_esw_mode_node_add(bus_name, dev_name);
>> + if (err)
>> + return err;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static void __init
>> +devlink_default_esw_mode_node_free(struct devlink_default_esw_mode_node *node)
>> +{
>> + kfree(node->bus_name);
>> + kfree(node->dev_name);
>> + kfree(node);
>> +}
>> +
>> +static void __init devlink_default_esw_mode_nodes_clear(void)
>> +{
>> + struct devlink_default_esw_mode_node *node;
>> + struct devlink_default_esw_mode_node *node_tmp;
>> +
>> + list_for_each_entry_safe(node, node_tmp,
>> + &devlink_default_esw_mode_nodes, list) {
>> + list_del(&node->list);
>> + devlink_default_esw_mode_node_free(node);
>> + }
>> +
>> + devlink_default_esw_mode_match_all = false;
>> +}
>> +
>> +static int __init devlink_default_esw_mode_parse(char *str)
>> +{
>> + char *handles;
>> + char *separator;
>> + char *mode;
>> + enum devlink_eswitch_mode esw_mode;
>> + int err;
>> +
>> + if (!*str)
>> + return -EINVAL;
>> +
>> + separator = strrchr(str, '=');
>> + if (!separator || separator == str || !separator[1])
>> + return -EINVAL;
>> +
>> + *separator = '\0';
>> + handles = str;
>> + mode = separator + 1;
>> +
>> + err = devlink_default_esw_mode_to_value(mode, &esw_mode);
>> + if (err)
>> + return err;
>> +
>> + err = devlink_default_esw_mode_handles_parse(handles);
>> + if (err)
>> + devlink_default_esw_mode_nodes_clear();
>> + else
>> + devlink_default_esw_mode = esw_mode;
>> +
>> + return err;
>> +}
>> +
>> +static int __init devlink_default_esw_mode_setup(char *str)
>> +{
>> + devlink_default_esw_mode_param = str;
>> + return 1;
>> +}
>> +__setup("devlink_eswitch_mode=", devlink_default_esw_mode_setup);
>> +
>> static struct devlink *devlinks_xa_get(unsigned long index)
>> {
>> struct devlink *devlink;
>> @@ -382,6 +573,14 @@ struct devlink *devlinks_xa_lookup_get(struct net *net, unsigned long index)
>> /**
>> * devl_register - Register devlink instance
>> * @devlink: devlink
>> + *
>> + * Make @devlink visible to userspace. Drivers must call this only after the
>> + * instance is fully initialized and its devlink operations can be called.
>> + *
>> + * Context: Caller must hold the devlink instance lock. Use devlink_register()
>> + * when the lock is not already held.
>> + *
>> + * Return: 0 on success.
>> */
>> int devl_register(struct devlink *devlink)
>> {
>> @@ -580,6 +779,31 @@ static int __init devlink_init(void)
>> {
>> int err;
>>
>> + if (devlink_default_esw_mode_param) {
>> + char *def;
>> +
>> + def = kstrdup(devlink_default_esw_mode_param, GFP_KERNEL);
>> + if (!def) {
>> + devlink_default_esw_mode_param = NULL;
>> + pr_warn("devlink: devlink_eswitch_mode parameter ignored, failed to allocate memory\n");
>> + } else {
>> + err = devlink_default_esw_mode_parse(def);
>> + kfree(def);
>> + if (err == -EEXIST) {
>> + devlink_default_esw_mode_param = NULL;
>> + pr_warn("devlink: duplicate eswitch mode handles ignored\n");
>> + } else if (err == -EINVAL) {
>> + devlink_default_esw_mode_param = NULL;
>> + pr_warn("devlink: invalid devlink_eswitch_mode parameter ignored\n");
>> + } else if (err == -ENOMEM) {
>> + devlink_default_esw_mode_param = NULL;
>> + pr_warn("devlink: devlink_eswitch_mode parameter ignored, failed to allocate memory\n");
>> + } else if (err) {
>> + goto out;
>> + }
>
> Move this to a separate helper alongside the other "default" functions?
>
>
>> + }
>> + }
>> +
>> err = register_pernet_subsys(&devlink_pernet_ops);
>> if (err)
>> goto out;
>> @@ -595,7 +819,10 @@ static int __init devlink_init(void)
>> out_unreg_pernet_subsys:
>> unregister_pernet_subsys(&devlink_pernet_ops);
>> out:
>> + if (err)
>> + devlink_default_esw_mode_nodes_clear();
>> WARN_ON(err);
>> +
>> return err;
>> }
>>
>> --
>> 2.43.0
>>
^ permalink raw reply
* Re: [PATCH net] ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF
From: Breno Leitao @ 2026-07-01 13:15 UTC (permalink / raw)
To: Norbert Szetei
Cc: netdev, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Qingfang Deng, Taegu Ha, Yue Haibing,
Sebastian Andrzej Siewior, Kees Cook, linux-ppp, linux-kernel
In-Reply-To: <C954A7EA-AA98-4E3C-80B5-42C34B3183A3@doyensec.com>
On Wed, Jul 01, 2026 at 02:14:39PM +0200, Norbert Szetei wrote:
> diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
> index 57c68efa5ff8..cb8fe37170d3 100644
> --- a/drivers/net/ppp/ppp_generic.c
> +++ b/drivers/net/ppp/ppp_generic.c
> @@ -184,6 +184,7 @@ struct channel {
> struct list_head clist; /* link in list of channels per unit */
> spinlock_t upl; /* protects `ppp' and 'bridge' */
> struct channel __rcu *bridge; /* "bridged" ppp channel */
> + struct rcu_head rcu; /* for RCU-deferred free of the channel */
> #ifdef CONFIG_PPP_MULTILINK
> u8 avail; /* flag used in multilink stuff */
> u8 had_frag; /* >= 1 fragments have been sent */
> @@ -3583,7 +3584,7 @@ static void ppp_release_channel(struct channel *pch)
> }
> skb_queue_purge(&pch->file.xq);
> skb_queue_purge(&pch->file.rq);
> - kfree(pch);
> + kfree_rcu(pch, rcu);
Why not use kfree_rcu_mightsleep() instead? That would eliminate the need
for the additional `struct rcu_head rcu;` field.
^ permalink raw reply
* Re: [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes
From: George Moussalem @ 2026-07-01 13:15 UTC (permalink / raw)
To: Konrad Dybcio, Jens Axboe, Ulf Hansson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Saravana Kannan, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Bjorn Andersson,
Konrad Dybcio, Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
In-Reply-To: <175f7835-df18-4bc6-8267-ceef35696af8@oss.qualcomm.com>
On 7/1/26 14:40, Konrad Dybcio wrote:
> On 6/29/26 3:01 PM, George Moussalem via B4 Relay wrote:
>> From: George Moussalem <george.moussalem@outlook.com>
>>
>> The Bluetooth subsystem (BTSS) on the IPQ5018 SoC supports setting power
>> modes which are required to be configured through a Secure Channel
>> Manager (SCM) call to TrustZone. However, not all Trusted Execution
>> Environment (QSEE) images support this call, so first check if the call
>> is available.
>>
>> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
>> ---
>
> I'm amazed changing this setting is a secure operation
>
> [...]
>
>> +/**
>> + * qcom_scm_pas_set_bluetooth_power_mode() - Configure power optimization mode
>> + * for the Bluetooth subsystem (BTSS)
>> + * @pas_id: peripheral authentication service id
>> + * @val: 0x0 for normal operation, 0x4 for ECO mode
>
> If there's just two values, maybe we should make this take a `bool eco_mode`?
that was the direction I was going in initially but then thought that
there may be more (undocumented) power modes I'm unaware off so changed
it to u32. I'll change it back to bool.
>
>> + *
>> + * Return: 0 on success, negative errno on failure.
>> + * Returns -EOPNOTSUPP if the firmware configuration call is unavailable.
>> + */
>> +int qcom_scm_pas_set_bluetooth_power_mode(u32 pas_id, u32 val)
>> +{
>> + if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
>> + QCOM_SCM_PIL_PAS_BT_PWR_MODE))
>> + return -EOPNOTSUPP;
>> +
>> + return __qcom_scm_pas_set_bluetooth_power_mode(pas_id, val);
>
> Let's just inline the whole definition here - it's single-use anyway
will update, thanks.
>
> Konrad
Cheers,
George
^ permalink raw reply
* Re: [PATCH net] gve: fix Rx queue stall on alloc failure
From: Maciej Fijalkowski @ 2026-07-01 13:21 UTC (permalink / raw)
To: Harshitha Ramamurthy
Cc: netdev, joshwash, andrew+netdev, davem, edumazet, kuba, pabeni,
ast, daniel, hawk, john.fastabend, bpf, sdf, willemb, jordanrhee,
nktgrg, maolson, jacob.e.keller, thostet, csully, bcf,
linux-kernel, stable, Eddie Phillips
In-Reply-To: <20260701005341.3699161-1-hramamurthy@google.com>
On Wed, Jul 01, 2026 at 12:53:41AM +0000, Harshitha Ramamurthy wrote:
> From: Eddie Phillips <eddiephillips@google.com>
>
> When the system is under extreme memory pressure, page allocations can
> fail during the Rx buffer refill loop. If the number of buffers posted
> to hardware falls below a critical low threshold and the refill loop
> exits due to allocation failures, the queue can stall:
>
> 1. The device drops incoming packets because there are no descriptors.
> 2. Since no packets are processed, no Rx completions are generated.
> 3. Because no completions occur, NAPI is never scheduled, preventing
> the refill loop from running again even after memory is freed.
>
> This results in a permanent queue stall.
>
> Resolve this by introducing a starvation recovery timer for each Rx queue.
> If the number of buffers posted to hardware falls below a critical low
> threshold, start a timer to periodically reschedule NAPI. Once NAPI runs
> and successfully refills the queue above the threshold, the timer is
> not rescheduled.
>
> Also add a new ethtool statistic "rx_critical_low_bufs" to track the
> number of times the starvation recovery timer is triggered.
I think this deserves to be pulled out of the timer logic?
Two questions tho:
- couldn't you detect this case within napi poll loop?
- if not, does it have to be per-q timer? wouldn't one global per pf timer
satisfy your needs?
>
> Cc: stable@vger.kernel.org
> Fixes: 9b8dd5e5ea48 ("gve: DQO: Add RX path")
> Reviewed-by: Jordan Rhee <jordanrhee@google.com>
> Signed-off-by: Eddie Phillips <eddiephillips@google.com>
> Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
> ---
> drivers/net/ethernet/google/gve/gve.h | 4 ++++
> drivers/net/ethernet/google/gve/gve_ethtool.c | 14 +++++++++++++-
> drivers/net/ethernet/google/gve/gve_rx_dqo.c | 32 ++++++++++++++++++++++++++++++++
> 3 files changed, 49 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
> index 2f7bd330..8378bef2 100644
> --- a/drivers/net/ethernet/google/gve/gve.h
> +++ b/drivers/net/ethernet/google/gve/gve.h
> @@ -13,6 +13,7 @@
> #include <linux/netdevice.h>
> #include <linux/net_tstamp.h>
> #include <linux/pci.h>
> +#include <linux/timer.h>
> #include <linux/ptp_clock_kernel.h>
> #include <linux/u64_stats_sync.h>
> #include <net/page_pool/helpers.h>
> @@ -41,6 +42,7 @@
>
> /* Interval to schedule a stats report update, 20000ms. */
> #define GVE_STATS_REPORT_TIMER_PERIOD 20000
> +#define GVE_RX_NAPI_RESCHED_MS 20 /* msecs */
>
> /* Numbers of NIC tx/rx stats in stats report. */
> #define NIC_TX_STATS_REPORT_NUM 0
> @@ -318,6 +320,7 @@ struct gve_rx_ring {
> u64 rx_copied_pkt; /* free-running total number of copied packets */
> u64 rx_skb_alloc_fail; /* free-running count of skb alloc fails */
> u64 rx_buf_alloc_fail; /* free-running count of buffer alloc fails */
> + u64 rx_critical_low_bufs; /* count of critical low buffer events */
> u64 rx_desc_err_dropped_pkt; /* free-running count of packets dropped by descriptor error */
> /* free-running count of unsplit packets due to header buffer overflow or hdr_len is 0 */
> u64 rx_hsplit_unsplit_pkt;
> @@ -334,6 +337,7 @@ struct gve_rx_ring {
> struct gve_queue_resources *q_resources; /* head and tail pointer idx */
> dma_addr_t q_resources_bus; /* dma address for the queue resources */
> struct u64_stats_sync statss; /* sync stats for 32bit archs */
> + struct timer_list starvation_timer; /* for queue starvation recovery */
>
> struct gve_rx_ctx ctx; /* Info for packet currently being processed in this ring. */
>
> diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
> index a0e0472b..71b6efbf 100644
> --- a/drivers/net/ethernet/google/gve/gve_ethtool.c
> +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
> @@ -46,6 +46,7 @@ static const char gve_gstrings_main_stats[][ETH_GSTRING_LEN] = {
> "rx_hsplit_unsplit_pkt",
> "interface_up_cnt", "interface_down_cnt", "reset_cnt",
> "page_alloc_fail", "dma_mapping_error", "stats_report_trigger_cnt",
> + "rx_critical_low_bufs",
> };
>
> static const char gve_gstrings_rx_stats[][ETH_GSTRING_LEN] = {
> @@ -58,6 +59,7 @@ static const char gve_gstrings_rx_stats[][ETH_GSTRING_LEN] = {
> "rx_xdp_aborted[%u]", "rx_xdp_drop[%u]", "rx_xdp_pass[%u]",
> "rx_xdp_tx[%u]", "rx_xdp_redirect[%u]",
> "rx_xdp_tx_errors[%u]", "rx_xdp_redirect_errors[%u]", "rx_xdp_alloc_fails[%u]",
> + "rx_critical_low_bufs[%u]",
> };
>
> static const char gve_gstrings_tx_stats[][ETH_GSTRING_LEN] = {
> @@ -151,12 +153,14 @@ gve_get_ethtool_stats(struct net_device *netdev,
> {
> u64 tmp_rx_pkts, tmp_rx_hsplit_pkt, tmp_rx_bytes, tmp_rx_hsplit_bytes,
> tmp_rx_skb_alloc_fail, tmp_rx_buf_alloc_fail,
> + tmp_rx_critical_low_bufs,
> tmp_rx_desc_err_dropped_pkt, tmp_rx_hsplit_unsplit_pkt,
> tmp_tx_pkts, tmp_tx_bytes,
> tmp_xdp_tx_errors, tmp_xdp_redirect_errors;
> u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_hsplit_unsplit_pkt,
> rx_pkts, rx_hsplit_pkt, rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes,
> - tx_dropped, xdp_tx_errors, xdp_redirect_errors;
> + rx_critical_low_bufs, tx_dropped, xdp_tx_errors,
> + xdp_redirect_errors;
> int rx_base_stats_idx, max_rx_stats_idx, max_tx_stats_idx;
> int stats_idx, stats_region_len, nic_stats_len;
> struct stats *report_stats;
> @@ -197,6 +201,7 @@ gve_get_ethtool_stats(struct net_device *netdev,
>
> for (rx_pkts = 0, rx_bytes = 0, rx_hsplit_pkt = 0,
> rx_skb_alloc_fail = 0, rx_buf_alloc_fail = 0,
> + rx_critical_low_bufs = 0,
> rx_desc_err_dropped_pkt = 0, rx_hsplit_unsplit_pkt = 0,
> xdp_tx_errors = 0, xdp_redirect_errors = 0,
> ring = 0;
> @@ -212,6 +217,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
> tmp_rx_bytes = rx->rbytes;
> tmp_rx_skb_alloc_fail = rx->rx_skb_alloc_fail;
> tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
> + tmp_rx_critical_low_bufs =
> + rx->rx_critical_low_bufs;
> tmp_rx_desc_err_dropped_pkt =
> rx->rx_desc_err_dropped_pkt;
> tmp_rx_hsplit_unsplit_pkt =
> @@ -226,6 +233,7 @@ gve_get_ethtool_stats(struct net_device *netdev,
> rx_bytes += tmp_rx_bytes;
> rx_skb_alloc_fail += tmp_rx_skb_alloc_fail;
> rx_buf_alloc_fail += tmp_rx_buf_alloc_fail;
> + rx_critical_low_bufs += tmp_rx_critical_low_bufs;
> rx_desc_err_dropped_pkt += tmp_rx_desc_err_dropped_pkt;
> rx_hsplit_unsplit_pkt += tmp_rx_hsplit_unsplit_pkt;
> xdp_tx_errors += tmp_xdp_tx_errors;
> @@ -269,6 +277,7 @@ gve_get_ethtool_stats(struct net_device *netdev,
> data[i++] = priv->page_alloc_fail;
> data[i++] = priv->dma_mapping_error;
> data[i++] = priv->stats_report_trigger_cnt;
> + data[i++] = rx_critical_low_bufs;
> i = GVE_MAIN_STATS_LEN;
>
> rx_base_stats_idx = 0;
> @@ -337,6 +346,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
> tmp_rx_hsplit_bytes = rx->rx_hsplit_bytes;
> tmp_rx_skb_alloc_fail = rx->rx_skb_alloc_fail;
> tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
> + tmp_rx_critical_low_bufs =
> + rx->rx_critical_low_bufs;
> tmp_rx_desc_err_dropped_pkt =
> rx->rx_desc_err_dropped_pkt;
> tmp_xdp_tx_errors = rx->xdp_tx_errors;
> @@ -381,6 +392,7 @@ gve_get_ethtool_stats(struct net_device *netdev,
> } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
> start));
> i += GVE_XDP_ACTIONS + 3; /* XDP rx counters */
> + data[i++] = tmp_rx_critical_low_bufs;
> }
> } else {
> i += priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS;
> diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
> index 02cba280..303db4fa 100644
> --- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
> +++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
> @@ -18,6 +18,16 @@
> #include <net/tcp.h>
> #include <net/xdp_sock_drv.h>
>
> +static void gve_rx_starvation_timer(struct timer_list *t)
> +{
> + struct gve_rx_ring *rx = timer_container_of(rx, t, starvation_timer);
> + struct gve_priv *priv = rx->gve;
> + struct gve_notify_block *block;
> +
> + block = &priv->ntfy_blocks[rx->ntfy_id];
> + napi_schedule(&block->napi);
> +}
> +
> static void gve_rx_free_hdr_bufs(struct gve_priv *priv, struct gve_rx_ring *rx)
> {
> struct device *hdev = &priv->pdev->dev;
> @@ -120,6 +130,7 @@ void gve_rx_stop_ring_dqo(struct gve_priv *priv, int idx)
>
> if (rx->dqo.page_pool)
> page_pool_disable_direct_recycling(rx->dqo.page_pool);
> + timer_delete_sync(&rx->starvation_timer);
> gve_remove_napi(priv, ntfy_idx);
> gve_rx_remove_from_block(priv, idx);
> gve_rx_reset_ring_dqo(priv, idx);
> @@ -136,6 +147,8 @@ void gve_rx_free_ring_dqo(struct gve_priv *priv, struct gve_rx_ring *rx,
> u32 qpl_id;
> int i;
>
> + timer_shutdown_sync(&rx->starvation_timer);
> +
> completion_queue_slots = rx->dqo.complq.mask + 1;
> buffer_queue_slots = rx->dqo.bufq.mask + 1;
>
> @@ -232,6 +245,7 @@ int gve_rx_alloc_ring_dqo(struct gve_priv *priv,
> rx->gve = priv;
> rx->q_num = idx;
> rx->packet_buffer_size = cfg->packet_buffer_size;
> + timer_setup(&rx->starvation_timer, gve_rx_starvation_timer, 0);
>
> if (cfg->xdp) {
> rx->packet_buffer_truesize = GVE_XDP_RX_BUFFER_SIZE_DQO;
> @@ -365,6 +379,7 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx)
> struct gve_rx_compl_queue_dqo *complq = &rx->dqo.complq;
> struct gve_rx_buf_queue_dqo *bufq = &rx->dqo.bufq;
> struct gve_priv *priv = rx->gve;
> + u32 num_bufs_avail_to_hw;
> u32 num_avail_slots;
> u32 num_full_slots;
> u32 num_posted = 0;
> @@ -400,6 +415,23 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx)
> }
>
> rx->fill_cnt += num_posted;
> +
> + /* If the queue has fewer than GVE_RX_BUF_THRESH_DQO descriptors
> + * visible to the hardware, and no doorbell was written, the hardware
> + * is in danger of starving and cannot trigger interrupts. Start the
> + * timer to periodically reschedule NAPI and recover from starvation.
> + */
> + num_bufs_avail_to_hw =
> + ((bufq->tail & ~(GVE_RX_BUF_THRESH_DQO - 1)) -
> + bufq->head) & bufq->mask;
> +
> + if (num_bufs_avail_to_hw < GVE_RX_BUF_THRESH_DQO) {
> + u64_stats_update_begin(&rx->statss);
> + rx->rx_critical_low_bufs++;
> + u64_stats_update_end(&rx->statss);
> + mod_timer(&rx->starvation_timer,
> + jiffies + msecs_to_jiffies(GVE_RX_NAPI_RESCHED_MS));
> + }
> }
>
> static void gve_rx_skb_csum(struct sk_buff *skb,
> --
> 2.55.0.rc2.803.g1fd1e6609c-goog
>
>
^ permalink raw reply
* Re: [PATCH net] ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF
From: Sebastian Andrzej Siewior @ 2026-07-01 13:25 UTC (permalink / raw)
To: Norbert Szetei
Cc: netdev, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Qingfang Deng, Taegu Ha, Yue Haibing,
Kees Cook, linux-ppp, linux-kernel
In-Reply-To: <C954A7EA-AA98-4E3C-80B5-42C34B3183A3@doyensec.com>
On 2026-07-01 14:14:39 [+0200], Norbert Szetei wrote:
> --- a/drivers/net/ppp/ppp_generic.c
> +++ b/drivers/net/ppp/ppp_generic.c
> @@ -184,6 +184,7 @@ struct channel {
> struct list_head clist; /* link in list of channels per unit */
> spinlock_t upl; /* protects `ppp' and 'bridge' */
> struct channel __rcu *bridge; /* "bridged" ppp channel */
> + struct rcu_head rcu; /* for RCU-deferred free of the channel */
> #ifdef CONFIG_PPP_MULTILINK
> u8 avail; /* flag used in multilink stuff */
> u8 had_frag; /* >= 1 fragments have been sent */
> @@ -3583,7 +3584,7 @@ static void ppp_release_channel(struct channel *pch)
> }
> skb_queue_purge(&pch->file.xq);
> skb_queue_purge(&pch->file.rq);
> - kfree(pch);
> + kfree_rcu(pch, rcu);
From looking at ppp_input(), what ensures that the skb in-flight is not
added skb_queue which is purged above?
> }
Sebastian
^ permalink raw reply
* [PATCH RFC net-next] net: hns3: add VF representor for tc flower queue selection
From: Jijie Shao @ 2026-07-01 13:08 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, andrew+netdev, horms
Cc: shenjian15, liuyonglong, chenhao418, yangshuaisong, netdev,
linux-kernel, shaojijie
Background
The hns3 driver supports configuring FD (Flow Director) rules via
ethtool to specify queue mapping or drop actions for traffic received
by the PF. ethtool also supports specifying a vf parameter to
configure the same rules for VF traffic (ethtool -U eth0 flow-type
tcp4 vf 1 queue 3).
The community recommends using tc flower to replace ethtool ntuple/rss
flow configuration. tc flower already supports FD rule configuration
on the PF side, but there is currently no mechanism to configure
equivalent rules for VF traffic through tc flower.
The hns3 FD engine is a TCAM-based match+action engine, not a
switching or forwarding engine. It matches packets by the DST_VPORT
tuple (vport_id) in TCAM key metadata, with actions being queue
selection or packet drop. FD rules are configured by the PF driver
and sent to firmware. Since firmware has visibility into all PF and
VF vport resources, the PF can configure queue selection and drop
rules on behalf of VFs.
Motivation
We would like to add tc flower support for configuring queue selection
and drop rules on VF traffic in the hns3 driver. We investigated
several approaches:
Approach A (REDIRECT + QUEUE_MAPPING dual action):
Configure tc flower on the PF netdev, using FLOW_ACTION_REDIRECT to
specify the VF device and FLOW_ACTION_RX_QUEUE_MAPPING for the queue.
However, REDIRECT semantically means "redirect the packet to another
device" (forwarding), while the hns3 FD engine does not forward
packets -- it only matches packets and selects a queue or drops them.
The semantics do not align.
Approach B (MARK encoding vf_id):
Use FLOW_ACTION_MARK high bits to encode the VF ID and
QUEUE_MAPPING for the queue number. But MARK is designed for packet
marking for downstream processing. Encoding driver-internal
parameters in it is a semantic abuse with no community precedent.
Approach C (VF Representor):
Create a representor net_device for each VF. TC flower rules are
configured on the representor, whose identity implicitly encodes
the VF. This approach has clear semantics -- "configure a rule for
VF1" means operating on VF1's representor -- and has precedent
in other drivers. Considering code complexity, semantic correctness,
and alignment with community conventions, we chose Approach C.
This RFC patch presents our initial implementation to gather feedback
on whether this approach is reasonable and what improvements are needed.
Approach
Introduce VF representor net_devices to provide tc flower capability
equivalent to ethtool "flow-type ... vf N queue M".
The PF creates one representor net_device (e.g. eno2_rep0) per VF at
SRIOV enable time, serving as the tc flower rule configuration handle.
The representor is NOT a switch port and does NOT participate in
datapath forwarding -- its ndo_start_xmit simply drops packets.
When a tc flower rule is configured on the representor, the PF driver
automatically extracts the corresponding VF vport from the
representor's cb_priv (struct hclge_vf_rep) and sets DST_VPORT in
the TCAM key to that VF's vport_id, so the FD engine only matches
packets destined for that VF.
Implementation
- Extract hclge_add_cls_flower_common() from hclge_add_cls_flower(),
accepting a struct hclge_vport pointer to derive vport_id and
num_tqps, shared by both PF and VF representor paths.
- Set rule->vf_id to vport->vport_id (0 for PF, hardware-assigned
vport_id for VF) for TCAM DST_VPORT matching and FD counter
differentiation.
- Queue ID is validated against the VF's actual queue count
(vport->nic.kinfo.num_tqps).
- VF representor does NOT support implicit TC selection via classid
(HCLGE_FD_ACTION_SELECT_TC). Only explicit actions are supported:
- FLOW_ACTION_RX_QUEUE_MAPPING: queue selection
- FLOW_ACTION_DROP: packet drop
- VF representor creation failure does not roll back SRIOV. The VF
datapath works independently and is not affected.
- ndo_get_phys_port_name returns "pfNvfM" for user-space
identification.
This is an RFC patch for early review. It has been through basic
verification but is not intended for formal submission. Further
review and testing are required.
Signed-off-by: Jijie Shao <shaojijie@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/Makefile | 2 +-
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 +
.../net/ethernet/hisilicon/hns3/hns3_enet.c | 16 +-
.../ethernet/hisilicon/hns3/hns3pf/hclge_fd.c | 48 +++++-
.../ethernet/hisilicon/hns3/hns3pf/hclge_fd.h | 7 +
.../hisilicon/hns3/hns3pf/hclge_main.c | 2 +
.../hisilicon/hns3/hns3pf/hclge_main.h | 6 +
.../hisilicon/hns3/hns3pf/hclge_vf_rep.c | 159 ++++++++++++++++++
.../hisilicon/hns3/hns3pf/hclge_vf_rep.h | 21 +++
9 files changed, 251 insertions(+), 12 deletions(-)
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_vf_rep.c
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_vf_rep.h
diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile
index 5785d4c5709e..6fd83c959495 100644
--- a/drivers/net/ethernet/hisilicon/hns3/Makefile
+++ b/drivers/net/ethernet/hisilicon/hns3/Makefile
@@ -24,6 +24,6 @@ hclgevf-objs = hns3vf/hclgevf_main.o hns3vf/hclgevf_mbx.o hns3vf/hclgevf_devlin
obj-$(CONFIG_HNS3_HCLGE) += hclge.o hclge-common.o
hclge-objs = hns3pf/hclge_main.o hns3pf/hclge_mdio.o hns3pf/hclge_tm.o hns3pf/hclge_regs.o \
hns3pf/hclge_mbx.o hns3pf/hclge_err.o hns3pf/hclge_debugfs.o hns3pf/hclge_ptp.o hns3pf/hclge_devlink.o \
- hns3pf/hclge_fd.o
+ hns3pf/hclge_fd.o hns3pf/hclge_vf_rep.o
hclge-$(CONFIG_HNS3_DCB) += hns3pf/hclge_dcb.o
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index a8798eecd9fb..d2c1c73617a4 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -796,6 +796,8 @@ struct hnae3_ae_ops {
int (*get_link_diagnosis_info)(struct hnae3_handle *handle,
u32 *status_code);
void (*clean_vf_config)(struct hnae3_ae_dev *ae_dev, int num_vfs);
+ int (*create_vf_reps)(struct hnae3_ae_dev *ae_dev, int num_vfs);
+ void (*destroy_vf_reps)(struct hnae3_ae_dev *ae_dev);
int (*get_dscp_prio)(struct hnae3_handle *handle, u8 dscp,
u8 *tc_map_mode, u8 *priority);
void (*get_wol)(struct hnae3_handle *handle,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 6ecb32e28e79..f393e9f81fa6 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -3211,6 +3211,7 @@ static void hns3_remove(struct pci_dev *pdev)
**/
static int hns3_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
{
+ struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
int ret;
if (!(hns3_is_phys_func(pdev) && IS_ENABLED(CONFIG_PCI_IOV))) {
@@ -3220,13 +3221,24 @@ static int hns3_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
if (num_vfs) {
ret = pci_enable_sriov(pdev, num_vfs);
- if (ret)
+ if (ret) {
dev_err(&pdev->dev, "SRIOV enable failed %d\n", ret);
- else
+ } else {
+ if (ae_dev->ops->create_vf_reps) {
+ ret = ae_dev->ops->create_vf_reps(ae_dev,
+ num_vfs);
+ if (ret)
+ dev_warn(&pdev->dev,
+ "failed to create VF representors: %d\n",
+ ret);
+ }
return num_vfs;
+ }
} else if (!pci_vfs_assigned(pdev)) {
int num_vfs_pre = pci_num_vf(pdev);
+ if (ae_dev->ops->destroy_vf_reps)
+ ae_dev->ops->destroy_vf_reps(ae_dev);
pci_disable_sriov(pdev);
hns3_clean_vf_config(pdev, num_vfs_pre);
} else {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_fd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_fd.c
index 2fccb0a870b5..8cd9a1a8eff1 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_fd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_fd.c
@@ -6,6 +6,7 @@
#include <net/vxlan.h>
#include "hclge_fd.h"
#include "hclge_main.h"
+#include "hclge_vf_rep.h"
static const struct key_info meta_data_key_info[] = {
{ PACKET_TYPE_ID, 6 },
@@ -2285,6 +2286,7 @@ static int hclge_get_cls_key_ip_tos(const struct flow_rule *flow,
}
static int hclge_get_tc_flower_action(struct hclge_dev *hdev,
+ struct hclge_vport *vport,
struct flow_cls_offload *cls_flower,
struct hclge_fd_rule *rule)
{
@@ -2292,10 +2294,17 @@ static int hclge_get_tc_flower_action(struct hclge_dev *hdev,
struct netlink_ext_ack *extack = cls_flower->common.extack;
struct hnae3_handle *handle = &hdev->vport[0].nic;
struct flow_action *action = &flow->action;
+ u16 num_tqps = vport->nic.kinfo.num_tqps;
struct flow_action_entry *act;
int tc;
if (!flow_action_has_entries(&flow->action)) {
+ if (vport != &hdev->vport[0]) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "VF does not support select TC action");
+ return -EOPNOTSUPP;
+ }
+
tc = tc_classid_to_hwtc(handle->netdev, cls_flower->classid);
if (tc < 0 || tc > hdev->tc_max) {
NL_SET_ERR_MSG_FMT_MOD(extack,
@@ -2311,11 +2320,10 @@ static int hclge_get_tc_flower_action(struct hclge_dev *hdev,
act = &action->entries[0];
switch (act->id) {
case FLOW_ACTION_RX_QUEUE_MAPPING:
- if (act->rx_queue >= handle->kinfo.num_tqps) {
+ if (act->rx_queue >= num_tqps) {
NL_SET_ERR_MSG_FMT_MOD(extack,
"queue id (%u) should be less than %u",
- act->rx_queue,
- handle->kinfo.num_tqps);
+ act->rx_queue, num_tqps);
return -EINVAL;
}
@@ -2423,12 +2431,11 @@ static int hclge_check_cls_flower(struct hclge_dev *hdev,
return 0;
}
-int hclge_add_cls_flower(struct hnae3_handle *handle,
- struct flow_cls_offload *cls_flower)
+static int hclge_add_cls_flower_common(struct hclge_dev *hdev,
+ struct hclge_vport *vport,
+ struct flow_cls_offload *cls_flower)
{
struct netlink_ext_ack *extack = cls_flower->common.extack;
- struct hclge_vport *vport = hclge_get_vport(handle);
- struct hclge_dev *hdev = vport->back;
struct hclge_fd_rule *rule;
int ret;
@@ -2451,14 +2458,14 @@ int hclge_add_cls_flower(struct hnae3_handle *handle,
return ret;
}
- ret = hclge_get_tc_flower_action(hdev, cls_flower, rule);
+ ret = hclge_get_tc_flower_action(hdev, vport, cls_flower, rule);
if (ret) {
kfree(rule);
return ret;
}
rule->location = cls_flower->common.prio - 1;
- rule->vf_id = 0;
+ rule->vf_id = vport->vport_id;
rule->cls_flower.cookie = cls_flower->cookie;
rule->rule_type = HCLGE_FD_TC_FLOWER_ACTIVE;
@@ -2469,6 +2476,21 @@ int hclge_add_cls_flower(struct hnae3_handle *handle,
return ret;
}
+int hclge_add_cls_flower(struct hnae3_handle *handle,
+ struct flow_cls_offload *cls_flower)
+{
+ struct hclge_vport *vport = hclge_get_vport(handle);
+
+ return hclge_add_cls_flower_common(vport->back, vport, cls_flower);
+}
+
+int hclge_add_cls_flower_vf(struct hclge_vf_rep *vf_rep,
+ struct flow_cls_offload *cls_flower)
+{
+ return hclge_add_cls_flower_common(vf_rep->hdev, vf_rep->vport,
+ cls_flower);
+}
+
static struct hclge_fd_rule *hclge_find_cls_flower(struct hclge_dev *hdev,
unsigned long cookie)
{
@@ -2522,6 +2544,14 @@ int hclge_del_cls_flower(struct hnae3_handle *handle,
return 0;
}
+int hclge_del_cls_flower_vf(struct hclge_vf_rep *vf_rep,
+ struct flow_cls_offload *cls_flower)
+{
+ struct hclge_dev *hdev = vf_rep->hdev;
+
+ return hclge_del_cls_flower(&hdev->vport[0].nic, cls_flower);
+}
+
static void hclge_sync_fd_list(struct hclge_dev *hdev, struct hlist_head *hlist)
{
struct hclge_fd_rule *rule;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_fd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_fd.h
index 2f66cc9c3c65..200d81ce12c8 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_fd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_fd.h
@@ -6,6 +6,8 @@
struct hnae3_handle;
struct hclge_dev;
+struct hclge_vf_rep;
+struct flow_cls_offload;
int hclge_init_fd_config(struct hclge_dev *hdev);
int hclge_add_fd_entry(struct hnae3_handle *handle, struct ethtool_rxnfc *cmd);
@@ -26,6 +28,11 @@ int hclge_add_cls_flower(struct hnae3_handle *handle,
int hclge_del_cls_flower(struct hnae3_handle *handle,
struct flow_cls_offload *cls_flower);
bool hclge_is_cls_flower_active(struct hnae3_handle *handle);
+
+int hclge_add_cls_flower_vf(struct hclge_vf_rep *vf_rep,
+ struct flow_cls_offload *cls_flower);
+int hclge_del_cls_flower_vf(struct hclge_vf_rep *vf_rep,
+ struct flow_cls_offload *cls_flower);
int hclge_clear_arfs_rules(struct hclge_dev *hdev);
void hclge_sync_fd_table(struct hclge_dev *hdev);
void hclge_rfs_filter_expire(struct hclge_dev *hdev);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index fc8587c80813..5f88187f1ca8 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -10534,6 +10534,8 @@ static const struct hnae3_ae_ops hclge_ops = {
.get_ts_info = hclge_ptp_get_ts_info,
.get_link_diagnosis_info = hclge_get_link_diagnosis_info,
.clean_vf_config = hclge_clean_vport_config,
+ .create_vf_reps = hclge_create_vf_reps,
+ .destroy_vf_reps = hclge_destroy_vf_reps,
.get_dscp_prio = hclge_get_dscp_prio,
.get_wol = hclge_get_wol,
.set_wol = hclge_set_wol,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 7419481422c3..4f11b9c38e69 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -17,6 +17,9 @@
#include "hnae3.h"
#include "hclge_comm_rss.h"
#include "hclge_comm_tqp_stats.h"
+#include "hclge_vf_rep.h"
+
+struct hclge_vf_rep;
#define HCLGE_MOD_VERSION "1.0"
#define HCLGE_DRIVER_NAME "hclge"
@@ -935,6 +938,9 @@ struct hclge_dev {
bool cur_promisc;
int num_alloc_vfs; /* Actual number of VFs allocated */
+ struct hclge_vf_rep **vf_reps;
+ u16 num_vf_reps;
+
struct hclge_comm_tqp *htqp;
struct hclge_vport *vport;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_vf_rep.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_vf_rep.c
new file mode 100644
index 000000000000..c51336040d6f
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_vf_rep.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2026 Hisilicon Limited.
+
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <net/flow_offload.h>
+
+#include "hclge_main.h"
+#include "hclge_vf_rep.h"
+#include "hclge_fd.h"
+
+static netdev_tx_t hclge_vf_rep_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ dev_kfree_skb_any(skb);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+}
+
+static int hclge_vf_rep_get_phys_port_name(struct net_device *dev,
+ char *buf, size_t len)
+{
+ struct hclge_vf_rep *vf_rep = netdev_priv(dev);
+ struct hclge_dev *hdev = vf_rep->hdev;
+ int rc;
+
+ rc = snprintf(buf, len, "pf%uvf%u", PCI_FUNC(hdev->pdev->devfn),
+ vf_rep->vport->vport_id - 1);
+ if (rc >= len)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static int hclge_vf_rep_setup_tc_block_cb(enum tc_setup_type type,
+ void *type_data, void *cb_priv)
+{
+ struct flow_cls_offload *cls_flower = type_data;
+ struct hclge_vf_rep *vf_rep = cb_priv;
+
+ if (!tc_cls_can_offload_and_chain0(vf_rep->netdev, type_data))
+ return -EOPNOTSUPP;
+
+ switch (type) {
+ case TC_SETUP_CLSFLOWER:
+ switch (cls_flower->command) {
+ case FLOW_CLS_REPLACE:
+ return hclge_add_cls_flower_vf(vf_rep, cls_flower);
+ case FLOW_CLS_DESTROY:
+ return hclge_del_cls_flower_vf(vf_rep, cls_flower);
+ default:
+ return -EOPNOTSUPP;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static LIST_HEAD(hclge_vf_rep_block_cb_list);
+
+static int hclge_vf_rep_setup_tc(struct net_device *dev,
+ enum tc_setup_type type, void *type_data)
+{
+ struct hclge_vf_rep *vf_rep = netdev_priv(dev);
+
+ switch (type) {
+ case TC_SETUP_BLOCK:
+ return flow_block_cb_setup_simple(type_data,
+ &hclge_vf_rep_block_cb_list,
+ hclge_vf_rep_setup_tc_block_cb,
+ vf_rep, vf_rep, true);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static const struct net_device_ops hclge_vf_rep_netdev_ops = {
+ .ndo_start_xmit = hclge_vf_rep_xmit,
+ .ndo_get_phys_port_name = hclge_vf_rep_get_phys_port_name,
+ .ndo_setup_tc = hclge_vf_rep_setup_tc,
+};
+
+static void hclge_vf_rep_net_setup(struct net_device *ndev)
+{
+ ndev->netdev_ops = &hclge_vf_rep_netdev_ops;
+ ndev->needs_free_netdev = true;
+ ndev->features |= NETIF_F_HW_TC;
+}
+
+int hclge_create_vf_reps(struct hnae3_ae_dev *ae_dev, int num_vfs)
+{
+ struct hclge_dev *hdev = ae_dev->priv;
+ struct hclge_vf_rep *vf_rep;
+ struct net_device *ndev;
+ char name[IFNAMSIZ];
+ int ret, i;
+
+ if (!num_vfs)
+ return 0;
+
+ hdev->vf_reps = kcalloc(num_vfs, sizeof(struct hclge_vf_rep *),
+ GFP_KERNEL);
+ if (!hdev->vf_reps)
+ return -ENOMEM;
+
+ for (i = 0; i < num_vfs; i++) {
+ snprintf(name, IFNAMSIZ, "%s_rep%d",
+ hdev->vport[0].nic.netdev->name, i);
+ ndev = alloc_netdev(sizeof(struct hclge_vf_rep), name,
+ NET_NAME_UNKNOWN, ether_setup);
+ if (!ndev) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ hclge_vf_rep_net_setup(ndev);
+
+ vf_rep = netdev_priv(ndev);
+ vf_rep->hdev = hdev;
+ vf_rep->vport = &hdev->vport[i + HCLGE_VF_VPORT_START_NUM];
+ vf_rep->netdev = ndev;
+
+ ret = register_netdev(ndev);
+ if (ret) {
+ free_netdev(ndev);
+ goto err;
+ }
+
+ hdev->vf_reps[i] = vf_rep;
+ }
+
+ hdev->num_vf_reps = num_vfs;
+ return 0;
+
+err:
+ while (i--)
+ unregister_netdev(hdev->vf_reps[i]->netdev);
+ kfree(hdev->vf_reps);
+ hdev->vf_reps = NULL;
+ return ret;
+}
+
+void hclge_destroy_vf_reps(struct hnae3_ae_dev *ae_dev)
+{
+ struct hclge_dev *hdev = ae_dev->priv;
+ int i;
+
+ if (!hdev->vf_reps)
+ return;
+
+ for (i = 0; i < hdev->num_vf_reps; i++) {
+ if (hdev->vf_reps[i])
+ unregister_netdev(hdev->vf_reps[i]->netdev);
+ }
+
+ kfree(hdev->vf_reps);
+ hdev->vf_reps = NULL;
+ hdev->num_vf_reps = 0;
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_vf_rep.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_vf_rep.h
new file mode 100644
index 000000000000..fb2080ae627b
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_vf_rep.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2026 Hisilicon Limited. */
+
+#ifndef __HCLGE_VF_REP_H
+#define __HCLGE_VF_REP_H
+
+struct hnae3_ae_dev;
+struct hclge_dev;
+struct hclge_vport;
+struct net_device;
+
+struct hclge_vf_rep {
+ struct hclge_dev *hdev;
+ struct hclge_vport *vport;
+ struct net_device *netdev;
+};
+
+int hclge_create_vf_reps(struct hnae3_ae_dev *ae_dev, int num_vfs);
+void hclge_destroy_vf_reps(struct hnae3_ae_dev *ae_dev);
+
+#endif
base-commit: 1c664ec4b9ea827b609d296921ed5bad8a40a158
--
2.33.0
^ permalink raw reply related
* Re: [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes
From: Konrad Dybcio @ 2026-07-01 13:31 UTC (permalink / raw)
To: George Moussalem, Jens Axboe, Ulf Hansson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Saravana Kannan, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Bjorn Andersson,
Konrad Dybcio, Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
In-Reply-To: <SN7PR19MB6736B784D6A16CBA531DBD5C9DF62@SN7PR19MB6736.namprd19.prod.outlook.com>
On 7/1/26 3:15 PM, George Moussalem wrote:
> On 7/1/26 14:40, Konrad Dybcio wrote:
>> On 6/29/26 3:01 PM, George Moussalem via B4 Relay wrote:
>>> From: George Moussalem <george.moussalem@outlook.com>
>>>
>>> The Bluetooth subsystem (BTSS) on the IPQ5018 SoC supports setting power
>>> modes which are required to be configured through a Secure Channel
>>> Manager (SCM) call to TrustZone. However, not all Trusted Execution
>>> Environment (QSEE) images support this call, so first check if the call
>>> is available.
>>>
>>> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
>>> ---
>>
>> I'm amazed changing this setting is a secure operation
>>
>> [...]
>>
>>> +/**
>>> + * qcom_scm_pas_set_bluetooth_power_mode() - Configure power optimization mode
>>> + * for the Bluetooth subsystem (BTSS)
>>> + * @pas_id: peripheral authentication service id
>>> + * @val: 0x0 for normal operation, 0x4 for ECO mode
>>
>> If there's just two values, maybe we should make this take a `bool eco_mode`?
>
> that was the direction I was going in initially but then thought that
> there may be more (undocumented) power modes I'm unaware off so changed
> it to u32. I'll change it back to bool.
We can always change back if needed
Konrad
^ permalink raw reply
* Re: [PATCH net 1/2] octeon_ep: fix skb frags overflow in the RX path
From: Maciej Fijalkowski @ 2026-07-01 13:31 UTC (permalink / raw)
To: Maoyi Xie
Cc: Veerasenareddy Burru, Sathesh Edara, Andrew Lunn,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
netdev, linux-kernel
In-Reply-To: <20260701112825.1653044-2-maoyixie.tju@gmail.com>
On Wed, Jul 01, 2026 at 07:28:24PM +0800, Maoyi Xie wrote:
> __octep_oq_process_rx() builds an skb for a multi-buffer packet by adding
> one fragment per buffer_size chunk:
>
> data_len = buff_info->len - oq->max_single_buffer_size;
> while (data_len) {
> ...
> skb_add_rx_frag(skb, shinfo->nr_frags, buff_info->page, 0,
> buff_info->len, buff_info->len);
> ...
> }
>
> buff_info->len comes from the device response header
> (be64_to_cpu(resp_hw->length)). Nothing bounds the fragment count against
> MAX_SKB_FRAGS. data_len can be close to 65535. buffer_size defaults to
> about 3776 on 4K pages, so a full packet yields about 18 fragments. That
> is one more than the default MAX_SKB_FRAGS of 17, so skb_add_rx_frag()
> writes past shinfo->frags[].
>
> The driver now drops a packet that would need more fragments than the skb
> can hold. octep_oq_drop_rx() consumes its descriptors, as on the build_skb
> failure path. The same class was fixed in other RX paths, including
> commit 5ffcb7b890f6 ("net: atlantic: fix fragment overflow handling in RX
> path") and commit f0813bcd2d9d ("net: wwan: t7xx: fix potential skb->frags
> overflow in RX path").
>
> Fixes: 37d79d059606 ("octeon_ep: add Tx/Rx processing and interrupt support")
> Co-developed-by: Kaixuan Li <kaixuan.li@ntu.edu.sg>
> Signed-off-by: Kaixuan Li <kaixuan.li@ntu.edu.sg>
> Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
> ---
> drivers/net/ethernet/marvell/octeon_ep/octep_rx.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
> index e6ebc7e44a00c..4ee911b6c0107 100644
> --- a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
> +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
> @@ -476,6 +476,12 @@ static int __octep_oq_process_rx(struct octep_device *oct,
> skb_put(skb, oq->max_single_buffer_size);
> shinfo = skb_shinfo(skb);
> data_len = buff_info->len - oq->max_single_buffer_size;
> + if (DIV_ROUND_UP(data_len, oq->buffer_size) > MAX_SKB_FRAGS) {
> + dev_kfree_skb_any(skb);
> + octep_oq_drop_rx(oq, buff_info,
> + &read_idx, &desc_used);
nit: would it make sense to pass data_len to octep_oq_drop_rx() to avoid
re-calculation here
But besides, wouldn't this be better to do even before build_skb() call ?
> + continue;
> + }
> while (data_len) {
> buff_info = (struct octep_rx_buffer *)
> &oq->buff_info[read_idx];
> --
> 2.34.1
>
>
^ permalink raw reply
* [PATCH iwl-net v3 0/2] ice: fix DFLT Rx rule handling for promisc and switchdev
From: Petr Oros @ 2026-07-01 13:35 UTC (permalink / raw)
To: netdev
Cc: Petr Oros, Tony Nguyen, Przemek Kitszel, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Ivan Vecera, Jacob Keller, Alice Michael, Simon Horman,
Martyna Szapar-Mudlaw, Marcin Szycik, intel-wired-lan,
linux-kernel
Two fixes for the uplink default VSI Rx rule (DFLT) on E810 when the
netdev is in IFF_PROMISC.
Patch 1 drops the redundant per-VLAN promisc expansion that exhausts
the FLU pool on a wide VLAN trunk across several PFs.
Patch 2 keeps the DFLT Rx rule across a switchdev teardown instead of
clobbering the promisc state the operator asked for.
Changes since v2:
- Patch 1: dropped the two vid=0 ICE_SW_LKUP_PROMISC <->
ICE_SW_LKUP_PROMISC_VLAN recipe-swap guards; each swap is net-zero and
guarding the demote stranded the vid=0 rule when the last VLAN was
removed under the DFLT rule.
- Patch 1: drop the now-redundant per-VID multicast promisc rules right
after ice_set_dflt_vsi(). A bridge join raises IFF_ALLMULTI and
IFF_PROMISC in separate sync passes, so the allmulti pass expands the
per-VID rules before the DFLT rule exists; the cleanup keeps them from
lingering and exhausting the FLU pool. exit_dflt_promisc() reinstates
them on promisc off.
- Patch 1: issue ice_set_promisc(ICE_MCAST_PROMISC_BITS) whenever the
netdev is promiscuous, not only when this VSI installs the default VSI
rule, so multicast promisc is not lost when the rule is already in use
(owned by another VSI, or preserved across a switchdev session).
- Patch 1: hoisted the combined VLAN promisc mask in ice_clear_promisc()
into a local for alignment. Dropped Aleksandr's Reviewed-by since the
code changed.
- Patch 2: corrected the Fixes tag to 5c07be96d8b3, the commit that made
ice_eswitch_setup_env() use the idempotent ice_set_dflt_vsi(); before
it a pre-existing promisc DFLT rule made setup fail with -EEXIST so the
release path was never reached.
Link to v2:
https://lore.kernel.org/all/20260622113428.2565255-1-poros@redhat.com/
Link to v1:
https://lore.kernel.org/all/cover.1781786935.git.poros@redhat.com/
Petr Oros (2):
ice: skip per-VLAN promisc rules when default VSI Rx rule is set
ice: preserve uplink DFLT Rx rule on switchdev release
drivers/net/ethernet/intel/ice/ice_eswitch.c | 18 ++-
drivers/net/ethernet/intel/ice/ice_main.c | 111 +++++++++++++++----
2 files changed, 104 insertions(+), 25 deletions(-)
--
2.54.0
^ permalink raw reply
* Re: [PATCH v6 1/9] block: partitions: of: Skip child nodes without reg property
From: Loic Poulain @ 2026-07-01 13:35 UTC (permalink / raw)
To: Rob Herring
Cc: Ulf Hansson, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Konrad Dybcio, Jens Axboe, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Srinivas Kandagatla,
Andrew Lunn, Heiner Kallweit, Russell King, Saravana Kannan,
Christian Marangi, linux-mmc, devicetree, linux-kernel,
linux-arm-msm, linux-block, linux-wireless, ath10k,
linux-bluetooth, netdev, daniel, stable, Bartosz Golaszewski
In-Reply-To: <CAL_JsqKFjk-mdaAAOzNB6rFiJbw5gd4eDpRBLQL-4q+uJKnp3g@mail.gmail.com>
On Tue, Jun 30, 2026 at 11:46 PM Rob Herring <robh@kernel.org> wrote:
>
> On Tue, Jun 30, 2026 at 2:59 PM Loic Poulain
> <loic.poulain@oss.qualcomm.com> wrote:
> >
> > Hi Rob,
> >
> > On Tue, Jun 30, 2026 at 8:02 PM Rob Herring <robh@kernel.org> wrote:
> > >
> > > On Mon, Jun 29, 2026 at 10:55:20AM +0200, Loic Poulain wrote:
> > > > Child nodes of a fixed-partitions node are not necessarily partition
> > > > entries, for example an nvmem-layout node has no reg property. The
> > > > current code passes a NULL reg pointer and uninitialized len to the
> > > > length check, which can result in a kernel panic or silent failure to
> > > > register any partitions.
> > >
> > > That does not sound right to me. A fixed-partitions node should only be
> > > defining partitions with address ranges. I would expect a partition node
> > > could be nvmem-layout, but not the whole address range. If you wanted
> > > the latter, then just do:
> > >
> > > partitions {
> > > ...
> > > };
> > >
> > > nvmem-layout {
> > > ...
> > > };
> >
> > In our case, the nvmem-layout needs to be associated with a specific
> > eMMC hardware partition, nvmem cells can be a simple sub-range within
> > the global eMMC, each hardware partition (boot0, boot1, user...)
> > having its own address spaces.
> >
> > That said, your point about not abusing fixed-partitions is valid. I
> > initially dropped the compatible = "fixed-partitions" from the
> > partitions-boot1 node when it only carries an nvmem-layout and no
> > actual partition entries, making it a plain named container node. But
> > it's a bit fragile if we want to support both nvmem-layout and
> > fixed-partitions.
> >
> > Regarding your expectation of a partition node being a nvmem-layout,
> > do you mean that the nvmem-layout should live under a fixed-partitions
> > node? Something along these lines:
> >
> > partitions-boot1 {
> > compatible = "fixed-partitions";
> > #address-cells = <1>;
> > #size-cells = <1>;
> >
> > nvmem@4400 {
>
> partition@4400
>
> > reg = <0x4400 0x1000>;
> >
> > nvmem-layout {
> > compatible = "fixed-layout";
> > #address-cells = <1>;
> > #size-cells = <1>;
> >
> > wifi_mac_addr: mac-addr@0 {
> > compatible = "mac-base";
> > reg = <0x0 0x6>;
> > #nvmem-cell-cells = <1>;
> > };
> > [...]
>
> Either this or replacing "fixed-partitions" with "fixed-layout" if you
> want to make the whole boot1 partition nvmem-layout looks like the
> right way to me.
Well, now I think both approaches make sense. We should support a
fixed-layout on the entire hw-part/block, while also allowing it
within individual logical partitions.
Support for the former would only require a small rework/addition in
this series (to have the hw boot partition a fixed-layout) . The
latter could come in a follow-up series, as it would require some
additional fwnode logic.
>
> > That makes some sense, this would require extra work for the
> > emmc/block layer to also associate fwnodes with logical partitions,
> > not just the whole disk/hw (hw part), Is that the direction you'd like
> > us to go?
>
> Yes.
>
> > Also, Note that regardless of which approach we settle on, this
> > specific fix/patch remains necessary to validate the partition node
> > and prevent NULL-deref.
>
> Fair enough, though the reasoning for it would be different and
> perhaps should give a warning.
Sure.
Thanks,
Loic
^ permalink raw reply
* [PATCH iwl-net v3 1/2] ice: skip per-VLAN promisc rules when default VSI Rx rule is set
From: Petr Oros @ 2026-07-01 13:36 UTC (permalink / raw)
To: netdev
Cc: Petr Oros, Tony Nguyen, Przemek Kitszel, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Ivan Vecera, Jacob Keller, Alice Michael, Simon Horman,
Martyna Szapar-Mudlaw, Marcin Szycik, intel-wired-lan,
linux-kernel
In-Reply-To: <20260701133601.2118382-1-poros@redhat.com>
When an ice port in a vlan-filtering bridge goes promiscuous (typical for
bond slaves), the driver installs a per-VLAN ICE_SW_LKUP_PROMISC_VLAN rule
for every VID on top of the broad ICE_SW_LKUP_DFLT VSI Rx rule. Each rule
consumes one of the ~32K Flow Lookup Unit (FLU) entries the device shares
across PFs, so a wide trunk (vid 2-4094) over several PFs overruns the
pool: firmware rejects further Add Switch Rules with ENOSPC (AQ 0x10) and
the DFLT Rx rule itself fails to install:
ice 0000:5c:00.1: Failed to set VSI 14 as the default forwarding
VSI, error -5
ice 0000:5c:00.1 ens1f1: Error -5 setting default VSI 14 Rx rule
Once a switch context is overrun the retries can also come back as ENOENT
(AQ 0x2), which has misled triage toward a perceived recipe binding defect
rather than a capacity issue.
The DFLT rule already catches every packet on the port regardless of VLAN
tag, so the per-VLAN promisc expansion is redundant while it is installed.
Skip it at the two sites that drive it, ice_set_promisc() and
ice_vlan_rx_add_vid(), keyed on ice_is_vsi_dflt_vsi() rather than the
netdev IFF_PROMISC flag so a failed or LAG-suppressed DFLT install still
falls back to the per-VLAN rules.
IFF_ALLMULTI and IFF_PROMISC can reach ice_vsi_sync_fltr() in separate
passes (a bridge join sets them through separate calls), so the allmulti
pass may expand the per-VID rules before the DFLT rule exists. Drop those
now-redundant rules right after ice_set_dflt_vsi() installs the DFLT rule;
ice_vsi_exit_dflt_promisc() reinstates them when promisc is cleared.
ice_vsi_sync_fltr() subscribed multicast promiscuity only inside the
"default VSI not yet in use" branch, so a promiscuous VSI that finds the
default VSI rule already present (owned by another VSI, or preserved
across a switchdev session) ended up in unicast promisc with no multicast
subscription. Issue ice_set_promisc(ICE_MCAST_PROMISC_BITS) whenever the
netdev is promiscuous; it is idempotent and returns 0 if the rule is
already present.
Fixes: 1273f89578f2 ("ice: Fix broken IFF_ALLMULTI handling")
Signed-off-by: Petr Oros <poros@redhat.com>
---
v3:
- Dropped the two vid=0 ICE_SW_LKUP_PROMISC <-> ICE_SW_LKUP_PROMISC_VLAN
recipe-swap guards in ice_vlan_rx_add_vid() and ice_vlan_rx_kill_vid();
each swap is net-zero and guarding the demote stranded the vid=0 rule
in ICE_SW_LKUP_PROMISC_VLAN when the last VLAN was removed under the
DFLT rule. Reported by review.
- Drop the now-redundant per-VID multicast promisc rules right after
ice_set_dflt_vsi(). A bridge join raises IFF_ALLMULTI and IFF_PROMISC
in separate sync passes, so the allmulti pass expands the per-VID rules
before the DFLT rule exists; the cleanup keeps them from lingering and
exhausting the FLU pool. ice_vsi_exit_dflt_promisc() reinstates them on
promisc off. Reported by review.
- Issue ice_set_promisc(ICE_MCAST_PROMISC_BITS) whenever the netdev is
promiscuous, not only when this VSI installs the default VSI rule, so
multicast promisc is not lost when the rule is already in use (owned by
another VSI, or preserved across a switchdev session). Reported by
review.
- Hoisted the combined VLAN promisc mask in ice_clear_promisc() into a
local for alignment. Dropped Aleksandr's Reviewed-by since the code
changed.
v2: https://lore.kernel.org/all/20260622113428.2565255-2-poros@redhat.com/
v1: https://lore.kernel.org/all/89efbea9831175e6f57e9fe8557f7a0e48e050b7.1781786935.git.poros@redhat.com/
---
drivers/net/ethernet/intel/ice/ice_main.c | 111 ++++++++++++++++++----
1 file changed, 90 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index b43d420ece99ca..a84de6cf6eb078 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -274,7 +274,8 @@ static int ice_set_promisc(struct ice_vsi *vsi, u8 promisc_m)
if (vsi->type != ICE_VSI_PF)
return 0;
- if (ice_vsi_has_non_zero_vlans(vsi)) {
+ /* skip per-VID expansion; the DFLT Rx rule already covers every VID */
+ if (ice_vsi_has_non_zero_vlans(vsi) && !ice_is_vsi_dflt_vsi(vsi)) {
promisc_m |= (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX);
status = ice_fltr_set_vlan_vsi_promisc(&vsi->back->hw, vsi,
promisc_m);
@@ -304,9 +305,20 @@ static int ice_clear_promisc(struct ice_vsi *vsi, u8 promisc_m)
return 0;
if (ice_vsi_has_non_zero_vlans(vsi)) {
- promisc_m |= (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX);
+ u8 vlan_promisc_m = promisc_m | ICE_PROMISC_VLAN_RX |
+ ICE_PROMISC_VLAN_TX;
+ int vid0_status;
+
+ /* set time used either recipe (per-VID PROMISC_VLAN, or vid=0
+ * PROMISC via the ice_set_promisc() else branch), so clear
+ * both; clearing an absent rule succeeds
+ */
status = ice_fltr_clear_vlan_vsi_promisc(&vsi->back->hw, vsi,
- promisc_m);
+ vlan_promisc_m);
+ vid0_status = ice_fltr_clear_vsi_promisc(&vsi->back->hw,
+ vsi->idx, promisc_m, 0);
+ if (!status)
+ status = vid0_status;
} else {
status = ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx,
promisc_m, 0);
@@ -317,6 +329,59 @@ static int ice_clear_promisc(struct ice_vsi *vsi, u8 promisc_m)
return status;
}
+/**
+ * ice_vsi_exit_dflt_promisc - drop the default VSI Rx rule on promisc off
+ * @vsi: the VSI leaving promiscuous mode
+ *
+ * For an IFF_ALLMULTI VSI with VLANs the per-VID multicast rules are
+ * reinstated before the default rule is cleared so coverage never lapses;
+ * the then redundant vid=0 rule is dropped best-effort. The callees log
+ * their own failures, so error returns are not re-logged here.
+ *
+ * Return: 0 on success, negative on error with the default rule left in place.
+ */
+static int ice_vsi_exit_dflt_promisc(struct ice_vsi *vsi)
+{
+ struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
+ struct net_device *netdev = vsi->netdev;
+ struct ice_hw *hw = &vsi->back->hw;
+ bool restore_mc;
+ int err;
+
+ restore_mc = (vsi->current_netdev_flags & IFF_ALLMULTI) &&
+ ice_vsi_has_non_zero_vlans(vsi);
+
+ if (restore_mc) {
+ err = ice_fltr_set_vlan_vsi_promisc(hw, vsi,
+ ICE_MCAST_VLAN_PROMISC_BITS);
+ if (err && err != -EEXIST)
+ return err;
+ }
+
+ err = ice_clear_dflt_vsi(vsi);
+ if (err)
+ return err;
+
+ if (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+ vlan_ops->ena_rx_filtering(vsi);
+
+ if (restore_mc)
+ ice_fltr_clear_vsi_promisc(hw, vsi->idx, ICE_MCAST_PROMISC_BITS,
+ 0);
+
+ return 0;
+}
+
+/* Drop the per-VID multicast promisc rules, redundant once the default
+ * VSI Rx rule covers every VID. A no-op when the VSI has no VLANs.
+ */
+static void ice_vsi_clear_vlan_mc_promisc(struct ice_vsi *vsi)
+{
+ if (ice_vsi_has_non_zero_vlans(vsi))
+ ice_fltr_clear_vlan_vsi_promisc(&vsi->back->hw, vsi,
+ ICE_MCAST_VLAN_PROMISC_BITS);
+}
+
/**
* ice_vsi_sync_fltr - Update the VSI filter list to the HW
* @vsi: ptr to the VSI
@@ -429,30 +494,35 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
err = 0;
vlan_ops->dis_rx_filtering(vsi);
- /* promiscuous mode implies allmulticast so
- * that VSIs that are in promiscuous mode are
- * subscribed to multicast packets coming to
- * the port
+ /* DFLT now covers every VID; drop the per-VID
+ * multicast promisc rules a prior IFF_ALLMULTI
+ * pass may have installed (separate passes on a
+ * bridge join) so they do not linger and exhaust
+ * the FLU pool. exit_dflt_promisc() reinstates
+ * them on promisc off.
*/
- err = ice_set_promisc(vsi,
- ICE_MCAST_PROMISC_BITS);
- if (err)
- goto out_promisc;
+ ice_vsi_clear_vlan_mc_promisc(vsi);
}
+
+ /* Promiscuous mode implies allmulticast. Subscribe
+ * the VSI to all multicast even when the default VSI
+ * rule is already in use and the block above is
+ * skipped (it may be owned by another VSI, or
+ * preserved across a switchdev session); the unicast
+ * catch-all does not cover the multicast subscription.
+ */
+ err = ice_set_promisc(vsi, ICE_MCAST_PROMISC_BITS);
+ if (err)
+ goto out_promisc;
} else {
/* Clear Rx filter to remove traffic from wire */
if (ice_is_vsi_dflt_vsi(vsi)) {
- err = ice_clear_dflt_vsi(vsi);
+ err = ice_vsi_exit_dflt_promisc(vsi);
if (err) {
- netdev_err(netdev, "Error %d clearing default VSI %i Rx rule\n",
- err, vsi->vsi_num);
vsi->current_netdev_flags |=
IFF_PROMISC;
goto out_promisc;
}
- if (vsi->netdev->features &
- NETIF_F_HW_VLAN_CTAG_FILTER)
- vlan_ops->ena_rx_filtering(vsi);
}
/* disable allmulti here, but only if allmulti is not
@@ -3676,10 +3746,9 @@ int ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
while (test_and_set_bit(ICE_CFG_BUSY, vsi->state))
usleep_range(1000, 2000);
- /* Add multicast promisc rule for the VLAN ID to be added if
- * all-multicast is currently enabled.
- */
- if (vsi->current_netdev_flags & IFF_ALLMULTI) {
+ /* skip the per-VID rule when the DFLT Rx rule already covers this VID */
+ if ((vsi->current_netdev_flags & IFF_ALLMULTI) &&
+ !ice_is_vsi_dflt_vsi(vsi)) {
ret = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx,
ICE_MCAST_VLAN_PROMISC_BITS,
vid);
--
2.54.0
^ permalink raw reply related
* [PATCH iwl-net v3 2/2] ice: preserve uplink DFLT Rx rule on switchdev release
From: Petr Oros @ 2026-07-01 13:36 UTC (permalink / raw)
To: netdev
Cc: Petr Oros, Tony Nguyen, Przemek Kitszel, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Ivan Vecera, Jacob Keller, Alice Michael, Simon Horman,
Martyna Szapar-Mudlaw, Marcin Szycik, intel-wired-lan,
linux-kernel
In-Reply-To: <20260701133601.2118382-1-poros@redhat.com>
When the uplink PF is promiscuous, ice_vsi_sync_fltr() installs an
ICE_SW_LKUP_DFLT catch-all Rx rule on the uplink VSI. Entering switchdev
re-affirms it through the idempotent ice_set_dflt_vsi(), but
ice_eswitch_release_env() removed both the Rx and Tx DFLT rules
unconditionally on teardown. That clobbered a promisc-owned Rx rule: it
disappeared while IFF_PROMISC was still set and the sync path was not
retriggered, leaving the uplink without the catch-all the netdev
requested.
Skip the Rx DFLT removal when the uplink is promiscuous, both in
ice_eswitch_release_env() and the err_def_tx unwind of
ice_eswitch_setup_env(); the Tx leg, owned by switchdev, is still removed.
Test the live netdev->flags, the same value ena_rx_filtering() ->
ice_cfg_vlan_pruning() above already keys on, so the preserved rule and
the pruning state stay consistent, including for a promisc change made
while switchdev ran (which never reached the gated filter sync).
Fixes: 5c07be96d8b3 ("ice: Avoid setting default Rx VSI twice in switchdev setup")
Signed-off-by: Petr Oros <poros@redhat.com>
---
v3:
- Corrected the Fixes tag from 1a1c40df2e80 ("ice: set and release
switchdev environment") to 5c07be96d8b3 ("ice: Avoid setting default
Rx VSI twice in switchdev setup"), the commit that made
ice_eswitch_setup_env() use the idempotent ice_set_dflt_vsi(); before
it a pre-existing promisc DFLT rule made setup fail with -EEXIST so the
release path was never reached. No code change.
v2: https://lore.kernel.org/all/20260622113428.2565255-3-poros@redhat.com/
v1: https://lore.kernel.org/all/deef5756e534ef06c12d910c5305d3fd205d30a0.1781786935.git.poros@redhat.com/
---
drivers/net/ethernet/intel/ice/ice_eswitch.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c
index c30e27bbfe6e25..07e2016fb9481f 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c
@@ -66,8 +66,10 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, false,
ICE_FLTR_TX);
err_def_tx:
- ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, false,
- ICE_FLTR_RX);
+ /* keep the Rx DFLT rule if the uplink is promiscuous (see release_env) */
+ if (!(uplink_vsi->netdev->flags & IFF_PROMISC))
+ ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx,
+ false, ICE_FLTR_RX);
err_def_rx:
ice_vsi_del_vlan_zero(uplink_vsi);
err_vlan_zero:
@@ -276,8 +278,16 @@ static void ice_eswitch_release_env(struct ice_pf *pf)
vlan_ops->ena_rx_filtering(uplink_vsi);
ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, false,
ICE_FLTR_TX);
- ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, false,
- ICE_FLTR_RX);
+
+ /* Keep the Rx DFLT rule if the uplink is promiscuous; it must outlive
+ * the session. Test the live netdev->flags, the same value
+ * ena_rx_filtering() -> ice_cfg_vlan_pruning() above keys its decision
+ * on, so the preserved DFLT rule and the pruning state stay consistent.
+ */
+ if (!(uplink_vsi->netdev->flags & IFF_PROMISC))
+ ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx,
+ false, ICE_FLTR_RX);
+
ice_fltr_add_mac_and_broadcast(uplink_vsi,
uplink_vsi->port_info->mac.perm_addr,
ICE_FWD_TO_VSI);
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v1 net-next 00/10] net: fib_rules: RTNL-less RTM_NEWRULE and RTM_DELRULE.
From: Ido Schimmel @ 2026-07-01 13:38 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: David Ahern, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Kuniyuki Iwashima, netdev
In-Reply-To: <20260629181226.1929658-1-kuniyu@google.com>
On Mon, Jun 29, 2026 at 06:10:52PM +0000, Kuniyuki Iwashima wrote:
> RTM_NEWRULE and RTM_DELRULE acquire rtnl_net_lock(), but this is
> only for fib_unmerge() in IPv4.
>
> Since commit d954a67a7dfa ("ipv4: fib_rule: Move fib4_rules_exit()
> to ->exit()."), RTM_DELRULE no longer needs RTNL.
>
> fib_unmerge() is one-time event for each netns, so we only need
> RTNL for the first IPv4 rule.
>
> This series introduces per-fib_rules_ops mutex and drops RTNL
> from fib_rules code except for the first IPv4 RTM_NEWRULE.
LGTM, thanks:
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
A few nits that can be addressed in a follow-up:
1. Patch #3:
The comment at the top of netns_ipv4 suggests that we should document
the new lock in
Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst
Related: Did you consider moving this lock under
CONFIG_IP_MULTIPLE_TABLES?
2. Patch #5:
Sashiko suggests a mutex_destroy() in fib_rules_unregister():
https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260629181226.1929658-1-kuniyu%40google.com?part=5
^ permalink raw reply
* [PATCH 0/4] drivers/net/ethernet: replace __get_free_pages() with kmalloc()
From: Mike Rapoport (Microsoft) @ 2026-07-01 13:57 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Manish Chopra, Paolo Abeni
Cc: Edward Cree, Przemek Kitszel, Sudarsana Kalluru, Tony Nguyen,
Mike Rapoport, intel-wired-lan, linux-kernel, linux-mm,
linux-net-drivers, netdev
This is a (small) part of larger work of replacing page allocator calls
with kmalloc.
My initial intention a few month ago was to remove ugly casts [1], but then
willy pointed out that Linus objected to something like this [2] and it
looks like more than a decade old technical debt.
Largely, anything that doesn't need struct page (or a memdesc in the
future) should just use kmalloc() or kvmalloc() to allocate memory.
kmalloc() guarantees alignment, physical contiguity and working
virt_to_phys() and beside nicer API that returns void * on alloc and
doesn't require to know the allocation size on free, kmalloc() provides
better debugging capabilities than page allocator.
Another thing is that touching these allocation sites gives the reviewers
opportunity to see if a PAGE_SIZE buffer is actually needed or maybe
another size is appropriate.
For larger allocations that don't need physically contiguous memory
kvmalloc() can be a better option that __get_free_pages() because under
memory pressure it's is easier to allocate several order-0 pages than a
physically contiguous chunk with the same number of pages.
And last, but not least, removing needless calls to page allocator should
help with memdesc (aka project folio) conversion. There will be way less
places to audit to see if the user was actually using struct page.
Also in git:
https://git.kernel.org/pub/scm/linux/kernel/git/rppt/linux.git gfp-to-kmalloc/drivers-net-ethernet
[1] https://lore.kernel.org/all/20251018093002.3660549-1-rppt@kernel.org/
[2] https://lore.kernel.org/all/CA+55aFwp4iy4rtX2gE2WjBGFL=NxMVnoFeHqYa2j1dYOMMGqxg@mail.gmail.com/
---
v2 changes:
- split out ethernet drivers from a larger set
v1: https://patch.msgid.link/20260630-b4-drivers-net-v1-0-672162a91f37@kernel.org
---
Mike Rapoport (Microsoft) (4):
bnx2x: use kzalloc() to allocate mac filtering list
ice: use kzalloc() to allocate staging buffer for reading from GNSS
sfc/siena: use kmalloc() to allocate logging buffer
sfc: use kmalloc() to allocate logging buffer
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 6 +++---
drivers/net/ethernet/intel/ice/ice_gnss.c | 5 +++--
drivers/net/ethernet/sfc/mcdi.c | 7 ++++---
drivers/net/ethernet/sfc/siena/mcdi.c | 7 ++++---
4 files changed, 14 insertions(+), 11 deletions(-)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20260630-b4-drivers-ethernet-b5e085b98ab1
Best regards,
--
Sincerely yours,
Mike.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox