162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2021, The Linux Foundation. All rights reserved.
462306a36Sopenharmony_ci * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
562306a36Sopenharmony_ci * Copyright (c) 2022, Linaro Limited
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/clk-provider.h>
962306a36Sopenharmony_ci#include <linux/module.h>
1062306a36Sopenharmony_ci#include <linux/of.h>
1162306a36Sopenharmony_ci#include <linux/platform_device.h>
1262306a36Sopenharmony_ci#include <linux/regmap.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <dt-bindings/clock/qcom,sm8550-tcsr.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include "clk-alpha-pll.h"
1762306a36Sopenharmony_ci#include "clk-branch.h"
1862306a36Sopenharmony_ci#include "clk-pll.h"
1962306a36Sopenharmony_ci#include "clk-rcg.h"
2062306a36Sopenharmony_ci#include "clk-regmap.h"
2162306a36Sopenharmony_ci#include "clk-regmap-divider.h"
2262306a36Sopenharmony_ci#include "clk-regmap-mux.h"
2362306a36Sopenharmony_ci#include "common.h"
2462306a36Sopenharmony_ci#include "reset.h"
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cienum {
2762306a36Sopenharmony_ci	DT_BI_TCXO_PAD,
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic struct clk_branch tcsr_pcie_0_clkref_en = {
3162306a36Sopenharmony_ci	.halt_reg = 0x15100,
3262306a36Sopenharmony_ci	.halt_check = BRANCH_HALT_SKIP,
3362306a36Sopenharmony_ci	.clkr = {
3462306a36Sopenharmony_ci		.enable_reg = 0x15100,
3562306a36Sopenharmony_ci		.enable_mask = BIT(0),
3662306a36Sopenharmony_ci		.hw.init = &(struct clk_init_data){
3762306a36Sopenharmony_ci			.name = "tcsr_pcie_0_clkref_en",
3862306a36Sopenharmony_ci			.parent_data = &(const struct clk_parent_data){
3962306a36Sopenharmony_ci				.index = DT_BI_TCXO_PAD,
4062306a36Sopenharmony_ci			},
4162306a36Sopenharmony_ci			.num_parents = 1,
4262306a36Sopenharmony_ci			.ops = &clk_branch2_ops,
4362306a36Sopenharmony_ci		},
4462306a36Sopenharmony_ci	},
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic struct clk_branch tcsr_pcie_1_clkref_en = {
4862306a36Sopenharmony_ci	.halt_reg = 0x15114,
4962306a36Sopenharmony_ci	.halt_check = BRANCH_HALT_SKIP,
5062306a36Sopenharmony_ci	.clkr = {
5162306a36Sopenharmony_ci		.enable_reg = 0x15114,
5262306a36Sopenharmony_ci		.enable_mask = BIT(0),
5362306a36Sopenharmony_ci		.hw.init = &(struct clk_init_data){
5462306a36Sopenharmony_ci			.name = "tcsr_pcie_1_clkref_en",
5562306a36Sopenharmony_ci			.parent_data = &(const struct clk_parent_data){
5662306a36Sopenharmony_ci				.index = DT_BI_TCXO_PAD,
5762306a36Sopenharmony_ci			},
5862306a36Sopenharmony_ci			.num_parents = 1,
5962306a36Sopenharmony_ci			.ops = &clk_branch2_ops,
6062306a36Sopenharmony_ci		},
6162306a36Sopenharmony_ci	},
6262306a36Sopenharmony_ci};
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic struct clk_branch tcsr_ufs_clkref_en = {
6562306a36Sopenharmony_ci	.halt_reg = 0x15110,
6662306a36Sopenharmony_ci	.halt_check = BRANCH_HALT_SKIP,
6762306a36Sopenharmony_ci	.clkr = {
6862306a36Sopenharmony_ci		.enable_reg = 0x15110,
6962306a36Sopenharmony_ci		.enable_mask = BIT(0),
7062306a36Sopenharmony_ci		.hw.init = &(struct clk_init_data){
7162306a36Sopenharmony_ci			.name = "tcsr_ufs_clkref_en",
7262306a36Sopenharmony_ci			.parent_data = &(const struct clk_parent_data){
7362306a36Sopenharmony_ci				.index = DT_BI_TCXO_PAD,
7462306a36Sopenharmony_ci			},
7562306a36Sopenharmony_ci			.num_parents = 1,
7662306a36Sopenharmony_ci			.ops = &clk_branch2_ops,
7762306a36Sopenharmony_ci		},
7862306a36Sopenharmony_ci	},
7962306a36Sopenharmony_ci};
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistatic struct clk_branch tcsr_ufs_pad_clkref_en = {
8262306a36Sopenharmony_ci	.halt_reg = 0x15104,
8362306a36Sopenharmony_ci	.halt_check = BRANCH_HALT_SKIP,
8462306a36Sopenharmony_ci	.clkr = {
8562306a36Sopenharmony_ci		.enable_reg = 0x15104,
8662306a36Sopenharmony_ci		.enable_mask = BIT(0),
8762306a36Sopenharmony_ci		.hw.init = &(struct clk_init_data){
8862306a36Sopenharmony_ci			.name = "tcsr_ufs_pad_clkref_en",
8962306a36Sopenharmony_ci			.parent_data = &(const struct clk_parent_data){
9062306a36Sopenharmony_ci				.index = DT_BI_TCXO_PAD,
9162306a36Sopenharmony_ci			},
9262306a36Sopenharmony_ci			.num_parents = 1,
9362306a36Sopenharmony_ci			.ops = &clk_branch2_ops,
9462306a36Sopenharmony_ci		},
9562306a36Sopenharmony_ci	},
9662306a36Sopenharmony_ci};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic struct clk_branch tcsr_usb2_clkref_en = {
9962306a36Sopenharmony_ci	.halt_reg = 0x15118,
10062306a36Sopenharmony_ci	.halt_check = BRANCH_HALT_SKIP,
10162306a36Sopenharmony_ci	.clkr = {
10262306a36Sopenharmony_ci		.enable_reg = 0x15118,
10362306a36Sopenharmony_ci		.enable_mask = BIT(0),
10462306a36Sopenharmony_ci		.hw.init = &(struct clk_init_data){
10562306a36Sopenharmony_ci			.name = "tcsr_usb2_clkref_en",
10662306a36Sopenharmony_ci			.parent_data = &(const struct clk_parent_data){
10762306a36Sopenharmony_ci				.index = DT_BI_TCXO_PAD,
10862306a36Sopenharmony_ci			},
10962306a36Sopenharmony_ci			.num_parents = 1,
11062306a36Sopenharmony_ci			.ops = &clk_branch2_ops,
11162306a36Sopenharmony_ci		},
11262306a36Sopenharmony_ci	},
11362306a36Sopenharmony_ci};
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic struct clk_branch tcsr_usb3_clkref_en = {
11662306a36Sopenharmony_ci	.halt_reg = 0x15108,
11762306a36Sopenharmony_ci	.halt_check = BRANCH_HALT_SKIP,
11862306a36Sopenharmony_ci	.clkr = {
11962306a36Sopenharmony_ci		.enable_reg = 0x15108,
12062306a36Sopenharmony_ci		.enable_mask = BIT(0),
12162306a36Sopenharmony_ci		.hw.init = &(struct clk_init_data){
12262306a36Sopenharmony_ci			.name = "tcsr_usb3_clkref_en",
12362306a36Sopenharmony_ci			.parent_data = &(const struct clk_parent_data){
12462306a36Sopenharmony_ci				.index = DT_BI_TCXO_PAD,
12562306a36Sopenharmony_ci			},
12662306a36Sopenharmony_ci			.num_parents = 1,
12762306a36Sopenharmony_ci			.ops = &clk_branch2_ops,
12862306a36Sopenharmony_ci		},
12962306a36Sopenharmony_ci	},
13062306a36Sopenharmony_ci};
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic struct clk_regmap *tcsr_cc_sm8550_clocks[] = {
13362306a36Sopenharmony_ci	[TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr,
13462306a36Sopenharmony_ci	[TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr,
13562306a36Sopenharmony_ci	[TCSR_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr,
13662306a36Sopenharmony_ci	[TCSR_UFS_PAD_CLKREF_EN] = &tcsr_ufs_pad_clkref_en.clkr,
13762306a36Sopenharmony_ci	[TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr,
13862306a36Sopenharmony_ci	[TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr,
13962306a36Sopenharmony_ci};
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic const struct regmap_config tcsr_cc_sm8550_regmap_config = {
14262306a36Sopenharmony_ci	.reg_bits = 32,
14362306a36Sopenharmony_ci	.reg_stride = 4,
14462306a36Sopenharmony_ci	.val_bits = 32,
14562306a36Sopenharmony_ci	.max_register = 0x2f000,
14662306a36Sopenharmony_ci	.fast_io = true,
14762306a36Sopenharmony_ci};
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic const struct qcom_cc_desc tcsr_cc_sm8550_desc = {
15062306a36Sopenharmony_ci	.config = &tcsr_cc_sm8550_regmap_config,
15162306a36Sopenharmony_ci	.clks = tcsr_cc_sm8550_clocks,
15262306a36Sopenharmony_ci	.num_clks = ARRAY_SIZE(tcsr_cc_sm8550_clocks),
15362306a36Sopenharmony_ci};
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic const struct of_device_id tcsr_cc_sm8550_match_table[] = {
15662306a36Sopenharmony_ci	{ .compatible = "qcom,sm8550-tcsr" },
15762306a36Sopenharmony_ci	{ }
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, tcsr_cc_sm8550_match_table);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic int tcsr_cc_sm8550_probe(struct platform_device *pdev)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	struct regmap *regmap;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	regmap = qcom_cc_map(pdev, &tcsr_cc_sm8550_desc);
16662306a36Sopenharmony_ci	if (IS_ERR(regmap))
16762306a36Sopenharmony_ci		return PTR_ERR(regmap);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	return qcom_cc_really_probe(pdev, &tcsr_cc_sm8550_desc, regmap);
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistatic struct platform_driver tcsr_cc_sm8550_driver = {
17362306a36Sopenharmony_ci	.probe = tcsr_cc_sm8550_probe,
17462306a36Sopenharmony_ci	.driver = {
17562306a36Sopenharmony_ci		.name = "tcsr_cc-sm8550",
17662306a36Sopenharmony_ci		.of_match_table = tcsr_cc_sm8550_match_table,
17762306a36Sopenharmony_ci	},
17862306a36Sopenharmony_ci};
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cistatic int __init tcsr_cc_sm8550_init(void)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	return platform_driver_register(&tcsr_cc_sm8550_driver);
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_cisubsys_initcall(tcsr_cc_sm8550_init);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic void __exit tcsr_cc_sm8550_exit(void)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	platform_driver_unregister(&tcsr_cc_sm8550_driver);
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_cimodule_exit(tcsr_cc_sm8550_exit);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ciMODULE_DESCRIPTION("QTI TCSRCC SM8550 Driver");
19362306a36Sopenharmony_ciMODULE_LICENSE("GPL");
194