]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
clk: qcom: apss-ipq5424: Add ipq5424 apss clock controller
authorSricharan Ramabadhran <quic_srichara@quicinc.com>
Mon, 11 Aug 2025 09:09:52 +0000 (14:39 +0530)
committerBjorn Andersson <andersson@kernel.org>
Mon, 11 Aug 2025 15:06:36 +0000 (10:06 -0500)
CPU on Qualcomm ipq5424 is clocked by huayra PLL with RCG support.
Add support for the APSS PLL, RCG and clock enable for ipq5424.
The PLL, RCG register space are clubbed. Hence adding new APSS driver
for both PLL and RCG/CBC control. Also the L3 cache has a separate pll
and needs to be scaled along with the CPU and is modeled as an ICC clock.

[ Removed clock notifier, moved L3 pll to icc-clk, used existing
alpha pll structure ]

Co-developed-by: Md Sadre Alam <quic_mdalam@quicinc.com>
Signed-off-by: Md Sadre Alam <quic_mdalam@quicinc.com>
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250811090954.2854440-3-quic_varada@quicinc.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
drivers/clk/qcom/Kconfig
drivers/clk/qcom/Makefile
drivers/clk/qcom/apss-ipq5424.c [new file with mode: 0644]

index 6cb6cd3e1778ad3f2b6af3b8ebf22c7fb927cfe9..aeb6197d7c902098459c9b2cba75072bd519b0f3 100644 (file)
@@ -187,6 +187,15 @@ config IPQ_APSS_PLL
          Say Y if you want to support CPU frequency scaling on ipq based
          devices.
 
+config IPQ_APSS_5424
+       tristate "IPQ APSS Clock Controller"
+       select IPQ_APSS_PLL
+       default y if IPQ_GCC_5424
+       help
+         Support for APSS Clock controller on Qualcom IPQ5424 platform.
+         Say Y if you want to support CPU frequency scaling on ipq based
+         devices.
+
 config IPQ_APSS_6018
        tristate "IPQ APSS Clock Controller"
        select IPQ_APSS_PLL
index ddb7e06fae405de33c1cd4a68f4cf976f503c930..98de55eb64026a12d89587db295f8a6ac59ee2f7 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_CLK_X1E80100_TCSRCC) += tcsrcc-x1e80100.o
 obj-$(CONFIG_CLK_X1P42100_GPUCC) += gpucc-x1p42100.o
 obj-$(CONFIG_CLK_QCM2290_GPUCC) += gpucc-qcm2290.o
 obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o
+obj-$(CONFIG_IPQ_APSS_5424) += apss-ipq5424.o
 obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o
 obj-$(CONFIG_IPQ_CMN_PLL) += ipq-cmn-pll.o
 obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
diff --git a/drivers/clk/qcom/apss-ipq5424.c b/drivers/clk/qcom/apss-ipq5424.c
new file mode 100644 (file)
index 0000000..4c67f72
--- /dev/null
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/interconnect-provider.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/arm/qcom,ids.h>
+#include <dt-bindings/clock/qcom,apss-ipq.h>
+#include <dt-bindings/interconnect/qcom,ipq5424.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "common.h"
+
+enum {
+       DT_XO,
+       DT_CLK_REF,
+};
+
+enum {
+       P_XO,
+       P_GPLL0,
+       P_APSS_PLL_EARLY,
+       P_L3_PLL,
+};
+
+struct apss_clk {
+       struct notifier_block cpu_clk_notifier;
+       struct clk_hw *hw;
+       struct device *dev;
+       struct clk *l3_clk;
+};
+
+static const struct alpha_pll_config apss_pll_config = {
+       .l = 0x3b,
+       .config_ctl_val = 0x08200920,
+       .config_ctl_hi_val = 0x05008001,
+       .config_ctl_hi1_val = 0x04000000,
+       .user_ctl_val = 0xf,
+};
+
+static struct clk_alpha_pll ipq5424_apss_pll = {
+       .offset = 0x0,
+       .config = &apss_pll_config,
+       .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_HUAYRA_2290],
+       .flags = SUPPORTS_DYNAMIC_UPDATE,
+       .clkr = {
+               .enable_reg = 0x0,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "apss_pll",
+                       .parent_data = &(const struct clk_parent_data) {
+                               .index = DT_XO,
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_alpha_pll_huayra_ops,
+               },
+       },
+};
+
+static const struct clk_parent_data parents_apss_silver_clk_src[] = {
+       { .index = DT_XO },
+       { .index = DT_CLK_REF },
+       { .hw = &ipq5424_apss_pll.clkr.hw },
+};
+
+static const struct parent_map parents_apss_silver_clk_src_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 4 },
+       { P_APSS_PLL_EARLY, 5 },
+};
+
+static const struct freq_tbl ftbl_apss_clk_src[] = {
+       F(816000000, P_APSS_PLL_EARLY, 1, 0, 0),
+       F(1416000000, P_APSS_PLL_EARLY, 1, 0, 0),
+       F(1800000000, P_APSS_PLL_EARLY, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 apss_silver_clk_src = {
+       .cmd_rcgr = 0x0080,
+       .freq_tbl = ftbl_apss_clk_src,
+       .hid_width = 5,
+       .parent_map = parents_apss_silver_clk_src_map,
+       .clkr.hw.init = &(struct clk_init_data) {
+               .name = "apss_silver_clk_src",
+               .parent_data = parents_apss_silver_clk_src,
+               .num_parents = ARRAY_SIZE(parents_apss_silver_clk_src),
+               .ops = &clk_rcg2_ops,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_branch apss_silver_core_clk = {
+       .halt_reg = 0x008c,
+       .clkr = {
+               .enable_reg = 0x008c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data) {
+                       .name = "apss_silver_core_clk",
+                       .parent_hws = (const struct clk_hw *[]) {
+                               &apss_silver_clk_src.clkr.hw
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static const struct alpha_pll_config l3_pll_config = {
+       .l = 0x29,
+       .config_ctl_val = 0x08200920,
+       .config_ctl_hi_val = 0x05008001,
+       .config_ctl_hi1_val = 0x04000000,
+       .user_ctl_val = 0xf,
+};
+
+static struct clk_alpha_pll ipq5424_l3_pll = {
+       .offset = 0x10000,
+       .config = &l3_pll_config,
+       .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_HUAYRA_2290],
+       .flags = SUPPORTS_DYNAMIC_UPDATE,
+       .clkr = {
+               .enable_reg = 0x0,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data) {
+                       .name = "l3_pll",
+                       .parent_data = &(const struct clk_parent_data) {
+                               .index = DT_XO,
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_alpha_pll_huayra_ops,
+               },
+       },
+};
+
+static const struct clk_parent_data parents_l3_clk_src[] = {
+       { .index = DT_XO },
+       { .index = DT_CLK_REF },
+       { .hw = &ipq5424_l3_pll.clkr.hw },
+};
+
+static const struct parent_map parents_l3_clk_src_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 4 },
+       { P_L3_PLL, 5 },
+};
+
+static const struct freq_tbl ftbl_l3_clk_src[] = {
+       F(816000000, P_L3_PLL, 1, 0, 0),
+       F(984000000, P_L3_PLL, 1, 0, 0),
+       F(1272000000, P_L3_PLL, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 l3_clk_src = {
+       .cmd_rcgr = 0x10080,
+       .freq_tbl = ftbl_l3_clk_src,
+       .hid_width = 5,
+       .parent_map = parents_l3_clk_src_map,
+       .clkr.hw.init = &(struct clk_init_data) {
+               .name = "l3_clk_src",
+               .parent_data = parents_l3_clk_src,
+               .num_parents = ARRAY_SIZE(parents_l3_clk_src),
+               .ops = &clk_rcg2_ops,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_branch l3_core_clk = {
+       .halt_reg = 0x1008c,
+       .clkr = {
+               .enable_reg = 0x1008c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data) {
+                       .name = "l3_clk",
+                       .parent_hws = (const struct clk_hw *[]) {
+                               &l3_clk_src.clkr.hw
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static const struct regmap_config apss_ipq5424_regmap_config = {
+       .reg_bits       = 32,
+       .reg_stride     = 4,
+       .val_bits       = 32,
+       .max_register   = 0x20000,
+       .fast_io        = true,
+};
+
+static struct clk_regmap *apss_ipq5424_clks[] = {
+       [APSS_PLL_EARLY] = &ipq5424_apss_pll.clkr,
+       [APSS_SILVER_CLK_SRC] = &apss_silver_clk_src.clkr,
+       [APSS_SILVER_CORE_CLK] = &apss_silver_core_clk.clkr,
+       [L3_PLL] = &ipq5424_l3_pll.clkr,
+       [L3_CLK_SRC] = &l3_clk_src.clkr,
+       [L3_CORE_CLK] = &l3_core_clk.clkr,
+};
+
+static struct clk_alpha_pll *ipa5424_apss_plls[] = {
+       &ipq5424_l3_pll,
+       &ipq5424_apss_pll,
+};
+
+static struct qcom_cc_driver_data ipa5424_apss_driver_data = {
+       .alpha_plls = ipa5424_apss_plls,
+       .num_alpha_plls = ARRAY_SIZE(ipa5424_apss_plls),
+};
+
+#define IPQ_APPS_PLL_ID                        (5424 * 3)      /* some unique value */
+
+static const struct qcom_icc_hws_data icc_ipq5424_cpu_l3[] = {
+       { MASTER_CPU, SLAVE_L3, L3_CORE_CLK },
+};
+
+static const struct qcom_cc_desc apss_ipq5424_desc = {
+       .config = &apss_ipq5424_regmap_config,
+       .clks = apss_ipq5424_clks,
+       .num_clks = ARRAY_SIZE(apss_ipq5424_clks),
+       .icc_hws = icc_ipq5424_cpu_l3,
+       .num_icc_hws = ARRAY_SIZE(icc_ipq5424_cpu_l3),
+       .icc_first_node_id = IPQ_APPS_PLL_ID,
+       .driver_data = &ipa5424_apss_driver_data,
+};
+
+static int apss_ipq5424_probe(struct platform_device *pdev)
+{
+       return qcom_cc_probe(pdev, &apss_ipq5424_desc);
+}
+
+static const struct of_device_id apss_ipq5424_match_table[] = {
+       { .compatible = "qcom,ipq5424-apss-clk" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, apss_ipq5424_match_table);
+
+static struct platform_driver apss_ipq5424_driver = {
+       .probe = apss_ipq5424_probe,
+       .driver = {
+               .name   = "apss-ipq5424-clk",
+               .of_match_table = apss_ipq5424_match_table,
+               .sync_state = icc_sync_state,
+       },
+};
+
+module_platform_driver(apss_ipq5424_driver);
+
+MODULE_DESCRIPTION("QCOM APSS IPQ5424 CLK Driver");
+MODULE_LICENSE("GPL");