* [PATCH 0/5] clk: qcom: Add PDM GP_MN fractional clock divider driver and DT support
@ 2026-06-02 15:21 Taniya Das
2026-06-02 15:21 ` [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider Taniya Das
` (4 more replies)
0 siblings, 5 replies; 29+ messages in thread
From: Taniya Das @ 2026-06-02 15:21 UTC (permalink / raw)
To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
Richard Cochran, Konrad Dybcio
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel, linux-gpio, netdev,
Taniya Das
The Peripheral Web's PDM hardware block on several Qualcomm SoCs
contains a GP_MN clock divider that generates a fractional output
frequency from a fixed input clock (typically TCXO4):
Fout = Fin * (M / N)
The output is routed to an external GPIO pin via a dedicated pin mux
function, making it useful as a reference clock for external devices.
The hardware uses three registers:
- MDIV: holds M (9-bit numerator)
- NDIV: holds the 1's complement of (N - M) (13-bit period)
- DUTY: holds D, the low-phase count, constrained to M < D < (N - M)
This series adds full upstream support for the block:
Patch 1: dt-bindings YAML schema for qcom,clk-gp-mnd
Patch 2: standalone platform driver using rational_best_approximation()
to find the closest M/N pair, with full clk_ops coverage
(determine_rate, set_rate, recalc_rate, get_duty_cycle,
set_duty_cycle) and AHB bus clock gating around register
accesses
Patch 3: gp_mn pin mux function for QCS8300, SA8775P and SC7280
TLMM pin controllers
Patch 4: pinctrl state nodes for the GP_MN output pin in the
kodiak (SA8775P), lemans (SA8775P) and monaco (QCS8300)
SoC device trees
Patch 5: GP_MN clock controller DT nodes for SA8775P (kodiak,
lemans) and QCS8300 (monaco), clocked from GCC PDM XO4
and AHB clocks with the XO4 pre-assigned to 4.8 MHz
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
---
Taniya Das (5):
dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider
clk: qcom: Add a driver for PDM GP_MN fractional clock divider
pinctrl: qcom: Add gp_mn mux function for QCS8300, SA8775P and SC7280
arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output
arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300
.../devicetree/bindings/clock/qcom,clk-gp-mnd.yaml | 105 +++++++
arch/arm64/boot/dts/qcom/kodiak.dtsi | 21 ++
arch/arm64/boot/dts/qcom/lemans.dtsi | 21 ++
arch/arm64/boot/dts/qcom/monaco.dtsi | 21 ++
drivers/clk/qcom/Kconfig | 15 +
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/clk-gp-mnd.c | 333 +++++++++++++++++++++
drivers/pinctrl/qcom/pinctrl-qcs8300.c | 9 +-
drivers/pinctrl/qcom/pinctrl-sa8775p.c | 8 +-
drivers/pinctrl/qcom/pinctrl-sc7280.c | 8 +-
10 files changed, 539 insertions(+), 3 deletions(-)
---
base-commit: 08484c504b55a98bd100527fbe10a3caf55ff3ff
change-id: 20260602-pdm_clk_gp_mnd_v1-7e9c2c1b39ab
Best regards,
--
Taniya Das <taniya.das@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 29+ messages in thread* [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider 2026-06-02 15:21 [PATCH 0/5] clk: qcom: Add PDM GP_MN fractional clock divider driver and DT support Taniya Das @ 2026-06-02 15:21 ` Taniya Das 2026-06-03 15:25 ` sashiko-bot ` (2 more replies) 2026-06-02 15:21 ` [PATCH 2/5] clk: qcom: Add a driver for PDM GP_MN fractional " Taniya Das ` (3 subsequent siblings) 4 siblings, 3 replies; 29+ messages in thread From: Taniya Das @ 2026-06-02 15:21 UTC (permalink / raw) To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev, Taniya Das Add device tree bindings for the Qualcomm Peripheral Web's PDM GP_MN clock divider. The hardware generates a fractional output frequency from a fixed input clock (typically TCXO4) using the relation Fout = Fin * (M / N), with duty cycle controlled by a separate D register. The clock output is routed over a gpio controlled pin. Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> --- .../devicetree/bindings/clock/qcom,clk-gp-mnd.yaml | 105 +++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml b/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c1688bb3d68d8d476a8d498aa2774606b8b26018 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,clk-gp-mnd.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Peripheral Web's PDM GP_MN Clock Divider + +maintainers: + - Taniya Das <taniya.das@oss.qualcomm.com> + +description: | + The Peripheral Web's PDM GP_MN clock divider receives an input clock + (TCXO4) with frequency Fin and generates an output clock with + frequency Fout = Fin * (M / N) and a duty cycle controlled by D + and routed over a gpio pin. + + The divider is configured using three registers: + + - GP_MN_CLK_MDIV: holds the M value. + - GP_MN_CLK_NDIV: holds the ones complement of (N - M). + - GP_MN_CLK_DUTY: holds the D value. + + For every N input clock cycles the GP_MN produces M output clock + cycles. D is the number of native clock cycles in which the GP_MN + output is low, counted over 2^13 native clock cycles. + + Hardware constraints: + + M <= 511 + N <= 8191 + N > 2 * M + M < D < (N - M) + M and N must be coprime (no common divisor) + +properties: + compatible: + const: qcom,clk-gp-mnd + + reg: + maxItems: 1 + + clocks: + items: + - description: PDM XO4 source clock + - description: PDM AHB bus clock for register access + + clock-names: + items: + - const: pdm_clk + - const: ahb_clk + + '#clock-cells': + const: 0 + + clock-output-names: + maxItems: 1 + + pinctrl-0: + description: Pin configuration for the GP_MN output in the active state. + + pinctrl-names: + items: + - const: active + + assigned-clocks: + maxItems: 1 + description: Parent clock phandle used to set the input frequency. + + assigned-clock-rates: + maxItems: 1 + description: | + Rate for the parent clock in Hz. + Supported rates: 19200000, 9600000, 6400000, 4800000. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - clock-output-names + - pinctrl-0 + - pinctrl-names + - assigned-clocks + - assigned-clock-rates + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/qcom,gcc-sdm845.h> + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x88d3000 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + pinctrl-0 = <&gp_mn_pin_active>; + pinctrl-names = "active"; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + #clock-cells = <0>; + }; -- 2.34.1 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider 2026-06-02 15:21 ` [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider Taniya Das @ 2026-06-03 15:25 ` sashiko-bot 2026-06-09 13:24 ` Konrad Dybcio 2026-06-09 13:25 ` Konrad Dybcio 2 siblings, 0 replies; 29+ messages in thread From: sashiko-bot @ 2026-06-03 15:25 UTC (permalink / raw) To: Taniya Das; +Cc: robh, conor+dt, devicetree Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: - [Medium] The binding incorrectly defines and mandates generic clock configuration properties (`assigned-clocks`, `assigned-clock-rates`). - [Medium] The compatible string `qcom,clk-gp-mnd` is too generic and lacks an SoC-specific identifier. - [Low] Generic pinctrl properties (`pinctrl-0`, `pinctrl-names`) are marked as strictly required. - [Low] The `pinctrl-names` property is restricted exclusively to the `"active"` state, omitting standard states or an inactive state. -- commit 3c2905ca3a8455710ab289217cbf668b7b5c48ce Author: Taniya Das <taniya.das@oss.qualcomm.com> dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider Add device tree bindings for the Qualcomm Peripheral Web's PDM GP_MN clock divider. The hardware generates a fractional output frequency from a fixed input clock with a controllable duty cycle. > diff --git a/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml b/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml > new file mode 100644 > index 0000000000000..c1688bb3d68d8 > --- /dev/null > +++ b/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml [ ... ] > +properties: > + compatible: > + const: qcom,clk-gp-mnd [Severity: Medium] Should this compatible string include an SoC-specific identifier? Devicetree guidelines usually require an SoC-specific compatible string (e.g., "qcom,sa8775p-clk-gp-mnd") even when a generic fallback is provided. This ensures that future hardware quirks can be handled without modifying existing shipped device trees. [ ... ] > + pinctrl-names: > + items: > + - const: active [Severity: Low] Does restricting this to only "active" prevent the core framework from automatically applying the pins? The standard pinctrl framework usually expects a "default" state to apply the configuration upon device probe. Omitting it forces the driver to manually apply the state. Additionally, this prevents defining a low-power state (like "sleep" or "idle") for suspend or driver removal. > + > + assigned-clocks: > + maxItems: 1 > + description: Parent clock phandle used to set the input frequency. > + > + assigned-clock-rates: > + maxItems: 1 > + description: | > + Rate for the parent clock in Hz. > + Supported rates: 19200000, 9600000, 6400000, 4800000. [Severity: Medium] Should these generic clock configuration properties be explicitly defined here? Properties like assigned-clocks and assigned-clock-rates are common core device tree directives. Defining them in the binding enforces software configuration policy rather than describing the hardware. > + > +required: > + - compatible > + - reg > + - clocks > + - clock-names > + - '#clock-cells' > + - clock-output-names > + - pinctrl-0 > + - pinctrl-names [Severity: Low] Is it necessary to strictly require the pinctrl properties? Since pins can sometimes be pre-configured by earlier boot stages or firmware, mandating them as required can reject valid hardware descriptions unless the hardware is fundamentally non-functional without OS-level muxing. > + - assigned-clocks > + - assigned-clock-rates [Severity: Medium] Should generic clock configurations be mandated as strictly required? Because these define software configuration policy, requiring them will wrongly reject valid hardware descriptions where the bootloader has already configured the clock or the driver relies on a default rate. -- Sashiko AI review · https://sashiko.dev/#/patchset/20260602-pdm_clk_gp_mnd_v1-v1-0-1522662b6c53@oss.qualcomm.com?part=1 ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider 2026-06-02 15:21 ` [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider Taniya Das 2026-06-03 15:25 ` sashiko-bot @ 2026-06-09 13:24 ` Konrad Dybcio 2026-10-15 7:15 ` Taniya Das 2026-06-09 13:25 ` Konrad Dybcio 2 siblings, 1 reply; 29+ messages in thread From: Konrad Dybcio @ 2026-06-09 13:24 UTC (permalink / raw) To: Taniya Das, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/2/26 5:21 PM, Taniya Das wrote: > Add device tree bindings for the Qualcomm Peripheral Web's PDM GP_MN > clock divider. The hardware generates a fractional output frequency > from a fixed input clock (typically TCXO4) using the relation > Fout = Fin * (M / N), with duty cycle controlled by a separate D > register. The clock output is routed over a gpio controlled pin. > > Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> > --- [...] > + #include <dt-bindings/clock/qcom,gcc-sdm845.h> > + gp_mn: clock-controller@88d3000 { > + compatible = "qcom,clk-gp-mnd"; The compatible must be SoC-specific, looking at the table, we could use these example socs for the versions of this block: 8960 (v1.0.0) 8974 (v1.1.1) 8994 (v2.1.0) 8996 (v2.2.0) > + reg = <0x88d3000 0xc>; Let's map the entire 0x4000 that this block spans Konrad ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider 2026-06-09 13:24 ` Konrad Dybcio @ 2026-10-15 7:15 ` Taniya Das 0 siblings, 0 replies; 29+ messages in thread From: Taniya Das @ 2026-10-15 7:15 UTC (permalink / raw) To: Konrad Dybcio, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/9/2026 6:54 PM, Konrad Dybcio wrote: > On 6/2/26 5:21 PM, Taniya Das wrote: >> Add device tree bindings for the Qualcomm Peripheral Web's PDM GP_MN >> clock divider. The hardware generates a fractional output frequency >> from a fixed input clock (typically TCXO4) using the relation >> Fout = Fin * (M / N), with duty cycle controlled by a separate D >> register. The clock output is routed over a gpio controlled pin. >> >> Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> >> --- > > [...] > >> + #include <dt-bindings/clock/qcom,gcc-sdm845.h> >> + gp_mn: clock-controller@88d3000 { >> + compatible = "qcom,clk-gp-mnd"; > > The compatible must be SoC-specific, looking at the table, we could > use these example socs for the versions of this block: > > 8960 (v1.0.0) > 8974 (v1.1.1) > 8994 (v2.1.0) > 8996 (v2.2.0) > Apologies for the late response. The GP_MND block does not have any functional differences across the supported SoCs. To reflect this, the DT binding will use a SoC-specific compatible followed by a generic fallback compatible that represents the common GP_MND implementation. compatible = "qcom,sc7280-gp-mnd", "qcom,gp-mnd"; >> + reg = <0x88d3000 0xc>; > > Let's map the entire 0x4000 that this block spans > This region support 2 or 3 different blocks of HW and they have different functionalities and for which I am going to add the driver support. What I can do is map 0x88d3000 size - 0x1000. Please let me know your comments. -- Thanks, Taniya Das ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider 2026-06-02 15:21 ` [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider Taniya Das 2026-06-03 15:25 ` sashiko-bot 2026-06-09 13:24 ` Konrad Dybcio @ 2026-06-09 13:25 ` Konrad Dybcio 2026-10-15 7:15 ` Taniya Das 2 siblings, 1 reply; 29+ messages in thread From: Konrad Dybcio @ 2026-06-09 13:25 UTC (permalink / raw) To: Taniya Das, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/2/26 5:21 PM, Taniya Das wrote: > Add device tree bindings for the Qualcomm Peripheral Web's PDM GP_MN > clock divider. The hardware generates a fractional output frequency > from a fixed input clock (typically TCXO4) using the relation > Fout = Fin * (M / N), with duty cycle controlled by a separate D > register. The clock output is routed over a gpio controlled pin. > > Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> > --- [...] > + clock-output-names: > + maxItems: 1 This should be deferred to the driver > + > + pinctrl-0: > + description: Pin configuration for the GP_MN output in the active state. > + > + pinctrl-names: > + items: > + - const: active I think these 2 are always allowed/defined > + > + assigned-clocks: > + maxItems: 1 > + description: Parent clock phandle used to set the input frequency. > + > + assigned-clock-rates: > + maxItems: 1 > + description: | > + Rate for the parent clock in Hz. > + Supported rates: 19200000, 9600000, 6400000, 4800000. Likewise, we could simply set_rate on the GCC clock which is the parent of this one, via something like CLK_SET_RATE_PARENT Konrad ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider 2026-06-09 13:25 ` Konrad Dybcio @ 2026-10-15 7:15 ` Taniya Das 0 siblings, 0 replies; 29+ messages in thread From: Taniya Das @ 2026-10-15 7:15 UTC (permalink / raw) To: Konrad Dybcio, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/9/2026 6:55 PM, Konrad Dybcio wrote: > On 6/2/26 5:21 PM, Taniya Das wrote: >> Add device tree bindings for the Qualcomm Peripheral Web's PDM GP_MN >> clock divider. The hardware generates a fractional output frequency >> from a fixed input clock (typically TCXO4) using the relation >> Fout = Fin * (M / N), with duty cycle controlled by a separate D >> register. The clock output is routed over a gpio controlled pin. >> >> Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> >> --- > > [...] >> + clock-output-names: >> + maxItems: 1 > > This should be deferred to the driver Sure. > >> + >> + pinctrl-0: >> + description: Pin configuration for the GP_MN output in the active state. >> + >> + pinctrl-names: >> + items: >> + - const: active > > I think these 2 are always allowed/defined Sure, will remove them. >> + >> + assigned-clocks: >> + maxItems: 1 >> + description: Parent clock phandle used to set the input frequency. >> + >> + assigned-clock-rates: >> + maxItems: 1 >> + description: | >> + Rate for the parent clock in Hz. >> + Supported rates: 19200000, 9600000, 6400000, 4800000. > > Likewise, we could simply set_rate on the GCC clock which is the > parent of this one, via something like CLK_SET_RATE_PARENT The GCC clock could be either at 19.2MHz, 9.6MHz, 6.4MHz, or 4.8MHz(consumer/customer use case dependent) and the output clock at GP_MND can be a range of frequencies(which are not fixed). assigned-clock-rates | v bi_tcxo (19.2 MHz) | v CDIV (1, 2, 3, 4) | | v gcc_pdm_xo4_clk (CBC) | +----> 19.2 MHz +----> 9.6 MHz +----> 6.4 MHz +----> 4.8 MHz | v PDM GP_MND (Variable frequency range) I missed one patch where I didn't add the CLK_SET_RATE_PARENT on the gcc_pdm_xo4_clk and CDIV(additional) modelling. -- Thanks, Taniya Das ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 2/5] clk: qcom: Add a driver for PDM GP_MN fractional clock divider 2026-06-02 15:21 [PATCH 0/5] clk: qcom: Add PDM GP_MN fractional clock divider driver and DT support Taniya Das 2026-06-02 15:21 ` [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider Taniya Das @ 2026-06-02 15:21 ` Taniya Das 2026-06-03 15:25 ` sashiko-bot 2026-06-08 3:31 ` Dmitry Baryshkov 2026-06-02 15:21 ` [PATCH 3/5] pinctrl: qcom: Add gp_mn mux function for QCS8300, SA8775P and SC7280 Taniya Das ` (2 subsequent siblings) 4 siblings, 2 replies; 29+ messages in thread From: Taniya Das @ 2026-06-02 15:21 UTC (permalink / raw) To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev, Taniya Das The PDM (Pulse Density Modulation) hardware block on Qualcomm SoCs contains a GP_MN clock divider that produces a fractional output frequency from a fixed input clock (typically TCXO4): Fout = Fin * (M / N) The hardware encodes the period in the NDIV register as the 1's complement of (N - M), and controls the duty cycle via a separate DUTY register that counts the number of low-phase native clock cycles over the period N. Add a standalone platform driver for this block that uses rational_best_approximation() to find the closest M/N pair within the 9-bit M and 13-bit N hardware limits, programs the MDIV, NDIV, and DUTY registers via regmap, and implements the full clk_ops surface including determine_rate, set_rate, recalc_rate, get_duty_cycle, and set_duty_cycle. The PDM AHB bus clock is gated around every register access. Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> --- drivers/clk/qcom/Kconfig | 15 ++ drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/clk-gp-mnd.c | 333 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 349 insertions(+) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index d9cff5b0281d8cc373b8ab14683370cb9b7f8bf3..df27aa10243435a20a57cca3ed4644284630d11e 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -1759,4 +1759,19 @@ config SM_VIDEOCC_8450 SM8450 or SM8475 devices. Say Y if you want to support video devices and functionality such as video encode/decode. + +config QCOM_CLK_GP_MND + tristate "Qualcomm PDM GP_MN clock divider" + depends on ARM64 || COMPILE_TEST + help + Support for the Qualcomm PDM GP_MN clock divider found in PDM + (Pulse Density Modulation) hardware blocks. + Given an input clock of frequency Fin (TCXO4), the output + frequency is Fout = Fin * (M / N). For every N input cycles + the divider produces M output cycles. D controls the duty + cycle: it is the number of native clock cycles in which the + GP_MN output is low, counted over 8192 native clock cycles. + + Say Y or M if you want to support GP_MN-based frequency and + duty-cycle configuration on Qualcomm SoCs. endif diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index e100cfd6a52de9f88f11720d9c2043db5e553618..438f59b25c009ee72308fe41707d6efff6613690 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -207,6 +207,7 @@ obj-$(CONFIG_SM_VIDEOCC_8550) += videocc-sm8550.o obj-$(CONFIG_SM_VIDEOCC_8750) += videocc-sm8750.o obj-$(CONFIG_SM_VIDEOCC_MILOS) += videocc-milos.o obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o +obj-$(CONFIG_QCOM_CLK_GP_MND) += clk-gp-mnd.o obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o obj-$(CONFIG_QCOM_HFPLL) += hfpll.o obj-$(CONFIG_KRAITCC) += krait-cc.o diff --git a/drivers/clk/qcom/clk-gp-mnd.c b/drivers/clk/qcom/clk-gp-mnd.c new file mode 100644 index 0000000000000000000000000000000000000000..826b6b62ddc7b272511accde1ca0e885018a8064 --- /dev/null +++ b/drivers/clk/qcom/clk-gp-mnd.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/pinctrl/consumer.h> +#include <linux/platform_device.h> +#include <linux/rational.h> +#include <linux/regmap.h> + +/* + * PDM GP_MND clock divider register offsets. + * + * The hardware computes: + * Fout = Fin * (M / N) + * + * with duty cycle controlled by D, where M < D < (N - M). + * + * Register encoding: + * MDIV = M + * NDIV = ~(N - M) [1's complement of (N - M), masked to N_REG_WIDTH bits] + * DUTY = D + */ +#define GP_MND_MDIV_REG 0x0 +#define GP_MND_NDIV_REG 0x4 +#define GP_MND_DUTY_REG 0x8 + +#define GP_MND_M_WIDTH 9 +#define GP_MND_N_WIDTH 13 + +#define GP_MND_MAX_M GENMASK(GP_MND_M_WIDTH - 1, 0) +#define GP_MND_MAX_N GENMASK(GP_MND_N_WIDTH - 1, 0) + +/** + * struct clk_gp_mnd - GP_MND fractional clock divider + * @pdm_ahb_clk: AHB bus clock required for register access + * @regmap: register map for the PDM block + * @hw: handle between common and hardware-specific interfaces + * @m_val: M value (numerator) + * @n_val: N value (period) + */ +struct clk_gp_mnd { + struct clk *pdm_ahb_clk; + struct regmap *regmap; + struct clk_hw hw; + unsigned int m_val; + unsigned int n_val; +}; + +#define to_clk_gp_mnd(_hw) container_of(_hw, struct clk_gp_mnd, hw) + +static int gp_mnd_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + unsigned long m = 0, n = 0; + + rational_best_approximation(req->rate, req->best_parent_rate, + (unsigned long)GP_MND_MAX_M, + (unsigned long)GP_MND_MAX_N, + &m, &n); + + if (!m || !n) + return -EINVAL; + + /* N = 2M + 1 leaves no valid D satisfying M < D < (N - M) */ + if (n == 2 * m + 1) + return -EINVAL; + + req->rate = DIV_ROUND_CLOSEST_ULL((u64)req->best_parent_rate * m, n); + + return 0; +} + +static int gp_mnd_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned long m = 0, n = 0; + unsigned int d_val, n_val; + int ret; + + rational_best_approximation(rate, parent_rate, + (unsigned long)GP_MND_MAX_M, + (unsigned long)GP_MND_MAX_N, + &m, &n); + + if (!m || !n) + return -EINVAL; + + /* + * When N = 2M + 1 the valid D range [M+1, M] is empty; no duty + * cycle can satisfy M < D < (N - M). Reject before touching hw. + */ + if (n == 2 * m + 1) + return -EINVAL; + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return ret; + + ret = regmap_write(gp->regmap, GP_MND_MDIV_REG, m); + if (ret) + goto err_unprepare; + + /* N divider holds the 1's complement of (N - M), N_WIDTH bits wide */ + n_val = ~(n - m) & GP_MND_MAX_N; + ret = regmap_write(gp->regmap, GP_MND_NDIV_REG, n_val); + if (ret) + goto err_unprepare; + + /* Program the closest-to-50% duty cycle. */ + d_val = n / 2; + ret = regmap_write(gp->regmap, GP_MND_DUTY_REG, d_val); + if (ret) + goto err_unprepare; + + gp->m_val = m; + gp->n_val = n; + +err_unprepare: + clk_disable_unprepare(gp->pdm_ahb_clk); + + return ret; +} + +static unsigned long gp_mnd_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned int m_val, n_val; + int ret; + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return 0; + + ret = regmap_read(gp->regmap, GP_MND_MDIV_REG, &m_val); + if (ret) + goto out_unprepare; + + m_val &= GP_MND_MAX_M; + + ret = regmap_read(gp->regmap, GP_MND_NDIV_REG, &n_val); + if (ret) + goto out_unprepare; + + /* Reverse the 1's complement encoding: N = ~NDIV_REG + M */ + n_val = (~n_val & GP_MND_MAX_N) + m_val; + +out_unprepare: + clk_disable_unprepare(gp->pdm_ahb_clk); + + if (ret) + return 0; + + if (!n_val) + return 0; + + gp->m_val = m_val; + gp->n_val = n_val; + + return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * m_val, n_val); +} + +static int gp_mnd_clk_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned int d_val; + int ret; + + if (!gp->n_val) { + duty->num = 1; + duty->den = 2; + return 0; + } + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return ret; + + ret = regmap_read(gp->regmap, GP_MND_DUTY_REG, &d_val); + + clk_disable_unprepare(gp->pdm_ahb_clk); + + if (ret) + return ret; + + duty->num = d_val; + duty->den = gp->n_val; + + return 0; +} + +static int gp_mnd_clk_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned int d_val; + int ret; + + if (!gp->n_val || !gp->m_val) + return -EINVAL; + + /* D = (1 - duty) * N, giving the low-phase count */ + d_val = DIV_ROUND_UP((u64)(duty->den - duty->num) * gp->n_val, duty->den); + + /* Hardware constraint: M < D < (N - M) */ + if (d_val <= gp->m_val || d_val >= (gp->n_val - gp->m_val)) + return -EINVAL; + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return ret; + + ret = regmap_write(gp->regmap, GP_MND_DUTY_REG, d_val); + + clk_disable_unprepare(gp->pdm_ahb_clk); + + return ret; +} + +static const struct clk_ops clk_gp_mnd_ops = { + .determine_rate = gp_mnd_clk_determine_rate, + .set_rate = gp_mnd_clk_set_rate, + .recalc_rate = gp_mnd_clk_recalc_rate, + .get_duty_cycle = gp_mnd_clk_get_duty_cycle, + .set_duty_cycle = gp_mnd_clk_set_duty_cycle, +}; + +static const struct regmap_config gp_mnd_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, +}; + +static int clk_gp_mnd_probe(struct platform_device *pdev) +{ + struct clk_parent_data parent_data = { .index = 0 }; + struct clk_init_data init = { + .ops = &clk_gp_mnd_ops, + .parent_data = &parent_data, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }; + struct device *dev = &pdev->dev; + struct clk_gp_mnd *gp; + struct clk *clk; + struct pinctrl *pin; + struct pinctrl_state *pin_default_state; + void __iomem *base; + int ret; + + gp = devm_kzalloc(dev, sizeof(*gp), GFP_KERNEL); + if (!gp) + return -ENOMEM; + + gp->pdm_ahb_clk = devm_clk_get(dev, "ahb_clk"); + if (IS_ERR(gp->pdm_ahb_clk)) + return dev_err_probe(dev, PTR_ERR(gp->pdm_ahb_clk), + "failed to get ahb_clk\n"); + + clk = devm_clk_get(dev, "pdm_clk"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + /* Set default rate if not already configured */ + if (!clk_get_rate(clk)) { + ret = clk_set_rate(clk, 19200000); + if (ret) + dev_warn(dev, "failed to set default pdm_clk rate\n"); + } + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "failed to map PDM registers\n"); + + gp->regmap = devm_regmap_init_mmio(dev, base, &gp_mnd_regmap_config); + if (IS_ERR(gp->regmap)) + return dev_err_probe(dev, PTR_ERR(gp->regmap), + "failed to init regmap\n"); + + ret = of_property_read_string_index(dev->of_node, + "clock-output-names", 0, + &init.name); + if (ret) + return dev_err_probe(dev, ret, "missing clock-output-names\n"); + + gp->hw.init = &init; + + pin = devm_pinctrl_get(dev); + if (IS_ERR(pin)) + return dev_err_probe(dev, PTR_ERR(pin), "missing pinctrl device\n"); + + pin_default_state = pinctrl_lookup_state(pin, "active"); + if (IS_ERR(pin_default_state)) + return dev_err_probe(dev, PTR_ERR(pin_default_state), + "missing pinctrl default state\n"); + + ret = pinctrl_select_state(pin, pin_default_state); + if (ret) + return dev_err_probe(dev, ret, + "failed to select pinctrl default state\n"); + + ret = devm_clk_hw_register(dev, &gp->hw); + if (ret) + return dev_err_probe(dev, ret, + "failed to register gp_mnd clock\n"); + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &gp->hw); +} + +static const struct of_device_id clk_gp_mnd_match_table[] = { + { .compatible = "qcom,clk-gp-mnd" }, + { } +}; +MODULE_DEVICE_TABLE(of, clk_gp_mnd_match_table); + +static struct platform_driver clk_gp_mnd_driver = { + .probe = clk_gp_mnd_probe, + .driver = { + .name = "qcom-clk-gp-mnd", + .of_match_table = clk_gp_mnd_match_table, + }, +}; +module_platform_driver(clk_gp_mnd_driver); + +MODULE_DESCRIPTION("Qualcomm PDM GP_MND clock divider driver"); +MODULE_LICENSE("GPL"); -- 2.34.1 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 2/5] clk: qcom: Add a driver for PDM GP_MN fractional clock divider 2026-06-02 15:21 ` [PATCH 2/5] clk: qcom: Add a driver for PDM GP_MN fractional " Taniya Das @ 2026-06-03 15:25 ` sashiko-bot 2026-06-08 3:31 ` Dmitry Baryshkov 1 sibling, 0 replies; 29+ messages in thread From: sashiko-bot @ 2026-06-03 15:25 UTC (permalink / raw) To: Taniya Das; +Cc: devicetree, conor+dt, robh Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: - [High] `gp_mnd_clk_get_duty_cycle` incorrectly returns the low-phase ratio instead of the high-phase ratio, violating the CCF API. - [High] `determine_rate` and `set_rate` fail to reject configurations where `N <= 2M`, leading to invalid hardware states and integer underflow. - [Medium] Relying on `parent_data.index = 0` is brittle and may select the wrong parent clock from the DT node. -- commit 7c3592c8935c3d0c132fc4ece0d8bc638c3fc17a Author: Taniya Das <taniya.das@oss.qualcomm.com> clk: qcom: Add a driver for PDM GP_MN fractional clock divider This commit adds a standalone platform driver for the PDM GP_MN clock divider. It provides rate and duty-cycle configuration by programming the MDIV, NDIV, and DUTY registers. > diff --git a/drivers/clk/qcom/clk-gp-mnd.c b/drivers/clk/qcom/clk-gp-mnd.c > new file mode 100644 > index 0000000000000..826b6b62ddc7b > --- /dev/null > +++ b/drivers/clk/qcom/clk-gp-mnd.c [ ... ] > +static int gp_mnd_clk_determine_rate(struct clk_hw *hw, > + struct clk_rate_request *req) > +{ > + unsigned long m = 0, n = 0; > + > + rational_best_approximation(req->rate, req->best_parent_rate, > + (unsigned long)GP_MND_MAX_M, > + (unsigned long)GP_MND_MAX_N, > + &m, &n); > + > + if (!m || !n) > + return -EINVAL; > + > + /* N = 2M + 1 leaves no valid D satisfying M < D < (N - M) */ > + if (n == 2 * m + 1) > + return -EINVAL; [Severity: High] Does this check fail to reject all invalid configurations where n <= 2 * m? The hardware constraint M < D < (N - M) requires N >= 2M + 2, but this code only checks for exact equality. [ ... ] > +static int gp_mnd_clk_set_rate(struct clk_hw *hw, unsigned long rate, > + unsigned long parent_rate) > +{ > + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); > + unsigned long m = 0, n = 0; > + unsigned int d_val, n_val; > + int ret; [ ... ] > + /* > + * When N = 2M + 1 the valid D range [M+1, M] is empty; no duty > + * cycle can satisfy M < D < (N - M). Reject before touching hw. > + */ > + if (n == 2 * m + 1) > + return -EINVAL; > + > + ret = clk_prepare_enable(gp->pdm_ahb_clk); > + if (ret) > + return ret; > + > + ret = regmap_write(gp->regmap, GP_MND_MDIV_REG, m); > + if (ret) > + goto err_unprepare; > + > + /* N divider holds the 1's complement of (N - M), N_WIDTH bits wide */ > + n_val = ~(n - m) & GP_MND_MAX_N; > + ret = regmap_write(gp->regmap, GP_MND_NDIV_REG, n_val); [Severity: High] Can this unsigned underflow when the requested rate is higher than the parent rate, causing m > n? Since n <= 2 * m is not fully rejected above, (n - m) could wrap around and program a corrupted value into GP_MND_NDIV_REG. [ ... ] > +static int gp_mnd_clk_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) > +{ > + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); > + unsigned int d_val; > + int ret; > + > + if (!gp->n_val) { > + duty->num = 1; > + duty->den = 2; > + return 0; > + } > + > + ret = clk_prepare_enable(gp->pdm_ahb_clk); > + if (ret) > + return ret; > + > + ret = regmap_read(gp->regmap, GP_MND_DUTY_REG, &d_val); > + > + clk_disable_unprepare(gp->pdm_ahb_clk); > + > + if (ret) > + return ret; > + > + duty->num = d_val; [Severity: High] Does this report an inverted duty cycle to the clock framework? The hardware DUTY register holds the low-phase clock cycle count: gp_mnd_clk_set_duty_cycle() { ... /* D = (1 - duty) * N, giving the low-phase count */ d_val = DIV_ROUND_UP((u64)(duty->den - duty->num) * gp->n_val, duty->den); ... } Assigning d_val directly to duty->num here appears to return the low-phase ratio instead of the active high-phase ratio. [ ... ] > +static int clk_gp_mnd_probe(struct platform_device *pdev) > +{ > + struct clk_parent_data parent_data = { .index = 0 }; [Severity: Medium] Can this select the wrong parent clock if ahb_clk is listed first in the device tree? Relying on .index = 0 might cause the framework to use the AHB bus clock instead of pdm_clk for rate calculations. Would it be safer to use .fw_name = "pdm_clk" to deterministically bind the parent? [ ... ] -- Sashiko AI review · https://sashiko.dev/#/patchset/20260602-pdm_clk_gp_mnd_v1-v1-0-1522662b6c53@oss.qualcomm.com?part=2 ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 2/5] clk: qcom: Add a driver for PDM GP_MN fractional clock divider 2026-06-02 15:21 ` [PATCH 2/5] clk: qcom: Add a driver for PDM GP_MN fractional " Taniya Das 2026-06-03 15:25 ` sashiko-bot @ 2026-06-08 3:31 ` Dmitry Baryshkov 2026-10-15 7:15 ` Taniya Das 1 sibling, 1 reply; 29+ messages in thread From: Dmitry Baryshkov @ 2026-06-08 3:31 UTC (permalink / raw) To: Taniya Das Cc: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio, Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On Tue, Jun 02, 2026 at 08:51:50PM +0530, Taniya Das wrote: > The PDM (Pulse Density Modulation) hardware block on Qualcomm SoCs > contains a GP_MN clock divider that produces a fractional output > frequency from a fixed input clock (typically TCXO4): > > Fout = Fin * (M / N) > > The hardware encodes the period in the NDIV register as the 1's > complement of (N - M), and controls the duty cycle via a separate > DUTY register that counts the number of low-phase native clock > cycles over the period N. > > Add a standalone platform driver for this block that uses > rational_best_approximation() to find the closest M/N pair within > the 9-bit M and 13-bit N hardware limits, programs the MDIV, NDIV, > and DUTY registers via regmap, and implements the full clk_ops > surface including determine_rate, set_rate, recalc_rate, > get_duty_cycle, and set_duty_cycle. The PDM AHB bus clock is gated > around every register access. > > Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> > --- > drivers/clk/qcom/Kconfig | 15 ++ > drivers/clk/qcom/Makefile | 1 + > drivers/clk/qcom/clk-gp-mnd.c | 333 ++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 349 insertions(+) > > diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig > index d9cff5b0281d8cc373b8ab14683370cb9b7f8bf3..df27aa10243435a20a57cca3ed4644284630d11e 100644 > --- a/drivers/clk/qcom/Kconfig > +++ b/drivers/clk/qcom/Kconfig > @@ -1759,4 +1759,19 @@ config SM_VIDEOCC_8450 > SM8450 or SM8475 devices. > Say Y if you want to support video devices and functionality such as > video encode/decode. > + > +config QCOM_CLK_GP_MND > + tristate "Qualcomm PDM GP_MN clock divider" > + depends on ARM64 || COMPILE_TEST > + help > + Support for the Qualcomm PDM GP_MN clock divider found in PDM > + (Pulse Density Modulation) hardware blocks. > + Given an input clock of frequency Fin (TCXO4), the output > + frequency is Fout = Fin * (M / N). For every N input cycles > + the divider produces M output cycles. D controls the duty > + cycle: it is the number of native clock cycles in which the > + GP_MN output is low, counted over 8192 native clock cycles. > + > + Say Y or M if you want to support GP_MN-based frequency and > + duty-cycle configuration on Qualcomm SoCs. > endif > diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile > index e100cfd6a52de9f88f11720d9c2043db5e553618..438f59b25c009ee72308fe41707d6efff6613690 100644 > --- a/drivers/clk/qcom/Makefile > +++ b/drivers/clk/qcom/Makefile > @@ -207,6 +207,7 @@ obj-$(CONFIG_SM_VIDEOCC_8550) += videocc-sm8550.o > obj-$(CONFIG_SM_VIDEOCC_8750) += videocc-sm8750.o > obj-$(CONFIG_SM_VIDEOCC_MILOS) += videocc-milos.o > obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o > +obj-$(CONFIG_QCOM_CLK_GP_MND) += clk-gp-mnd.o > obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o > obj-$(CONFIG_QCOM_HFPLL) += hfpll.o > obj-$(CONFIG_KRAITCC) += krait-cc.o > diff --git a/drivers/clk/qcom/clk-gp-mnd.c b/drivers/clk/qcom/clk-gp-mnd.c > new file mode 100644 > index 0000000000000000000000000000000000000000..826b6b62ddc7b272511accde1ca0e885018a8064 > --- /dev/null > +++ b/drivers/clk/qcom/clk-gp-mnd.c > @@ -0,0 +1,333 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. > + */ > + > +#include <linux/clk.h> > +#include <linux/clk-provider.h> > +#include <linux/module.h> > +#include <linux/of.h> > +#include <linux/pinctrl/consumer.h> > +#include <linux/platform_device.h> > +#include <linux/rational.h> > +#include <linux/regmap.h> > + > +/* > + * PDM GP_MND clock divider register offsets. > + * > + * The hardware computes: > + * Fout = Fin * (M / N) > + * > + * with duty cycle controlled by D, where M < D < (N - M). > + * > + * Register encoding: > + * MDIV = M > + * NDIV = ~(N - M) [1's complement of (N - M), masked to N_REG_WIDTH bits] > + * DUTY = D > + */ > +#define GP_MND_MDIV_REG 0x0 > +#define GP_MND_NDIV_REG 0x4 > +#define GP_MND_DUTY_REG 0x8 > + > +#define GP_MND_M_WIDTH 9 > +#define GP_MND_N_WIDTH 13 > + > +#define GP_MND_MAX_M GENMASK(GP_MND_M_WIDTH - 1, 0) > +#define GP_MND_MAX_N GENMASK(GP_MND_N_WIDTH - 1, 0) > + > +/** > + * struct clk_gp_mnd - GP_MND fractional clock divider > + * @pdm_ahb_clk: AHB bus clock required for register access > + * @regmap: register map for the PDM block > + * @hw: handle between common and hardware-specific interfaces > + * @m_val: M value (numerator) > + * @n_val: N value (period) > + */ > +struct clk_gp_mnd { > + struct clk *pdm_ahb_clk; > + struct regmap *regmap; > + struct clk_hw hw; > + unsigned int m_val; > + unsigned int n_val; > +}; > + > +#define to_clk_gp_mnd(_hw) container_of(_hw, struct clk_gp_mnd, hw) > + > +static int gp_mnd_clk_determine_rate(struct clk_hw *hw, > + struct clk_rate_request *req) > +{ > + unsigned long m = 0, n = 0; > + > + rational_best_approximation(req->rate, req->best_parent_rate, > + (unsigned long)GP_MND_MAX_M, > + (unsigned long)GP_MND_MAX_N, > + &m, &n); > + > + if (!m || !n) > + return -EINVAL; > + > + /* N = 2M + 1 leaves no valid D satisfying M < D < (N - M) */ > + if (n == 2 * m + 1) > + return -EINVAL; > + > + req->rate = DIV_ROUND_CLOSEST_ULL((u64)req->best_parent_rate * m, n); > + > + return 0; > +} > + > +static int gp_mnd_clk_set_rate(struct clk_hw *hw, unsigned long rate, > + unsigned long parent_rate) > +{ > + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); > + unsigned long m = 0, n = 0; > + unsigned int d_val, n_val; > + int ret; > + > + rational_best_approximation(rate, parent_rate, > + (unsigned long)GP_MND_MAX_M, > + (unsigned long)GP_MND_MAX_N, > + &m, &n); > + > + if (!m || !n) > + return -EINVAL; > + > + /* > + * When N = 2M + 1 the valid D range [M+1, M] is empty; no duty > + * cycle can satisfy M < D < (N - M). Reject before touching hw. > + */ > + if (n == 2 * m + 1) > + return -EINVAL; > + > + ret = clk_prepare_enable(gp->pdm_ahb_clk); Can we use CLK_OPS_PARENT_ENABLE or pm_clk instead? Having to manually toggle the clock looks like a coomplete overkill. > + if (ret) > + return ret; > + > + > + ret = of_property_read_string_index(dev->of_node, > + "clock-output-names", 0, > + &init.name); Do we need it? Can we generate the name instead? > + if (ret) > + return dev_err_probe(dev, ret, "missing clock-output-names\n"); > + > + gp->hw.init = &init; > + > + pin = devm_pinctrl_get(dev); > + if (IS_ERR(pin)) > + return dev_err_probe(dev, PTR_ERR(pin), "missing pinctrl device\n"); > + > + pin_default_state = pinctrl_lookup_state(pin, "active"); > + if (IS_ERR(pin_default_state)) > + return dev_err_probe(dev, PTR_ERR(pin_default_state), > + "missing pinctrl default state\n"); Isn't it done by default for you? > + > + ret = pinctrl_select_state(pin, pin_default_state); > + if (ret) > + return dev_err_probe(dev, ret, > + "failed to select pinctrl default state\n"); > + > + ret = devm_clk_hw_register(dev, &gp->hw); > + if (ret) > + return dev_err_probe(dev, ret, > + "failed to register gp_mnd clock\n"); > + > + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &gp->hw); > +} > + > +static const struct of_device_id clk_gp_mnd_match_table[] = { > + { .compatible = "qcom,clk-gp-mnd" }, > + { } > +}; > +MODULE_DEVICE_TABLE(of, clk_gp_mnd_match_table); > + > +static struct platform_driver clk_gp_mnd_driver = { > + .probe = clk_gp_mnd_probe, > + .driver = { > + .name = "qcom-clk-gp-mnd", > + .of_match_table = clk_gp_mnd_match_table, > + }, > +}; > +module_platform_driver(clk_gp_mnd_driver); > + > +MODULE_DESCRIPTION("Qualcomm PDM GP_MND clock divider driver"); > +MODULE_LICENSE("GPL"); > > -- > 2.34.1 > -- With best wishes Dmitry ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 2/5] clk: qcom: Add a driver for PDM GP_MN fractional clock divider 2026-06-08 3:31 ` Dmitry Baryshkov @ 2026-10-15 7:15 ` Taniya Das 0 siblings, 0 replies; 29+ messages in thread From: Taniya Das @ 2026-10-15 7:15 UTC (permalink / raw) To: Dmitry Baryshkov Cc: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio, Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/8/2026 9:01 AM, Dmitry Baryshkov wrote: >> +static int gp_mnd_clk_set_rate(struct clk_hw *hw, unsigned long rate, >> + unsigned long parent_rate) >> +{ >> + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); >> + unsigned long m = 0, n = 0; >> + unsigned int d_val, n_val; >> + int ret; >> + >> + rational_best_approximation(rate, parent_rate, >> + (unsigned long)GP_MND_MAX_M, >> + (unsigned long)GP_MND_MAX_N, >> + &m, &n); >> + >> + if (!m || !n) >> + return -EINVAL; >> + >> + /* >> + * When N = 2M + 1 the valid D range [M+1, M] is empty; no duty >> + * cycle can satisfy M < D < (N - M). Reject before touching hw. >> + */ >> + if (n == 2 * m + 1) >> + return -EINVAL; >> + >> + ret = clk_prepare_enable(gp->pdm_ahb_clk); > Can we use CLK_OPS_PARENT_ENABLE or pm_clk instead? Having to manually > toggle the clock looks like a coomplete overkill. > Sorry for the delayed response. Yes, I will model it as pm_clk. >> + if (ret) >> + return ret; >> + >> + >> + ret = of_property_read_string_index(dev->of_node, >> + "clock-output-names", 0, >> + &init.name); > Do we need it? Can we generate the name instead? Yes, I will generate the name. > >> + if (ret) >> + return dev_err_probe(dev, ret, "missing clock-output-names\n"); >> + >> + gp->hw.init = &init; >> + >> + pin = devm_pinctrl_get(dev); >> + if (IS_ERR(pin)) >> + return dev_err_probe(dev, PTR_ERR(pin), "missing pinctrl device\n"); >> + >> + pin_default_state = pinctrl_lookup_state(pin, "active"); >> + if (IS_ERR(pin_default_state)) >> + return dev_err_probe(dev, PTR_ERR(pin_default_state), >> + "missing pinctrl default state\n"); > Isn't it done by default for you? > Yeah, I will move it to default. >> + >> + ret = pinctrl_select_state(pin, pin_default_state); >> + if (ret) >> + return dev_err_probe(dev, ret, >> + "failed to select pinctrl default state\n"); >> + >> + ret = devm_clk_hw_register(dev, &gp->hw); >> + if (ret) >> + return dev_err_probe(dev, ret, >> + "failed to register gp_mnd clock\n"); >> + >> + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &gp->hw); >> +} >> + >> +static const struct of_device_id clk_gp_mnd_match_table[] = { >> + { .compatible = "qcom,clk-gp-mnd" }, >> + { } >> +}; >> +MODULE_DEVICE_TABLE(of, clk_gp_mnd_match_table); >> + >> +static struct platform_driver clk_gp_mnd_driver = { >> + .probe = clk_gp_mnd_probe, >> + .driver = { >> + .name = "qcom-clk-gp-mnd", >> + .of_match_table = clk_gp_mnd_match_table, >> + }, >> +}; >> +module_platform_driver(clk_gp_mnd_driver); >> + >> +MODULE_DESCRIPTION("Qualcomm PDM GP_MND clock divider driver"); >> +MODULE_LICENSE("GPL"); -- Thanks, Taniya Das ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/5] pinctrl: qcom: Add gp_mn mux function for QCS8300, SA8775P and SC7280 2026-06-02 15:21 [PATCH 0/5] clk: qcom: Add PDM GP_MN fractional clock divider driver and DT support Taniya Das 2026-06-02 15:21 ` [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider Taniya Das 2026-06-02 15:21 ` [PATCH 2/5] clk: qcom: Add a driver for PDM GP_MN fractional " Taniya Das @ 2026-06-02 15:21 ` Taniya Das 2026-06-08 22:43 ` Linus Walleij 2026-06-09 13:27 ` Konrad Dybcio 2026-06-02 15:21 ` [PATCH 4/5] arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output Taniya Das 2026-06-02 15:21 ` [PATCH 5/5] arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 Taniya Das 4 siblings, 2 replies; 29+ messages in thread From: Taniya Das @ 2026-06-02 15:21 UTC (permalink / raw) To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev, Taniya Das Add the gp_mn pin mux function to the TLMM pin controllers for the QCS8300, SA8775P and SC7280 SoCs. This function exposes the GP M/N divider clock output on a dedicated GPIO pin, allowing the clock signal to be routed externally. - QCS8300: gpio32 - SA8775P: gpio35 - SC7280: gpio60 Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> --- drivers/pinctrl/qcom/pinctrl-qcs8300.c | 9 ++++++++- drivers/pinctrl/qcom/pinctrl-sa8775p.c | 8 +++++++- drivers/pinctrl/qcom/pinctrl-sc7280.c | 8 +++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-qcs8300.c b/drivers/pinctrl/qcom/pinctrl-qcs8300.c index 852cd36df6d5fc6d0aece7d57f8f59fe48c0cfee..1430abd9258989bdbd8a12249196bbf4e9bbbde3 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs8300.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs8300.c @@ -429,6 +429,7 @@ enum qcs8300_functions { msm_mux_gcc_gp3, msm_mux_gcc_gp4, msm_mux_gcc_gp5, + msm_mux_gp_mn, msm_mux_hs0_mi2s, msm_mux_hs1_mi2s, msm_mux_hs2_mi2s, @@ -656,6 +657,10 @@ static const char *const gcc_gp5_groups[] = { "gpio76", "gpio77", }; +static const char *const gp_mn_groups[] = { + "gpio32", +}; + static const char * const hs0_mi2s_groups[] = { "gpio106", "gpio107", "gpio108", "gpio109", }; @@ -960,6 +965,7 @@ static const struct pinfunction qcs8300_functions[] = { MSM_PIN_FUNCTION(gcc_gp3), MSM_PIN_FUNCTION(gcc_gp4), MSM_PIN_FUNCTION(gcc_gp5), + MSM_PIN_FUNCTION(gp_mn), MSM_PIN_FUNCTION(hs0_mi2s), MSM_PIN_FUNCTION(hs1_mi2s), MSM_PIN_FUNCTION(hs2_mi2s), @@ -1067,7 +1073,8 @@ static const struct msm_pingroup qcs8300_groups[] = { [30] = PINGROUP(30, qup0_se4, cci_i2c_scl, cci_async, emac0_ptp_pps, tgu_ch3, _, _, _, _, _, _), [31] = PINGROUP(31, qup0_se4, cci_i2c_sda, cci_async, emac0_ptp_aux, _, _, _, _, _, _, _), - [32] = PINGROUP(32, qup0_se4, cci_i2c_scl, emac0_ptp_aux, mdp_vsync, _, _, _, _, _, _, _), + [32] = PINGROUP(32, qup0_se4, cci_i2c_scl, emac0_ptp_aux, mdp_vsync, gp_mn, _, _, _, _, + _, _), [33] = PINGROUP(33, qup0_se2, qdss_gpio, _, _, _, _, _, _, _, _, _), [34] = PINGROUP(34, qup0_se2, qdss_gpio, _, _, _, _, _, _, _, _, _), [35] = PINGROUP(35, qup0_se2, gcc_gp1, _, _, _, _, _, _, _, _, _), diff --git a/drivers/pinctrl/qcom/pinctrl-sa8775p.c b/drivers/pinctrl/qcom/pinctrl-sa8775p.c index e9a510d3583f5c392acb833be4ce67c6b421cd48..2c29743cca7a259b5a41e73de347c536d373a01e 100644 --- a/drivers/pinctrl/qcom/pinctrl-sa8775p.c +++ b/drivers/pinctrl/qcom/pinctrl-sa8775p.c @@ -486,6 +486,7 @@ enum sa8775p_functions { msm_mux_gcc_gp3, msm_mux_gcc_gp4, msm_mux_gcc_gp5, + msm_mux_gp_mn, msm_mux_hs0_mi2s, msm_mux_hs1_mi2s, msm_mux_hs2_mi2s, @@ -834,6 +835,10 @@ static const char * const gcc_gp5_groups[] = { "gpio34", "gpio42", }; +static const char * const gp_mn_groups[] = { + "gpio35", +}; + static const char * const hs0_mi2s_groups[] = { "gpio114", "gpio115", "gpio116", "gpio117", }; @@ -1236,6 +1241,7 @@ static const struct pinfunction sa8775p_functions[] = { MSM_PIN_FUNCTION(gcc_gp3), MSM_PIN_FUNCTION(gcc_gp4), MSM_PIN_FUNCTION(gcc_gp5), + MSM_PIN_FUNCTION(gp_mn), MSM_PIN_FUNCTION(hs0_mi2s), MSM_PIN_FUNCTION(hs1_mi2s), MSM_PIN_FUNCTION(hs2_mi2s), @@ -1367,7 +1373,7 @@ static const struct msm_pingroup sa8775p_groups[] = { [32] = PINGROUP(32, qup0_se4, phase_flag, _, _, _, _, _, _, _), [33] = PINGROUP(33, qup0_se4, gcc_gp4, _, ddr_pxi0, _, _, _, _, _), [34] = PINGROUP(34, qup0_se4, gcc_gp5, _, ddr_pxi0, _, _, _, _, _), - [35] = PINGROUP(35, qup0_se4, phase_flag, _, _, _, _, _, _, _), + [35] = PINGROUP(35, qup0_se4, phase_flag, gp_mn, _, _, _, _, _, _), [36] = PINGROUP(36, qup0_se2, qup0_se5, phase_flag, tgu_ch2, _, _, _, _, _), [37] = PINGROUP(37, qup0_se2, qup0_se5, phase_flag, tgu_ch3, _, _, _, _, _), [38] = PINGROUP(38, qup0_se5, qup0_se2, qdss_cti, phase_flag, tgu_ch4, _, _, _, _), diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280.c b/drivers/pinctrl/qcom/pinctrl-sc7280.c index bb32a56649df6faf1aecd470435d74558c20db27..5e210b399f88f5beb68e511bca9c0dd93a1b75dc 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc7280.c +++ b/drivers/pinctrl/qcom/pinctrl-sc7280.c @@ -515,6 +515,7 @@ enum sc7280_functions { msm_mux_gcc_gp1, msm_mux_gcc_gp2, msm_mux_gcc_gp3, + msm_mux_gp_mn, msm_mux_gpio, msm_mux_host2wlan_sol, msm_mux_ibi_i3c, @@ -788,6 +789,10 @@ static const char * const gcc_gp2_groups[] = { static const char * const gcc_gp3_groups[] = { "gpio78", "gpio107", }; + +static const char *const gp_mn_groups[] = { + "gpio60", +}; static const char * const host2wlan_sol_groups[] = { "gpio26", }; @@ -1154,6 +1159,7 @@ static const struct pinfunction sc7280_functions[] = { MSM_PIN_FUNCTION(gcc_gp1), MSM_PIN_FUNCTION(gcc_gp2), MSM_PIN_FUNCTION(gcc_gp3), + MSM_PIN_FUNCTION(gp_mn), MSM_GPIO_PIN_FUNCTION(gpio), MSM_PIN_FUNCTION(host2wlan_sol), MSM_PIN_FUNCTION(ibi_i3c), @@ -1325,7 +1331,7 @@ static const struct msm_pingroup sc7280_groups[] = { [57] = PINGROUP(57, qup16, ddr_bist, phase_flag, _, _, _, _, _, _), [58] = PINGROUP(58, qup16, ddr_bist, phase_flag, qdss, _, _, _, _, _), [59] = PINGROUP(59, qup16, ddr_bist, phase_flag, qdss, _, _, _, _, _), - [60] = PINGROUP(60, qup17, edp_hot, _, phase_flag, _, _, _, _, _), + [60] = PINGROUP(60, qup17, edp_hot, gp_mn, phase_flag, _, _, _, _, _), [61] = PINGROUP(61, qup17, sd_write, phase_flag, tsense_pwm1, tsense_pwm2, _, _, _, _), [62] = PINGROUP(62, qup17, qup16, phase_flag, _, _, _, _, _, _), [63] = PINGROUP(63, qup17, qup16, phase_flag, _, _, _, _, _, _), -- 2.34.1 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 3/5] pinctrl: qcom: Add gp_mn mux function for QCS8300, SA8775P and SC7280 2026-06-02 15:21 ` [PATCH 3/5] pinctrl: qcom: Add gp_mn mux function for QCS8300, SA8775P and SC7280 Taniya Das @ 2026-06-08 22:43 ` Linus Walleij 2026-10-15 7:14 ` Taniya Das 2026-06-09 13:27 ` Konrad Dybcio 1 sibling, 1 reply; 29+ messages in thread From: Linus Walleij @ 2026-06-08 22:43 UTC (permalink / raw) To: Taniya Das Cc: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Richard Cochran, Konrad Dybcio, Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On Tue, Jun 2, 2026 at 5:22 PM Taniya Das <taniya.das@oss.qualcomm.com> wrote: > Add the gp_mn pin mux function to the TLMM pin controllers for the > QCS8300, SA8775P and SC7280 SoCs. This function exposes the GP M/N > divider clock output on a dedicated GPIO pin, allowing the clock signal > to be routed externally. > > - QCS8300: gpio32 > - SA8775P: gpio35 > - SC7280: gpio60 > > Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> This looks all right and no-one is saying anything about it, should I just apply this one patch to the pin control tree? It doesn't seem to have any dependencies. Yours, Linus Walleij ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 3/5] pinctrl: qcom: Add gp_mn mux function for QCS8300, SA8775P and SC7280 2026-06-08 22:43 ` Linus Walleij @ 2026-10-15 7:14 ` Taniya Das 2026-10-15 8:28 ` Linus Walleij 0 siblings, 1 reply; 29+ messages in thread From: Taniya Das @ 2026-10-15 7:14 UTC (permalink / raw) To: Linus Walleij Cc: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Richard Cochran, Konrad Dybcio, Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/9/2026 4:13 AM, Linus Walleij wrote: > On Tue, Jun 2, 2026 at 5:22 PM Taniya Das <taniya.das@oss.qualcomm.com> wrote: > >> Add the gp_mn pin mux function to the TLMM pin controllers for the >> QCS8300, SA8775P and SC7280 SoCs. This function exposes the GP M/N >> divider clock output on a dedicated GPIO pin, allowing the clock signal >> to be routed externally. >> >> - QCS8300: gpio32 >> - SA8775P: gpio35 >> - SC7280: gpio60 >> >> Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> > > This looks all right and no-one is saying anything about it, should > I just apply this one patch to the pin control tree? It doesn't seem > to have any dependencies. > Linus Walleij, sorry for the late response. I will split the patches as per comments from Konrad. -- Thanks, Taniya Das ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 3/5] pinctrl: qcom: Add gp_mn mux function for QCS8300, SA8775P and SC7280 2026-10-15 7:14 ` Taniya Das @ 2026-10-15 8:28 ` Linus Walleij 0 siblings, 0 replies; 29+ messages in thread From: Linus Walleij @ 2026-10-15 8:28 UTC (permalink / raw) To: Taniya Das, Bartosz Golaszewski Cc: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Richard Cochran, Konrad Dybcio, Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On Thu, Oct 15, 2026 at 9:14 AM Taniya Das <taniya.das@oss.qualcomm.com> wrote: > > This looks all right and no-one is saying anything about it, should > > I just apply this one patch to the pin control tree? It doesn't seem > > to have any dependencies. > > > Linus Walleij, sorry for the late response. I will split the patches as > per comments from Konrad. In the meantime Bartosz has taken responsibility of Qualcomm pin control patch collection and integration, so check with him how he want to merge this, I think just some separate patches for pin control would work fine. Yours, Linus Walleij ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 3/5] pinctrl: qcom: Add gp_mn mux function for QCS8300, SA8775P and SC7280 2026-06-02 15:21 ` [PATCH 3/5] pinctrl: qcom: Add gp_mn mux function for QCS8300, SA8775P and SC7280 Taniya Das 2026-06-08 22:43 ` Linus Walleij @ 2026-06-09 13:27 ` Konrad Dybcio 2026-10-15 7:14 ` Taniya Das 1 sibling, 1 reply; 29+ messages in thread From: Konrad Dybcio @ 2026-06-09 13:27 UTC (permalink / raw) To: Taniya Das, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/2/26 5:21 PM, Taniya Das wrote: > Add the gp_mn pin mux function to the TLMM pin controllers for the > QCS8300, SA8775P and SC7280 SoCs. This function exposes the GP M/N > divider clock output on a dedicated GPIO pin, allowing the clock signal > to be routed externally. > > - QCS8300: gpio32 > - SA8775P: gpio35 > - SC7280: gpio60 With the changes split into separate commits for each platform: Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> Konrad ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 3/5] pinctrl: qcom: Add gp_mn mux function for QCS8300, SA8775P and SC7280 2026-06-09 13:27 ` Konrad Dybcio @ 2026-10-15 7:14 ` Taniya Das 0 siblings, 0 replies; 29+ messages in thread From: Taniya Das @ 2026-10-15 7:14 UTC (permalink / raw) To: Konrad Dybcio, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/9/2026 6:57 PM, Konrad Dybcio wrote: > On 6/2/26 5:21 PM, Taniya Das wrote: >> Add the gp_mn pin mux function to the TLMM pin controllers for the >> QCS8300, SA8775P and SC7280 SoCs. This function exposes the GP M/N >> divider clock output on a dedicated GPIO pin, allowing the clock signal >> to be routed externally. >> >> - QCS8300: gpio32 >> - SA8775P: gpio35 >> - SC7280: gpio60 > > With the changes split into separate commits for each platform: > > Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> Sure, will take care. -- Thanks, Taniya Das ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 4/5] arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output 2026-06-02 15:21 [PATCH 0/5] clk: qcom: Add PDM GP_MN fractional clock divider driver and DT support Taniya Das ` (2 preceding siblings ...) 2026-06-02 15:21 ` [PATCH 3/5] pinctrl: qcom: Add gp_mn mux function for QCS8300, SA8775P and SC7280 Taniya Das @ 2026-06-02 15:21 ` Taniya Das 2026-06-03 15:25 ` sashiko-bot ` (2 more replies) 2026-06-02 15:21 ` [PATCH 5/5] arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 Taniya Das 4 siblings, 3 replies; 29+ messages in thread From: Taniya Das @ 2026-06-02 15:21 UTC (permalink / raw) To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev, Taniya Das Add pinctrl states for the GP M/N divider clock output pin across multiple Qualcomm SoCs: wire it to the GP M/N clock controller node via pinctrl-0. - kodiak (sa8775p): Add gp_mn_active state on gpio35 (gp_mn function). - lemans (sa8775p): Add gp_mn_active state on gpio35 (gp_mn function). - monaco (qcs8300): Add gp_mn_active state on gpio32 (gp_mn function). Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 7 +++++++ arch/arm64/boot/dts/qcom/lemans.dtsi | 7 +++++++ arch/arm64/boot/dts/qcom/monaco.dtsi | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index fa540d8c2615dc02d941eb16bc7253204c2750bd..1ff9e1598d00429c03b2bcae41fa370ab2c892bd 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -5908,6 +5908,13 @@ edp_hot_plug_det: edp-hot-plug-det-state { function = "edp_hot"; }; + gp_mn_active: gp_mn_active-state { + pins = "gpio35"; + function = "gp_mn"; + drive-strength = <2>; + bias-disable; + }; + mi2s0_data0: mi2s0-data0-state { pins = "gpio98"; function = "mi2s0_data0"; diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 353a6e6fd3acb22ef228bee340212b8b2c300957..19f8cf4e15482947f6049188050c370340afaead 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -6022,6 +6022,13 @@ dp1_hot_plug_det: dp1-hot-plug-det-state { bias-disable; }; + gp_mn_active: gp_mn_active-state { + pins = "gpio35"; + function = "gp_mn"; + drive-strength = <2>; + bias-disable; + }; + hs0_mi2s_active: hs0-mi2s-active-state { pins = "gpio114", "gpio115", "gpio116", "gpio117"; function = "hs0_mi2s"; diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index e4c8466f941bdba04f99b988fd7bf5afd926b31d..ebe5889daa5300efa7857314e9170d7d2fc33ef7 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -6433,6 +6433,13 @@ dp_hot_plug_det: dp-hot-plug-det-state { bias-disable; }; + gp_mn_active: gp_mn_active-state { + pins = "gpio32"; + function = "gp_mn"; + drive-strength = <2>; + bias-disable; + }; + hs0_mi2s_active: hs0-mi2s-active-state { pins = "gpio106", "gpio107", "gpio108", "gpio109"; function = "hs0_mi2s"; -- 2.34.1 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 4/5] arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output 2026-06-02 15:21 ` [PATCH 4/5] arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output Taniya Das @ 2026-06-03 15:25 ` sashiko-bot 2026-06-08 7:22 ` Luca Weiss 2026-06-09 13:28 ` Konrad Dybcio 2 siblings, 0 replies; 29+ messages in thread From: sashiko-bot @ 2026-06-03 15:25 UTC (permalink / raw) To: Taniya Das; +Cc: robh, conor+dt, devicetree Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: - [High] The clock rate calculation logic fails to reject `N` and `M` combinations where `n <= 2 * m`, violating the hardware's duty cycle constraint and writing invalid states. - [High] Invalid pinctrl function configuration for `kodiak.dtsi`. The `gp_mn` function is mapped to `gpio35`, but the SoC (SC7280) only supports it on `gpio60`. - [Medium] `gp_mnd_clk_get_duty_cycle` incorrectly returns the low-phase duty cycle ratio, creating a broken, asymmetric API contract with `gp_mnd_clk_set_duty_cycle`. - [Low] The 'gp_mn' function is not added to the devicetree bindings for the QCS8300, SA8775P, or SC7280 TLMM schemas, which will cause dtbs_check errors. - [Low] The newly added pinctrl state nodes use underscores in their names (`gp_mn_active-state`), violating devicetree node naming conventions. -- commit 39d6c11fb73944a2319cdb23d2516a67b5ac2e61 Author: Taniya Das <taniya.das@oss.qualcomm.com> arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output This commit adds pinctrl states for the GP M/N divider clock output pin across multiple Qualcomm SoCs. It wires the GP M/N clock controller node via pinctrl-0 for the kodiak, lemans, and monaco device trees. > - kodiak (sa8775p): Add gp_mn_active state on gpio35 (gp_mn function). [Severity: High] The commit message indicates kodiak is an sa8775p board, but kodiak.dtsi is an sc7280 device tree. Does the sc7280 SoC support the gp_mn function on gpio35, or is it exclusively available on gpio60? Applying this DT state might cause a runtime pinmux failure. > diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi > index fa540d8c2615d..1ff9e1598d004 100644 > --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi > +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi > @@ -5908,6 +5908,13 @@ edp_hot_plug_det: edp-hot-plug-det-state { > function = "edp_hot"; > }; > > + gp_mn_active: gp_mn_active-state { [Severity: Low] Could this node name be updated to use hyphens instead of underscores to match devicetree naming conventions? > + pins = "gpio35"; > + function = "gp_mn"; [Severity: Low] Is the gp_mn function missing from the devicetree binding schemas for the SC7280 TLMM? This might cause dtbs_check errors. > + drive-strength = <2>; > + bias-disable; > + }; > + [ ... ] > diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi > index 353a6e6fd3acb..19f8cf4e15482 100644 > --- a/arch/arm64/boot/dts/qcom/lemans.dtsi > +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi > @@ -6022,6 +6022,13 @@ dp1_hot_plug_det: dp1-hot-plug-det-state { > bias-disable; > }; > > + gp_mn_active: gp_mn_active-state { [Severity: Low] Should this node name be updated to use hyphens instead of underscores to match devicetree naming conventions? > + pins = "gpio35"; > + function = "gp_mn"; [Severity: Low] Might the gp_mn function be missing from the devicetree binding schemas for the SA8775P TLMM? This could lead to dtbs_check errors. > + drive-strength = <2>; > + bias-disable; > + }; > + [ ... ] > diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi > index e4c8466f941bd..ebe5889daa530 100644 > --- a/arch/arm64/boot/dts/qcom/monaco.dtsi > +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi > @@ -6433,6 +6433,13 @@ dp_hot_plug_det: dp-hot-plug-det-state { > bias-disable; > }; > > + gp_mn_active: gp_mn_active-state { [Severity: Low] Are underscores permitted in this devicetree node name, or should they be replaced with hyphens? > + pins = "gpio32"; > + function = "gp_mn"; [Severity: Low] Could the gp_mn function also be missing from the QCS8300 TLMM binding schemas? > + drive-strength = <2>; > + bias-disable; > + }; [Severity: High] Are combinations where n <= 2 * m properly handled in the clock rate calculation logic in gp_mnd_clk_determine_rate()? drivers/clk/qcom/clk-gp-mnd.c:gp_mnd_clk_determine_rate() { ... /* N = 2M + 1 leaves no valid D satisfying M < D < (N - M) */ if (n == 2 * m + 1) return -EINVAL; ... } If an invalid rate is not rejected here, gp_mnd_clk_set_rate() calculates d_val = n / 2 and blind-writes it to the hardware, which violates the M < D hardware requirement: drivers/clk/qcom/clk-gp-mnd.c:gp_mnd_clk_set_rate() { ... if (n == 2 * m + 1) return -EINVAL; ... /* Program the closest-to-50% duty cycle. */ d_val = n / 2; ret = regmap_write(gp->regmap, GP_MND_DUTY_REG, d_val); ... } [Severity: Medium] Will gp_mnd_clk_get_duty_cycle() incorrectly return the low-phase duty cycle ratio instead of the high-phase ratio? drivers/clk/qcom/clk-gp-mnd.c:gp_mnd_clk_get_duty_cycle() { ... duty->num = d_val; duty->den = gp->n_val; return 0; } In gp_mnd_clk_set_duty_cycle(), duty->num is treated as the high-phase ratio and the low-phase cycle count (d_val) is computed using duty->den - duty->num. By returning d_val directly as duty->num in gp_mnd_clk_get_duty_cycle(), a consumer setting a 75% duty cycle will read back 25%, which breaks the Common Clock Framework semantics. -- Sashiko AI review · https://sashiko.dev/#/patchset/20260602-pdm_clk_gp_mnd_v1-v1-0-1522662b6c53@oss.qualcomm.com?part=4 ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 4/5] arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output 2026-06-02 15:21 ` [PATCH 4/5] arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output Taniya Das 2026-06-03 15:25 ` sashiko-bot @ 2026-06-08 7:22 ` Luca Weiss 2026-10-15 10:44 ` Taniya Das 2026-06-09 13:28 ` Konrad Dybcio 2 siblings, 1 reply; 29+ messages in thread From: Luca Weiss @ 2026-06-08 7:22 UTC (permalink / raw) To: Taniya Das, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On Tue Jun 2, 2026 at 5:21 PM CEST, Taniya Das wrote: > Add pinctrl states for the GP M/N divider clock output pin across > multiple Qualcomm SoCs: > > wire it to the GP M/N clock controller node via pinctrl-0. > - kodiak (sa8775p): Add gp_mn_active state on gpio35 (gp_mn function). kodiak (sc7280) - this should be gpio60? > - lemans (sa8775p): Add gp_mn_active state on gpio35 (gp_mn function). > - monaco (qcs8300): Add gp_mn_active state on gpio32 (gp_mn function). > > Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> > --- > arch/arm64/boot/dts/qcom/kodiak.dtsi | 7 +++++++ > arch/arm64/boot/dts/qcom/lemans.dtsi | 7 +++++++ > arch/arm64/boot/dts/qcom/monaco.dtsi | 7 +++++++ > 3 files changed, 21 insertions(+) > > diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi > index fa540d8c2615dc02d941eb16bc7253204c2750bd..1ff9e1598d00429c03b2bcae41fa370ab2c892bd 100644 > --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi > +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi > @@ -5908,6 +5908,13 @@ edp_hot_plug_det: edp-hot-plug-det-state { > function = "edp_hot"; > }; > > + gp_mn_active: gp_mn_active-state { > + pins = "gpio35"; gpio60? I still find it incredible that the QCM6490 datasheet (80-20659-1 Rev. AJ) doesn't even mention this functionality on GPIO_60.. I wonder what else is hidden on these SoCs. Regards Luca > + function = "gp_mn"; > + drive-strength = <2>; > + bias-disable; > + }; > + > mi2s0_data0: mi2s0-data0-state { > pins = "gpio98"; > function = "mi2s0_data0"; > diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi > index 353a6e6fd3acb22ef228bee340212b8b2c300957..19f8cf4e15482947f6049188050c370340afaead 100644 > --- a/arch/arm64/boot/dts/qcom/lemans.dtsi > +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi > @@ -6022,6 +6022,13 @@ dp1_hot_plug_det: dp1-hot-plug-det-state { > bias-disable; > }; > > + gp_mn_active: gp_mn_active-state { > + pins = "gpio35"; > + function = "gp_mn"; > + drive-strength = <2>; > + bias-disable; > + }; > + > hs0_mi2s_active: hs0-mi2s-active-state { > pins = "gpio114", "gpio115", "gpio116", "gpio117"; > function = "hs0_mi2s"; > diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi > index e4c8466f941bdba04f99b988fd7bf5afd926b31d..ebe5889daa5300efa7857314e9170d7d2fc33ef7 100644 > --- a/arch/arm64/boot/dts/qcom/monaco.dtsi > +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi > @@ -6433,6 +6433,13 @@ dp_hot_plug_det: dp-hot-plug-det-state { > bias-disable; > }; > > + gp_mn_active: gp_mn_active-state { > + pins = "gpio32"; > + function = "gp_mn"; > + drive-strength = <2>; > + bias-disable; > + }; > + > hs0_mi2s_active: hs0-mi2s-active-state { > pins = "gpio106", "gpio107", "gpio108", "gpio109"; > function = "hs0_mi2s"; ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 4/5] arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output 2026-06-08 7:22 ` Luca Weiss @ 2026-10-15 10:44 ` Taniya Das 0 siblings, 0 replies; 29+ messages in thread From: Taniya Das @ 2026-10-15 10:44 UTC (permalink / raw) To: Luca Weiss, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/8/2026 12:52 PM, Luca Weiss wrote: >> diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi >> index fa540d8c2615dc02d941eb16bc7253204c2750bd..1ff9e1598d00429c03b2bcae41fa370ab2c892bd 100644 >> --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi >> +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi >> @@ -5908,6 +5908,13 @@ edp_hot_plug_det: edp-hot-plug-det-state { >> function = "edp_hot"; >> }; >> >> + gp_mn_active: gp_mn_active-state { >> + pins = "gpio35"; > gpio60? > > I still find it incredible that the QCM6490 datasheet (80-20659-1 Rev. > AJ) doesn't even mention this functionality on GPIO_60.. I wonder what > else is hidden on these SoCs. Thanks Luca, my bad will update this in the next patch. -- Thanks, Taniya Das ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 4/5] arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output 2026-06-02 15:21 ` [PATCH 4/5] arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output Taniya Das 2026-06-03 15:25 ` sashiko-bot 2026-06-08 7:22 ` Luca Weiss @ 2026-06-09 13:28 ` Konrad Dybcio 2026-10-15 7:14 ` Taniya Das 2 siblings, 1 reply; 29+ messages in thread From: Konrad Dybcio @ 2026-06-09 13:28 UTC (permalink / raw) To: Taniya Das, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/2/26 5:21 PM, Taniya Das wrote: > Add pinctrl states for the GP M/N divider clock output pin across > multiple Qualcomm SoCs: > > wire it to the GP M/N clock controller node via pinctrl-0. > - kodiak (sa8775p): Add gp_mn_active state on gpio35 (gp_mn function). > - lemans (sa8775p): Add gp_mn_active state on gpio35 (gp_mn function). > - monaco (qcs8300): Add gp_mn_active state on gpio32 (gp_mn function). > > Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> > --- Please squash the pinctrl addition and clock controller node addition patches together (single logical change), and separate them per-platform Konrad ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 4/5] arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output 2026-06-09 13:28 ` Konrad Dybcio @ 2026-10-15 7:14 ` Taniya Das 0 siblings, 0 replies; 29+ messages in thread From: Taniya Das @ 2026-10-15 7:14 UTC (permalink / raw) To: Konrad Dybcio, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/9/2026 6:58 PM, Konrad Dybcio wrote: > On 6/2/26 5:21 PM, Taniya Das wrote: >> Add pinctrl states for the GP M/N divider clock output pin across >> multiple Qualcomm SoCs: >> >> wire it to the GP M/N clock controller node via pinctrl-0. >> - kodiak (sa8775p): Add gp_mn_active state on gpio35 (gp_mn function). >> - lemans (sa8775p): Add gp_mn_active state on gpio35 (gp_mn function). >> - monaco (qcs8300): Add gp_mn_active state on gpio32 (gp_mn function). >> >> Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> >> --- > > Please squash the pinctrl addition and clock controller node addition > patches together (single logical change), and separate them per-platform Sure Konrad, will take care. -- Thanks, Taniya Das ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 5/5] arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 2026-06-02 15:21 [PATCH 0/5] clk: qcom: Add PDM GP_MN fractional clock divider driver and DT support Taniya Das ` (3 preceding siblings ...) 2026-06-02 15:21 ` [PATCH 4/5] arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output Taniya Das @ 2026-06-02 15:21 ` Taniya Das 2026-06-03 15:25 ` sashiko-bot ` (2 more replies) 4 siblings, 3 replies; 29+ messages in thread From: Taniya Das @ 2026-06-02 15:21 UTC (permalink / raw) To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev, Taniya Das Add the GP M/N divider clock controller node at 0x088d3000 to the SA8775P (kodiak, lemans) and QCS8300 (monaco) SoC device trees. The node uses the qcom,clk-gp-mnd compatible, is clocked by the PDM XO4 and AHB clocks from GCC, and exposes a single clock output (gp_mn_clk) on the dedicated gp_mn pin mux function. The XO4 clock is pre-assigned to 4.8 MHz (XO/4). Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 14 ++++++++++++++ arch/arm64/boot/dts/qcom/lemans.dtsi | 14 ++++++++++++++ arch/arm64/boot/dts/qcom/monaco.dtsi | 14 ++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 1ff9e1598d00429c03b2bcae41fa370ab2c892bd..cbc13ac37f8aeb0b1071ad0609ec11e829d2c798 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -4412,6 +4412,20 @@ usb2_role_switch: endpoint { }; }; + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x0 0x088d3000 0x0 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + #clock-cells = <0>; + pinctrl-names = "active"; + pinctrl-0 = <&gp_mn_active>; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + }; + qspi: spi@88dc000 { compatible = "qcom,sc7280-qspi", "qcom,qspi-v1"; reg = <0 0x088dc000 0 0x1000>; diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 19f8cf4e15482947f6049188050c370340afaead..d192f92a896bb13017abdf82062e8305aab3e5d5 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -4353,6 +4353,20 @@ opp-384000000 { }; }; + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x0 0x088d3000 0x0 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + #clock-cells = <0>; + pinctrl-names = "active"; + pinctrl-0 = <&gp_mn_active>; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + }; + usb_0_hsphy: phy@88e4000 { compatible = "qcom,sa8775p-usb-hs-phy", "qcom,usb-snps-hs-5nm-phy"; diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index ebe5889daa5300efa7857314e9170d7d2fc33ef7..f6c5ec38c7491b7a16ebfb853f8af88bdf1f0db3 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -4867,6 +4867,20 @@ opp-384000000 { }; }; + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x0 0x088d3000 0x0 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + #clock-cells = <0>; + pinctrl-names = "active"; + pinctrl-0 = <&gp_mn_active>; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + }; + usb_1_hsphy: phy@8904000 { compatible = "qcom,qcs8300-usb-hs-phy", "qcom,usb-snps-hs-7nm-phy"; -- 2.34.1 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PATCH 5/5] arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 2026-06-02 15:21 ` [PATCH 5/5] arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 Taniya Das @ 2026-06-03 15:25 ` sashiko-bot 2026-06-08 7:32 ` Luca Weiss 2026-06-08 7:33 ` Luca Weiss 2 siblings, 0 replies; 29+ messages in thread From: sashiko-bot @ 2026-06-03 15:25 UTC (permalink / raw) To: Taniya Das; +Cc: devicetree, conor+dt, robh Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: New issues: - [High] Intent Mismatch / Incorrect File Modification - [High] Missing 'status = "disabled";' causes unconditional probe and pin conflict - [Low] Device Tree Node Sorting violation Pre-existing issues: - [High] Hardware Constraint Violation in duty cycle computation -- commit 6b4f5403f54605460d10e6b912f07451ceb5b128 Author: Taniya Das <taniya.das@oss.qualcomm.com> arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 This commit adds the GP M/N divider clock controller node to the SA8775P and QCS8300 device trees. The new node uses the qcom,clk-gp-mnd compatible and is clocked by the PDM XO4 and AHB clocks to expose a single clock output. > Add the GP M/N divider clock controller node at 0x088d3000 to the > SA8775P (kodiak, lemans) and QCS8300 (monaco) SoC device trees. [Severity: High] Is Kodiak actually an SA8775P variant? Kodiak is typically the core SoC device tree for the SC7280 family (Snapdragon 7c Gen 3 / QCM6490), while SA8775P is exclusively Lemans. Does modifying kodiak.dtsi incorrectly apply this clock controller to the SC7280 family and break its device tree? > diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi > --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi > +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi > @@ -4412,6 +4412,20 @@ usb2_role_switch: endpoint { > }; > }; > > + gp_mn: clock-controller@88d3000 { [Severity: Low] Is this node placed in the correct sorting order? It appears to be inserted sequentially after the usb@8c00000 node, but 0x088d3000 is less than 0x08c00000, which causes a unit-address sorting violation. > + compatible = "qcom,clk-gp-mnd"; > + reg = <0x0 0x088d3000 0x0 0xc>; > + clocks = <&gcc GCC_PDM_XO4_CLK>, > + <&gcc GCC_PDM_AHB_CLK>; > + clock-names = "pdm_clk", "ahb_clk"; > + clock-output-names = "gp_mn_clk"; > + #clock-cells = <0>; > + pinctrl-names = "active"; > + pinctrl-0 = <&gp_mn_active>; > + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; > + assigned-clock-rates = <4800000>; > + }; [Severity: High] Should this node include a status = "disabled" property? IP blocks that export signals to external pads are usually disabled by default in SoC dtsi files. Without it, does the qcom,clk-gp-mnd driver probe unconditionally on every board, forcibly multiplexing gpio35 to the gp_mn function? This could potentially break boards that require gpio35 for other functions like qup_spi8_cs or qup_uart8_rx. [ ... ] > diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi > --- a/arch/arm64/boot/dts/qcom/lemans.dtsi > +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi > @@ -4353,6 +4353,20 @@ opp-384000000 { > }; > }; > > + gp_mn: clock-controller@88d3000 { > + compatible = "qcom,clk-gp-mnd"; > + reg = <0x0 0x088d3000 0x0 0xc>; > + clocks = <&gcc GCC_PDM_XO4_CLK>, > + <&gcc GCC_PDM_AHB_CLK>; > + clock-names = "pdm_clk", "ahb_clk"; > + clock-output-names = "gp_mn_clk"; > + #clock-cells = <0>; > + pinctrl-names = "active"; > + pinctrl-0 = <&gp_mn_active>; > + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; > + assigned-clock-rates = <4800000>; > + }; [Severity: High] Would it be necessary to add a status = "disabled" property here as well to prevent the unconditional multiplexing of gpio35? [ ... ] > diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi > --- a/arch/arm64/boot/dts/qcom/monaco.dtsi > +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi > @@ -4867,6 +4867,20 @@ opp-384000000 { > }; > }; > > + gp_mn: clock-controller@88d3000 { > + compatible = "qcom,clk-gp-mnd"; > + reg = <0x0 0x088d3000 0x0 0xc>; > + clocks = <&gcc GCC_PDM_XO4_CLK>, > + <&gcc GCC_PDM_AHB_CLK>; > + clock-names = "pdm_clk", "ahb_clk"; > + clock-output-names = "gp_mn_clk"; > + #clock-cells = <0>; > + pinctrl-names = "active"; > + pinctrl-0 = <&gp_mn_active>; > + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; > + assigned-clock-rates = <4800000>; > + }; [Severity: High] Similarly, does this node also need status = "disabled" to ensure safe default behavior? [ ... ] While reviewing this change, a pre-existing issue was noticed in the clock driver itself regarding hardware duty cycle constraints: drivers/clk/qcom/clk-gp-mnd.c:gp_mnd_clk_set_rate() { /* * When N = 2M + 1 the valid D range [M+1, M] is empty; no duty * cycle can satisfy M < D < (N - M). Reject before touching hw. */ if (n == 2 * m + 1) return -EINVAL; ... /* Program the closest-to-50% duty cycle. */ d_val = n / 2; ret = regmap_write(gp->regmap, GP_MND_DUTY_REG, d_val); } [Severity: High] This is a pre-existing issue, but does the driver fail to fully enforce the hardware duty cycle constraint M < D < (N - M)? If req->rate >= parent_rate / 2, rational_best_approximation can return M=1, N=2. In this scenario, N <= 2 * M is true, making the check n == 2 * m + 1 evaluate to false, and the calculation proceeds. Does the driver then blindly compute d_val = N / 2 = 1 and program M=1, D=1, N=2 into the hardware, violating the M < D constraint? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260602-pdm_clk_gp_mnd_v1-v1-0-1522662b6c53@oss.qualcomm.com?part=5 ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 5/5] arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 2026-06-02 15:21 ` [PATCH 5/5] arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 Taniya Das 2026-06-03 15:25 ` sashiko-bot @ 2026-06-08 7:32 ` Luca Weiss 2026-10-15 10:45 ` Taniya Das 2026-06-08 7:33 ` Luca Weiss 2 siblings, 1 reply; 29+ messages in thread From: Luca Weiss @ 2026-06-08 7:32 UTC (permalink / raw) To: Taniya Das, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev Hi Taniya, On Tue Jun 2, 2026 at 5:21 PM CEST, Taniya Das wrote: > Add the GP M/N divider clock controller node at 0x088d3000 to the > SA8775P (kodiak, lemans) and QCS8300 (monaco) SoC device trees. > > The node uses the qcom,clk-gp-mnd compatible, is clocked by the PDM > XO4 and AHB clocks from GCC, and exposes a single clock output > (gp_mn_clk) on the dedicated gp_mn pin mux function. The XO4 clock > is pre-assigned to 4.8 MHz (XO/4). > > Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> > --- > arch/arm64/boot/dts/qcom/kodiak.dtsi | 14 ++++++++++++++ > arch/arm64/boot/dts/qcom/lemans.dtsi | 14 ++++++++++++++ > arch/arm64/boot/dts/qcom/monaco.dtsi | 14 ++++++++++++++ > 3 files changed, 42 insertions(+) > > diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi > index 1ff9e1598d00429c03b2bcae41fa370ab2c892bd..cbc13ac37f8aeb0b1071ad0609ec11e829d2c798 100644 > --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi > +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi > @@ -4412,6 +4412,20 @@ usb2_role_switch: endpoint { > }; > }; > > + gp_mn: clock-controller@88d3000 { > + compatible = "qcom,clk-gp-mnd"; > + reg = <0x0 0x088d3000 0x0 0xc>; > + clocks = <&gcc GCC_PDM_XO4_CLK>, > + <&gcc GCC_PDM_AHB_CLK>; > + clock-names = "pdm_clk", "ahb_clk"; > + clock-output-names = "gp_mn_clk"; > + #clock-cells = <0>; > + pinctrl-names = "active"; > + pinctrl-0 = <&gp_mn_active>; > + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; > + assigned-clock-rates = <4800000>; > + }; Am I missing something, or would this just configure gpio60 for all boards for this clock controller output? On QCM6490 Fairphone 5 this pin is connected to FP_3P3_EN, so it's definitely not unused. Maybe disable them by default and let the board enable it, if it wants to make use of this clock? Regards Luca > + > qspi: spi@88dc000 { > compatible = "qcom,sc7280-qspi", "qcom,qspi-v1"; > reg = <0 0x088dc000 0 0x1000>; > diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi > index 19f8cf4e15482947f6049188050c370340afaead..d192f92a896bb13017abdf82062e8305aab3e5d5 100644 > --- a/arch/arm64/boot/dts/qcom/lemans.dtsi > +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi > @@ -4353,6 +4353,20 @@ opp-384000000 { > }; > }; > > + gp_mn: clock-controller@88d3000 { > + compatible = "qcom,clk-gp-mnd"; > + reg = <0x0 0x088d3000 0x0 0xc>; > + clocks = <&gcc GCC_PDM_XO4_CLK>, > + <&gcc GCC_PDM_AHB_CLK>; > + clock-names = "pdm_clk", "ahb_clk"; > + clock-output-names = "gp_mn_clk"; > + #clock-cells = <0>; > + pinctrl-names = "active"; > + pinctrl-0 = <&gp_mn_active>; > + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; > + assigned-clock-rates = <4800000>; > + }; > + > usb_0_hsphy: phy@88e4000 { > compatible = "qcom,sa8775p-usb-hs-phy", > "qcom,usb-snps-hs-5nm-phy"; > diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi > index ebe5889daa5300efa7857314e9170d7d2fc33ef7..f6c5ec38c7491b7a16ebfb853f8af88bdf1f0db3 100644 > --- a/arch/arm64/boot/dts/qcom/monaco.dtsi > +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi > @@ -4867,6 +4867,20 @@ opp-384000000 { > }; > }; > > + gp_mn: clock-controller@88d3000 { > + compatible = "qcom,clk-gp-mnd"; > + reg = <0x0 0x088d3000 0x0 0xc>; > + clocks = <&gcc GCC_PDM_XO4_CLK>, > + <&gcc GCC_PDM_AHB_CLK>; > + clock-names = "pdm_clk", "ahb_clk"; > + clock-output-names = "gp_mn_clk"; > + #clock-cells = <0>; > + pinctrl-names = "active"; > + pinctrl-0 = <&gp_mn_active>; > + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; > + assigned-clock-rates = <4800000>; > + }; > + > usb_1_hsphy: phy@8904000 { > compatible = "qcom,qcs8300-usb-hs-phy", > "qcom,usb-snps-hs-7nm-phy"; ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 5/5] arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 2026-06-08 7:32 ` Luca Weiss @ 2026-10-15 10:45 ` Taniya Das 0 siblings, 0 replies; 29+ messages in thread From: Taniya Das @ 2026-10-15 10:45 UTC (permalink / raw) To: Luca Weiss, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/8/2026 1:02 PM, Luca Weiss wrote: >> @@ -4412,6 +4412,20 @@ usb2_role_switch: endpoint { >> }; >> }; >> >> + gp_mn: clock-controller@88d3000 { >> + compatible = "qcom,clk-gp-mnd"; >> + reg = <0x0 0x088d3000 0x0 0xc>; >> + clocks = <&gcc GCC_PDM_XO4_CLK>, >> + <&gcc GCC_PDM_AHB_CLK>; >> + clock-names = "pdm_clk", "ahb_clk"; >> + clock-output-names = "gp_mn_clk"; >> + #clock-cells = <0>; >> + pinctrl-names = "active"; >> + pinctrl-0 = <&gp_mn_active>; >> + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; >> + assigned-clock-rates = <4800000>; >> + }; > Am I missing something, or would this just configure gpio60 for all > boards for this clock controller output? On QCM6490 Fairphone 5 this pin > is connected to FP_3P3_EN, so it's definitely not unused. > > Maybe disable them by default and let the board enable it, if it wants > to make use of this clock? yes I will keep it disabled and will let board enable them. -- Thanks, Taniya Das ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 5/5] arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 2026-06-02 15:21 ` [PATCH 5/5] arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 Taniya Das 2026-06-03 15:25 ` sashiko-bot 2026-06-08 7:32 ` Luca Weiss @ 2026-06-08 7:33 ` Luca Weiss 2026-10-15 7:14 ` Taniya Das 2 siblings, 1 reply; 29+ messages in thread From: Luca Weiss @ 2026-06-08 7:33 UTC (permalink / raw) To: Taniya Das, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On Tue Jun 2, 2026 at 5:21 PM CEST, Taniya Das wrote: > Add the GP M/N divider clock controller node at 0x088d3000 to the > SA8775P (kodiak, lemans) and QCS8300 (monaco) SoC device trees. forgot this in the previous email, another kodiak==sc7280 Regards Luca > > The node uses the qcom,clk-gp-mnd compatible, is clocked by the PDM > XO4 and AHB clocks from GCC, and exposes a single clock output > (gp_mn_clk) on the dedicated gp_mn pin mux function. The XO4 clock > is pre-assigned to 4.8 MHz (XO/4). > > Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> > --- ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 5/5] arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 2026-06-08 7:33 ` Luca Weiss @ 2026-10-15 7:14 ` Taniya Das 0 siblings, 0 replies; 29+ messages in thread From: Taniya Das @ 2026-10-15 7:14 UTC (permalink / raw) To: Luca Weiss, Bjorn Andersson, Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij, Richard Cochran, Konrad Dybcio Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm, linux-clk, devicetree, linux-kernel, linux-gpio, netdev On 6/8/2026 1:03 PM, Luca Weiss wrote: >> Add the GP M/N divider clock controller node at 0x088d3000 to the >> SA8775P (kodiak, lemans) and QCS8300 (monaco) SoC device trees. > forgot this in the previous email, another kodiak==sc7280 > Yeah I missed the name. -- Thanks, Taniya Das ^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2026-10-15 10:45 UTC | newest] Thread overview: 29+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-06-02 15:21 [PATCH 0/5] clk: qcom: Add PDM GP_MN fractional clock divider driver and DT support Taniya Das 2026-06-02 15:21 ` [PATCH 1/5] dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider Taniya Das 2026-06-03 15:25 ` sashiko-bot 2026-06-09 13:24 ` Konrad Dybcio 2026-10-15 7:15 ` Taniya Das 2026-06-09 13:25 ` Konrad Dybcio 2026-10-15 7:15 ` Taniya Das 2026-06-02 15:21 ` [PATCH 2/5] clk: qcom: Add a driver for PDM GP_MN fractional " Taniya Das 2026-06-03 15:25 ` sashiko-bot 2026-06-08 3:31 ` Dmitry Baryshkov 2026-10-15 7:15 ` Taniya Das 2026-06-02 15:21 ` [PATCH 3/5] pinctrl: qcom: Add gp_mn mux function for QCS8300, SA8775P and SC7280 Taniya Das 2026-06-08 22:43 ` Linus Walleij 2026-10-15 7:14 ` Taniya Das 2026-10-15 8:28 ` Linus Walleij 2026-06-09 13:27 ` Konrad Dybcio 2026-10-15 7:14 ` Taniya Das 2026-06-02 15:21 ` [PATCH 4/5] arm64: dts: qcom: Add gp_mn pin state for GP M/N clock output Taniya Das 2026-06-03 15:25 ` sashiko-bot 2026-06-08 7:22 ` Luca Weiss 2026-10-15 10:44 ` Taniya Das 2026-06-09 13:28 ` Konrad Dybcio 2026-10-15 7:14 ` Taniya Das 2026-06-02 15:21 ` [PATCH 5/5] arm64: dts: qcom: Add GP M/N clock controller node for SA8775P and QCS8300 Taniya Das 2026-06-03 15:25 ` sashiko-bot 2026-06-08 7:32 ` Luca Weiss 2026-10-15 10:45 ` Taniya Das 2026-06-08 7:33 ` Luca Weiss 2026-10-15 7:14 ` Taniya Das
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox