diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-ax6000.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-ax6000.dts index 93898d88e0..8c8766327d 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-ax6000.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-ax6000.dts @@ -98,7 +98,8 @@ }; &xo_board_clk { - clock-frequency = <24000000>; + clock-div = <4>; + clock-mult = <1>; }; &blsp1_uart1 { diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-ax830.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-ax830.dts index 2853c84c46..de36118c0a 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-ax830.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-ax830.dts @@ -147,7 +147,8 @@ }; &xo_board_clk { - clock-frequency = <24000000>; + clock-div = <4>; + clock-mult = <1>; }; &blsp1_uart1 { diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-gl-b3000.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-gl-b3000.dts index 30fce130bf..f389bb0386 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-gl-b3000.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-gl-b3000.dts @@ -181,7 +181,8 @@ }; &xo_board_clk { - clock-frequency = <24000000>; + clock-div = <4>; + clock-mult = <1>; }; &blsp1_uart1 { diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx-base.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx-base.dtsi index 29754b1e03..c56882fb7a 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx-base.dtsi +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-mx-base.dtsi @@ -76,7 +76,8 @@ }; &xo_board_clk { - clock-frequency = <24000000>; + clock-div = <4>; + clock-mult = <1>; }; &blsp1_uart1 { diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-wn-dax3000gr.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-wn-dax3000gr.dts index 572f2fbcb2..18c4a7a233 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-wn-dax3000gr.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-wn-dax3000gr.dts @@ -127,7 +127,8 @@ }; &xo_board_clk { - clock-frequency = <24000000>; + clock-div = <4>; + clock-mult = <1>; }; &blsp1_uart1 { diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-wrc-x3000gs2.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-wrc-x3000gs2.dts index 3e01b8dbd1..c6ff01bfb8 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-wrc-x3000gs2.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq5018-wrc-x3000gs2.dts @@ -122,7 +122,8 @@ }; &xo_board_clk { - clock-frequency = <24000000>; + clock-div = <4>; + clock-mult = <1>; }; &blsp1_uart1 { diff --git a/target/linux/qualcommax/patches-6.12/0063-v6.14-clk-qcom-Add-CMN-PLL-clock-controller-driver-for-IPQ-SoC.patch b/target/linux/qualcommax/patches-6.12/0063-v6.14-clk-qcom-Add-CMN-PLL-clock-controller-driver-for-IPQ-SoC.patch new file mode 100644 index 0000000000..7317a13edc --- /dev/null +++ b/target/linux/qualcommax/patches-6.12/0063-v6.14-clk-qcom-Add-CMN-PLL-clock-controller-driver-for-IPQ-SoC.patch @@ -0,0 +1,472 @@ +From f81715a4c87c3b75ca2640bb61b6c66506061a64 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Fri, 3 Jan 2025 15:31:35 +0800 +Subject: clk: qcom: Add CMN PLL clock controller driver for IPQ SoC + +The CMN PLL clock controller supplies clocks to the hardware +blocks that together make up the Ethernet function on Qualcomm +IPQ SoCs and to GCC. The driver is initially supported for +IPQ9574 SoC. + +The CMN PLL clock controller expects a reference input clock +from the on-board Wi-Fi block acting as clock source. The input +reference clock needs to be configured to one of the supported +clock rates. + +The controller supplies a number of fixed-rate output clocks. +For the IPQ9574, there is one output clock of 353 MHZ to PPE +(Packet Process Engine) hardware block, three 50 MHZ output +clocks and an additional 25 MHZ output clock supplied to the +connected Ethernet devices. The PLL also supplies a 24 MHZ +clock as XO and a 32 KHZ sleep clock to GCC, and one 31.25 +MHZ clock to PCS. + +Signed-off-by: Luo Jie +Acked-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20250103-qcom_ipq_cmnpll-v8-2-c89fb4d4849d@quicinc.com +Signed-off-by: Bjorn Andersson +--- + drivers/clk/qcom/ipq-cmn-pll.c | 435 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 435 insertions(+) + create mode 100644 drivers/clk/qcom/ipq-cmn-pll.c + +(limited to 'drivers/clk/qcom/ipq-cmn-pll.c') + +--- /dev/null ++++ b/drivers/clk/qcom/ipq-cmn-pll.c +@@ -0,0 +1,435 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++/* ++ * CMN PLL block expects the reference clock from on-board Wi-Fi block, ++ * and supplies fixed rate clocks as output to the networking hardware ++ * blocks and to GCC. The networking related blocks include PPE (packet ++ * process engine), the externally connected PHY or switch devices, and ++ * the PCS. ++ * ++ * On the IPQ9574 SoC, there are three clocks with 50 MHZ and one clock ++ * with 25 MHZ which are output from the CMN PLL to Ethernet PHY (or switch), ++ * and one clock with 353 MHZ to PPE. The other fixed rate output clocks ++ * are supplied to GCC (24 MHZ as XO and 32 KHZ as sleep clock), and to PCS ++ * with 31.25 MHZ. ++ * ++ * +---------+ ++ * | GCC | ++ * +--+---+--+ ++ * AHB CLK| |SYS CLK ++ * V V ++ * +-------+---+------+ ++ * | +-------------> eth0-50mhz ++ * REF CLK | IPQ9574 | ++ * -------->+ +-------------> eth1-50mhz ++ * | CMN PLL block | ++ * | +-------------> eth2-50mhz ++ * | | ++ * +----+----+----+---+-------------> eth-25mhz ++ * | | | ++ * V V V ++ * GCC PCS NSS/PPE ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define CMN_PLL_REFCLK_SRC_SELECTION 0x28 ++#define CMN_PLL_REFCLK_SRC_DIV GENMASK(9, 8) ++ ++#define CMN_PLL_LOCKED 0x64 ++#define CMN_PLL_CLKS_LOCKED BIT(8) ++ ++#define CMN_PLL_POWER_ON_AND_RESET 0x780 ++#define CMN_ANA_EN_SW_RSTN BIT(6) ++ ++#define CMN_PLL_REFCLK_CONFIG 0x784 ++#define CMN_PLL_REFCLK_EXTERNAL BIT(9) ++#define CMN_PLL_REFCLK_DIV GENMASK(8, 4) ++#define CMN_PLL_REFCLK_INDEX GENMASK(3, 0) ++ ++#define CMN_PLL_CTRL 0x78c ++#define CMN_PLL_CTRL_LOCK_DETECT_EN BIT(15) ++ ++#define CMN_PLL_DIVIDER_CTRL 0x794 ++#define CMN_PLL_DIVIDER_CTRL_FACTOR GENMASK(9, 0) ++ ++/** ++ * struct cmn_pll_fixed_output_clk - CMN PLL output clocks information ++ * @id: Clock specifier to be supplied ++ * @name: Clock name to be registered ++ * @rate: Clock rate ++ */ ++struct cmn_pll_fixed_output_clk { ++ unsigned int id; ++ const char *name; ++ unsigned long rate; ++}; ++ ++/** ++ * struct clk_cmn_pll - CMN PLL hardware specific data ++ * @regmap: hardware regmap. ++ * @hw: handle between common and hardware-specific interfaces ++ */ ++struct clk_cmn_pll { ++ struct regmap *regmap; ++ struct clk_hw hw; ++}; ++ ++#define CLK_PLL_OUTPUT(_id, _name, _rate) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .rate = _rate, \ ++} ++ ++#define to_clk_cmn_pll(_hw) container_of(_hw, struct clk_cmn_pll, hw) ++ ++static const struct regmap_config ipq_cmn_pll_regmap_config = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .max_register = 0x7fc, ++ .fast_io = true, ++}; ++ ++static const struct cmn_pll_fixed_output_clk ipq9574_output_clks[] = { ++ CLK_PLL_OUTPUT(XO_24MHZ_CLK, "xo-24mhz", 24000000UL), ++ CLK_PLL_OUTPUT(SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL), ++ CLK_PLL_OUTPUT(PCS_31P25MHZ_CLK, "pcs-31p25mhz", 31250000UL), ++ CLK_PLL_OUTPUT(NSS_1200MHZ_CLK, "nss-1200mhz", 1200000000UL), ++ CLK_PLL_OUTPUT(PPE_353MHZ_CLK, "ppe-353mhz", 353000000UL), ++ CLK_PLL_OUTPUT(ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL), ++ CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL), ++ CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL), ++ CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL), ++}; ++ ++/* ++ * CMN PLL has the single parent clock, which supports the several ++ * possible parent clock rates, each parent clock rate is reflected ++ * by the specific reference index value in the hardware. ++ */ ++static int ipq_cmn_pll_find_freq_index(unsigned long parent_rate) ++{ ++ int index = -EINVAL; ++ ++ switch (parent_rate) { ++ case 25000000: ++ index = 3; ++ break; ++ case 31250000: ++ index = 4; ++ break; ++ case 40000000: ++ index = 6; ++ break; ++ case 48000000: ++ case 96000000: ++ /* ++ * Parent clock rate 48 MHZ and 96 MHZ take the same value ++ * of reference clock index. 96 MHZ needs the source clock ++ * divider to be programmed as 2. ++ */ ++ index = 7; ++ break; ++ case 50000000: ++ index = 8; ++ break; ++ default: ++ break; ++ } ++ ++ return index; ++} ++ ++static unsigned long clk_cmn_pll_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct clk_cmn_pll *cmn_pll = to_clk_cmn_pll(hw); ++ u32 val, factor; ++ ++ /* ++ * The value of CMN_PLL_DIVIDER_CTRL_FACTOR is automatically adjusted ++ * by HW according to the parent clock rate. ++ */ ++ regmap_read(cmn_pll->regmap, CMN_PLL_DIVIDER_CTRL, &val); ++ factor = FIELD_GET(CMN_PLL_DIVIDER_CTRL_FACTOR, val); ++ ++ return parent_rate * 2 * factor; ++} ++ ++static int clk_cmn_pll_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ int ret; ++ ++ /* Validate the rate of the single parent clock. */ ++ ret = ipq_cmn_pll_find_freq_index(req->best_parent_rate); ++ ++ return ret < 0 ? ret : 0; ++} ++ ++/* ++ * This function is used to initialize the CMN PLL to enable the fixed ++ * rate output clocks. It is expected to be configured once. ++ */ ++static int clk_cmn_pll_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct clk_cmn_pll *cmn_pll = to_clk_cmn_pll(hw); ++ int ret, index; ++ u32 val; ++ ++ /* ++ * Configure the reference input clock selection as per the given ++ * parent clock. The output clock rates are always of fixed value. ++ */ ++ index = ipq_cmn_pll_find_freq_index(parent_rate); ++ if (index < 0) ++ return index; ++ ++ ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_CONFIG, ++ CMN_PLL_REFCLK_INDEX, ++ FIELD_PREP(CMN_PLL_REFCLK_INDEX, index)); ++ if (ret) ++ return ret; ++ ++ /* ++ * Update the source clock rate selection and source clock ++ * divider as 2 when the parent clock rate is 96 MHZ. ++ */ ++ if (parent_rate == 96000000) { ++ ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_CONFIG, ++ CMN_PLL_REFCLK_DIV, ++ FIELD_PREP(CMN_PLL_REFCLK_DIV, 2)); ++ if (ret) ++ return ret; ++ ++ ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_SRC_SELECTION, ++ CMN_PLL_REFCLK_SRC_DIV, ++ FIELD_PREP(CMN_PLL_REFCLK_SRC_DIV, 0)); ++ if (ret) ++ return ret; ++ } ++ ++ /* Enable PLL locked detect. */ ++ ret = regmap_set_bits(cmn_pll->regmap, CMN_PLL_CTRL, ++ CMN_PLL_CTRL_LOCK_DETECT_EN); ++ if (ret) ++ return ret; ++ ++ /* ++ * Reset the CMN PLL block to ensure the updated configurations ++ * take effect. ++ */ ++ ret = regmap_clear_bits(cmn_pll->regmap, CMN_PLL_POWER_ON_AND_RESET, ++ CMN_ANA_EN_SW_RSTN); ++ if (ret) ++ return ret; ++ ++ usleep_range(1000, 1200); ++ ret = regmap_set_bits(cmn_pll->regmap, CMN_PLL_POWER_ON_AND_RESET, ++ CMN_ANA_EN_SW_RSTN); ++ if (ret) ++ return ret; ++ ++ /* Stability check of CMN PLL output clocks. */ ++ return regmap_read_poll_timeout(cmn_pll->regmap, CMN_PLL_LOCKED, val, ++ (val & CMN_PLL_CLKS_LOCKED), ++ 100, 100 * USEC_PER_MSEC); ++} ++ ++static const struct clk_ops clk_cmn_pll_ops = { ++ .recalc_rate = clk_cmn_pll_recalc_rate, ++ .determine_rate = clk_cmn_pll_determine_rate, ++ .set_rate = clk_cmn_pll_set_rate, ++}; ++ ++static struct clk_hw *ipq_cmn_pll_clk_hw_register(struct platform_device *pdev) ++{ ++ struct clk_parent_data pdata = { .index = 0 }; ++ struct device *dev = &pdev->dev; ++ struct clk_init_data init = {}; ++ struct clk_cmn_pll *cmn_pll; ++ struct regmap *regmap; ++ void __iomem *base; ++ int ret; ++ ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return ERR_CAST(base); ++ ++ regmap = devm_regmap_init_mmio(dev, base, &ipq_cmn_pll_regmap_config); ++ if (IS_ERR(regmap)) ++ return ERR_CAST(regmap); ++ ++ cmn_pll = devm_kzalloc(dev, sizeof(*cmn_pll), GFP_KERNEL); ++ if (!cmn_pll) ++ return ERR_PTR(-ENOMEM); ++ ++ init.name = "cmn_pll"; ++ init.parent_data = &pdata; ++ init.num_parents = 1; ++ init.ops = &clk_cmn_pll_ops; ++ ++ cmn_pll->hw.init = &init; ++ cmn_pll->regmap = regmap; ++ ++ ret = devm_clk_hw_register(dev, &cmn_pll->hw); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ return &cmn_pll->hw; ++} ++ ++static int ipq_cmn_pll_register_clks(struct platform_device *pdev) ++{ ++ const struct cmn_pll_fixed_output_clk *fixed_clk; ++ struct clk_hw_onecell_data *hw_data; ++ struct device *dev = &pdev->dev; ++ struct clk_hw *cmn_pll_hw; ++ unsigned int num_clks; ++ struct clk_hw *hw; ++ int ret, i; ++ ++ fixed_clk = ipq9574_output_clks; ++ num_clks = ARRAY_SIZE(ipq9574_output_clks); ++ ++ hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, num_clks + 1), ++ GFP_KERNEL); ++ if (!hw_data) ++ return -ENOMEM; ++ ++ /* ++ * Register the CMN PLL clock, which is the parent clock of ++ * the fixed rate output clocks. ++ */ ++ cmn_pll_hw = ipq_cmn_pll_clk_hw_register(pdev); ++ if (IS_ERR(cmn_pll_hw)) ++ return PTR_ERR(cmn_pll_hw); ++ ++ /* Register the fixed rate output clocks. */ ++ for (i = 0; i < num_clks; i++) { ++ hw = clk_hw_register_fixed_rate_parent_hw(dev, fixed_clk[i].name, ++ cmn_pll_hw, 0, ++ fixed_clk[i].rate); ++ if (IS_ERR(hw)) { ++ ret = PTR_ERR(hw); ++ goto unregister_fixed_clk; ++ } ++ ++ hw_data->hws[fixed_clk[i].id] = hw; ++ } ++ ++ /* ++ * Provide the CMN PLL clock. The clock rate of CMN PLL ++ * is configured to 12 GHZ by DT property assigned-clock-rates-u64. ++ */ ++ hw_data->hws[CMN_PLL_CLK] = cmn_pll_hw; ++ hw_data->num = num_clks + 1; ++ ++ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data); ++ if (ret) ++ goto unregister_fixed_clk; ++ ++ platform_set_drvdata(pdev, hw_data); ++ ++ return 0; ++ ++unregister_fixed_clk: ++ while (i > 0) ++ clk_hw_unregister(hw_data->hws[fixed_clk[--i].id]); ++ ++ return ret; ++} ++ ++static int ipq_cmn_pll_clk_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ int ret; ++ ++ ret = devm_pm_runtime_enable(dev); ++ if (ret) ++ return ret; ++ ++ ret = devm_pm_clk_create(dev); ++ if (ret) ++ return ret; ++ ++ /* ++ * To access the CMN PLL registers, the GCC AHB & SYS clocks ++ * of CMN PLL block need to be enabled. ++ */ ++ ret = pm_clk_add(dev, "ahb"); ++ if (ret) ++ return dev_err_probe(dev, ret, "Fail to add AHB clock\n"); ++ ++ ret = pm_clk_add(dev, "sys"); ++ if (ret) ++ return dev_err_probe(dev, ret, "Fail to add SYS clock\n"); ++ ++ ret = pm_runtime_resume_and_get(dev); ++ if (ret) ++ return ret; ++ ++ /* Register CMN PLL clock and fixed rate output clocks. */ ++ ret = ipq_cmn_pll_register_clks(pdev); ++ pm_runtime_put(dev); ++ if (ret) ++ return dev_err_probe(dev, ret, ++ "Fail to register CMN PLL clocks\n"); ++ ++ return 0; ++} ++ ++static void ipq_cmn_pll_clk_remove(struct platform_device *pdev) ++{ ++ struct clk_hw_onecell_data *hw_data = platform_get_drvdata(pdev); ++ int i; ++ ++ /* ++ * The clock with index CMN_PLL_CLK is unregistered by ++ * device management. ++ */ ++ for (i = 0; i < hw_data->num; i++) { ++ if (i != CMN_PLL_CLK) ++ clk_hw_unregister(hw_data->hws[i]); ++ } ++} ++ ++static const struct dev_pm_ops ipq_cmn_pll_pm_ops = { ++ SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) ++}; ++ ++static const struct of_device_id ipq_cmn_pll_clk_ids[] = { ++ { .compatible = "qcom,ipq9574-cmn-pll", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ipq_cmn_pll_clk_ids); ++ ++static struct platform_driver ipq_cmn_pll_clk_driver = { ++ .probe = ipq_cmn_pll_clk_probe, ++ .remove = ipq_cmn_pll_clk_remove, ++ .driver = { ++ .name = "ipq_cmn_pll", ++ .of_match_table = ipq_cmn_pll_clk_ids, ++ .pm = &ipq_cmn_pll_pm_ops, ++ }, ++}; ++module_platform_driver(ipq_cmn_pll_clk_driver); ++ ++MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ CMN PLL Driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/qualcommax/patches-6.12/0064-v6.17-clk-qcom-cmnpll-Add-IPQ5424-SoC-support.patch b/target/linux/qualcommax/patches-6.12/0064-v6.17-clk-qcom-cmnpll-Add-IPQ5424-SoC-support.patch new file mode 100644 index 0000000000..d13e0b1fd5 --- /dev/null +++ b/target/linux/qualcommax/patches-6.12/0064-v6.17-clk-qcom-cmnpll-Add-IPQ5424-SoC-support.patch @@ -0,0 +1,104 @@ +From a2afa4c33f0a7f7f70d54a1bc5110e326753f982 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Tue, 10 Jun 2025 18:35:19 +0800 +Subject: clk: qcom: cmnpll: Add IPQ5424 SoC support + +The CMN PLL in IPQ5424 SoC supplies the fixed clock to NSS at 300 MHZ +and to PPE at 375 MHZ. Other output clocks from CMN PLL on this SoC, +and their rates are same as IPQ9574. + +Acked-by: Stephen Boyd +Signed-off-by: Luo Jie +Link: https://lore.kernel.org/r/20250610-qcom_ipq5424_cmnpll-v3-2-ceada8165645@quicinc.com +Signed-off-by: Bjorn Andersson +--- + drivers/clk/qcom/ipq-cmn-pll.c | 35 ++++++++++++++++++++++++++++++----- + 1 file changed, 30 insertions(+), 5 deletions(-) + +(limited to 'drivers/clk/qcom/ipq-cmn-pll.c') + +--- a/drivers/clk/qcom/ipq-cmn-pll.c ++++ b/drivers/clk/qcom/ipq-cmn-pll.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* +- * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + /* +@@ -16,6 +16,10 @@ + * are supplied to GCC (24 MHZ as XO and 32 KHZ as sleep clock), and to PCS + * with 31.25 MHZ. + * ++ * On the IPQ5424 SoC, there is an output clock from CMN PLL to PPE at 375 MHZ, ++ * and an output clock to NSS (network subsystem) at 300 MHZ. The other output ++ * clocks from CMN PLL on IPQ5424 are the same as IPQ9574. ++ * + * +---------+ + * | GCC | + * +--+---+--+ +@@ -46,6 +50,7 @@ + #include + + #include ++#include + + #define CMN_PLL_REFCLK_SRC_SELECTION 0x28 + #define CMN_PLL_REFCLK_SRC_DIV GENMASK(9, 8) +@@ -115,6 +120,20 @@ static const struct cmn_pll_fixed_output + CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL), + CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL), + CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL), ++ { /* Sentinel */ } ++}; ++ ++static const struct cmn_pll_fixed_output_clk ipq5424_output_clks[] = { ++ CLK_PLL_OUTPUT(IPQ5424_XO_24MHZ_CLK, "xo-24mhz", 24000000UL), ++ CLK_PLL_OUTPUT(IPQ5424_SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL), ++ CLK_PLL_OUTPUT(IPQ5424_PCS_31P25MHZ_CLK, "pcs-31p25mhz", 31250000UL), ++ CLK_PLL_OUTPUT(IPQ5424_NSS_300MHZ_CLK, "nss-300mhz", 300000000UL), ++ CLK_PLL_OUTPUT(IPQ5424_PPE_375MHZ_CLK, "ppe-375mhz", 375000000UL), ++ CLK_PLL_OUTPUT(IPQ5424_ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL), ++ CLK_PLL_OUTPUT(IPQ5424_ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL), ++ CLK_PLL_OUTPUT(IPQ5424_ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL), ++ CLK_PLL_OUTPUT(IPQ5424_ETH_25MHZ_CLK, "eth-25mhz", 25000000UL), ++ { /* Sentinel */ } + }; + + /* +@@ -297,7 +316,7 @@ static struct clk_hw *ipq_cmn_pll_clk_hw + + static int ipq_cmn_pll_register_clks(struct platform_device *pdev) + { +- const struct cmn_pll_fixed_output_clk *fixed_clk; ++ const struct cmn_pll_fixed_output_clk *p, *fixed_clk; + struct clk_hw_onecell_data *hw_data; + struct device *dev = &pdev->dev; + struct clk_hw *cmn_pll_hw; +@@ -305,8 +324,13 @@ static int ipq_cmn_pll_register_clks(str + struct clk_hw *hw; + int ret, i; + +- fixed_clk = ipq9574_output_clks; +- num_clks = ARRAY_SIZE(ipq9574_output_clks); ++ fixed_clk = device_get_match_data(dev); ++ if (!fixed_clk) ++ return -EINVAL; ++ ++ num_clks = 0; ++ for (p = fixed_clk; p->name; p++) ++ num_clks++; + + hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, num_clks + 1), + GFP_KERNEL); +@@ -415,7 +439,8 @@ static const struct dev_pm_ops ipq_cmn_p + }; + + static const struct of_device_id ipq_cmn_pll_clk_ids[] = { +- { .compatible = "qcom,ipq9574-cmn-pll", }, ++ { .compatible = "qcom,ipq9574-cmn-pll", .data = &ipq9574_output_clks }, ++ { .compatible = "qcom,ipq5424-cmn-pll", .data = &ipq5424_output_clks }, + { } + }; + MODULE_DEVICE_TABLE(of, ipq_cmn_pll_clk_ids); diff --git a/target/linux/qualcommax/patches-6.12/0065-v6.17-dt-bindings-clock-qcom-Add-CMN-PLL-support-for-IPQ5018-SoC.patch b/target/linux/qualcommax/patches-6.12/0065-v6.17-dt-bindings-clock-qcom-Add-CMN-PLL-support-for-IPQ5018-SoC.patch new file mode 100644 index 0000000000..c0d887f9a1 --- /dev/null +++ b/target/linux/qualcommax/patches-6.12/0065-v6.17-dt-bindings-clock-qcom-Add-CMN-PLL-support-for-IPQ5018-SoC.patch @@ -0,0 +1,39 @@ +From 314b903c30040632db7edd187cd33003b2aee512 Mon Sep 17 00:00:00 2001 +From: George Moussalem +Date: Fri, 16 May 2025 16:36:09 +0400 +Subject: dt-bindings: clock: qcom: Add CMN PLL support for IPQ5018 SoC + +The CMN PLL block in the IPQ5018 SoC takes 96 MHZ as the reference +input clock. Its output clocks are the XO (24Mhz), sleep (32Khz), and +ethernet (50Mhz) clocks. + +Reviewed-by: Rob Herring (Arm) +Signed-off-by: George Moussalem +Link: https://lore.kernel.org/r/20250516-ipq5018-cmn-pll-v4-2-389a6b30e504@outlook.com +Signed-off-by: Bjorn Andersson +--- + include/dt-bindings/clock/qcom,ipq5018-cmn-pll.h | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + create mode 100644 include/dt-bindings/clock/qcom,ipq5018-cmn-pll.h + +(limited to 'include/dt-bindings/clock/qcom,ipq5018-cmn-pll.h') + +--- /dev/null ++++ b/include/dt-bindings/clock/qcom,ipq5018-cmn-pll.h +@@ -0,0 +1,16 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ ++/* ++ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#ifndef _DT_BINDINGS_CLK_QCOM_IPQ5018_CMN_PLL_H ++#define _DT_BINDINGS_CLK_QCOM_IPQ5018_CMN_PLL_H ++ ++/* CMN PLL core clock. */ ++#define IPQ5018_CMN_PLL_CLK 0 ++ ++/* The output clocks from CMN PLL of IPQ5018. */ ++#define IPQ5018_XO_24MHZ_CLK 1 ++#define IPQ5018_SLEEP_32KHZ_CLK 2 ++#define IPQ5018_ETH_50MHZ_CLK 3 ++#endif diff --git a/target/linux/qualcommax/patches-6.12/0066-v6.17-clk-qcom-ipq-cmn-pll-Add-IPQ5018-SoC-support.patch b/target/linux/qualcommax/patches-6.12/0066-v6.17-clk-qcom-ipq-cmn-pll-Add-IPQ5018-SoC-support.patch new file mode 100644 index 0000000000..d113c2d6c0 --- /dev/null +++ b/target/linux/qualcommax/patches-6.12/0066-v6.17-clk-qcom-ipq-cmn-pll-Add-IPQ5018-SoC-support.patch @@ -0,0 +1,102 @@ +From 25d12630561d8d0906f1f5eceb055da3af67c8c9 Mon Sep 17 00:00:00 2001 +From: George Moussalem +Date: Fri, 16 May 2025 16:36:10 +0400 +Subject: clk: qcom: ipq-cmn-pll: Add IPQ5018 SoC support + +The CMN PLL in IPQ5018 SoC supplies fixed clocks to XO, sleep, and the +ethernet block. + +Signed-off-by: George Moussalem +Link: https://lore.kernel.org/r/20250516-ipq5018-cmn-pll-v4-3-389a6b30e504@outlook.com +Signed-off-by: Bjorn Andersson +--- + drivers/clk/qcom/ipq-cmn-pll.c | 37 +++++++++++++++++++++++-------------- + 1 file changed, 23 insertions(+), 14 deletions(-) + +(limited to 'drivers/clk/qcom/ipq-cmn-pll.c') + +--- a/drivers/clk/qcom/ipq-cmn-pll.c ++++ b/drivers/clk/qcom/ipq-cmn-pll.c +@@ -50,6 +50,7 @@ + #include + + #include ++#include + #include + + #define CMN_PLL_REFCLK_SRC_SELECTION 0x28 +@@ -110,16 +111,10 @@ static const struct regmap_config ipq_cm + .fast_io = true, + }; + +-static const struct cmn_pll_fixed_output_clk ipq9574_output_clks[] = { +- CLK_PLL_OUTPUT(XO_24MHZ_CLK, "xo-24mhz", 24000000UL), +- CLK_PLL_OUTPUT(SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL), +- CLK_PLL_OUTPUT(PCS_31P25MHZ_CLK, "pcs-31p25mhz", 31250000UL), +- CLK_PLL_OUTPUT(NSS_1200MHZ_CLK, "nss-1200mhz", 1200000000UL), +- CLK_PLL_OUTPUT(PPE_353MHZ_CLK, "ppe-353mhz", 353000000UL), +- CLK_PLL_OUTPUT(ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL), +- CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL), +- CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL), +- CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL), ++static const struct cmn_pll_fixed_output_clk ipq5018_output_clks[] = { ++ CLK_PLL_OUTPUT(IPQ5018_XO_24MHZ_CLK, "xo-24mhz", 24000000UL), ++ CLK_PLL_OUTPUT(IPQ5018_SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL), ++ CLK_PLL_OUTPUT(IPQ5018_ETH_50MHZ_CLK, "eth-50mhz", 50000000UL), + { /* Sentinel */ } + }; + +@@ -136,6 +131,19 @@ static const struct cmn_pll_fixed_output + { /* Sentinel */ } + }; + ++static const struct cmn_pll_fixed_output_clk ipq9574_output_clks[] = { ++ CLK_PLL_OUTPUT(XO_24MHZ_CLK, "xo-24mhz", 24000000UL), ++ CLK_PLL_OUTPUT(SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL), ++ CLK_PLL_OUTPUT(PCS_31P25MHZ_CLK, "pcs-31p25mhz", 31250000UL), ++ CLK_PLL_OUTPUT(NSS_1200MHZ_CLK, "nss-1200mhz", 1200000000UL), ++ CLK_PLL_OUTPUT(PPE_353MHZ_CLK, "ppe-353mhz", 353000000UL), ++ CLK_PLL_OUTPUT(ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL), ++ CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL), ++ CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL), ++ CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL), ++ { /* Sentinel */ } ++}; ++ + /* + * CMN PLL has the single parent clock, which supports the several + * possible parent clock rates, each parent clock rate is reflected +@@ -399,11 +407,11 @@ static int ipq_cmn_pll_clk_probe(struct + */ + ret = pm_clk_add(dev, "ahb"); + if (ret) +- return dev_err_probe(dev, ret, "Fail to add AHB clock\n"); ++ return dev_err_probe(dev, ret, "Failed to add AHB clock\n"); + + ret = pm_clk_add(dev, "sys"); + if (ret) +- return dev_err_probe(dev, ret, "Fail to add SYS clock\n"); ++ return dev_err_probe(dev, ret, "Failed to add SYS clock\n"); + + ret = pm_runtime_resume_and_get(dev); + if (ret) +@@ -414,7 +422,7 @@ static int ipq_cmn_pll_clk_probe(struct + pm_runtime_put(dev); + if (ret) + return dev_err_probe(dev, ret, +- "Fail to register CMN PLL clocks\n"); ++ "Failed to register CMN PLL clocks\n"); + + return 0; + } +@@ -439,8 +447,9 @@ static const struct dev_pm_ops ipq_cmn_p + }; + + static const struct of_device_id ipq_cmn_pll_clk_ids[] = { +- { .compatible = "qcom,ipq9574-cmn-pll", .data = &ipq9574_output_clks }, ++ { .compatible = "qcom,ipq5018-cmn-pll", .data = &ipq5018_output_clks }, + { .compatible = "qcom,ipq5424-cmn-pll", .data = &ipq5424_output_clks }, ++ { .compatible = "qcom,ipq9574-cmn-pll", .data = &ipq9574_output_clks }, + { } + }; + MODULE_DEVICE_TABLE(of, ipq_cmn_pll_clk_ids); diff --git a/target/linux/qualcommax/patches-6.12/0067-v6.18-arm64-dts-ipq5018-Add-CMN-PLL-node.patch b/target/linux/qualcommax/patches-6.12/0067-v6.18-arm64-dts-ipq5018-Add-CMN-PLL-node.patch new file mode 100644 index 0000000000..83d6714153 --- /dev/null +++ b/target/linux/qualcommax/patches-6.12/0067-v6.18-arm64-dts-ipq5018-Add-CMN-PLL-node.patch @@ -0,0 +1,89 @@ +From c006b249c54441dd8a3a493c7c87158f441f8178 Mon Sep 17 00:00:00 2001 +From: George Moussalem +Date: Mon, 21 Jul 2025 10:04:35 +0400 +Subject: arm64: dts: ipq5018: Add CMN PLL node + +Add CMN PLL node for enabling output clocks to the networking +hardware blocks on IPQ5018 devices. + +The reference clock of CMN PLL is routed from XO to the CMN PLL +through the internal WiFi block. +.XO (48 MHZ) --> WiFi (multiplier/divider)--> 96 MHZ to CMN PLL. + +Reviewed-by: Konrad Dybcio +Signed-off-by: George Moussalem +Link: https://lore.kernel.org/r/20250721-ipq5018-cmn-pll-v5-1-4cbf3479af65@outlook.com +Signed-off-by: Bjorn Andersson +--- + arch/arm64/boot/dts/qcom/ipq5018.dtsi | 33 +++++++++++++++++++++++++++++++-- + 1 file changed, 31 insertions(+), 2 deletions(-) + +(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi') + +--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi +@@ -2,12 +2,13 @@ + /* + * IPQ5018 SoC device tree source + * +- * Copyright (c) 2023 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2023-2025 The Linux Foundation. All rights reserved. + */ + + #include +-#include + #include ++#include ++#include + #include + #include + +@@ -29,6 +30,14 @@ + #clock-cells = <0>; + }; + ++ ref_96mhz_clk: ref-96mhz-clk { ++ compatible = "fixed-factor-clock"; ++ clocks = <&xo_clk>; ++ #clock-cells = <0>; ++ clock-div = <1>; ++ clock-mult = <2>; ++ }; ++ + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; +@@ -38,6 +47,12 @@ + compatible = "fixed-clock"; + #clock-cells = <0>; + }; ++ ++ xo_clk: xo-clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <48000000>; ++ }; + }; + + cpus { +@@ -229,6 +244,20 @@ + status = "disabled"; + }; + ++ cmn_pll: clock-controller@9b000 { ++ compatible = "qcom,ipq5018-cmn-pll"; ++ reg = <0x0009b000 0x800>; ++ clocks = <&ref_96mhz_clk>, ++ <&gcc GCC_CMN_BLK_AHB_CLK>, ++ <&gcc GCC_CMN_BLK_SYS_CLK>; ++ clock-names = "ref", ++ "ahb", ++ "sys"; ++ #clock-cells = <1>; ++ assigned-clocks = <&cmn_pll IPQ5018_CMN_PLL_CLK>; ++ assigned-clock-rates-u64 = /bits/ 64 <9600000000>; ++ }; ++ + qfprom: qfprom@a0000 { + compatible = "qcom,ipq5018-qfprom", "qcom,qfprom"; + reg = <0x000a0000 0x1000>; diff --git a/target/linux/qualcommax/patches-6.12/0068-v6.18-arm64-dts-qcom-Update-IPQ5018-xo_board_clk-to-use-fixed-factor-clock.patch b/target/linux/qualcommax/patches-6.12/0068-v6.18-arm64-dts-qcom-Update-IPQ5018-xo_board_clk-to-use-fixed-factor-clock.patch new file mode 100644 index 0000000000..20c184d262 --- /dev/null +++ b/target/linux/qualcommax/patches-6.12/0068-v6.18-arm64-dts-qcom-Update-IPQ5018-xo_board_clk-to-use-fixed-factor-clock.patch @@ -0,0 +1,33 @@ +From 5ca3d42384a66bcb66f91d75da16ec9e9f053aab Mon Sep 17 00:00:00 2001 +From: George Moussalem +Date: Mon, 21 Jul 2025 10:04:36 +0400 +Subject: arm64: dts: qcom: Update IPQ5018 xo_board_clk to use fixed factor + clock + +The xo_board_clk is fixed to 24 MHZ, which is routed from WiFi output +clock 96 MHZ (also being the reference clock of CMN PLL) divided by 4 +to the analog block routing channel. Update the xo_board_clk nodes in +the board DTS files to use clock-div/clock-mult accordingly. + +Reviewed-by: Konrad Dybcio +Signed-off-by: George Moussalem +Link: https://lore.kernel.org/r/20250721-ipq5018-cmn-pll-v5-2-4cbf3479af65@outlook.com +Signed-off-by: Bjorn Andersson +--- + arch/arm64/boot/dts/qcom/ipq5018.dtsi | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi') + +--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi +@@ -44,7 +44,8 @@ + }; + + xo_board_clk: xo-board-clk { +- compatible = "fixed-clock"; ++ compatible = "fixed-factor-clock"; ++ clocks = <&ref_96mhz_clk>; + #clock-cells = <0>; + }; + diff --git a/target/linux/qualcommax/patches-6.12/0306-arm64-dts-qcom-ipq5018-Add-PWM-node.patch b/target/linux/qualcommax/patches-6.12/0306-arm64-dts-qcom-ipq5018-Add-PWM-node.patch index 42d5a4a387..74b82ea0a0 100644 --- a/target/linux/qualcommax/patches-6.12/0306-arm64-dts-qcom-ipq5018-Add-PWM-node.patch +++ b/target/linux/qualcommax/patches-6.12/0306-arm64-dts-qcom-ipq5018-Add-PWM-node.patch @@ -8,7 +8,7 @@ Signed-off-by: George Moussalem --- --- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi -@@ -423,6 +423,16 @@ +@@ -453,6 +453,16 @@ reg = <0x01937000 0x21000>; }; diff --git a/target/linux/qualcommax/patches-6.12/0339-arm64-dts-qcom-ipq5018-Add-QUP1-UART2-node.patch b/target/linux/qualcommax/patches-6.12/0339-arm64-dts-qcom-ipq5018-Add-QUP1-UART2-node.patch index 4bb0e0fd26..16f81cc416 100644 --- a/target/linux/qualcommax/patches-6.12/0339-arm64-dts-qcom-ipq5018-Add-QUP1-UART2-node.patch +++ b/target/linux/qualcommax/patches-6.12/0339-arm64-dts-qcom-ipq5018-Add-QUP1-UART2-node.patch @@ -8,7 +8,7 @@ Signed-off-by: George Moussalem --- --- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi -@@ -470,6 +470,16 @@ +@@ -500,6 +500,16 @@ status = "disabled"; }; diff --git a/target/linux/qualcommax/patches-6.12/0340-arm64-dts-qcom-ipq5018-Add-QUP3-I2C-node.patch b/target/linux/qualcommax/patches-6.12/0340-arm64-dts-qcom-ipq5018-Add-QUP3-I2C-node.patch index bc28b61985..6a384a7566 100644 --- a/target/linux/qualcommax/patches-6.12/0340-arm64-dts-qcom-ipq5018-Add-QUP3-I2C-node.patch +++ b/target/linux/qualcommax/patches-6.12/0340-arm64-dts-qcom-ipq5018-Add-QUP3-I2C-node.patch @@ -8,7 +8,7 @@ Signed-off-by: George Moussalem --- --- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi -@@ -494,6 +494,21 @@ +@@ -524,6 +524,21 @@ status = "disabled"; }; diff --git a/target/linux/qualcommax/patches-6.12/0701-dt-bindings-clock-qcom-Add-CMN-PLL-clock-controller-.patch b/target/linux/qualcommax/patches-6.12/0701-dt-bindings-clock-qcom-Add-CMN-PLL-clock-controller-.patch deleted file mode 100644 index ad7e08c895..0000000000 --- a/target/linux/qualcommax/patches-6.12/0701-dt-bindings-clock-qcom-Add-CMN-PLL-clock-controller-.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 7b89dbf5c7dcd8a9c131721e93c1292e5993968b Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Tue, 20 Aug 2024 22:02:42 +0800 -Subject: [PATCH] dt-bindings: clock: qcom: Add CMN PLL clock controller - for IPQ SoC - -The CMN PLL controller provides clocks to networking hardware blocks -on Qualcomm IPQ9574 SoC. It receives input clock from the on-chip Wi-Fi, -and produces output clocks at fixed rates. These output rates are -predetermined, and are unrelated to the input clock rate. The output -clocks are supplied to the Ethernet hardware such as PPE (packet -process engine) and the externally connected switch or PHY device. - -Signed-off-by: Luo Jie -Reviewed-by: Krzysztof Kozlowski ---- - .../bindings/clock/qcom,ipq9574-cmn-pll.yaml | 70 +++++++++++++++++++ - include/dt-bindings/clock/qcom,ipq-cmn-pll.h | 15 ++++ - 2 files changed, 85 insertions(+) - create mode 100644 Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml - create mode 100644 include/dt-bindings/clock/qcom,ipq-cmn-pll.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml -@@ -0,0 +1,70 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/clock/qcom,ipq9574-cmn-pll.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm CMN PLL Clock Controller on IPQ SoC -+ -+maintainers: -+ - Bjorn Andersson -+ - Luo Jie -+ -+description: -+ The CMN PLL clock controller expects a reference input clock. -+ This reference clock is from the on-board Wi-Fi. The CMN PLL -+ supplies a number of fixed rate output clocks to the Ethernet -+ devices including PPE (packet process engine) and the connected -+ switch or PHY device. -+ -+properties: -+ compatible: -+ enum: -+ - qcom,ipq9574-cmn-pll -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ items: -+ - description: The reference clock. The supported clock rates include -+ 25000000, 31250000, 40000000, 48000000, 50000000 and 96000000 HZ. -+ - description: The AHB clock -+ - description: The SYS clock -+ description: -+ The reference clock is the source clock of CMN PLL, which is from the -+ Wi-Fi. The AHB and SYS clocks must be enabled to access CMN PLL -+ clock registers. -+ -+ clock-names: -+ items: -+ - const: ref -+ - const: ahb -+ - const: sys -+ -+ "#clock-cells": -+ const: 1 -+ -+required: -+ - compatible -+ - reg -+ - clocks -+ - clock-names -+ - "#clock-cells" -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ -+ clock-controller@9b000 { -+ compatible = "qcom,ipq9574-cmn-pll"; -+ reg = <0x0009b000 0x800>; -+ clocks = <&cmn_pll_ref_clk>, -+ <&gcc GCC_CMN_12GPLL_AHB_CLK>, -+ <&gcc GCC_CMN_12GPLL_SYS_CLK>; -+ clock-names = "ref", "ahb", "sys"; -+ #clock-cells = <1>; -+ }; -+... ---- /dev/null -+++ b/include/dt-bindings/clock/qcom,ipq-cmn-pll.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef _DT_BINDINGS_CLK_QCOM_IPQ_CMN_PLL_H -+#define _DT_BINDINGS_CLK_QCOM_IPQ_CMN_PLL_H -+ -+/* The output clocks from CMN PLL of IPQ9574. */ -+#define PPE_353MHZ_CLK 0 -+#define ETH0_50MHZ_CLK 1 -+#define ETH1_50MHZ_CLK 2 -+#define ETH2_50MHZ_CLK 3 -+#define ETH_25MHZ_CLK 4 -+#endif diff --git a/target/linux/qualcommax/patches-6.12/0702-clk-qcom-Add-CMN-PLL-clock-controller-driver-for-IPQ.patch b/target/linux/qualcommax/patches-6.12/0702-clk-qcom-Add-CMN-PLL-clock-controller-driver-for-IPQ.patch deleted file mode 100644 index a9587b5796..0000000000 --- a/target/linux/qualcommax/patches-6.12/0702-clk-qcom-Add-CMN-PLL-clock-controller-driver-for-IPQ.patch +++ /dev/null @@ -1,288 +0,0 @@ -From a7e8397e2db6133e3435054a3f312dbd9cab05ed Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Tue, 20 Aug 2024 22:02:43 +0800 -Subject: [PATCH] clk: qcom: Add CMN PLL clock controller driver for IPQ - SoC - -The CMN PLL clock controller supplies clocks to the hardware -blocks that together make up the Ethernet function on Qualcomm -IPQ SoCs. The driver is initially supported for IPQ9574 SoC. - -The CMN PLL clock controller expects a reference input clock -from the on-board Wi-Fi block acting as clock source. The input -reference clock needs to be configured to one of the supported -clock rates. - -The controller supplies a number of fixed-rate output clocks. -For the IPQ9574, there is one output clock of 353 MHZ to PPE -(Packet Process Engine) hardware block, three 50 MHZ output -clocks and an additional 25 MHZ output clock supplied to the -connected Ethernet devices. - -Signed-off-by: Luo Jie ---- - drivers/clk/qcom/Kconfig | 10 ++ - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/clk-ipq-cmn-pll.c | 227 +++++++++++++++++++++++++++++ - 3 files changed, 238 insertions(+) - create mode 100644 drivers/clk/qcom/clk-ipq-cmn-pll.c - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -190,6 +190,16 @@ config IPQ_APSS_6018 - Say Y if you want to support CPU frequency scaling on - ipq based devices. - -+config IPQ_CMN_PLL -+ tristate "IPQ CMN PLL Clock Controller" -+ depends on IPQ_GCC_9574 -+ help -+ Support for CMN PLL clock controller on IPQ platform. The -+ CMN PLL feeds the reference clocks to the Ethernet devices -+ based on IPQ SoC. -+ Say Y or M if you want to support CMN PLL clock on the IPQ -+ based devices. -+ - config IPQ_GCC_4019 - tristate "IPQ4019 Global Clock Controller" - help ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -29,6 +29,7 @@ obj-$(CONFIG_CLK_X1E80100_TCSRCC) += tcs - obj-$(CONFIG_CLK_QCM2290_GPUCC) += gpucc-qcm2290.o - obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o - obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o -+obj-$(CONFIG_IPQ_CMN_PLL) += clk-ipq-cmn-pll.o - obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o - obj-$(CONFIG_IPQ_GCC_5018) += gcc-ipq5018.o - obj-$(CONFIG_IPQ_GCC_5332) += gcc-ipq5332.o ---- /dev/null -+++ b/drivers/clk/qcom/clk-ipq-cmn-pll.c -@@ -0,0 +1,227 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* -+ * CMN PLL block expects the reference clock from on-board Wi-Fi block, and -+ * supplies fixed rate clocks as output to the Ethernet hardware blocks. -+ * The Ethernet related blocks include PPE (packet process engine) and the -+ * external connected PHY (or switch) chip receiving clocks from the CMN PLL. -+ * -+ * On the IPQ9574 SoC, There are three clocks with 50 MHZ, one clock with -+ * 25 MHZ which are output from the CMN PLL to Ethernet PHY (or switch), -+ * and one clock with 353 MHZ to PPE. -+ * -+ * +---------+ -+ * | GCC | -+ * +--+---+--+ -+ * AHB CLK| |SYS CLK -+ * V V -+ * +-------+---+------+ -+ * | +-------------> eth0-50mhz -+ * REF CLK | IPQ9574 | -+ * -------->+ +-------------> eth1-50mhz -+ * | CMN PLL block | -+ * | +-------------> eth2-50mhz -+ * | | -+ * +---------+--------+-------------> eth-25mhz -+ * | -+ * V -+ * ppe-353mhz -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define CMN_PLL_REFCLK_SRC_SELECTION 0x28 -+#define CMN_PLL_REFCLK_SRC_DIV GENMASK(9, 8) -+ -+#define CMN_PLL_REFCLK_CONFIG 0x784 -+#define CMN_PLL_REFCLK_EXTERNAL BIT(9) -+#define CMN_PLL_REFCLK_DIV GENMASK(8, 4) -+#define CMN_PLL_REFCLK_INDEX GENMASK(3, 0) -+ -+#define CMN_PLL_POWER_ON_AND_RESET 0x780 -+#define CMN_ANA_EN_SW_RSTN BIT(6) -+ -+/** -+ * struct cmn_pll_fixed_output_clk - CMN PLL output clocks information -+ * @id: Clock specifier to be supplied -+ * @name: Clock name to be registered -+ * @rate: Clock rate -+ */ -+struct cmn_pll_fixed_output_clk { -+ unsigned int id; -+ const char *name; -+ const unsigned long rate; -+}; -+ -+#define CLK_PLL_OUTPUT(_id, _name, _rate) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .rate = _rate, \ -+} -+ -+static const struct cmn_pll_fixed_output_clk ipq9574_output_clks[] = { -+ CLK_PLL_OUTPUT(PPE_353MHZ_CLK, "ppe-353mhz", 353000000UL), -+ CLK_PLL_OUTPUT(ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL), -+ CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL), -+ CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL), -+ CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL), -+}; -+ -+static int ipq_cmn_pll_config(struct device *dev, unsigned long parent_rate) -+{ -+ void __iomem *base; -+ u32 val; -+ -+ base = devm_of_iomap(dev, dev->of_node, 0, NULL); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ val = readl(base + CMN_PLL_REFCLK_CONFIG); -+ val &= ~(CMN_PLL_REFCLK_EXTERNAL | CMN_PLL_REFCLK_INDEX); -+ -+ /* -+ * Configure the reference input clock selection as per the given rate. -+ * The output clock rates are always of fixed value. -+ */ -+ switch (parent_rate) { -+ case 25000000: -+ val |= FIELD_PREP(CMN_PLL_REFCLK_INDEX, 3); -+ break; -+ case 31250000: -+ val |= FIELD_PREP(CMN_PLL_REFCLK_INDEX, 4); -+ break; -+ case 40000000: -+ val |= FIELD_PREP(CMN_PLL_REFCLK_INDEX, 6); -+ break; -+ case 48000000: -+ val |= FIELD_PREP(CMN_PLL_REFCLK_INDEX, 7); -+ break; -+ case 50000000: -+ val |= FIELD_PREP(CMN_PLL_REFCLK_INDEX, 8); -+ break; -+ case 96000000: -+ val |= FIELD_PREP(CMN_PLL_REFCLK_INDEX, 7); -+ val &= ~CMN_PLL_REFCLK_DIV; -+ val |= FIELD_PREP(CMN_PLL_REFCLK_DIV, 2); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ writel(val, base + CMN_PLL_REFCLK_CONFIG); -+ -+ /* Update the source clock rate selection. Only 96 MHZ uses 0. */ -+ val = readl(base + CMN_PLL_REFCLK_SRC_SELECTION); -+ val &= ~CMN_PLL_REFCLK_SRC_DIV; -+ if (parent_rate != 96000000) -+ val |= FIELD_PREP(CMN_PLL_REFCLK_SRC_DIV, 1); -+ -+ writel(val, base + CMN_PLL_REFCLK_SRC_SELECTION); -+ -+ /* -+ * Reset the CMN PLL block by asserting/de-asserting for 100 ms -+ * each, to ensure the updated configurations take effect. -+ */ -+ val = readl(base + CMN_PLL_POWER_ON_AND_RESET); -+ val &= ~CMN_ANA_EN_SW_RSTN; -+ writel(val, base); -+ msleep(100); -+ -+ val |= CMN_ANA_EN_SW_RSTN; -+ writel(val, base + CMN_PLL_POWER_ON_AND_RESET); -+ msleep(100); -+ -+ return 0; -+} -+ -+static int ipq_cmn_pll_clk_register(struct device *dev, const char *parent) -+{ -+ const struct cmn_pll_fixed_output_clk *fixed_clk; -+ struct clk_hw_onecell_data *data; -+ unsigned int num_clks; -+ struct clk_hw *hw; -+ int i; -+ -+ num_clks = ARRAY_SIZE(ipq9574_output_clks); -+ fixed_clk = ipq9574_output_clks; -+ -+ data = devm_kzalloc(dev, struct_size(data, hws, num_clks), GFP_KERNEL); -+ if (!data) -+ return -ENOMEM; -+ -+ for (i = 0; i < num_clks; i++) { -+ hw = devm_clk_hw_register_fixed_rate(dev, fixed_clk[i].name, -+ parent, 0, -+ fixed_clk[i].rate); -+ if (IS_ERR(hw)) -+ return PTR_ERR(hw); -+ -+ data->hws[fixed_clk[i].id] = hw; -+ } -+ data->num = num_clks; -+ -+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data); -+} -+ -+static int ipq_cmn_pll_clk_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct clk *clk; -+ int ret; -+ -+ /* -+ * To access the CMN PLL registers, the GCC AHB & SYSY clocks -+ * for CMN PLL block need to be enabled. -+ */ -+ clk = devm_clk_get_enabled(dev, "ahb"); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Enable AHB clock failed\n"); -+ -+ clk = devm_clk_get_enabled(dev, "sys"); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Enable SYS clock failed\n"); -+ -+ clk = devm_clk_get(dev, "ref"); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Get reference clock failed\n"); -+ -+ /* Configure CMN PLL to apply the reference clock. */ -+ ret = ipq_cmn_pll_config(dev, clk_get_rate(clk)); -+ if (ret) -+ return dev_err_probe(dev, ret, "Configure CMN PLL failed\n"); -+ -+ return ipq_cmn_pll_clk_register(dev, __clk_get_name(clk)); -+} -+ -+static const struct of_device_id ipq_cmn_pll_clk_ids[] = { -+ { .compatible = "qcom,ipq9574-cmn-pll", }, -+ { } -+}; -+ -+static struct platform_driver ipq_cmn_pll_clk_driver = { -+ .probe = ipq_cmn_pll_clk_probe, -+ .driver = { -+ .name = "ipq_cmn_pll", -+ .of_match_table = ipq_cmn_pll_clk_ids, -+ }, -+}; -+ -+module_platform_driver(ipq_cmn_pll_clk_driver); -+ -+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ CMN PLL Driver"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/qualcommax/patches-6.12/0703-clk-qcom-cmn-pll-add-IPQ5018-support.patch b/target/linux/qualcommax/patches-6.12/0703-clk-qcom-cmn-pll-add-IPQ5018-support.patch deleted file mode 100644 index 75b37df9aa..0000000000 --- a/target/linux/qualcommax/patches-6.12/0703-clk-qcom-cmn-pll-add-IPQ5018-support.patch +++ /dev/null @@ -1,78 +0,0 @@ -From a28797563b8c97c9abced82e0cf89302fcd2bf37 Mon Sep 17 00:00:00 2001 -From: Ziyang Huang -Date: Sun, 8 Sep 2024 16:40:11 +0800 -Subject: [PATCH 1/2] clk: qcom: cmn-pll: add IPQ5018 support - -Add support for IPQ5018 (and removing dependency on the IPQ9574 platform). -The common network block in IPQ5018 must be enabled first through a -specific register at a fixed offset in the TCSR area, set in the DTS. - -Signed-off-by: Ziyang Huang -Signed-off-by: George Moussalem ---- - drivers/clk/qcom/Kconfig | 1 - - drivers/clk/qcom/clk-ipq-cmn-pll.c | 29 +++++++++++++++++++++++++++++ - 2 files changed, 29 insertions(+), 1 deletion(-) - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -192,7 +192,6 @@ config IPQ_APSS_6018 - - config IPQ_CMN_PLL - tristate "IPQ CMN PLL Clock Controller" -- depends on IPQ_GCC_9574 - help - Support for CMN PLL clock controller on IPQ platform. The - CMN PLL feeds the reference clocks to the Ethernet devices ---- a/drivers/clk/qcom/clk-ipq-cmn-pll.c -+++ b/drivers/clk/qcom/clk-ipq-cmn-pll.c -@@ -42,6 +42,9 @@ - #include - #include - -+#define TCSR_ETH_CMN 0x0 -+#define TCSR_ETH_CMN_ENABLE BIT(0) -+ - #define CMN_PLL_REFCLK_SRC_SELECTION 0x28 - #define CMN_PLL_REFCLK_SRC_DIV GENMASK(9, 8) - -@@ -79,6 +82,28 @@ static const struct cmn_pll_fixed_output - CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL), - }; - -+static int ipq_cmn_pll_tcsr_enable(struct platform_device *pdev) -+{ -+ struct resource *res; -+ void __iomem *tcsr_base; -+ u32 val; -+ -+ /* For IPQ50xx, tcsr is necessary to enable cmn block */ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tcsr"); -+ if (!res) -+ return 0; -+ -+ tcsr_base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR_OR_NULL(tcsr_base)) -+ return PTR_ERR(tcsr_base); -+ -+ val = readl(tcsr_base + TCSR_ETH_CMN); -+ val |= TCSR_ETH_CMN_ENABLE; -+ writel(val, (tcsr_base + TCSR_ETH_CMN)); -+ -+ return 0; -+} -+ - static int ipq_cmn_pll_config(struct device *dev, unsigned long parent_rate) - { - void __iomem *base; -@@ -181,6 +206,10 @@ static int ipq_cmn_pll_clk_probe(struct - struct clk *clk; - int ret; - -+ ret = ipq_cmn_pll_tcsr_enable(pdev); -+ if (ret) -+ return dev_err_probe(dev, ret, "Enable CMN PLL failed\n"); -+ - /* - * To access the CMN PLL registers, the GCC AHB & SYSY clocks - * for CMN PLL block need to be enabled. diff --git a/target/linux/qualcommax/patches-6.12/0704-arm64-dts-qcom-ipq5018-Add-ethernet-cmn-node.patch b/target/linux/qualcommax/patches-6.12/0704-arm64-dts-qcom-ipq5018-Add-ethernet-cmn-node.patch deleted file mode 100644 index 04508da2b7..0000000000 --- a/target/linux/qualcommax/patches-6.12/0704-arm64-dts-qcom-ipq5018-Add-ethernet-cmn-node.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 1b625a37b96b0448aac126d7720eec38de8e5956 Mon Sep 17 00:00:00 2001 -From: Ziyang Huang -Date: Sun, 8 Sep 2024 16:40:11 +0800 -Subject: [PATCH 2/2] arm64: dts: qcom: ipq5018: Add ethernet cmn node - -Signed-off-by: Ziyang Huang ---- - arch/arm64/boot/dts/qcom/ipq5018.dtsi | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi -@@ -17,6 +17,12 @@ - #size-cells = <2>; - - clocks { -+ cmn_pll_ref_clk: cmn-pll-ref-clk { -+ compatible = "fixed-clock"; -+ clock-frequency = <96000000>; -+ #clock-cells = <0>; -+ }; -+ - gephy_rx_clk: gephy-rx-clk { - compatible = "fixed-clock"; - clock-frequency = <125000000>; -@@ -229,6 +235,17 @@ - status = "disabled"; - }; - -+ cmn_pll: clock-controller@9b000 { -+ compatible = "qcom,ipq9574-cmn-pll"; -+ reg = <0x0009b000 0x800>; -+ reg-names = "cmn"; -+ clocks = <&cmn_pll_ref_clk>, -+ <&gcc GCC_CMN_BLK_AHB_CLK>, -+ <&gcc GCC_CMN_BLK_SYS_CLK>; -+ clock-names = "ref", "ahb", "sys"; -+ #clock-cells = <1>; -+ }; -+ - qfprom: qfprom@a0000 { - compatible = "qcom,ipq5018-qfprom", "qcom,qfprom"; - reg = <0x000a0000 0x1000>; diff --git a/target/linux/qualcommax/patches-6.12/0715-arm64-dts-qcom-ipq5018-add-vendor-compatible-to-mdio-node.patch b/target/linux/qualcommax/patches-6.12/0715-arm64-dts-qcom-ipq5018-add-vendor-compatible-to-mdio-node.patch index fd22ba7e37..18272f3d9a 100644 --- a/target/linux/qualcommax/patches-6.12/0715-arm64-dts-qcom-ipq5018-add-vendor-compatible-to-mdio-node.patch +++ b/target/linux/qualcommax/patches-6.12/0715-arm64-dts-qcom-ipq5018-add-vendor-compatible-to-mdio-node.patch @@ -9,7 +9,7 @@ aren't upstreamed, add the vendor compatible. Signed-off-by: George Moussalem --- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi -@@ -204,7 +204,7 @@ +@@ -214,7 +214,7 @@ }; mdio0: mdio@88000 { diff --git a/target/linux/qualcommax/patches-6.12/0816-arm64-dts-qcom-ipq5018-add-wifi-support.patch b/target/linux/qualcommax/patches-6.12/0816-arm64-dts-qcom-ipq5018-add-wifi-support.patch index 239e2a8454..c4575e6c91 100644 --- a/target/linux/qualcommax/patches-6.12/0816-arm64-dts-qcom-ipq5018-add-wifi-support.patch +++ b/target/linux/qualcommax/patches-6.12/0816-arm64-dts-qcom-ipq5018-add-wifi-support.patch @@ -13,7 +13,7 @@ Signed-off-by: George Moussalem --- --- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi -@@ -714,6 +714,225 @@ +@@ -727,6 +727,225 @@ }; }; diff --git a/target/linux/qualcommax/patches-6.12/0817-arm64-dts-qcom-ipq5018-add-tz_apps-reserved-memory-region.patch b/target/linux/qualcommax/patches-6.12/0817-arm64-dts-qcom-ipq5018-add-tz_apps-reserved-memory-region.patch index dccf9adceb..ce44b03755 100644 --- a/target/linux/qualcommax/patches-6.12/0817-arm64-dts-qcom-ipq5018-add-tz_apps-reserved-memory-region.patch +++ b/target/linux/qualcommax/patches-6.12/0817-arm64-dts-qcom-ipq5018-add-tz_apps-reserved-memory-region.patch @@ -8,7 +8,7 @@ Signed-off-by: George Moussalem --- --- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi -@@ -126,6 +126,11 @@ +@@ -136,6 +136,11 @@ #size-cells = <2>; ranges;