Commit e9a7b78b authored by Abel Vesa's avatar Abel Vesa Committed by Bjorn Andersson

clk: qcom: Add TCSR clock driver for SM8550

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: default avatarAbel Vesa <abel.vesa@linaro.org>
Reviewed-by: default avatarKonrad Dybcio <konrad.dybcio@linaro.org>
Signed-off-by: default avatarBjorn Andersson <andersson@kernel.org>
Link: https://lore.kernel.org/r/20230104093450.3150578-5-abel.vesa@linaro.org
parent 478a573b
......@@ -804,6 +804,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
......
......@@ -113,6 +113,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
......
// 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,sm8550-tcsr.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_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_PAD,
},
.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_PAD,
},
.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_PAD,
},
.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_PAD,
},
.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_PAD,
},
.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-tcsr" },
{ }
};
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");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment