Merge tag 'drm-misc-next-2021-03-03' of git://anongit.freedesktop.org/drm/drm-misc...
[linux-2.6-microblaze.git] / drivers / clk / meson / axg-aoclk.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Amlogic Meson-AXG Clock Controller Driver
4  *
5  * Copyright (c) 2016 Baylibre SAS.
6  * Author: Michael Turquette <mturquette@baylibre.com>
7  *
8  * Copyright (c) 2018 Amlogic, inc.
9  * Author: Qiufang Dai <qiufang.dai@amlogic.com>
10  */
11 #include <linux/clk-provider.h>
12 #include <linux/platform_device.h>
13 #include <linux/reset-controller.h>
14 #include <linux/mfd/syscon.h>
15 #include <linux/module.h>
16 #include "meson-aoclk.h"
17 #include "axg-aoclk.h"
18
19 #include "clk-regmap.h"
20 #include "clk-dualdiv.h"
21
22 /*
23  * AO Configuration Clock registers offsets
24  * Register offsets from the data sheet must be multiplied by 4.
25  */
26 #define AO_RTI_PWR_CNTL_REG1    0x0C
27 #define AO_RTI_PWR_CNTL_REG0    0x10
28 #define AO_RTI_GEN_CNTL_REG0    0x40
29 #define AO_OSCIN_CNTL           0x58
30 #define AO_CRT_CLK_CNTL1        0x68
31 #define AO_SAR_CLK              0x90
32 #define AO_RTC_ALT_CLK_CNTL0    0x94
33 #define AO_RTC_ALT_CLK_CNTL1    0x98
34
35 #define AXG_AO_GATE(_name, _bit)                                        \
36 static struct clk_regmap axg_aoclk_##_name = {                          \
37         .data = &(struct clk_regmap_gate_data) {                        \
38                 .offset = (AO_RTI_GEN_CNTL_REG0),                       \
39                 .bit_idx = (_bit),                                      \
40         },                                                              \
41         .hw.init = &(struct clk_init_data) {                            \
42                 .name =  "axg_ao_" #_name,                              \
43                 .ops = &clk_regmap_gate_ops,                            \
44                 .parent_data = &(const struct clk_parent_data) {        \
45                         .fw_name = "mpeg-clk",                          \
46                 },                                                      \
47                 .num_parents = 1,                                       \
48                 .flags = CLK_IGNORE_UNUSED,                             \
49         },                                                              \
50 }
51
52 AXG_AO_GATE(remote, 0);
53 AXG_AO_GATE(i2c_master, 1);
54 AXG_AO_GATE(i2c_slave, 2);
55 AXG_AO_GATE(uart1, 3);
56 AXG_AO_GATE(uart2, 5);
57 AXG_AO_GATE(ir_blaster, 6);
58 AXG_AO_GATE(saradc, 7);
59
60 static struct clk_regmap axg_aoclk_cts_oscin = {
61         .data = &(struct clk_regmap_gate_data){
62                 .offset = AO_RTI_PWR_CNTL_REG0,
63                 .bit_idx = 14,
64         },
65         .hw.init = &(struct clk_init_data){
66                 .name = "cts_oscin",
67                 .ops = &clk_regmap_gate_ro_ops,
68                 .parent_data = &(const struct clk_parent_data) {
69                         .fw_name = "xtal",
70                 },
71                 .num_parents = 1,
72         },
73 };
74
75 static struct clk_regmap axg_aoclk_32k_pre = {
76         .data = &(struct clk_regmap_gate_data){
77                 .offset = AO_RTC_ALT_CLK_CNTL0,
78                 .bit_idx = 31,
79         },
80         .hw.init = &(struct clk_init_data){
81                 .name = "axg_ao_32k_pre",
82                 .ops = &clk_regmap_gate_ops,
83                 .parent_hws = (const struct clk_hw *[]) {
84                         &axg_aoclk_cts_oscin.hw
85                 },
86                 .num_parents = 1,
87         },
88 };
89
90 static const struct meson_clk_dualdiv_param axg_32k_div_table[] = {
91         {
92                 .dual   = 1,
93                 .n1     = 733,
94                 .m1     = 8,
95                 .n2     = 732,
96                 .m2     = 11,
97         }, {}
98 };
99
100 static struct clk_regmap axg_aoclk_32k_div = {
101         .data = &(struct meson_clk_dualdiv_data){
102                 .n1 = {
103                         .reg_off = AO_RTC_ALT_CLK_CNTL0,
104                         .shift   = 0,
105                         .width   = 12,
106                 },
107                 .n2 = {
108                         .reg_off = AO_RTC_ALT_CLK_CNTL0,
109                         .shift   = 12,
110                         .width   = 12,
111                 },
112                 .m1 = {
113                         .reg_off = AO_RTC_ALT_CLK_CNTL1,
114                         .shift   = 0,
115                         .width   = 12,
116                 },
117                 .m2 = {
118                         .reg_off = AO_RTC_ALT_CLK_CNTL1,
119                         .shift   = 12,
120                         .width   = 12,
121                 },
122                 .dual = {
123                         .reg_off = AO_RTC_ALT_CLK_CNTL0,
124                         .shift   = 28,
125                         .width   = 1,
126                 },
127                 .table = axg_32k_div_table,
128         },
129         .hw.init = &(struct clk_init_data){
130                 .name = "axg_ao_32k_div",
131                 .ops = &meson_clk_dualdiv_ops,
132                 .parent_hws = (const struct clk_hw *[]) {
133                         &axg_aoclk_32k_pre.hw
134                 },
135                 .num_parents = 1,
136         },
137 };
138
139 static struct clk_regmap axg_aoclk_32k_sel = {
140         .data = &(struct clk_regmap_mux_data) {
141                 .offset = AO_RTC_ALT_CLK_CNTL1,
142                 .mask = 0x1,
143                 .shift = 24,
144                 .flags = CLK_MUX_ROUND_CLOSEST,
145         },
146         .hw.init = &(struct clk_init_data){
147                 .name = "axg_ao_32k_sel",
148                 .ops = &clk_regmap_mux_ops,
149                 .parent_hws = (const struct clk_hw *[]) {
150                         &axg_aoclk_32k_div.hw,
151                         &axg_aoclk_32k_pre.hw,
152                 },
153                 .num_parents = 2,
154                 .flags = CLK_SET_RATE_PARENT,
155         },
156 };
157
158 static struct clk_regmap axg_aoclk_32k = {
159         .data = &(struct clk_regmap_gate_data){
160                 .offset = AO_RTC_ALT_CLK_CNTL0,
161                 .bit_idx = 30,
162         },
163         .hw.init = &(struct clk_init_data){
164                 .name = "axg_ao_32k",
165                 .ops = &clk_regmap_gate_ops,
166                 .parent_hws = (const struct clk_hw *[]) {
167                         &axg_aoclk_32k_sel.hw
168                 },
169                 .num_parents = 1,
170                 .flags = CLK_SET_RATE_PARENT,
171         },
172 };
173
174 static struct clk_regmap axg_aoclk_cts_rtc_oscin = {
175         .data = &(struct clk_regmap_mux_data) {
176                 .offset = AO_RTI_PWR_CNTL_REG0,
177                 .mask = 0x1,
178                 .shift = 10,
179                 .flags = CLK_MUX_ROUND_CLOSEST,
180         },
181         .hw.init = &(struct clk_init_data){
182                 .name = "axg_ao_cts_rtc_oscin",
183                 .ops = &clk_regmap_mux_ops,
184                 .parent_data = (const struct clk_parent_data []) {
185                         { .hw = &axg_aoclk_32k.hw },
186                         { .fw_name = "ext_32k-0", },
187                 },
188                 .num_parents = 2,
189                 .flags = CLK_SET_RATE_PARENT,
190         },
191 };
192
193 static struct clk_regmap axg_aoclk_clk81 = {
194         .data = &(struct clk_regmap_mux_data) {
195                 .offset = AO_RTI_PWR_CNTL_REG0,
196                 .mask = 0x1,
197                 .shift = 8,
198                 .flags = CLK_MUX_ROUND_CLOSEST,
199         },
200         .hw.init = &(struct clk_init_data){
201                 .name = "axg_ao_clk81",
202                 .ops = &clk_regmap_mux_ro_ops,
203                 .parent_data = (const struct clk_parent_data []) {
204                         { .fw_name = "mpeg-clk", },
205                         { .hw = &axg_aoclk_cts_rtc_oscin.hw },
206                 },
207                 .num_parents = 2,
208                 .flags = CLK_SET_RATE_PARENT,
209         },
210 };
211
212 static struct clk_regmap axg_aoclk_saradc_mux = {
213         .data = &(struct clk_regmap_mux_data) {
214                 .offset = AO_SAR_CLK,
215                 .mask = 0x3,
216                 .shift = 9,
217         },
218         .hw.init = &(struct clk_init_data){
219                 .name = "axg_ao_saradc_mux",
220                 .ops = &clk_regmap_mux_ops,
221                 .parent_data = (const struct clk_parent_data []) {
222                         { .fw_name = "xtal", },
223                         { .hw = &axg_aoclk_clk81.hw },
224                 },
225                 .num_parents = 2,
226         },
227 };
228
229 static struct clk_regmap axg_aoclk_saradc_div = {
230         .data = &(struct clk_regmap_div_data) {
231                 .offset = AO_SAR_CLK,
232                 .shift = 0,
233                 .width = 8,
234         },
235         .hw.init = &(struct clk_init_data){
236                 .name = "axg_ao_saradc_div",
237                 .ops = &clk_regmap_divider_ops,
238                 .parent_hws = (const struct clk_hw *[]) {
239                         &axg_aoclk_saradc_mux.hw
240                 },
241                 .num_parents = 1,
242                 .flags = CLK_SET_RATE_PARENT,
243         },
244 };
245
246 static struct clk_regmap axg_aoclk_saradc_gate = {
247         .data = &(struct clk_regmap_gate_data) {
248                 .offset = AO_SAR_CLK,
249                 .bit_idx = 8,
250         },
251         .hw.init = &(struct clk_init_data){
252                 .name = "axg_ao_saradc_gate",
253                 .ops = &clk_regmap_gate_ops,
254                 .parent_hws = (const struct clk_hw *[]) {
255                         &axg_aoclk_saradc_div.hw
256                 },
257                 .num_parents = 1,
258                 .flags = CLK_SET_RATE_PARENT,
259         },
260 };
261
262 static const unsigned int axg_aoclk_reset[] = {
263         [RESET_AO_REMOTE]       = 16,
264         [RESET_AO_I2C_MASTER]   = 18,
265         [RESET_AO_I2C_SLAVE]    = 19,
266         [RESET_AO_UART1]        = 17,
267         [RESET_AO_UART2]        = 22,
268         [RESET_AO_IR_BLASTER]   = 23,
269 };
270
271 static struct clk_regmap *axg_aoclk_regmap[] = {
272         &axg_aoclk_remote,
273         &axg_aoclk_i2c_master,
274         &axg_aoclk_i2c_slave,
275         &axg_aoclk_uart1,
276         &axg_aoclk_uart2,
277         &axg_aoclk_ir_blaster,
278         &axg_aoclk_saradc,
279         &axg_aoclk_cts_oscin,
280         &axg_aoclk_32k_pre,
281         &axg_aoclk_32k_div,
282         &axg_aoclk_32k_sel,
283         &axg_aoclk_32k,
284         &axg_aoclk_cts_rtc_oscin,
285         &axg_aoclk_clk81,
286         &axg_aoclk_saradc_mux,
287         &axg_aoclk_saradc_div,
288         &axg_aoclk_saradc_gate,
289 };
290
291 static const struct clk_hw_onecell_data axg_aoclk_onecell_data = {
292         .hws = {
293                 [CLKID_AO_REMOTE]       = &axg_aoclk_remote.hw,
294                 [CLKID_AO_I2C_MASTER]   = &axg_aoclk_i2c_master.hw,
295                 [CLKID_AO_I2C_SLAVE]    = &axg_aoclk_i2c_slave.hw,
296                 [CLKID_AO_UART1]        = &axg_aoclk_uart1.hw,
297                 [CLKID_AO_UART2]        = &axg_aoclk_uart2.hw,
298                 [CLKID_AO_IR_BLASTER]   = &axg_aoclk_ir_blaster.hw,
299                 [CLKID_AO_SAR_ADC]      = &axg_aoclk_saradc.hw,
300                 [CLKID_AO_CLK81]        = &axg_aoclk_clk81.hw,
301                 [CLKID_AO_SAR_ADC_SEL]  = &axg_aoclk_saradc_mux.hw,
302                 [CLKID_AO_SAR_ADC_DIV]  = &axg_aoclk_saradc_div.hw,
303                 [CLKID_AO_SAR_ADC_CLK]  = &axg_aoclk_saradc_gate.hw,
304                 [CLKID_AO_CTS_OSCIN]    = &axg_aoclk_cts_oscin.hw,
305                 [CLKID_AO_32K_PRE]      = &axg_aoclk_32k_pre.hw,
306                 [CLKID_AO_32K_DIV]      = &axg_aoclk_32k_div.hw,
307                 [CLKID_AO_32K_SEL]      = &axg_aoclk_32k_sel.hw,
308                 [CLKID_AO_32K]          = &axg_aoclk_32k.hw,
309                 [CLKID_AO_CTS_RTC_OSCIN] = &axg_aoclk_cts_rtc_oscin.hw,
310         },
311         .num = NR_CLKS,
312 };
313
314 static const struct meson_aoclk_data axg_aoclkc_data = {
315         .reset_reg      = AO_RTI_GEN_CNTL_REG0,
316         .num_reset      = ARRAY_SIZE(axg_aoclk_reset),
317         .reset          = axg_aoclk_reset,
318         .num_clks       = ARRAY_SIZE(axg_aoclk_regmap),
319         .clks           = axg_aoclk_regmap,
320         .hw_data        = &axg_aoclk_onecell_data,
321 };
322
323 static const struct of_device_id axg_aoclkc_match_table[] = {
324         {
325                 .compatible     = "amlogic,meson-axg-aoclkc",
326                 .data           = &axg_aoclkc_data,
327         },
328         { }
329 };
330 MODULE_DEVICE_TABLE(of, axg_aoclkc_match_table);
331
332 static struct platform_driver axg_aoclkc_driver = {
333         .probe          = meson_aoclkc_probe,
334         .driver         = {
335                 .name   = "axg-aoclkc",
336                 .of_match_table = axg_aoclkc_match_table,
337         },
338 };
339
340 module_platform_driver(axg_aoclkc_driver);
341 MODULE_LICENSE("GPL v2");