1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /*
3 * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
4 */
5
6 #include <linux/clk-provider.h>
7 #include <linux/module.h>
8 #include <linux/of.h>
9 #include <linux/platform_device.h>
10 #include <linux/regmap.h>
11
12 #include <dt-bindings/clock/qcom,sm8750-tcsr.h>
13
14 #include "clk-branch.h"
15 #include "clk-regmap.h"
16 #include "clk-regmap-divider.h"
17 #include "clk-regmap-mux.h"
18 #include "common.h"
19
20 enum {
21 DT_BI_TCXO_PAD,
22 };
23
24 static struct clk_branch tcsr_pcie_0_clkref_en = {
25 .halt_reg = 0x0,
26 .halt_check = BRANCH_HALT_DELAY,
27 .clkr = {
28 .enable_reg = 0x0,
29 .enable_mask = BIT(0),
30 .hw.init = &(const struct clk_init_data) {
31 .name = "tcsr_pcie_0_clkref_en",
32 .ops = &clk_branch2_ops,
33 },
34 },
35 };
36
37 static struct clk_branch tcsr_ufs_clkref_en = {
38 .halt_reg = 0x1000,
39 .halt_check = BRANCH_HALT_DELAY,
40 .clkr = {
41 .enable_reg = 0x1000,
42 .enable_mask = BIT(0),
43 .hw.init = &(const struct clk_init_data) {
44 .name = "tcsr_ufs_clkref_en",
45 .parent_data = &(const struct clk_parent_data){
46 .index = DT_BI_TCXO_PAD,
47 },
48 .num_parents = 1,
49 .ops = &clk_branch2_ops,
50 },
51 },
52 };
53
54 static struct clk_branch tcsr_usb2_clkref_en = {
55 .halt_reg = 0x2000,
56 .halt_check = BRANCH_HALT_DELAY,
57 .clkr = {
58 .enable_reg = 0x2000,
59 .enable_mask = BIT(0),
60 .hw.init = &(const struct clk_init_data) {
61 .name = "tcsr_usb2_clkref_en",
62 .parent_data = &(const struct clk_parent_data){
63 .index = DT_BI_TCXO_PAD,
64 },
65 .num_parents = 1,
66 .ops = &clk_branch2_ops,
67 },
68 },
69 };
70
71 static struct clk_branch tcsr_usb3_clkref_en = {
72 .halt_reg = 0x3000,
73 .halt_check = BRANCH_HALT_DELAY,
74 .clkr = {
75 .enable_reg = 0x3000,
76 .enable_mask = BIT(0),
77 .hw.init = &(const struct clk_init_data) {
78 .name = "tcsr_usb3_clkref_en",
79 .parent_data = &(const struct clk_parent_data){
80 .index = DT_BI_TCXO_PAD,
81 },
82 .num_parents = 1,
83 .ops = &clk_branch2_ops,
84 },
85 },
86 };
87
88 static struct clk_regmap *tcsr_cc_sm8750_clocks[] = {
89 [TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr,
90 [TCSR_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr,
91 [TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr,
92 [TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr,
93 };
94
95 static const struct regmap_config tcsr_cc_sm8750_regmap_config = {
96 .reg_bits = 32,
97 .reg_stride = 4,
98 .val_bits = 32,
99 .max_register = 0x3000,
100 .fast_io = true,
101 };
102
103 static const struct qcom_cc_desc tcsr_cc_sm8750_desc = {
104 .config = &tcsr_cc_sm8750_regmap_config,
105 .clks = tcsr_cc_sm8750_clocks,
106 .num_clks = ARRAY_SIZE(tcsr_cc_sm8750_clocks),
107 };
108
109 static const struct of_device_id tcsr_cc_sm8750_match_table[] = {
110 { .compatible = "qcom,sm8750-tcsr" },
111 { }
112 };
113 MODULE_DEVICE_TABLE(of, tcsr_cc_sm8750_match_table);
114
tcsr_cc_sm8750_probe(struct platform_device * pdev)115 static int tcsr_cc_sm8750_probe(struct platform_device *pdev)
116 {
117 return qcom_cc_probe(pdev, &tcsr_cc_sm8750_desc);
118 }
119
120 static struct platform_driver tcsr_cc_sm8750_driver = {
121 .probe = tcsr_cc_sm8750_probe,
122 .driver = {
123 .name = "tcsr_cc-sm8750",
124 .of_match_table = tcsr_cc_sm8750_match_table,
125 },
126 };
127
tcsr_cc_sm8750_init(void)128 static int __init tcsr_cc_sm8750_init(void)
129 {
130 return platform_driver_register(&tcsr_cc_sm8750_driver);
131 }
132 subsys_initcall(tcsr_cc_sm8750_init);
133
tcsr_cc_sm8750_exit(void)134 static void __exit tcsr_cc_sm8750_exit(void)
135 {
136 platform_driver_unregister(&tcsr_cc_sm8750_driver);
137 }
138 module_exit(tcsr_cc_sm8750_exit);
139
140 MODULE_DESCRIPTION("QTI TCSR_CC SM8750 Driver");
141 MODULE_LICENSE("GPL");
142