mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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®