xref: /openbmc/linux/drivers/clk/qcom/tcsrcc-sm8550.c (revision e9a7b78b)
1*e9a7b78bSAbel Vesa // SPDX-License-Identifier: GPL-2.0-only
2*e9a7b78bSAbel Vesa /*
3*e9a7b78bSAbel Vesa  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
4*e9a7b78bSAbel Vesa  * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
5*e9a7b78bSAbel Vesa  * Copyright (c) 2022, Linaro Limited
6*e9a7b78bSAbel Vesa  */
7*e9a7b78bSAbel Vesa 
8*e9a7b78bSAbel Vesa #include <linux/clk-provider.h>
9*e9a7b78bSAbel Vesa #include <linux/module.h>
10*e9a7b78bSAbel Vesa #include <linux/of_device.h>
11*e9a7b78bSAbel Vesa #include <linux/regmap.h>
12*e9a7b78bSAbel Vesa 
13*e9a7b78bSAbel Vesa #include <dt-bindings/clock/qcom,sm8550-tcsr.h>
14*e9a7b78bSAbel Vesa 
15*e9a7b78bSAbel Vesa #include "clk-alpha-pll.h"
16*e9a7b78bSAbel Vesa #include "clk-branch.h"
17*e9a7b78bSAbel Vesa #include "clk-pll.h"
18*e9a7b78bSAbel Vesa #include "clk-rcg.h"
19*e9a7b78bSAbel Vesa #include "clk-regmap.h"
20*e9a7b78bSAbel Vesa #include "clk-regmap-divider.h"
21*e9a7b78bSAbel Vesa #include "clk-regmap-mux.h"
22*e9a7b78bSAbel Vesa #include "common.h"
23*e9a7b78bSAbel Vesa #include "reset.h"
24*e9a7b78bSAbel Vesa 
25*e9a7b78bSAbel Vesa enum {
26*e9a7b78bSAbel Vesa 	DT_BI_TCXO_PAD,
27*e9a7b78bSAbel Vesa };
28*e9a7b78bSAbel Vesa 
29*e9a7b78bSAbel Vesa static struct clk_branch tcsr_pcie_0_clkref_en = {
30*e9a7b78bSAbel Vesa 	.halt_reg = 0x15100,
31*e9a7b78bSAbel Vesa 	.halt_check = BRANCH_HALT_SKIP,
32*e9a7b78bSAbel Vesa 	.clkr = {
33*e9a7b78bSAbel Vesa 		.enable_reg = 0x15100,
34*e9a7b78bSAbel Vesa 		.enable_mask = BIT(0),
35*e9a7b78bSAbel Vesa 		.hw.init = &(struct clk_init_data){
36*e9a7b78bSAbel Vesa 			.name = "tcsr_pcie_0_clkref_en",
37*e9a7b78bSAbel Vesa 			.parent_data = &(const struct clk_parent_data){
38*e9a7b78bSAbel Vesa 				.index = DT_BI_TCXO_PAD,
39*e9a7b78bSAbel Vesa 			},
40*e9a7b78bSAbel Vesa 			.num_parents = 1,
41*e9a7b78bSAbel Vesa 			.ops = &clk_branch2_ops,
42*e9a7b78bSAbel Vesa 		},
43*e9a7b78bSAbel Vesa 	},
44*e9a7b78bSAbel Vesa };
45*e9a7b78bSAbel Vesa 
46*e9a7b78bSAbel Vesa static struct clk_branch tcsr_pcie_1_clkref_en = {
47*e9a7b78bSAbel Vesa 	.halt_reg = 0x15114,
48*e9a7b78bSAbel Vesa 	.halt_check = BRANCH_HALT_SKIP,
49*e9a7b78bSAbel Vesa 	.clkr = {
50*e9a7b78bSAbel Vesa 		.enable_reg = 0x15114,
51*e9a7b78bSAbel Vesa 		.enable_mask = BIT(0),
52*e9a7b78bSAbel Vesa 		.hw.init = &(struct clk_init_data){
53*e9a7b78bSAbel Vesa 			.name = "tcsr_pcie_1_clkref_en",
54*e9a7b78bSAbel Vesa 			.parent_data = &(const struct clk_parent_data){
55*e9a7b78bSAbel Vesa 				.index = DT_BI_TCXO_PAD,
56*e9a7b78bSAbel Vesa 			},
57*e9a7b78bSAbel Vesa 			.num_parents = 1,
58*e9a7b78bSAbel Vesa 			.ops = &clk_branch2_ops,
59*e9a7b78bSAbel Vesa 		},
60*e9a7b78bSAbel Vesa 	},
61*e9a7b78bSAbel Vesa };
62*e9a7b78bSAbel Vesa 
63*e9a7b78bSAbel Vesa static struct clk_branch tcsr_ufs_clkref_en = {
64*e9a7b78bSAbel Vesa 	.halt_reg = 0x15110,
65*e9a7b78bSAbel Vesa 	.halt_check = BRANCH_HALT_SKIP,
66*e9a7b78bSAbel Vesa 	.clkr = {
67*e9a7b78bSAbel Vesa 		.enable_reg = 0x15110,
68*e9a7b78bSAbel Vesa 		.enable_mask = BIT(0),
69*e9a7b78bSAbel Vesa 		.hw.init = &(struct clk_init_data){
70*e9a7b78bSAbel Vesa 			.name = "tcsr_ufs_clkref_en",
71*e9a7b78bSAbel Vesa 			.parent_data = &(const struct clk_parent_data){
72*e9a7b78bSAbel Vesa 				.index = DT_BI_TCXO_PAD,
73*e9a7b78bSAbel Vesa 			},
74*e9a7b78bSAbel Vesa 			.num_parents = 1,
75*e9a7b78bSAbel Vesa 			.ops = &clk_branch2_ops,
76*e9a7b78bSAbel Vesa 		},
77*e9a7b78bSAbel Vesa 	},
78*e9a7b78bSAbel Vesa };
79*e9a7b78bSAbel Vesa 
80*e9a7b78bSAbel Vesa static struct clk_branch tcsr_ufs_pad_clkref_en = {
81*e9a7b78bSAbel Vesa 	.halt_reg = 0x15104,
82*e9a7b78bSAbel Vesa 	.halt_check = BRANCH_HALT_SKIP,
83*e9a7b78bSAbel Vesa 	.clkr = {
84*e9a7b78bSAbel Vesa 		.enable_reg = 0x15104,
85*e9a7b78bSAbel Vesa 		.enable_mask = BIT(0),
86*e9a7b78bSAbel Vesa 		.hw.init = &(struct clk_init_data){
87*e9a7b78bSAbel Vesa 			.name = "tcsr_ufs_pad_clkref_en",
88*e9a7b78bSAbel Vesa 			.parent_data = &(const struct clk_parent_data){
89*e9a7b78bSAbel Vesa 				.index = DT_BI_TCXO_PAD,
90*e9a7b78bSAbel Vesa 			},
91*e9a7b78bSAbel Vesa 			.num_parents = 1,
92*e9a7b78bSAbel Vesa 			.ops = &clk_branch2_ops,
93*e9a7b78bSAbel Vesa 		},
94*e9a7b78bSAbel Vesa 	},
95*e9a7b78bSAbel Vesa };
96*e9a7b78bSAbel Vesa 
97*e9a7b78bSAbel Vesa static struct clk_branch tcsr_usb2_clkref_en = {
98*e9a7b78bSAbel Vesa 	.halt_reg = 0x15118,
99*e9a7b78bSAbel Vesa 	.halt_check = BRANCH_HALT_SKIP,
100*e9a7b78bSAbel Vesa 	.clkr = {
101*e9a7b78bSAbel Vesa 		.enable_reg = 0x15118,
102*e9a7b78bSAbel Vesa 		.enable_mask = BIT(0),
103*e9a7b78bSAbel Vesa 		.hw.init = &(struct clk_init_data){
104*e9a7b78bSAbel Vesa 			.name = "tcsr_usb2_clkref_en",
105*e9a7b78bSAbel Vesa 			.parent_data = &(const struct clk_parent_data){
106*e9a7b78bSAbel Vesa 				.index = DT_BI_TCXO_PAD,
107*e9a7b78bSAbel Vesa 			},
108*e9a7b78bSAbel Vesa 			.num_parents = 1,
109*e9a7b78bSAbel Vesa 			.ops = &clk_branch2_ops,
110*e9a7b78bSAbel Vesa 		},
111*e9a7b78bSAbel Vesa 	},
112*e9a7b78bSAbel Vesa };
113*e9a7b78bSAbel Vesa 
114*e9a7b78bSAbel Vesa static struct clk_branch tcsr_usb3_clkref_en = {
115*e9a7b78bSAbel Vesa 	.halt_reg = 0x15108,
116*e9a7b78bSAbel Vesa 	.halt_check = BRANCH_HALT_SKIP,
117*e9a7b78bSAbel Vesa 	.clkr = {
118*e9a7b78bSAbel Vesa 		.enable_reg = 0x15108,
119*e9a7b78bSAbel Vesa 		.enable_mask = BIT(0),
120*e9a7b78bSAbel Vesa 		.hw.init = &(struct clk_init_data){
121*e9a7b78bSAbel Vesa 			.name = "tcsr_usb3_clkref_en",
122*e9a7b78bSAbel Vesa 			.parent_data = &(const struct clk_parent_data){
123*e9a7b78bSAbel Vesa 				.index = DT_BI_TCXO_PAD,
124*e9a7b78bSAbel Vesa 			},
125*e9a7b78bSAbel Vesa 			.num_parents = 1,
126*e9a7b78bSAbel Vesa 			.ops = &clk_branch2_ops,
127*e9a7b78bSAbel Vesa 		},
128*e9a7b78bSAbel Vesa 	},
129*e9a7b78bSAbel Vesa };
130*e9a7b78bSAbel Vesa 
131*e9a7b78bSAbel Vesa static struct clk_regmap *tcsr_cc_sm8550_clocks[] = {
132*e9a7b78bSAbel Vesa 	[TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr,
133*e9a7b78bSAbel Vesa 	[TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr,
134*e9a7b78bSAbel Vesa 	[TCSR_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr,
135*e9a7b78bSAbel Vesa 	[TCSR_UFS_PAD_CLKREF_EN] = &tcsr_ufs_pad_clkref_en.clkr,
136*e9a7b78bSAbel Vesa 	[TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr,
137*e9a7b78bSAbel Vesa 	[TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr,
138*e9a7b78bSAbel Vesa };
139*e9a7b78bSAbel Vesa 
140*e9a7b78bSAbel Vesa static const struct regmap_config tcsr_cc_sm8550_regmap_config = {
141*e9a7b78bSAbel Vesa 	.reg_bits = 32,
142*e9a7b78bSAbel Vesa 	.reg_stride = 4,
143*e9a7b78bSAbel Vesa 	.val_bits = 32,
144*e9a7b78bSAbel Vesa 	.max_register = 0x2f000,
145*e9a7b78bSAbel Vesa 	.fast_io = true,
146*e9a7b78bSAbel Vesa };
147*e9a7b78bSAbel Vesa 
148*e9a7b78bSAbel Vesa static const struct qcom_cc_desc tcsr_cc_sm8550_desc = {
149*e9a7b78bSAbel Vesa 	.config = &tcsr_cc_sm8550_regmap_config,
150*e9a7b78bSAbel Vesa 	.clks = tcsr_cc_sm8550_clocks,
151*e9a7b78bSAbel Vesa 	.num_clks = ARRAY_SIZE(tcsr_cc_sm8550_clocks),
152*e9a7b78bSAbel Vesa };
153*e9a7b78bSAbel Vesa 
154*e9a7b78bSAbel Vesa static const struct of_device_id tcsr_cc_sm8550_match_table[] = {
155*e9a7b78bSAbel Vesa 	{ .compatible = "qcom,sm8550-tcsr" },
156*e9a7b78bSAbel Vesa 	{ }
157*e9a7b78bSAbel Vesa };
158*e9a7b78bSAbel Vesa MODULE_DEVICE_TABLE(of, tcsr_cc_sm8550_match_table);
159*e9a7b78bSAbel Vesa 
160*e9a7b78bSAbel Vesa static int tcsr_cc_sm8550_probe(struct platform_device *pdev)
161*e9a7b78bSAbel Vesa {
162*e9a7b78bSAbel Vesa 	struct regmap *regmap;
163*e9a7b78bSAbel Vesa 
164*e9a7b78bSAbel Vesa 	regmap = qcom_cc_map(pdev, &tcsr_cc_sm8550_desc);
165*e9a7b78bSAbel Vesa 	if (IS_ERR(regmap))
166*e9a7b78bSAbel Vesa 		return PTR_ERR(regmap);
167*e9a7b78bSAbel Vesa 
168*e9a7b78bSAbel Vesa 	return qcom_cc_really_probe(pdev, &tcsr_cc_sm8550_desc, regmap);
169*e9a7b78bSAbel Vesa }
170*e9a7b78bSAbel Vesa 
171*e9a7b78bSAbel Vesa static struct platform_driver tcsr_cc_sm8550_driver = {
172*e9a7b78bSAbel Vesa 	.probe = tcsr_cc_sm8550_probe,
173*e9a7b78bSAbel Vesa 	.driver = {
174*e9a7b78bSAbel Vesa 		.name = "tcsr_cc-sm8550",
175*e9a7b78bSAbel Vesa 		.of_match_table = tcsr_cc_sm8550_match_table,
176*e9a7b78bSAbel Vesa 	},
177*e9a7b78bSAbel Vesa };
178*e9a7b78bSAbel Vesa 
179*e9a7b78bSAbel Vesa static int __init tcsr_cc_sm8550_init(void)
180*e9a7b78bSAbel Vesa {
181*e9a7b78bSAbel Vesa 	return platform_driver_register(&tcsr_cc_sm8550_driver);
182*e9a7b78bSAbel Vesa }
183*e9a7b78bSAbel Vesa subsys_initcall(tcsr_cc_sm8550_init);
184*e9a7b78bSAbel Vesa 
185*e9a7b78bSAbel Vesa static void __exit tcsr_cc_sm8550_exit(void)
186*e9a7b78bSAbel Vesa {
187*e9a7b78bSAbel Vesa 	platform_driver_unregister(&tcsr_cc_sm8550_driver);
188*e9a7b78bSAbel Vesa }
189*e9a7b78bSAbel Vesa module_exit(tcsr_cc_sm8550_exit);
190*e9a7b78bSAbel Vesa 
191*e9a7b78bSAbel Vesa MODULE_DESCRIPTION("QTI TCSRCC SM8550 Driver");
192*e9a7b78bSAbel Vesa MODULE_LICENSE("GPL");
193