* [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; 15+ 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] 15+ 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-09 13:24 ` Konrad Dybcio
2026-06-09 13:25 ` Konrad Dybcio
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, 2 replies; 15+ 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 [flat|nested] 15+ 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-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, 1 reply; 15+ 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 [flat|nested] 15+ 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; 15+ 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 [flat|nested] 15+ 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-08 7:22 ` Luca Weiss
2026-06-09 13:28 ` Konrad Dybcio
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; 15+ 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 [flat|nested] 15+ 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-08 7:32 ` Luca Weiss
2026-06-08 7:33 ` Luca Weiss
4 siblings, 2 replies; 15+ 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 [flat|nested] 15+ 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-08 3:31 ` Dmitry Baryshkov
0 siblings, 0 replies; 15+ 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] 15+ 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-08 7:22 ` Luca Weiss
2026-06-09 13:28 ` Konrad Dybcio
1 sibling, 0 replies; 15+ 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] 15+ 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-08 7:32 ` Luca Weiss
2026-06-08 7:33 ` Luca Weiss
1 sibling, 0 replies; 15+ 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] 15+ 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-08 7:32 ` Luca Weiss
@ 2026-06-08 7:33 ` Luca Weiss
1 sibling, 0 replies; 15+ 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] 15+ 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
1 sibling, 0 replies; 15+ 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] 15+ 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-09 13:24 ` Konrad Dybcio
2026-06-09 13:25 ` Konrad Dybcio
1 sibling, 0 replies; 15+ 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] 15+ 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-09 13:24 ` Konrad Dybcio
@ 2026-06-09 13:25 ` Konrad Dybcio
1 sibling, 0 replies; 15+ 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] 15+ 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
1 sibling, 0 replies; 15+ 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] 15+ 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-08 7:22 ` Luca Weiss
@ 2026-06-09 13:28 ` Konrad Dybcio
1 sibling, 0 replies; 15+ 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] 15+ messages in thread
end of thread, other threads:[~2026-06-09 13:28 UTC | newest]
Thread overview: 15+ 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-09 13:24 ` Konrad Dybcio
2026-06-09 13:25 ` Konrad Dybcio
2026-06-02 15:21 ` [PATCH 2/5] clk: qcom: Add a driver for PDM GP_MN fractional " Taniya Das
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
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-08 7:22 ` Luca Weiss
2026-06-09 13:28 ` Konrad Dybcio
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-08 7:32 ` Luca Weiss
2026-06-08 7:33 ` Luca Weiss
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®