Commit | Line | Data |
---|---|---|
042f01bb NA |
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) 2019 Baylibre SAS. | |
9 | * Author: Neil Armstrong <narmstrong@baylibre.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> | |
20425f63 | 15 | #include <linux/module.h> |
042f01bb | 16 | #include "meson-aoclk.h" |
042f01bb NA |
17 | |
18 | #include "clk-regmap.h" | |
19 | #include "clk-dualdiv.h" | |
20 | ||
eb10a264 NA |
21 | #include <dt-bindings/clock/g12a-aoclkc.h> |
22 | #include <dt-bindings/reset/g12a-aoclkc.h> | |
23 | ||
042f01bb NA |
24 | /* |
25 | * AO Configuration Clock registers offsets | |
26 | * Register offsets from the data sheet must be multiplied by 4. | |
27 | */ | |
28 | #define AO_RTI_STATUS_REG3 0x0C | |
29 | #define AO_RTI_PWR_CNTL_REG0 0x10 | |
30 | #define AO_RTI_GEN_CNTL_REG0 0x40 | |
31 | #define AO_CLK_GATE0 0x4c | |
32 | #define AO_CLK_GATE0_SP 0x50 | |
33 | #define AO_OSCIN_CNTL 0x58 | |
34 | #define AO_CEC_CLK_CNTL_REG0 0x74 | |
35 | #define AO_CEC_CLK_CNTL_REG1 0x78 | |
36 | #define AO_SAR_CLK 0x90 | |
37 | #define AO_RTC_ALT_CLK_CNTL0 0x94 | |
38 | #define AO_RTC_ALT_CLK_CNTL1 0x98 | |
39 | ||
40 | /* | |
41 | * Like every other peripheral clock gate in Amlogic Clock drivers, | |
42 | * we are using CLK_IGNORE_UNUSED here, so we keep the state of the | |
43 | * bootloader. The goal is to remove this flag at some point. | |
44 | * Actually removing it will require some extensive test to be done safely. | |
45 | */ | |
46 | #define AXG_AO_GATE(_name, _reg, _bit) \ | |
47 | static struct clk_regmap g12a_aoclk_##_name = { \ | |
48 | .data = &(struct clk_regmap_gate_data) { \ | |
49 | .offset = (_reg), \ | |
50 | .bit_idx = (_bit), \ | |
51 | }, \ | |
52 | .hw.init = &(struct clk_init_data) { \ | |
53 | .name = "g12a_ao_" #_name, \ | |
54 | .ops = &clk_regmap_gate_ops, \ | |
ba626081 AM |
55 | .parent_data = &(const struct clk_parent_data) { \ |
56 | .fw_name = "mpeg-clk", \ | |
57 | }, \ | |
042f01bb NA |
58 | .num_parents = 1, \ |
59 | .flags = CLK_IGNORE_UNUSED, \ | |
60 | }, \ | |
61 | } | |
62 | ||
63 | AXG_AO_GATE(ahb, AO_CLK_GATE0, 0); | |
64 | AXG_AO_GATE(ir_in, AO_CLK_GATE0, 1); | |
65 | AXG_AO_GATE(i2c_m0, AO_CLK_GATE0, 2); | |
66 | AXG_AO_GATE(i2c_s0, AO_CLK_GATE0, 3); | |
67 | AXG_AO_GATE(uart, AO_CLK_GATE0, 4); | |
68 | AXG_AO_GATE(prod_i2c, AO_CLK_GATE0, 5); | |
69 | AXG_AO_GATE(uart2, AO_CLK_GATE0, 6); | |
70 | AXG_AO_GATE(ir_out, AO_CLK_GATE0, 7); | |
71 | AXG_AO_GATE(saradc, AO_CLK_GATE0, 8); | |
72 | AXG_AO_GATE(mailbox, AO_CLK_GATE0_SP, 0); | |
73 | AXG_AO_GATE(m3, AO_CLK_GATE0_SP, 1); | |
74 | AXG_AO_GATE(ahb_sram, AO_CLK_GATE0_SP, 2); | |
75 | AXG_AO_GATE(rti, AO_CLK_GATE0_SP, 3); | |
76 | AXG_AO_GATE(m4_fclk, AO_CLK_GATE0_SP, 4); | |
77 | AXG_AO_GATE(m4_hclk, AO_CLK_GATE0_SP, 5); | |
78 | ||
79 | static struct clk_regmap g12a_aoclk_cts_oscin = { | |
80 | .data = &(struct clk_regmap_gate_data){ | |
81 | .offset = AO_RTI_PWR_CNTL_REG0, | |
82 | .bit_idx = 14, | |
83 | }, | |
84 | .hw.init = &(struct clk_init_data){ | |
85 | .name = "cts_oscin", | |
86 | .ops = &clk_regmap_gate_ro_ops, | |
ba626081 AM |
87 | .parent_data = &(const struct clk_parent_data) { |
88 | .fw_name = "xtal", | |
89 | }, | |
042f01bb NA |
90 | .num_parents = 1, |
91 | }, | |
92 | }; | |
93 | ||
94 | static const struct meson_clk_dualdiv_param g12a_32k_div_table[] = { | |
95 | { | |
96 | .dual = 1, | |
97 | .n1 = 733, | |
98 | .m1 = 8, | |
99 | .n2 = 732, | |
100 | .m2 = 11, | |
101 | }, {} | |
102 | }; | |
103 | ||
104 | /* 32k_by_oscin clock */ | |
105 | ||
106 | static struct clk_regmap g12a_aoclk_32k_by_oscin_pre = { | |
107 | .data = &(struct clk_regmap_gate_data){ | |
108 | .offset = AO_RTC_ALT_CLK_CNTL0, | |
109 | .bit_idx = 31, | |
110 | }, | |
111 | .hw.init = &(struct clk_init_data){ | |
112 | .name = "g12a_ao_32k_by_oscin_pre", | |
113 | .ops = &clk_regmap_gate_ops, | |
ba626081 AM |
114 | .parent_hws = (const struct clk_hw *[]) { |
115 | &g12a_aoclk_cts_oscin.hw | |
116 | }, | |
042f01bb NA |
117 | .num_parents = 1, |
118 | }, | |
119 | }; | |
120 | ||
121 | static struct clk_regmap g12a_aoclk_32k_by_oscin_div = { | |
122 | .data = &(struct meson_clk_dualdiv_data){ | |
123 | .n1 = { | |
124 | .reg_off = AO_RTC_ALT_CLK_CNTL0, | |
125 | .shift = 0, | |
126 | .width = 12, | |
127 | }, | |
128 | .n2 = { | |
129 | .reg_off = AO_RTC_ALT_CLK_CNTL0, | |
130 | .shift = 12, | |
131 | .width = 12, | |
132 | }, | |
133 | .m1 = { | |
134 | .reg_off = AO_RTC_ALT_CLK_CNTL1, | |
135 | .shift = 0, | |
136 | .width = 12, | |
137 | }, | |
138 | .m2 = { | |
139 | .reg_off = AO_RTC_ALT_CLK_CNTL1, | |
140 | .shift = 12, | |
141 | .width = 12, | |
142 | }, | |
143 | .dual = { | |
144 | .reg_off = AO_RTC_ALT_CLK_CNTL0, | |
145 | .shift = 28, | |
146 | .width = 1, | |
147 | }, | |
148 | .table = g12a_32k_div_table, | |
149 | }, | |
150 | .hw.init = &(struct clk_init_data){ | |
151 | .name = "g12a_ao_32k_by_oscin_div", | |
152 | .ops = &meson_clk_dualdiv_ops, | |
ba626081 AM |
153 | .parent_hws = (const struct clk_hw *[]) { |
154 | &g12a_aoclk_32k_by_oscin_pre.hw | |
155 | }, | |
042f01bb NA |
156 | .num_parents = 1, |
157 | }, | |
158 | }; | |
159 | ||
160 | static struct clk_regmap g12a_aoclk_32k_by_oscin_sel = { | |
161 | .data = &(struct clk_regmap_mux_data) { | |
162 | .offset = AO_RTC_ALT_CLK_CNTL1, | |
163 | .mask = 0x1, | |
164 | .shift = 24, | |
165 | .flags = CLK_MUX_ROUND_CLOSEST, | |
166 | }, | |
167 | .hw.init = &(struct clk_init_data){ | |
168 | .name = "g12a_ao_32k_by_oscin_sel", | |
169 | .ops = &clk_regmap_mux_ops, | |
ba626081 AM |
170 | .parent_hws = (const struct clk_hw *[]) { |
171 | &g12a_aoclk_32k_by_oscin_div.hw, | |
172 | &g12a_aoclk_32k_by_oscin_pre.hw, | |
173 | }, | |
042f01bb NA |
174 | .num_parents = 2, |
175 | .flags = CLK_SET_RATE_PARENT, | |
176 | }, | |
177 | }; | |
178 | ||
179 | static struct clk_regmap g12a_aoclk_32k_by_oscin = { | |
180 | .data = &(struct clk_regmap_gate_data){ | |
181 | .offset = AO_RTC_ALT_CLK_CNTL0, | |
182 | .bit_idx = 30, | |
183 | }, | |
184 | .hw.init = &(struct clk_init_data){ | |
185 | .name = "g12a_ao_32k_by_oscin", | |
186 | .ops = &clk_regmap_gate_ops, | |
ba626081 AM |
187 | .parent_hws = (const struct clk_hw *[]) { |
188 | &g12a_aoclk_32k_by_oscin_sel.hw | |
189 | }, | |
042f01bb NA |
190 | .num_parents = 1, |
191 | .flags = CLK_SET_RATE_PARENT, | |
192 | }, | |
193 | }; | |
194 | ||
195 | /* cec clock */ | |
196 | ||
197 | static struct clk_regmap g12a_aoclk_cec_pre = { | |
198 | .data = &(struct clk_regmap_gate_data){ | |
199 | .offset = AO_CEC_CLK_CNTL_REG0, | |
200 | .bit_idx = 31, | |
201 | }, | |
202 | .hw.init = &(struct clk_init_data){ | |
203 | .name = "g12a_ao_cec_pre", | |
204 | .ops = &clk_regmap_gate_ops, | |
ba626081 AM |
205 | .parent_hws = (const struct clk_hw *[]) { |
206 | &g12a_aoclk_cts_oscin.hw | |
207 | }, | |
042f01bb NA |
208 | .num_parents = 1, |
209 | }, | |
210 | }; | |
211 | ||
212 | static struct clk_regmap g12a_aoclk_cec_div = { | |
213 | .data = &(struct meson_clk_dualdiv_data){ | |
214 | .n1 = { | |
215 | .reg_off = AO_CEC_CLK_CNTL_REG0, | |
216 | .shift = 0, | |
217 | .width = 12, | |
218 | }, | |
219 | .n2 = { | |
220 | .reg_off = AO_CEC_CLK_CNTL_REG0, | |
221 | .shift = 12, | |
222 | .width = 12, | |
223 | }, | |
224 | .m1 = { | |
225 | .reg_off = AO_CEC_CLK_CNTL_REG1, | |
226 | .shift = 0, | |
227 | .width = 12, | |
228 | }, | |
229 | .m2 = { | |
230 | .reg_off = AO_CEC_CLK_CNTL_REG1, | |
231 | .shift = 12, | |
232 | .width = 12, | |
233 | }, | |
234 | .dual = { | |
235 | .reg_off = AO_CEC_CLK_CNTL_REG0, | |
236 | .shift = 28, | |
237 | .width = 1, | |
238 | }, | |
239 | .table = g12a_32k_div_table, | |
240 | }, | |
241 | .hw.init = &(struct clk_init_data){ | |
242 | .name = "g12a_ao_cec_div", | |
243 | .ops = &meson_clk_dualdiv_ops, | |
ba626081 AM |
244 | .parent_hws = (const struct clk_hw *[]) { |
245 | &g12a_aoclk_cec_pre.hw | |
246 | }, | |
042f01bb NA |
247 | .num_parents = 1, |
248 | }, | |
249 | }; | |
250 | ||
251 | static struct clk_regmap g12a_aoclk_cec_sel = { | |
252 | .data = &(struct clk_regmap_mux_data) { | |
253 | .offset = AO_CEC_CLK_CNTL_REG1, | |
254 | .mask = 0x1, | |
255 | .shift = 24, | |
256 | .flags = CLK_MUX_ROUND_CLOSEST, | |
257 | }, | |
258 | .hw.init = &(struct clk_init_data){ | |
259 | .name = "g12a_ao_cec_sel", | |
260 | .ops = &clk_regmap_mux_ops, | |
ba626081 AM |
261 | .parent_hws = (const struct clk_hw *[]) { |
262 | &g12a_aoclk_cec_div.hw, | |
263 | &g12a_aoclk_cec_pre.hw, | |
264 | }, | |
042f01bb NA |
265 | .num_parents = 2, |
266 | .flags = CLK_SET_RATE_PARENT, | |
267 | }, | |
268 | }; | |
269 | ||
270 | static struct clk_regmap g12a_aoclk_cec = { | |
271 | .data = &(struct clk_regmap_gate_data){ | |
272 | .offset = AO_CEC_CLK_CNTL_REG0, | |
273 | .bit_idx = 30, | |
274 | }, | |
275 | .hw.init = &(struct clk_init_data){ | |
276 | .name = "g12a_ao_cec", | |
277 | .ops = &clk_regmap_gate_ops, | |
ba626081 AM |
278 | .parent_hws = (const struct clk_hw *[]) { |
279 | &g12a_aoclk_cec_sel.hw | |
280 | }, | |
042f01bb NA |
281 | .num_parents = 1, |
282 | .flags = CLK_SET_RATE_PARENT, | |
283 | }, | |
284 | }; | |
285 | ||
286 | static struct clk_regmap g12a_aoclk_cts_rtc_oscin = { | |
287 | .data = &(struct clk_regmap_mux_data) { | |
288 | .offset = AO_RTI_PWR_CNTL_REG0, | |
289 | .mask = 0x1, | |
290 | .shift = 10, | |
291 | .flags = CLK_MUX_ROUND_CLOSEST, | |
292 | }, | |
293 | .hw.init = &(struct clk_init_data){ | |
294 | .name = "g12a_ao_cts_rtc_oscin", | |
295 | .ops = &clk_regmap_mux_ops, | |
ba626081 AM |
296 | .parent_data = (const struct clk_parent_data []) { |
297 | { .hw = &g12a_aoclk_32k_by_oscin.hw }, | |
298 | { .fw_name = "ext-32k-0", }, | |
299 | }, | |
042f01bb NA |
300 | .num_parents = 2, |
301 | .flags = CLK_SET_RATE_PARENT, | |
302 | }, | |
303 | }; | |
304 | ||
305 | static struct clk_regmap g12a_aoclk_clk81 = { | |
306 | .data = &(struct clk_regmap_mux_data) { | |
307 | .offset = AO_RTI_PWR_CNTL_REG0, | |
308 | .mask = 0x1, | |
309 | .shift = 8, | |
310 | .flags = CLK_MUX_ROUND_CLOSEST, | |
311 | }, | |
312 | .hw.init = &(struct clk_init_data){ | |
313 | .name = "g12a_ao_clk81", | |
314 | .ops = &clk_regmap_mux_ro_ops, | |
ba626081 AM |
315 | .parent_data = (const struct clk_parent_data []) { |
316 | { .fw_name = "mpeg-clk", }, | |
317 | { .hw = &g12a_aoclk_cts_rtc_oscin.hw }, | |
318 | }, | |
042f01bb NA |
319 | .num_parents = 2, |
320 | .flags = CLK_SET_RATE_PARENT, | |
321 | }, | |
322 | }; | |
323 | ||
324 | static struct clk_regmap g12a_aoclk_saradc_mux = { | |
325 | .data = &(struct clk_regmap_mux_data) { | |
326 | .offset = AO_SAR_CLK, | |
327 | .mask = 0x3, | |
328 | .shift = 9, | |
329 | }, | |
330 | .hw.init = &(struct clk_init_data){ | |
331 | .name = "g12a_ao_saradc_mux", | |
332 | .ops = &clk_regmap_mux_ops, | |
ba626081 AM |
333 | .parent_data = (const struct clk_parent_data []) { |
334 | { .fw_name = "xtal", }, | |
335 | { .hw = &g12a_aoclk_clk81.hw }, | |
336 | }, | |
042f01bb NA |
337 | .num_parents = 2, |
338 | }, | |
339 | }; | |
340 | ||
341 | static struct clk_regmap g12a_aoclk_saradc_div = { | |
342 | .data = &(struct clk_regmap_div_data) { | |
343 | .offset = AO_SAR_CLK, | |
344 | .shift = 0, | |
345 | .width = 8, | |
346 | }, | |
347 | .hw.init = &(struct clk_init_data){ | |
348 | .name = "g12a_ao_saradc_div", | |
349 | .ops = &clk_regmap_divider_ops, | |
ba626081 AM |
350 | .parent_hws = (const struct clk_hw *[]) { |
351 | &g12a_aoclk_saradc_mux.hw | |
352 | }, | |
042f01bb NA |
353 | .num_parents = 1, |
354 | .flags = CLK_SET_RATE_PARENT, | |
355 | }, | |
356 | }; | |
357 | ||
358 | static struct clk_regmap g12a_aoclk_saradc_gate = { | |
359 | .data = &(struct clk_regmap_gate_data) { | |
360 | .offset = AO_SAR_CLK, | |
361 | .bit_idx = 8, | |
362 | }, | |
363 | .hw.init = &(struct clk_init_data){ | |
364 | .name = "g12a_ao_saradc_gate", | |
365 | .ops = &clk_regmap_gate_ops, | |
ba626081 AM |
366 | .parent_hws = (const struct clk_hw *[]) { |
367 | &g12a_aoclk_saradc_div.hw | |
368 | }, | |
042f01bb NA |
369 | .num_parents = 1, |
370 | .flags = CLK_SET_RATE_PARENT, | |
371 | }, | |
372 | }; | |
373 | ||
374 | static const unsigned int g12a_aoclk_reset[] = { | |
375 | [RESET_AO_IR_IN] = 16, | |
376 | [RESET_AO_UART] = 17, | |
377 | [RESET_AO_I2C_M] = 18, | |
378 | [RESET_AO_I2C_S] = 19, | |
379 | [RESET_AO_SAR_ADC] = 20, | |
380 | [RESET_AO_UART2] = 22, | |
381 | [RESET_AO_IR_OUT] = 23, | |
382 | }; | |
383 | ||
384 | static struct clk_regmap *g12a_aoclk_regmap[] = { | |
385 | &g12a_aoclk_ahb, | |
386 | &g12a_aoclk_ir_in, | |
387 | &g12a_aoclk_i2c_m0, | |
388 | &g12a_aoclk_i2c_s0, | |
389 | &g12a_aoclk_uart, | |
390 | &g12a_aoclk_prod_i2c, | |
391 | &g12a_aoclk_uart2, | |
392 | &g12a_aoclk_ir_out, | |
393 | &g12a_aoclk_saradc, | |
394 | &g12a_aoclk_mailbox, | |
395 | &g12a_aoclk_m3, | |
396 | &g12a_aoclk_ahb_sram, | |
397 | &g12a_aoclk_rti, | |
398 | &g12a_aoclk_m4_fclk, | |
399 | &g12a_aoclk_m4_hclk, | |
400 | &g12a_aoclk_cts_oscin, | |
401 | &g12a_aoclk_32k_by_oscin_pre, | |
402 | &g12a_aoclk_32k_by_oscin_div, | |
403 | &g12a_aoclk_32k_by_oscin_sel, | |
404 | &g12a_aoclk_32k_by_oscin, | |
405 | &g12a_aoclk_cec_pre, | |
406 | &g12a_aoclk_cec_div, | |
407 | &g12a_aoclk_cec_sel, | |
408 | &g12a_aoclk_cec, | |
409 | &g12a_aoclk_cts_rtc_oscin, | |
410 | &g12a_aoclk_clk81, | |
411 | &g12a_aoclk_saradc_mux, | |
412 | &g12a_aoclk_saradc_div, | |
413 | &g12a_aoclk_saradc_gate, | |
414 | }; | |
415 | ||
7e1723fd NA |
416 | static struct clk_hw *g12a_aoclk_hw_clks[] = { |
417 | [CLKID_AO_AHB] = &g12a_aoclk_ahb.hw, | |
418 | [CLKID_AO_IR_IN] = &g12a_aoclk_ir_in.hw, | |
419 | [CLKID_AO_I2C_M0] = &g12a_aoclk_i2c_m0.hw, | |
420 | [CLKID_AO_I2C_S0] = &g12a_aoclk_i2c_s0.hw, | |
421 | [CLKID_AO_UART] = &g12a_aoclk_uart.hw, | |
422 | [CLKID_AO_PROD_I2C] = &g12a_aoclk_prod_i2c.hw, | |
423 | [CLKID_AO_UART2] = &g12a_aoclk_uart2.hw, | |
424 | [CLKID_AO_IR_OUT] = &g12a_aoclk_ir_out.hw, | |
425 | [CLKID_AO_SAR_ADC] = &g12a_aoclk_saradc.hw, | |
426 | [CLKID_AO_MAILBOX] = &g12a_aoclk_mailbox.hw, | |
427 | [CLKID_AO_M3] = &g12a_aoclk_m3.hw, | |
428 | [CLKID_AO_AHB_SRAM] = &g12a_aoclk_ahb_sram.hw, | |
429 | [CLKID_AO_RTI] = &g12a_aoclk_rti.hw, | |
430 | [CLKID_AO_M4_FCLK] = &g12a_aoclk_m4_fclk.hw, | |
431 | [CLKID_AO_M4_HCLK] = &g12a_aoclk_m4_hclk.hw, | |
432 | [CLKID_AO_CLK81] = &g12a_aoclk_clk81.hw, | |
433 | [CLKID_AO_SAR_ADC_SEL] = &g12a_aoclk_saradc_mux.hw, | |
434 | [CLKID_AO_SAR_ADC_DIV] = &g12a_aoclk_saradc_div.hw, | |
435 | [CLKID_AO_SAR_ADC_CLK] = &g12a_aoclk_saradc_gate.hw, | |
436 | [CLKID_AO_CTS_OSCIN] = &g12a_aoclk_cts_oscin.hw, | |
437 | [CLKID_AO_32K_PRE] = &g12a_aoclk_32k_by_oscin_pre.hw, | |
438 | [CLKID_AO_32K_DIV] = &g12a_aoclk_32k_by_oscin_div.hw, | |
439 | [CLKID_AO_32K_SEL] = &g12a_aoclk_32k_by_oscin_sel.hw, | |
440 | [CLKID_AO_32K] = &g12a_aoclk_32k_by_oscin.hw, | |
441 | [CLKID_AO_CEC_PRE] = &g12a_aoclk_cec_pre.hw, | |
442 | [CLKID_AO_CEC_DIV] = &g12a_aoclk_cec_div.hw, | |
443 | [CLKID_AO_CEC_SEL] = &g12a_aoclk_cec_sel.hw, | |
444 | [CLKID_AO_CEC] = &g12a_aoclk_cec.hw, | |
445 | [CLKID_AO_CTS_RTC_OSCIN] = &g12a_aoclk_cts_rtc_oscin.hw, | |
042f01bb NA |
446 | }; |
447 | ||
042f01bb NA |
448 | static const struct meson_aoclk_data g12a_aoclkc_data = { |
449 | .reset_reg = AO_RTI_GEN_CNTL_REG0, | |
450 | .num_reset = ARRAY_SIZE(g12a_aoclk_reset), | |
451 | .reset = g12a_aoclk_reset, | |
452 | .num_clks = ARRAY_SIZE(g12a_aoclk_regmap), | |
453 | .clks = g12a_aoclk_regmap, | |
7e1723fd NA |
454 | .hw_clks = { |
455 | .hws = g12a_aoclk_hw_clks, | |
456 | .num = ARRAY_SIZE(g12a_aoclk_hw_clks), | |
457 | }, | |
042f01bb NA |
458 | }; |
459 | ||
460 | static const struct of_device_id g12a_aoclkc_match_table[] = { | |
461 | { | |
462 | .compatible = "amlogic,meson-g12a-aoclkc", | |
463 | .data = &g12a_aoclkc_data, | |
464 | }, | |
465 | { } | |
466 | }; | |
20425f63 | 467 | MODULE_DEVICE_TABLE(of, g12a_aoclkc_match_table); |
042f01bb NA |
468 | |
469 | static struct platform_driver g12a_aoclkc_driver = { | |
470 | .probe = meson_aoclkc_probe, | |
471 | .driver = { | |
472 | .name = "g12a-aoclkc", | |
473 | .of_match_table = g12a_aoclkc_match_table, | |
474 | }, | |
475 | }; | |
20425f63 | 476 | module_platform_driver(g12a_aoclkc_driver); |
befe8738 JB |
477 | |
478 | MODULE_DESCRIPTION("Amlogic G12A Always-ON Clock Controller driver"); | |
e0892cb4 | 479 | MODULE_LICENSE("GPL"); |