[9/9] clk: qcom: Add TCSR clock driver for SM8550
Commit Message
The TCSR clock controller found on SM8550 provides refclks
for PCIE, USB and UFS. Add clock driver for it.
This patch is based on initial code downstream.
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
---
drivers/clk/qcom/Kconfig | 7 ++
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/tcsrcc-sm8550.c | 193 +++++++++++++++++++++++++++++++
3 files changed, 201 insertions(+)
create mode 100644 drivers/clk/qcom/tcsrcc-sm8550.c
Comments
On 16/11/2022 11:47, Abel Vesa wrote:
> The TCSR clock controller found on SM8550 provides refclks
> for PCIE, USB and UFS. Add clock driver for it.
>
> This patch is based on initial code downstream.
>
> Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Konrad
> drivers/clk/qcom/Kconfig | 7 ++
> drivers/clk/qcom/Makefile | 1 +
> drivers/clk/qcom/tcsrcc-sm8550.c | 193 +++++++++++++++++++++++++++++++
> 3 files changed, 201 insertions(+)
> create mode 100644 drivers/clk/qcom/tcsrcc-sm8550.c
>
> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
> index 7186faf70562..653049b08a25 100644
> --- a/drivers/clk/qcom/Kconfig
> +++ b/drivers/clk/qcom/Kconfig
> @@ -788,6 +788,13 @@ config SM_GPUCC_8350
> Say Y if you want to support graphics controller devices and
> functionality such as 3D graphics.
>
> +config SM_TCSRCC_8550
> + tristate "SM8550 TCSR Clock Controller"
> + select QCOM_GDSC
> + help
> + Support for the TCSR clock controller on SM8550 devices.
> + Say Y if you want to use peripheral devices such as SD/UFS.
> +
> config SM_VIDEOCC_8150
> tristate "SM8150 Video Clock Controller"
> select SM_GCC_8150
> diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> index dc4b803d3f3d..17d878482a45 100644
> --- a/drivers/clk/qcom/Makefile
> +++ b/drivers/clk/qcom/Makefile
> @@ -111,6 +111,7 @@ obj-$(CONFIG_SM_GPUCC_6350) += gpucc-sm6350.o
> obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o
> obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o
> obj-$(CONFIG_SM_GPUCC_8350) += gpucc-sm8350.o
> +obj-$(CONFIG_SM_TCSRCC_8550) += tcsrcc-sm8550.o
> obj-$(CONFIG_SM_VIDEOCC_8150) += videocc-sm8150.o
> obj-$(CONFIG_SM_VIDEOCC_8250) += videocc-sm8250.o
> obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
> diff --git a/drivers/clk/qcom/tcsrcc-sm8550.c b/drivers/clk/qcom/tcsrcc-sm8550.c
> new file mode 100644
> index 000000000000..3e6756da1e83
> --- /dev/null
> +++ b/drivers/clk/qcom/tcsrcc-sm8550.c
> @@ -0,0 +1,193 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2021, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) 2022, Linaro Limited
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/regmap.h>
> +
> +#include <dt-bindings/clock/qcom,tcsrcc-sm8550.h>
> +
> +#include "clk-alpha-pll.h"
> +#include "clk-branch.h"
> +#include "clk-pll.h"
> +#include "clk-rcg.h"
> +#include "clk-regmap.h"
> +#include "clk-regmap-divider.h"
> +#include "clk-regmap-mux.h"
> +#include "common.h"
> +#include "reset.h"
> +
> +enum {
> + DT_BI_TCXO,
> + DT_BI_TCXO_PAD,
> +};
> +
> +static struct clk_branch tcsr_pcie_0_clkref_en = {
> + .halt_reg = 0x15100,
> + .halt_check = BRANCH_HALT_SKIP,
> + .clkr = {
> + .enable_reg = 0x15100,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "tcsr_pcie_0_clkref_en",
> + .parent_data = &(const struct clk_parent_data){
> + .index = DT_BI_TCXO,
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch tcsr_pcie_1_clkref_en = {
> + .halt_reg = 0x15114,
> + .halt_check = BRANCH_HALT_SKIP,
> + .clkr = {
> + .enable_reg = 0x15114,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "tcsr_pcie_1_clkref_en",
> + .parent_data = &(const struct clk_parent_data){
> + .index = DT_BI_TCXO,
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch tcsr_ufs_clkref_en = {
> + .halt_reg = 0x15110,
> + .halt_check = BRANCH_HALT_SKIP,
> + .clkr = {
> + .enable_reg = 0x15110,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "tcsr_ufs_clkref_en",
> + .parent_data = &(const struct clk_parent_data){
> + .index = DT_BI_TCXO,
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch tcsr_ufs_pad_clkref_en = {
> + .halt_reg = 0x15104,
> + .halt_check = BRANCH_HALT_SKIP,
> + .clkr = {
> + .enable_reg = 0x15104,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "tcsr_ufs_pad_clkref_en",
> + .parent_data = &(const struct clk_parent_data){
> + .index = DT_BI_TCXO,
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch tcsr_usb2_clkref_en = {
> + .halt_reg = 0x15118,
> + .halt_check = BRANCH_HALT_SKIP,
> + .clkr = {
> + .enable_reg = 0x15118,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "tcsr_usb2_clkref_en",
> + .parent_data = &(const struct clk_parent_data){
> + .index = DT_BI_TCXO_PAD,
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch tcsr_usb3_clkref_en = {
> + .halt_reg = 0x15108,
> + .halt_check = BRANCH_HALT_SKIP,
> + .clkr = {
> + .enable_reg = 0x15108,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "tcsr_usb3_clkref_en",
> + .parent_data = &(const struct clk_parent_data){
> + .index = DT_BI_TCXO,
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_regmap *tcsr_cc_sm8550_clocks[] = {
> + [TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr,
> + [TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr,
> + [TCSR_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr,
> + [TCSR_UFS_PAD_CLKREF_EN] = &tcsr_ufs_pad_clkref_en.clkr,
> + [TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr,
> + [TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr,
> +};
> +
> +static const struct regmap_config tcsr_cc_sm8550_regmap_config = {
> + .reg_bits = 32,
> + .reg_stride = 4,
> + .val_bits = 32,
> + .max_register = 0x2f000,
> + .fast_io = true,
> +};
> +
> +static const struct qcom_cc_desc tcsr_cc_sm8550_desc = {
> + .config = &tcsr_cc_sm8550_regmap_config,
> + .clks = tcsr_cc_sm8550_clocks,
> + .num_clks = ARRAY_SIZE(tcsr_cc_sm8550_clocks),
> +};
> +
> +static const struct of_device_id tcsr_cc_sm8550_match_table[] = {
> + { .compatible = "qcom,sm8550-tcsrcc" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, tcsr_cc_sm8550_match_table);
> +
> +static int tcsr_cc_sm8550_probe(struct platform_device *pdev)
> +{
> + struct regmap *regmap;
> +
> + regmap = qcom_cc_map(pdev, &tcsr_cc_sm8550_desc);
> + if (IS_ERR(regmap))
> + return PTR_ERR(regmap);
> +
> + return qcom_cc_really_probe(pdev, &tcsr_cc_sm8550_desc, regmap);
> +}
> +
> +static struct platform_driver tcsr_cc_sm8550_driver = {
> + .probe = tcsr_cc_sm8550_probe,
> + .driver = {
> + .name = "tcsr_cc-sm8550",
> + .of_match_table = tcsr_cc_sm8550_match_table,
> + },
> +};
> +
> +static int __init tcsr_cc_sm8550_init(void)
> +{
> + return platform_driver_register(&tcsr_cc_sm8550_driver);
> +}
> +subsys_initcall(tcsr_cc_sm8550_init);
> +
> +static void __exit tcsr_cc_sm8550_exit(void)
> +{
> + platform_driver_unregister(&tcsr_cc_sm8550_driver);
> +}
> +module_exit(tcsr_cc_sm8550_exit);
> +
> +MODULE_DESCRIPTION("QTI TCSRCC SM8550 Driver");
> +MODULE_LICENSE("GPL");
@@ -788,6 +788,13 @@ config SM_GPUCC_8350
Say Y if you want to support graphics controller devices and
functionality such as 3D graphics.
+config SM_TCSRCC_8550
+ tristate "SM8550 TCSR Clock Controller"
+ select QCOM_GDSC
+ help
+ Support for the TCSR clock controller on SM8550 devices.
+ Say Y if you want to use peripheral devices such as SD/UFS.
+
config SM_VIDEOCC_8150
tristate "SM8150 Video Clock Controller"
select SM_GCC_8150
@@ -111,6 +111,7 @@ obj-$(CONFIG_SM_GPUCC_6350) += gpucc-sm6350.o
obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o
obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o
obj-$(CONFIG_SM_GPUCC_8350) += gpucc-sm8350.o
+obj-$(CONFIG_SM_TCSRCC_8550) += tcsrcc-sm8550.o
obj-$(CONFIG_SM_VIDEOCC_8150) += videocc-sm8150.o
obj-$(CONFIG_SM_VIDEOCC_8250) += videocc-sm8250.o
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
new file mode 100644
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,tcsrcc-sm8550.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "reset.h"
+
+enum {
+ DT_BI_TCXO,
+ DT_BI_TCXO_PAD,
+};
+
+static struct clk_branch tcsr_pcie_0_clkref_en = {
+ .halt_reg = 0x15100,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x15100,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "tcsr_pcie_0_clkref_en",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch tcsr_pcie_1_clkref_en = {
+ .halt_reg = 0x15114,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x15114,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "tcsr_pcie_1_clkref_en",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch tcsr_ufs_clkref_en = {
+ .halt_reg = 0x15110,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x15110,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "tcsr_ufs_clkref_en",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch tcsr_ufs_pad_clkref_en = {
+ .halt_reg = 0x15104,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x15104,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "tcsr_ufs_pad_clkref_en",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch tcsr_usb2_clkref_en = {
+ .halt_reg = 0x15118,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x15118,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "tcsr_usb2_clkref_en",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_BI_TCXO_PAD,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch tcsr_usb3_clkref_en = {
+ .halt_reg = 0x15108,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x15108,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "tcsr_usb3_clkref_en",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_regmap *tcsr_cc_sm8550_clocks[] = {
+ [TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr,
+ [TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr,
+ [TCSR_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr,
+ [TCSR_UFS_PAD_CLKREF_EN] = &tcsr_ufs_pad_clkref_en.clkr,
+ [TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr,
+ [TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr,
+};
+
+static const struct regmap_config tcsr_cc_sm8550_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x2f000,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc tcsr_cc_sm8550_desc = {
+ .config = &tcsr_cc_sm8550_regmap_config,
+ .clks = tcsr_cc_sm8550_clocks,
+ .num_clks = ARRAY_SIZE(tcsr_cc_sm8550_clocks),
+};
+
+static const struct of_device_id tcsr_cc_sm8550_match_table[] = {
+ { .compatible = "qcom,sm8550-tcsrcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, tcsr_cc_sm8550_match_table);
+
+static int tcsr_cc_sm8550_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &tcsr_cc_sm8550_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return qcom_cc_really_probe(pdev, &tcsr_cc_sm8550_desc, regmap);
+}
+
+static struct platform_driver tcsr_cc_sm8550_driver = {
+ .probe = tcsr_cc_sm8550_probe,
+ .driver = {
+ .name = "tcsr_cc-sm8550",
+ .of_match_table = tcsr_cc_sm8550_match_table,
+ },
+};
+
+static int __init tcsr_cc_sm8550_init(void)
+{
+ return platform_driver_register(&tcsr_cc_sm8550_driver);
+}
+subsys_initcall(tcsr_cc_sm8550_init);
+
+static void __exit tcsr_cc_sm8550_exit(void)
+{
+ platform_driver_unregister(&tcsr_cc_sm8550_driver);
+}
+module_exit(tcsr_cc_sm8550_exit);
+
+MODULE_DESCRIPTION("QTI TCSRCC SM8550 Driver");
+MODULE_LICENSE("GPL");