Message ID | 20240325102036.95484-4-quic_varada@quicinc.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Add interconnect driver for IPQ9574 SoC | expand |
On 25.03.2024 11:20 AM, Varadarajan Narayanan wrote: > Unlike MSM platforms that manage NoC related clocks and scaling > from RPM, IPQ SoCs dont involve RPM in managing NoC related > clocks and there is no NoC scaling. > > However, there is a requirement to enable some NoC interface > clocks for accessing the peripheral controllers present on > these NoCs. Though exposing these as normal clocks would work, > having a minimalistic interconnect driver to handle these clocks > would make it consistent with other Qualcomm platforms resulting > in common code paths. This is similar to msm8996-cbf's usage of > icc-clk framework. > > Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com> > --- [...] > > + > +static struct icc_clk_data *icc_ipq9574; > + What does this help achieve? [...] > +static int noc_clks[] = { We could probably use indexed identifiers here to avoid confusion: [ICC_BINDING_NAME] = CLK_BINDING_NAME > static int gcc_ipq9574_probe(struct platform_device *pdev) > { > - return qcom_cc_probe(pdev, &gcc_ipq9574_desc); > + int ret = qcom_cc_probe(pdev, &gcc_ipq9574_desc); > + struct icc_provider *provider; > + struct icc_clk_data *icd; > + int i; > + > + if (ret) I'd personally prefer if you left ret uninitialized and assigned it above the if-statement. > + return dev_err_probe(&pdev->dev, ret, "%s failed\n", __func__); Please avoid the use of __func__ throughout your change and write a more useful error message. > + > + icd = devm_kmalloc(&pdev->dev, ARRAY_SIZE(noc_clks) * sizeof(*icd), > + GFP_KERNEL); devm_kcalloc > + > + if (IS_ERR_OR_NULL(icd)) > + return dev_err_probe(&pdev->dev, PTR_ERR(icd), > + "%s malloc failed\n", __func__); ditto > + > + icc_ipq9574 = icd; > + > + for (i = 0; i < ARRAY_SIZE(noc_clks); i++, icd++) { > + icd->clk = gcc_ipq9574_clks[noc_clks[i]]->hw.clk; > + if (IS_ERR_OR_NULL(icd->clk)) { > + dev_err(&pdev->dev, "%s: %d clock not found\n", > + __func__, noc_clks[i]); > + return -ENOENT; return dev_err_probe > + } > + icd->name = clk_hw_get_name(&gcc_ipq9574_clks[noc_clks[i]]->hw); > + } > + > + provider = icc_clk_register(&pdev->dev, IPQ_APPS_ID, > + ARRAY_SIZE(noc_clks), icc_ipq9574); > + if (IS_ERR_OR_NULL(provider)) > + return dev_err_probe(&pdev->dev, PTR_ERR(provider), > + "%s: icc_clk_register failed\n", __func__); ditto On a second thought, since I'm assuming you're going to expand this to other IPQ SoCs, it might be useful to factor this out into drivers/clk/qcom/common.c Konrad
On Mon, Mar 25, 2024 at 08:42:21PM +0100, Konrad Dybcio wrote: > On 25.03.2024 11:20 AM, Varadarajan Narayanan wrote: > > Unlike MSM platforms that manage NoC related clocks and scaling > > from RPM, IPQ SoCs dont involve RPM in managing NoC related > > clocks and there is no NoC scaling. > > > > However, there is a requirement to enable some NoC interface > > clocks for accessing the peripheral controllers present on > > these NoCs. Though exposing these as normal clocks would work, > > having a minimalistic interconnect driver to handle these clocks > > would make it consistent with other Qualcomm platforms resulting > > in common code paths. This is similar to msm8996-cbf's usage of > > icc-clk framework. > > > > Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com> > > --- > > [...] > > > > > + > > +static struct icc_clk_data *icc_ipq9574; > > + > > What does this help achieve? Had it as a place holder in case if the provider pointer is needed for any debug. Will remove it. > > +static int noc_clks[] = { > > We could probably use indexed identifiers here to avoid confusion: > [ICC_BINDING_NAME] = CLK_BINDING_NAME ok. > > static int gcc_ipq9574_probe(struct platform_device *pdev) > > { > > - return qcom_cc_probe(pdev, &gcc_ipq9574_desc); > > + int ret = qcom_cc_probe(pdev, &gcc_ipq9574_desc); > > + struct icc_provider *provider; > > + struct icc_clk_data *icd; > > + int i; > > + > > + if (ret) > > I'd personally prefer if you left ret uninitialized and assigned it > above the if-statement. ok > > + return dev_err_probe(&pdev->dev, ret, "%s failed\n", __func__); > > Please avoid the use of __func__ throughout your change and write > a more useful error message. > > > + > > + icd = devm_kmalloc(&pdev->dev, ARRAY_SIZE(noc_clks) * sizeof(*icd), > > + GFP_KERNEL); > > devm_kcalloc ok > > + > > + if (IS_ERR_OR_NULL(icd)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(icd), > > + "%s malloc failed\n", __func__); > > ditto ok > > + > > + icc_ipq9574 = icd; > > + > > + for (i = 0; i < ARRAY_SIZE(noc_clks); i++, icd++) { > > + icd->clk = gcc_ipq9574_clks[noc_clks[i]]->hw.clk; > > + if (IS_ERR_OR_NULL(icd->clk)) { > > + dev_err(&pdev->dev, "%s: %d clock not found\n", > > + __func__, noc_clks[i]); > > + return -ENOENT; > > return dev_err_probe ok > > + } > > + icd->name = clk_hw_get_name(&gcc_ipq9574_clks[noc_clks[i]]->hw); > > + } > > + > > + provider = icc_clk_register(&pdev->dev, IPQ_APPS_ID, > > + ARRAY_SIZE(noc_clks), icc_ipq9574); > > + if (IS_ERR_OR_NULL(provider)) > > + return dev_err_probe(&pdev->dev, PTR_ERR(provider), > > + "%s: icc_clk_register failed\n", __func__); > > ditto ok > On a second thought, since I'm assuming you're going to expand this to other > IPQ SoCs, it might be useful to factor this out into drivers/clk/qcom/common.c Will move it. Thanks Varada
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 8ab08e7b5b6c..af73a0b396eb 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -243,6 +243,8 @@ config IPQ_GCC_8074 config IPQ_GCC_9574 tristate "IPQ9574 Global Clock Controller" + select INTERCONNECT + select INTERCONNECT_CLK help Support for global clock controller on ipq9574 devices. Say Y if you want to use peripheral devices such as UART, SPI, diff --git a/drivers/clk/qcom/gcc-ipq9574.c b/drivers/clk/qcom/gcc-ipq9574.c index 0a3f846695b8..ed25bb34216a 100644 --- a/drivers/clk/qcom/gcc-ipq9574.c +++ b/drivers/clk/qcom/gcc-ipq9574.c @@ -9,9 +9,12 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> +#include <linux/interconnect-clk.h> +#include <linux/interconnect-provider.h> #include <dt-bindings/clock/qcom,ipq9574-gcc.h> #include <dt-bindings/reset/qcom,ipq9574-gcc.h> +#include <dt-bindings/interconnect/qcom,ipq9574.h> #include "clk-alpha-pll.h" #include "clk-branch.h" @@ -4301,6 +4304,33 @@ static const struct qcom_reset_map gcc_ipq9574_resets[] = { [GCC_WCSS_Q6_TBU_BCR] = { 0x12054, 0 }, }; + +static struct icc_clk_data *icc_ipq9574; + +static int noc_clks[] = { + GCC_ANOC_PCIE0_1LANE_M_CLK, + GCC_SNOC_PCIE0_1LANE_S_CLK, + GCC_ANOC_PCIE1_1LANE_M_CLK, + GCC_SNOC_PCIE1_1LANE_S_CLK, + GCC_ANOC_PCIE2_2LANE_M_CLK, + GCC_SNOC_PCIE2_2LANE_S_CLK, + GCC_ANOC_PCIE3_2LANE_M_CLK, + GCC_SNOC_PCIE3_2LANE_S_CLK, + GCC_SNOC_USB_CLK, + GCC_ANOC_USB_AXI_CLK, + GCC_NSSNOC_NSSCC_CLK, + GCC_NSSNOC_SNOC_CLK, + GCC_NSSNOC_SNOC_1_CLK, + GCC_NSSNOC_PCNOC_1_CLK, + GCC_NSSNOC_QOSGEN_REF_CLK, + GCC_NSSNOC_TIMEOUT_REF_CLK, + GCC_NSSNOC_XO_DCD_CLK, + GCC_NSSNOC_ATB_CLK, + GCC_MEM_NOC_NSSNOC_CLK, + GCC_NSSNOC_MEMNOC_CLK, + GCC_NSSNOC_MEM_NOC_1_CLK, +}; + static const struct of_device_id gcc_ipq9574_match_table[] = { { .compatible = "qcom,ipq9574-gcc" }, { } @@ -4327,7 +4357,40 @@ static const struct qcom_cc_desc gcc_ipq9574_desc = { static int gcc_ipq9574_probe(struct platform_device *pdev) { - return qcom_cc_probe(pdev, &gcc_ipq9574_desc); + int ret = qcom_cc_probe(pdev, &gcc_ipq9574_desc); + struct icc_provider *provider; + struct icc_clk_data *icd; + int i; + + if (ret) + return dev_err_probe(&pdev->dev, ret, "%s failed\n", __func__); + + icd = devm_kmalloc(&pdev->dev, ARRAY_SIZE(noc_clks) * sizeof(*icd), + GFP_KERNEL); + + if (IS_ERR_OR_NULL(icd)) + return dev_err_probe(&pdev->dev, PTR_ERR(icd), + "%s malloc failed\n", __func__); + + icc_ipq9574 = icd; + + for (i = 0; i < ARRAY_SIZE(noc_clks); i++, icd++) { + icd->clk = gcc_ipq9574_clks[noc_clks[i]]->hw.clk; + if (IS_ERR_OR_NULL(icd->clk)) { + dev_err(&pdev->dev, "%s: %d clock not found\n", + __func__, noc_clks[i]); + return -ENOENT; + } + icd->name = clk_hw_get_name(&gcc_ipq9574_clks[noc_clks[i]]->hw); + } + + provider = icc_clk_register(&pdev->dev, IPQ_APPS_ID, + ARRAY_SIZE(noc_clks), icc_ipq9574); + if (IS_ERR_OR_NULL(provider)) + return dev_err_probe(&pdev->dev, PTR_ERR(provider), + "%s: icc_clk_register failed\n", __func__); + + return 0; } static struct platform_driver gcc_ipq9574_driver = {
Unlike MSM platforms that manage NoC related clocks and scaling from RPM, IPQ SoCs dont involve RPM in managing NoC related clocks and there is no NoC scaling. However, there is a requirement to enable some NoC interface clocks for accessing the peripheral controllers present on these NoCs. Though exposing these as normal clocks would work, having a minimalistic interconnect driver to handle these clocks would make it consistent with other Qualcomm platforms resulting in common code paths. This is similar to msm8996-cbf's usage of icc-clk framework. Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com> --- v2: Move DTS to separate patch Update commit log Auto select CONFIG_INTERCONNECT & CONFIG_INTERCONNECT_CLK to fix build error --- drivers/clk/qcom/Kconfig | 2 ++ drivers/clk/qcom/gcc-ipq9574.c | 65 +++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-)