* [PATCH v9 1/2] dt-bindings: clock: qcom: Add LPASS VA CSR HeartBeat pulse clock
2026-09-28 15:57 [PATCH v9 0/2] Add LPASS VA CSR HeartBeat pulse clock support Sarath Ganapathiraju via B4 Relay
@ 2026-09-28 15:57 ` Sarath Ganapathiraju via B4 Relay
2026-09-28 21:13 ` Rob Herring (Arm)
2026-09-28 15:57 ` [PATCH v9 2/2] clk: qcom: Add LPASS VA CSR heartbeat " Sarath Ganapathiraju via B4 Relay
1 sibling, 1 reply; 4+ messages in thread
From: Sarath Ganapathiraju via B4 Relay @ 2026-09-28 15:57 UTC (permalink / raw)
To: andersson, abelvesa, sboyd, bmasney+clk, jbrunet+clk, robh,
krzk+dt, conor+dt, srinivas.kandagatla, sarath.ganapathiraju
Cc: linux-arm-msm, linux-clk, devicetree, linux-kernel, prasad.kumpatla
From: Sarath Ganapathiraju <sarath.ganapathiraju@oss.qualcomm.com>
Add a binding for the Qualcomm LPASS VA CSR rate generator node that
exposes the lpass_heartbeat_pulse clock on Hawi.
The HeartBeat Pulse, also known as RateGen Pulse, synchronizes the
start of DMAs and Codec Interfaces for the audio usecase and can serve
as a periodic wakeup source for the DSP.
Require the LPASS LPR and audio vote clocks to access VA CSR register
space safely.
Signed-off-by: Sarath Ganapathiraju <sarath.ganapathiraju@oss.qualcomm.com>
---
.../bindings/clock/qcom,hawi-lpass-va-csr.yaml | 62 ++++++++++++++++++++++
1 file changed, 62 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/qcom,hawi-lpass-va-csr.yaml b/Documentation/devicetree/bindings/clock/qcom,hawi-lpass-va-csr.yaml
new file mode 100644
index 000000000000..601da83add2b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,hawi-lpass-va-csr.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,hawi-lpass-va-csr.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm LPASS VA CSR heartbeat pulse clock provider
+
+maintainers:
+ - Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+ - Sarath Ganapathiraju <sarath.ganapathiraju@oss.qualcomm.com>
+
+description:
+ The Hawi LPASS (Low Power Audio Subsystem) VA CSR block contains a
+ rate generator that produces a periodic HeartBeat Pulse, also known
+ as the RateGen Pulse. This pulse synchronizes the start of DMAs and
+ Codec Interfaces for audio usecases and can serve as a periodic wakeup
+ source for the DSP.
+
+properties:
+ compatible:
+ enum:
+ - qcom,hawi-lpass-va-csr
+
+ reg:
+ maxItems: 1
+ description: Address and size of the VA CSR register block.
+
+ clocks:
+ items:
+ - description: LPASS LPR (Low Power Resource) voting clock
+ - description: LPASS Audio voting clock
+
+ clock-names:
+ items:
+ - const: lpr
+ - const: audio
+
+ "#clock-cells":
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/sound/qcom,q6dsp-lpass-ports.h>
+
+ clock-controller@7ee0000 {
+ compatible = "qcom,hawi-lpass-va-csr";
+ reg = <0x07ee0000 0xe000>;
+ clocks = <&q6prmcc LPASS_HW_LPR_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ clock-names = "lpr", "audio";
+ #clock-cells = <0>;
+ };
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH v9 2/2] clk: qcom: Add LPASS VA CSR heartbeat pulse clock
2026-09-28 15:57 [PATCH v9 0/2] Add LPASS VA CSR HeartBeat pulse clock support Sarath Ganapathiraju via B4 Relay
2026-09-28 15:57 ` [PATCH v9 1/2] dt-bindings: clock: qcom: Add LPASS VA CSR HeartBeat pulse clock Sarath Ganapathiraju via B4 Relay
@ 2026-09-28 15:57 ` Sarath Ganapathiraju via B4 Relay
1 sibling, 0 replies; 4+ messages in thread
From: Sarath Ganapathiraju via B4 Relay @ 2026-09-28 15:57 UTC (permalink / raw)
To: andersson, abelvesa, sboyd, bmasney+clk, jbrunet+clk, robh,
krzk+dt, conor+dt, srinivas.kandagatla, sarath.ganapathiraju
Cc: linux-arm-msm, linux-clk, devicetree, linux-kernel, prasad.kumpatla
From: Sarath Ganapathiraju <sarath.ganapathiraju@oss.qualcomm.com>
The HeartBeat Pulse, also known as RateGen Pulse, synchronizes the
start of DMAs and Codec Interfaces for the audio usecases and can
serve as a periodic wakeup source for the DSP.
Add the LPASS VA CSR driver that models the rate generator as a clock
provider so consumers can enable and disable it through the common
clock framework.
Attach the DT vote clocks to runtime PM and resume the device before
programming the rate generator registers in probe. Also take a runtime
PM reference from the clock prepare path so later enable and disable
register accesses happen only while the LPASS votes are active.
Signed-off-by: Sarath Ganapathiraju <sarath.ganapathiraju@oss.qualcomm.com>
---
drivers/clk/qcom/Kconfig | 14 ++++
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/lpass-va-csr.c | 174 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 189 insertions(+)
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 27d0ab24d50a..da2e8005d075 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -2137,6 +2137,20 @@ config CLK_GFM_LPASS_SM8250
Support for the Glitch Free Mux (GFM) Low power audio
subsystem (LPASS) clocks found on SM8250 SoCs.
+config QCOM_CLK_LPASS_HEARTBEAT_PULSE
+ tristate "Qualcomm LPASS VA CSR heartbeat pulse clock provider"
+ depends on COMMON_CLK
+ depends on ARM64 || COMPILE_TEST
+ select REGMAP_MMIO
+ default m if ARCH_QCOM
+ help
+ Qualcomm LPASS VA CSR block contains the rate generator hardware
+ that produces the HeartBeat Pulse (also known as RateGen Pulse).
+ This driver models the rate generator as a clock provider so
+ that consumers can enable or disable it via the common clock
+ framework, and it can be used to synchronize the start of DMAs
+ and Codec Interfaces or as a periodic wakeup source for the DSP.
+
config SM_VIDEOCC_8450
tristate "SM8450 Video Clock Controller"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 6affb5073f26..787a3761af3b 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_CLK_ELIZA_GPUCC) += gpucc-eliza.o
obj-$(CONFIG_CLK_ELIZA_TCSRCC) += tcsrcc-eliza.o
obj-$(CONFIG_CLK_ELIZA_VIDEOCC) += videocc-eliza.o
obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o
+obj-$(CONFIG_QCOM_CLK_LPASS_HEARTBEAT_PULSE) += lpass-va-csr.o
obj-$(CONFIG_CLK_GLYMUR_CAMCC) += camcc-glymur.o
obj-$(CONFIG_CLK_GLYMUR_DISPCC) += dispcc-glymur.o
obj-$(CONFIG_CLK_GLYMUR_EVACC) += evacc-glymur.o
diff --git a/drivers/clk/qcom/lpass-va-csr.c b/drivers/clk/qcom/lpass-va-csr.c
new file mode 100644
index 000000000000..93eafb2e043a
--- /dev/null
+++ b/drivers/clk/qcom/lpass-va-csr.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of_clk.h>
+#include <linux/pm_clock.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include "clk-regmap.h"
+
+#define LPASS_RATE_GEN_CTRL 0xd000
+#define LPASS_RATE_GEN_COUNTER_0 0xd004
+#define LPASS_RATE_GEN_DELAY 0xd010
+
+#define LPASS_RATE_GEN_MAX_REG LPASS_RATE_GEN_DELAY
+
+#define LPASS_RG_CTRL_EN BIT(0)
+
+struct lpass_va_csr_data {
+ u32 counter_0;
+ u32 delay;
+};
+
+static const struct lpass_va_csr_data hawi_csr_data = {
+ .counter_0 = 0x960,
+ .delay = 0x16,
+};
+
+static const struct regmap_config lpass_rate_gen_regmap_config = {
+ .name = "lpass_rate_gen",
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = LPASS_RATE_GEN_MAX_REG,
+ .cache_type = REGCACHE_MAPLE,
+};
+
+struct lpass_va_csr {
+ struct device *dev;
+ struct clk_regmap hb;
+};
+
+#define to_lpass_va_csr(_hw) \
+ container_of(to_clk_regmap(_hw), struct lpass_va_csr, hb)
+
+static int lpass_va_csr_hb_prepare(struct clk_hw *hw)
+{
+ struct lpass_va_csr *csr = to_lpass_va_csr(hw);
+
+ return pm_runtime_resume_and_get(csr->dev);
+}
+
+static void lpass_va_csr_hb_unprepare(struct clk_hw *hw)
+{
+ struct lpass_va_csr *csr = to_lpass_va_csr(hw);
+
+ pm_runtime_put_sync(csr->dev);
+}
+
+static const struct clk_ops lpass_va_csr_hb_ops = {
+ .prepare = lpass_va_csr_hb_prepare,
+ .unprepare = lpass_va_csr_hb_unprepare,
+ .enable = clk_enable_regmap,
+ .disable = clk_disable_regmap,
+};
+
+static int lpass_va_csr_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct lpass_va_csr_data *data = of_device_get_match_data(dev);
+ struct lpass_va_csr *csr;
+ struct clk_init_data init = {
+ .name = "lpass_heartbeat_pulse",
+ .ops = &lpass_va_csr_hb_ops,
+ };
+ struct regmap *regmap;
+ void __iomem *base;
+ int ret;
+
+ csr = devm_kzalloc(dev, sizeof(*csr), GFP_KERNEL);
+ if (!csr)
+ return -ENOMEM;
+
+ csr->dev = dev;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ regmap = devm_regmap_init_mmio(dev, base,
+ &lpass_rate_gen_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "failed to init regmap\n");
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable PM runtime\n");
+
+ ret = devm_pm_clk_create(dev);
+ if (ret)
+ return ret;
+
+ ret = of_pm_clk_add_clks(dev);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to get vote clocks\n");
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(regmap, LPASS_RATE_GEN_COUNTER_0, data->counter_0);
+ if (ret) {
+ pm_runtime_put_sync(dev);
+ return ret;
+ }
+
+ ret = regmap_write(regmap, LPASS_RATE_GEN_DELAY, data->delay);
+ if (ret) {
+ pm_runtime_put_sync(dev);
+ return ret;
+ }
+
+ csr->hb.regmap = regmap;
+ csr->hb.enable_reg = LPASS_RATE_GEN_CTRL;
+ csr->hb.enable_mask = LPASS_RG_CTRL_EN;
+ csr->hb.hw.init = &init;
+
+ ret = devm_clk_register_regmap(dev, &csr->hb);
+ if (ret) {
+ pm_runtime_put_sync(dev);
+ return ret;
+ }
+
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &csr->hb.hw);
+ if (ret) {
+ pm_runtime_put_sync(dev);
+ return ret;
+ }
+
+ pm_runtime_put_sync(dev);
+
+ return 0;
+}
+
+static const struct of_device_id lpass_va_csr_dt_match[] = {
+ { .compatible = "qcom,hawi-lpass-va-csr", .data = &hawi_csr_data },
+ {}
+};
+MODULE_DEVICE_TABLE(of, lpass_va_csr_dt_match);
+
+static const struct dev_pm_ops lpass_va_csr_pm_ops = {
+ SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
+};
+
+static struct platform_driver lpass_va_csr_driver = {
+ .driver = {
+ .name = "qcom-lpass-va-csr",
+ .of_match_table = lpass_va_csr_dt_match,
+ .pm = pm_ptr(&lpass_va_csr_pm_ops),
+ },
+ .probe = lpass_va_csr_probe,
+};
+
+module_platform_driver(lpass_va_csr_driver);
+
+MODULE_DESCRIPTION("Qualcomm LPASS VA CSR heartbeat pulse clock provider");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread