forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 61598093bbdd283a7edc367d900f223070ead8d2
kernel/drivers/clk/meson/gxbb-aoclk.c
....@@ -5,9 +5,21 @@
55 */
66 #include <linux/platform_device.h>
77 #include <linux/mfd/syscon.h>
8
-#include "clk-regmap.h"
8
+#include <linux/module.h>
99 #include "meson-aoclk.h"
1010 #include "gxbb-aoclk.h"
11
+
12
+#include "clk-regmap.h"
13
+#include "clk-dualdiv.h"
14
+
15
+/* AO Configuration Clock registers offsets */
16
+#define AO_RTI_PWR_CNTL_REG1 0x0c
17
+#define AO_RTI_PWR_CNTL_REG0 0x10
18
+#define AO_RTI_GEN_CNTL_REG0 0x40
19
+#define AO_OSCIN_CNTL 0x58
20
+#define AO_CRT_CLK_CNTL1 0x68
21
+#define AO_RTC_ALT_CLK_CNTL0 0x94
22
+#define AO_RTC_ALT_CLK_CNTL1 0x98
1123
1224 #define GXBB_AO_GATE(_name, _bit) \
1325 static struct clk_regmap _name##_ao = { \
....@@ -18,7 +30,9 @@
1830 .hw.init = &(struct clk_init_data) { \
1931 .name = #_name "_ao", \
2032 .ops = &clk_regmap_gate_ops, \
21
- .parent_names = (const char *[]){ "clk81" }, \
33
+ .parent_data = &(const struct clk_parent_data) { \
34
+ .fw_name = "mpeg-clk", \
35
+ }, \
2236 .num_parents = 1, \
2337 .flags = CLK_IGNORE_UNUSED, \
2438 }, \
....@@ -31,13 +45,184 @@
3145 GXBB_AO_GATE(uart2, 5);
3246 GXBB_AO_GATE(ir_blaster, 6);
3347
34
-static struct aoclk_cec_32k cec_32k_ao = {
35
- .hw.init = &(struct clk_init_data) {
36
- .name = "cec_32k_ao",
37
- .ops = &meson_aoclk_cec_32k_ops,
38
- .parent_names = (const char *[]){ "xtal" },
48
+static struct clk_regmap ao_cts_oscin = {
49
+ .data = &(struct clk_regmap_gate_data){
50
+ .offset = AO_RTI_PWR_CNTL_REG0,
51
+ .bit_idx = 6,
52
+ },
53
+ .hw.init = &(struct clk_init_data){
54
+ .name = "ao_cts_oscin",
55
+ .ops = &clk_regmap_gate_ro_ops,
56
+ .parent_data = &(const struct clk_parent_data) {
57
+ .fw_name = "xtal",
58
+ },
3959 .num_parents = 1,
40
- .flags = CLK_IGNORE_UNUSED,
60
+ },
61
+};
62
+
63
+static struct clk_regmap ao_32k_pre = {
64
+ .data = &(struct clk_regmap_gate_data){
65
+ .offset = AO_RTC_ALT_CLK_CNTL0,
66
+ .bit_idx = 31,
67
+ },
68
+ .hw.init = &(struct clk_init_data){
69
+ .name = "ao_32k_pre",
70
+ .ops = &clk_regmap_gate_ops,
71
+ .parent_hws = (const struct clk_hw *[]) { &ao_cts_oscin.hw },
72
+ .num_parents = 1,
73
+ },
74
+};
75
+
76
+static const struct meson_clk_dualdiv_param gxbb_32k_div_table[] = {
77
+ {
78
+ .dual = 1,
79
+ .n1 = 733,
80
+ .m1 = 8,
81
+ .n2 = 732,
82
+ .m2 = 11,
83
+ }, {}
84
+};
85
+
86
+static struct clk_regmap ao_32k_div = {
87
+ .data = &(struct meson_clk_dualdiv_data){
88
+ .n1 = {
89
+ .reg_off = AO_RTC_ALT_CLK_CNTL0,
90
+ .shift = 0,
91
+ .width = 12,
92
+ },
93
+ .n2 = {
94
+ .reg_off = AO_RTC_ALT_CLK_CNTL0,
95
+ .shift = 12,
96
+ .width = 12,
97
+ },
98
+ .m1 = {
99
+ .reg_off = AO_RTC_ALT_CLK_CNTL1,
100
+ .shift = 0,
101
+ .width = 12,
102
+ },
103
+ .m2 = {
104
+ .reg_off = AO_RTC_ALT_CLK_CNTL1,
105
+ .shift = 12,
106
+ .width = 12,
107
+ },
108
+ .dual = {
109
+ .reg_off = AO_RTC_ALT_CLK_CNTL0,
110
+ .shift = 28,
111
+ .width = 1,
112
+ },
113
+ .table = gxbb_32k_div_table,
114
+ },
115
+ .hw.init = &(struct clk_init_data){
116
+ .name = "ao_32k_div",
117
+ .ops = &meson_clk_dualdiv_ops,
118
+ .parent_hws = (const struct clk_hw *[]) { &ao_32k_pre.hw },
119
+ .num_parents = 1,
120
+ },
121
+};
122
+
123
+static struct clk_regmap ao_32k_sel = {
124
+ .data = &(struct clk_regmap_mux_data) {
125
+ .offset = AO_RTC_ALT_CLK_CNTL1,
126
+ .mask = 0x1,
127
+ .shift = 24,
128
+ .flags = CLK_MUX_ROUND_CLOSEST,
129
+ },
130
+ .hw.init = &(struct clk_init_data){
131
+ .name = "ao_32k_sel",
132
+ .ops = &clk_regmap_mux_ops,
133
+ .parent_hws = (const struct clk_hw *[]) {
134
+ &ao_32k_div.hw,
135
+ &ao_32k_pre.hw
136
+ },
137
+ .num_parents = 2,
138
+ .flags = CLK_SET_RATE_PARENT,
139
+ },
140
+};
141
+
142
+static struct clk_regmap ao_32k = {
143
+ .data = &(struct clk_regmap_gate_data){
144
+ .offset = AO_RTC_ALT_CLK_CNTL0,
145
+ .bit_idx = 30,
146
+ },
147
+ .hw.init = &(struct clk_init_data){
148
+ .name = "ao_32k",
149
+ .ops = &clk_regmap_gate_ops,
150
+ .parent_hws = (const struct clk_hw *[]) { &ao_32k_sel.hw },
151
+ .num_parents = 1,
152
+ .flags = CLK_SET_RATE_PARENT,
153
+ },
154
+};
155
+
156
+static struct clk_regmap ao_cts_rtc_oscin = {
157
+ .data = &(struct clk_regmap_mux_data) {
158
+ .offset = AO_RTI_PWR_CNTL_REG0,
159
+ .mask = 0x7,
160
+ .shift = 10,
161
+ .table = (u32[]){ 1, 2, 3, 4 },
162
+ .flags = CLK_MUX_ROUND_CLOSEST,
163
+ },
164
+ .hw.init = &(struct clk_init_data){
165
+ .name = "ao_cts_rtc_oscin",
166
+ .ops = &clk_regmap_mux_ops,
167
+ .parent_data = (const struct clk_parent_data []) {
168
+ { .fw_name = "ext-32k-0", },
169
+ { .fw_name = "ext-32k-1", },
170
+ { .fw_name = "ext-32k-2", },
171
+ { .hw = &ao_32k.hw },
172
+ },
173
+ .num_parents = 4,
174
+ .flags = CLK_SET_RATE_PARENT,
175
+ },
176
+};
177
+
178
+static struct clk_regmap ao_clk81 = {
179
+ .data = &(struct clk_regmap_mux_data) {
180
+ .offset = AO_RTI_PWR_CNTL_REG0,
181
+ .mask = 0x1,
182
+ .shift = 0,
183
+ .flags = CLK_MUX_ROUND_CLOSEST,
184
+ },
185
+ .hw.init = &(struct clk_init_data){
186
+ .name = "ao_clk81",
187
+ .ops = &clk_regmap_mux_ro_ops,
188
+ .parent_data = (const struct clk_parent_data []) {
189
+ { .fw_name = "mpeg-clk", },
190
+ { .hw = &ao_cts_rtc_oscin.hw },
191
+ },
192
+ .num_parents = 2,
193
+ .flags = CLK_SET_RATE_PARENT,
194
+ },
195
+};
196
+
197
+static struct clk_regmap ao_cts_cec = {
198
+ .data = &(struct clk_regmap_mux_data) {
199
+ .offset = AO_CRT_CLK_CNTL1,
200
+ .mask = 0x1,
201
+ .shift = 27,
202
+ .flags = CLK_MUX_ROUND_CLOSEST,
203
+ },
204
+ .hw.init = &(struct clk_init_data){
205
+ .name = "ao_cts_cec",
206
+ .ops = &clk_regmap_mux_ops,
207
+ /*
208
+ * FIXME: The 'fixme' parent obviously does not exist.
209
+ *
210
+ * ATM, CCF won't call get_parent() if num_parents is 1. It
211
+ * does not allow NULL as a parent name either.
212
+ *
213
+ * On this particular mux, we only know the input #1 parent
214
+ * but, on boot, unknown input #0 is set, so it is critical
215
+ * to call .get_parent() on it
216
+ *
217
+ * Until CCF gets fixed, adding this fake parent that won't
218
+ * ever be registered should work around the problem
219
+ */
220
+ .parent_data = (const struct clk_parent_data []) {
221
+ { .name = "fixme", .index = -1, },
222
+ { .hw = &ao_cts_rtc_oscin.hw },
223
+ },
224
+ .num_parents = 2,
225
+ .flags = CLK_SET_RATE_PARENT,
41226 },
42227 };
43228
....@@ -50,13 +235,21 @@
50235 [RESET_AO_IR_BLASTER] = 23,
51236 };
52237
53
-static struct clk_regmap *gxbb_aoclk_gate[] = {
54
- [CLKID_AO_REMOTE] = &remote_ao,
55
- [CLKID_AO_I2C_MASTER] = &i2c_master_ao,
56
- [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao,
57
- [CLKID_AO_UART1] = &uart1_ao,
58
- [CLKID_AO_UART2] = &uart2_ao,
59
- [CLKID_AO_IR_BLASTER] = &ir_blaster_ao,
238
+static struct clk_regmap *gxbb_aoclk[] = {
239
+ &remote_ao,
240
+ &i2c_master_ao,
241
+ &i2c_slave_ao,
242
+ &uart1_ao,
243
+ &uart2_ao,
244
+ &ir_blaster_ao,
245
+ &ao_cts_oscin,
246
+ &ao_32k_pre,
247
+ &ao_32k_div,
248
+ &ao_32k_sel,
249
+ &ao_32k,
250
+ &ao_cts_rtc_oscin,
251
+ &ao_clk81,
252
+ &ao_cts_cec,
60253 };
61254
62255 static const struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
....@@ -67,51 +260,26 @@
67260 [CLKID_AO_UART1] = &uart1_ao.hw,
68261 [CLKID_AO_UART2] = &uart2_ao.hw,
69262 [CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw,
70
- [CLKID_AO_CEC_32K] = &cec_32k_ao.hw,
263
+ [CLKID_AO_CEC_32K] = &ao_cts_cec.hw,
264
+ [CLKID_AO_CTS_OSCIN] = &ao_cts_oscin.hw,
265
+ [CLKID_AO_32K_PRE] = &ao_32k_pre.hw,
266
+ [CLKID_AO_32K_DIV] = &ao_32k_div.hw,
267
+ [CLKID_AO_32K_SEL] = &ao_32k_sel.hw,
268
+ [CLKID_AO_32K] = &ao_32k.hw,
269
+ [CLKID_AO_CTS_RTC_OSCIN] = &ao_cts_rtc_oscin.hw,
270
+ [CLKID_AO_CLK81] = &ao_clk81.hw,
71271 },
72272 .num = NR_CLKS,
73273 };
74
-
75
-static int gxbb_register_cec_ao_32k(struct platform_device *pdev)
76
-{
77
- struct device *dev = &pdev->dev;
78
- struct regmap *regmap;
79
- int ret;
80
-
81
- regmap = syscon_node_to_regmap(of_get_parent(dev->of_node));
82
- if (IS_ERR(regmap)) {
83
- dev_err(dev, "failed to get regmap\n");
84
- return PTR_ERR(regmap);
85
- }
86
-
87
- /* Specific clocks */
88
- cec_32k_ao.regmap = regmap;
89
- ret = devm_clk_hw_register(dev, &cec_32k_ao.hw);
90
- if (ret) {
91
- dev_err(&pdev->dev, "clk cec_32k_ao register failed.\n");
92
- return ret;
93
- }
94
-
95
- return 0;
96
-}
97274
98275 static const struct meson_aoclk_data gxbb_aoclkc_data = {
99276 .reset_reg = AO_RTI_GEN_CNTL_REG0,
100277 .num_reset = ARRAY_SIZE(gxbb_aoclk_reset),
101278 .reset = gxbb_aoclk_reset,
102
- .num_clks = ARRAY_SIZE(gxbb_aoclk_gate),
103
- .clks = gxbb_aoclk_gate,
279
+ .num_clks = ARRAY_SIZE(gxbb_aoclk),
280
+ .clks = gxbb_aoclk,
104281 .hw_data = &gxbb_aoclk_onecell_data,
105282 };
106
-
107
-static int gxbb_aoclkc_probe(struct platform_device *pdev)
108
-{
109
- int ret = gxbb_register_cec_ao_32k(pdev);
110
- if (ret)
111
- return ret;
112
-
113
- return meson_aoclkc_probe(pdev);
114
-}
115283
116284 static const struct of_device_id gxbb_aoclkc_match_table[] = {
117285 {
....@@ -120,12 +288,14 @@
120288 },
121289 { }
122290 };
291
+MODULE_DEVICE_TABLE(of, gxbb_aoclkc_match_table);
123292
124293 static struct platform_driver gxbb_aoclkc_driver = {
125
- .probe = gxbb_aoclkc_probe,
294
+ .probe = meson_aoclkc_probe,
126295 .driver = {
127296 .name = "gxbb-aoclkc",
128297 .of_match_table = gxbb_aoclkc_match_table,
129298 },
130299 };
131
-builtin_platform_driver(gxbb_aoclkc_driver);
300
+module_platform_driver(gxbb_aoclkc_driver);
301
+MODULE_LICENSE("GPL v2");