aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/meson
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/meson')
-rw-r--r--drivers/clk/meson/Kconfig9
-rw-r--r--drivers/clk/meson/Makefile5
-rw-r--r--drivers/clk/meson/axg.c955
-rw-r--r--drivers/clk/meson/axg.h12
-rw-r--r--drivers/clk/meson/clk-audio-divider.c63
-rw-r--r--drivers/clk/meson/clk-cpu.c178
-rw-r--r--drivers/clk/meson/clk-mpll.c125
-rw-r--r--drivers/clk/meson/clk-pll.c306
-rw-r--r--drivers/clk/meson/clk-regmap.c166
-rw-r--r--drivers/clk/meson/clk-regmap.h111
-rw-r--r--drivers/clk/meson/clkc.h107
-rw-r--r--drivers/clk/meson/gxbb-aoclk-regmap.c46
-rw-r--r--drivers/clk/meson/gxbb-aoclk.c20
-rw-r--r--drivers/clk/meson/gxbb-aoclk.h11
-rw-r--r--drivers/clk/meson/gxbb.c1591
-rw-r--r--drivers/clk/meson/gxbb.h14
-rw-r--r--drivers/clk/meson/meson8b.c705
-rw-r--r--drivers/clk/meson/meson8b.h17
18 files changed, 2458 insertions, 1983 deletions
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 7694302c70a4..d5cbec522aec 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -3,10 +3,15 @@ config COMMON_CLK_AMLOGIC
3 depends on OF 3 depends on OF
4 depends on ARCH_MESON || COMPILE_TEST 4 depends on ARCH_MESON || COMPILE_TEST
5 5
6config COMMON_CLK_REGMAP_MESON
7 bool
8 select REGMAP
9
6config COMMON_CLK_MESON8B 10config COMMON_CLK_MESON8B
7 bool 11 bool
8 depends on COMMON_CLK_AMLOGIC 12 depends on COMMON_CLK_AMLOGIC
9 select RESET_CONTROLLER 13 select RESET_CONTROLLER
14 select COMMON_CLK_REGMAP_MESON
10 help 15 help
11 Support for the clock controller on AmLogic S802 (Meson8), 16 Support for the clock controller on AmLogic S802 (Meson8),
12 S805 (Meson8b) and S812 (Meson8m2) devices. Say Y if you 17 S805 (Meson8b) and S812 (Meson8m2) devices. Say Y if you
@@ -16,6 +21,8 @@ config COMMON_CLK_GXBB
16 bool 21 bool
17 depends on COMMON_CLK_AMLOGIC 22 depends on COMMON_CLK_AMLOGIC
18 select RESET_CONTROLLER 23 select RESET_CONTROLLER
24 select COMMON_CLK_REGMAP_MESON
25 select MFD_SYSCON
19 help 26 help
20 Support for the clock controller on AmLogic S905 devices, aka gxbb. 27 Support for the clock controller on AmLogic S905 devices, aka gxbb.
21 Say Y if you want peripherals and CPU frequency scaling to work. 28 Say Y if you want peripherals and CPU frequency scaling to work.
@@ -24,6 +31,8 @@ config COMMON_CLK_AXG
24 bool 31 bool
25 depends on COMMON_CLK_AMLOGIC 32 depends on COMMON_CLK_AMLOGIC
26 select RESET_CONTROLLER 33 select RESET_CONTROLLER
34 select COMMON_CLK_REGMAP_MESON
35 select MFD_SYSCON
27 help 36 help
28 Support for the clock controller on AmLogic A113D devices, aka axg. 37 Support for the clock controller on AmLogic A113D devices, aka axg.
29 Say Y if you want peripherals and CPU frequency scaling to work. 38 Say Y if you want peripherals and CPU frequency scaling to work.
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 3c03ce583798..ffee82e60b7a 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -2,7 +2,8 @@
2# Makefile for Meson specific clk 2# Makefile for Meson specific clk
3# 3#
4 4
5obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o 5obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-audio-divider.o
6obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o 6obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
7obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-regmap.o gxbb-aoclk-32k.o 7obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-32k.o
8obj-$(CONFIG_COMMON_CLK_AXG) += axg.o 8obj-$(CONFIG_COMMON_CLK_AXG) += axg.o
9obj-$(CONFIG_COMMON_CLK_REGMAP_MESON) += clk-regmap.o
diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 1294f3ad7cd5..5f5d468c1efe 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -11,125 +11,51 @@
11 11
12#include <linux/clk.h> 12#include <linux/clk.h>
13#include <linux/clk-provider.h> 13#include <linux/clk-provider.h>
14#include <linux/init.h>
14#include <linux/of_address.h> 15#include <linux/of_address.h>
15#include <linux/of_device.h> 16#include <linux/of_device.h>
17#include <linux/mfd/syscon.h>
16#include <linux/platform_device.h> 18#include <linux/platform_device.h>
17#include <linux/init.h> 19#include <linux/regmap.h>
18 20
19#include "clkc.h" 21#include "clkc.h"
20#include "axg.h" 22#include "axg.h"
21 23
22static DEFINE_SPINLOCK(meson_clk_lock); 24static DEFINE_SPINLOCK(meson_clk_lock);
23 25
24static const struct pll_rate_table sys_pll_rate_table[] = { 26static struct clk_regmap axg_fixed_pll = {
25 PLL_RATE(24000000, 56, 1, 2), 27 .data = &(struct meson_clk_pll_data){
26 PLL_RATE(48000000, 64, 1, 2), 28 .m = {
27 PLL_RATE(72000000, 72, 1, 2), 29 .reg_off = HHI_MPLL_CNTL,
28 PLL_RATE(96000000, 64, 1, 2), 30 .shift = 0,
29 PLL_RATE(120000000, 80, 1, 2), 31 .width = 9,
30 PLL_RATE(144000000, 96, 1, 2), 32 },
31 PLL_RATE(168000000, 56, 1, 1), 33 .n = {
32 PLL_RATE(192000000, 64, 1, 1), 34 .reg_off = HHI_MPLL_CNTL,
33 PLL_RATE(216000000, 72, 1, 1), 35 .shift = 9,
34 PLL_RATE(240000000, 80, 1, 1), 36 .width = 5,
35 PLL_RATE(264000000, 88, 1, 1), 37 },
36 PLL_RATE(288000000, 96, 1, 1), 38 .od = {
37 PLL_RATE(312000000, 52, 1, 2), 39 .reg_off = HHI_MPLL_CNTL,
38 PLL_RATE(336000000, 56, 1, 2), 40 .shift = 16,
39 PLL_RATE(360000000, 60, 1, 2), 41 .width = 2,
40 PLL_RATE(384000000, 64, 1, 2), 42 },
41 PLL_RATE(408000000, 68, 1, 2), 43 .frac = {
42 PLL_RATE(432000000, 72, 1, 2), 44 .reg_off = HHI_MPLL_CNTL2,
43 PLL_RATE(456000000, 76, 1, 2), 45 .shift = 0,
44 PLL_RATE(480000000, 80, 1, 2), 46 .width = 12,
45 PLL_RATE(504000000, 84, 1, 2), 47 },
46 PLL_RATE(528000000, 88, 1, 2), 48 .l = {
47 PLL_RATE(552000000, 92, 1, 2), 49 .reg_off = HHI_MPLL_CNTL,
48 PLL_RATE(576000000, 96, 1, 2), 50 .shift = 31,
49 PLL_RATE(600000000, 50, 1, 1), 51 .width = 1,
50 PLL_RATE(624000000, 52, 1, 1), 52 },
51 PLL_RATE(648000000, 54, 1, 1), 53 .rst = {
52 PLL_RATE(672000000, 56, 1, 1), 54 .reg_off = HHI_MPLL_CNTL,
53 PLL_RATE(696000000, 58, 1, 1), 55 .shift = 29,
54 PLL_RATE(720000000, 60, 1, 1), 56 .width = 1,
55 PLL_RATE(744000000, 62, 1, 1), 57 },
56 PLL_RATE(768000000, 64, 1, 1),
57 PLL_RATE(792000000, 66, 1, 1),
58 PLL_RATE(816000000, 68, 1, 1),
59 PLL_RATE(840000000, 70, 1, 1),
60 PLL_RATE(864000000, 72, 1, 1),
61 PLL_RATE(888000000, 74, 1, 1),
62 PLL_RATE(912000000, 76, 1, 1),
63 PLL_RATE(936000000, 78, 1, 1),
64 PLL_RATE(960000000, 80, 1, 1),
65 PLL_RATE(984000000, 82, 1, 1),
66 PLL_RATE(1008000000, 84, 1, 1),
67 PLL_RATE(1032000000, 86, 1, 1),
68 PLL_RATE(1056000000, 88, 1, 1),
69 PLL_RATE(1080000000, 90, 1, 1),
70 PLL_RATE(1104000000, 92, 1, 1),
71 PLL_RATE(1128000000, 94, 1, 1),
72 PLL_RATE(1152000000, 96, 1, 1),
73 PLL_RATE(1176000000, 98, 1, 1),
74 PLL_RATE(1200000000, 50, 1, 0),
75 PLL_RATE(1224000000, 51, 1, 0),
76 PLL_RATE(1248000000, 52, 1, 0),
77 PLL_RATE(1272000000, 53, 1, 0),
78 PLL_RATE(1296000000, 54, 1, 0),
79 PLL_RATE(1320000000, 55, 1, 0),
80 PLL_RATE(1344000000, 56, 1, 0),
81 PLL_RATE(1368000000, 57, 1, 0),
82 PLL_RATE(1392000000, 58, 1, 0),
83 PLL_RATE(1416000000, 59, 1, 0),
84 PLL_RATE(1440000000, 60, 1, 0),
85 PLL_RATE(1464000000, 61, 1, 0),
86 PLL_RATE(1488000000, 62, 1, 0),
87 PLL_RATE(1512000000, 63, 1, 0),
88 PLL_RATE(1536000000, 64, 1, 0),
89 PLL_RATE(1560000000, 65, 1, 0),
90 PLL_RATE(1584000000, 66, 1, 0),
91 PLL_RATE(1608000000, 67, 1, 0),
92 PLL_RATE(1632000000, 68, 1, 0),
93 PLL_RATE(1656000000, 68, 1, 0),
94 PLL_RATE(1680000000, 68, 1, 0),
95 PLL_RATE(1704000000, 68, 1, 0),
96 PLL_RATE(1728000000, 69, 1, 0),
97 PLL_RATE(1752000000, 69, 1, 0),
98 PLL_RATE(1776000000, 69, 1, 0),
99 PLL_RATE(1800000000, 69, 1, 0),
100 PLL_RATE(1824000000, 70, 1, 0),
101 PLL_RATE(1848000000, 70, 1, 0),
102 PLL_RATE(1872000000, 70, 1, 0),
103 PLL_RATE(1896000000, 70, 1, 0),
104 PLL_RATE(1920000000, 71, 1, 0),
105 PLL_RATE(1944000000, 71, 1, 0),
106 PLL_RATE(1968000000, 71, 1, 0),
107 PLL_RATE(1992000000, 71, 1, 0),
108 PLL_RATE(2016000000, 72, 1, 0),
109 PLL_RATE(2040000000, 72, 1, 0),
110 PLL_RATE(2064000000, 72, 1, 0),
111 PLL_RATE(2088000000, 72, 1, 0),
112 PLL_RATE(2112000000, 73, 1, 0),
113 { /* sentinel */ },
114};
115
116static struct meson_clk_pll axg_fixed_pll = {
117 .m = {
118 .reg_off = HHI_MPLL_CNTL,
119 .shift = 0,
120 .width = 9,
121 },
122 .n = {
123 .reg_off = HHI_MPLL_CNTL,
124 .shift = 9,
125 .width = 5,
126 },
127 .od = {
128 .reg_off = HHI_MPLL_CNTL,
129 .shift = 16,
130 .width = 2,
131 }, 58 },
132 .lock = &meson_clk_lock,
133 .hw.init = &(struct clk_init_data){ 59 .hw.init = &(struct clk_init_data){
134 .name = "fixed_pll", 60 .name = "fixed_pll",
135 .ops = &meson_clk_pll_ro_ops, 61 .ops = &meson_clk_pll_ro_ops,
@@ -138,25 +64,34 @@ static struct meson_clk_pll axg_fixed_pll = {
138 }, 64 },
139}; 65};
140 66
141static struct meson_clk_pll axg_sys_pll = { 67static struct clk_regmap axg_sys_pll = {
142 .m = { 68 .data = &(struct meson_clk_pll_data){
143 .reg_off = HHI_SYS_PLL_CNTL, 69 .m = {
144 .shift = 0, 70 .reg_off = HHI_SYS_PLL_CNTL,
145 .width = 9, 71 .shift = 0,
72 .width = 9,
73 },
74 .n = {
75 .reg_off = HHI_SYS_PLL_CNTL,
76 .shift = 9,
77 .width = 5,
78 },
79 .od = {
80 .reg_off = HHI_SYS_PLL_CNTL,
81 .shift = 16,
82 .width = 2,
83 },
84 .l = {
85 .reg_off = HHI_SYS_PLL_CNTL,
86 .shift = 31,
87 .width = 1,
88 },
89 .rst = {
90 .reg_off = HHI_SYS_PLL_CNTL,
91 .shift = 29,
92 .width = 1,
93 },
146 }, 94 },
147 .n = {
148 .reg_off = HHI_SYS_PLL_CNTL,
149 .shift = 9,
150 .width = 5,
151 },
152 .od = {
153 .reg_off = HHI_SYS_PLL_CNTL,
154 .shift = 10,
155 .width = 2,
156 },
157 .rate_table = sys_pll_rate_table,
158 .rate_count = ARRAY_SIZE(sys_pll_rate_table),
159 .lock = &meson_clk_lock,
160 .hw.init = &(struct clk_init_data){ 95 .hw.init = &(struct clk_init_data){
161 .name = "sys_pll", 96 .name = "sys_pll",
162 .ops = &meson_clk_pll_ro_ops, 97 .ops = &meson_clk_pll_ro_ops,
@@ -257,40 +192,51 @@ static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
257 { /* sentinel */ }, 192 { /* sentinel */ },
258}; 193};
259 194
260static struct pll_params_table axg_gp0_params_table[] = { 195static const struct reg_sequence axg_gp0_init_regs[] = {
261 PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250), 196 { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084b000 },
262 PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000), 197 { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be },
263 PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be), 198 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
264 PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288), 199 { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
265 PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d), 200 { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
266 PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000), 201 { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
267}; 202};
268 203
269static struct meson_clk_pll axg_gp0_pll = { 204static struct clk_regmap axg_gp0_pll = {
270 .m = { 205 .data = &(struct meson_clk_pll_data){
271 .reg_off = HHI_GP0_PLL_CNTL, 206 .m = {
272 .shift = 0, 207 .reg_off = HHI_GP0_PLL_CNTL,
273 .width = 9, 208 .shift = 0,
274 }, 209 .width = 9,
275 .n = { 210 },
276 .reg_off = HHI_GP0_PLL_CNTL, 211 .n = {
277 .shift = 9, 212 .reg_off = HHI_GP0_PLL_CNTL,
278 .width = 5, 213 .shift = 9,
279 }, 214 .width = 5,
280 .od = { 215 },
281 .reg_off = HHI_GP0_PLL_CNTL, 216 .od = {
282 .shift = 16, 217 .reg_off = HHI_GP0_PLL_CNTL,
283 .width = 2, 218 .shift = 16,
284 }, 219 .width = 2,
285 .params = { 220 },
286 .params_table = axg_gp0_params_table, 221 .frac = {
287 .params_count = ARRAY_SIZE(axg_gp0_params_table), 222 .reg_off = HHI_GP0_PLL_CNTL1,
288 .no_init_reset = true, 223 .shift = 0,
289 .reset_lock_loop = true, 224 .width = 10,
290 }, 225 },
291 .rate_table = axg_gp0_pll_rate_table, 226 .l = {
292 .rate_count = ARRAY_SIZE(axg_gp0_pll_rate_table), 227 .reg_off = HHI_GP0_PLL_CNTL,
293 .lock = &meson_clk_lock, 228 .shift = 31,
229 .width = 1,
230 },
231 .rst = {
232 .reg_off = HHI_GP0_PLL_CNTL,
233 .shift = 29,
234 .width = 1,
235 },
236 .table = axg_gp0_pll_rate_table,
237 .init_regs = axg_gp0_init_regs,
238 .init_count = ARRAY_SIZE(axg_gp0_init_regs),
239 },
294 .hw.init = &(struct clk_init_data){ 240 .hw.init = &(struct clk_init_data){
295 .name = "gp0_pll", 241 .name = "gp0_pll",
296 .ops = &meson_clk_pll_ops, 242 .ops = &meson_clk_pll_ops,
@@ -299,234 +245,427 @@ static struct meson_clk_pll axg_gp0_pll = {
299 }, 245 },
300}; 246};
301 247
248static const struct reg_sequence axg_hifi_init_regs[] = {
249 { .reg = HHI_HIFI_PLL_CNTL1, .def = 0xc084b000 },
250 { .reg = HHI_HIFI_PLL_CNTL2, .def = 0xb75020be },
251 { .reg = HHI_HIFI_PLL_CNTL3, .def = 0x0a6a3a88 },
252 { .reg = HHI_HIFI_PLL_CNTL4, .def = 0xc000004d },
253 { .reg = HHI_HIFI_PLL_CNTL5, .def = 0x00058000 },
254 { .reg = HHI_HIFI_PLL_CNTL, .def = 0x40010250 },
255};
256
257static struct clk_regmap axg_hifi_pll = {
258 .data = &(struct meson_clk_pll_data){
259 .m = {
260 .reg_off = HHI_HIFI_PLL_CNTL,
261 .shift = 0,
262 .width = 9,
263 },
264 .n = {
265 .reg_off = HHI_HIFI_PLL_CNTL,
266 .shift = 9,
267 .width = 5,
268 },
269 .od = {
270 .reg_off = HHI_HIFI_PLL_CNTL,
271 .shift = 16,
272 .width = 2,
273 },
274 .frac = {
275 .reg_off = HHI_HIFI_PLL_CNTL5,
276 .shift = 0,
277 .width = 13,
278 },
279 .l = {
280 .reg_off = HHI_HIFI_PLL_CNTL,
281 .shift = 31,
282 .width = 1,
283 },
284 .rst = {
285 .reg_off = HHI_HIFI_PLL_CNTL,
286 .shift = 29,
287 .width = 1,
288 },
289 .table = axg_gp0_pll_rate_table,
290 .init_regs = axg_hifi_init_regs,
291 .init_count = ARRAY_SIZE(axg_hifi_init_regs),
292 .flags = CLK_MESON_PLL_ROUND_CLOSEST,
293 },
294 .hw.init = &(struct clk_init_data){
295 .name = "hifi_pll",
296 .ops = &meson_clk_pll_ops,
297 .parent_names = (const char *[]){ "xtal" },
298 .num_parents = 1,
299 },
300};
302 301
303static struct clk_fixed_factor axg_fclk_div2 = { 302static struct clk_fixed_factor axg_fclk_div2_div = {
304 .mult = 1, 303 .mult = 1,
305 .div = 2, 304 .div = 2,
306 .hw.init = &(struct clk_init_data){ 305 .hw.init = &(struct clk_init_data){
307 .name = "fclk_div2", 306 .name = "fclk_div2_div",
308 .ops = &clk_fixed_factor_ops, 307 .ops = &clk_fixed_factor_ops,
309 .parent_names = (const char *[]){ "fixed_pll" }, 308 .parent_names = (const char *[]){ "fixed_pll" },
310 .num_parents = 1, 309 .num_parents = 1,
311 }, 310 },
312}; 311};
313 312
314static struct clk_fixed_factor axg_fclk_div3 = { 313static struct clk_regmap axg_fclk_div2 = {
314 .data = &(struct clk_regmap_gate_data){
315 .offset = HHI_MPLL_CNTL6,
316 .bit_idx = 27,
317 },
318 .hw.init = &(struct clk_init_data){
319 .name = "fclk_div2",
320 .ops = &clk_regmap_gate_ops,
321 .parent_names = (const char *[]){ "fclk_div2_div" },
322 .num_parents = 1,
323 },
324};
325
326static struct clk_fixed_factor axg_fclk_div3_div = {
315 .mult = 1, 327 .mult = 1,
316 .div = 3, 328 .div = 3,
317 .hw.init = &(struct clk_init_data){ 329 .hw.init = &(struct clk_init_data){
318 .name = "fclk_div3", 330 .name = "fclk_div3_div",
319 .ops = &clk_fixed_factor_ops, 331 .ops = &clk_fixed_factor_ops,
320 .parent_names = (const char *[]){ "fixed_pll" }, 332 .parent_names = (const char *[]){ "fixed_pll" },
321 .num_parents = 1, 333 .num_parents = 1,
322 }, 334 },
323}; 335};
324 336
325static struct clk_fixed_factor axg_fclk_div4 = { 337static struct clk_regmap axg_fclk_div3 = {
338 .data = &(struct clk_regmap_gate_data){
339 .offset = HHI_MPLL_CNTL6,
340 .bit_idx = 28,
341 },
342 .hw.init = &(struct clk_init_data){
343 .name = "fclk_div3",
344 .ops = &clk_regmap_gate_ops,
345 .parent_names = (const char *[]){ "fclk_div3_div" },
346 .num_parents = 1,
347 },
348};
349
350static struct clk_fixed_factor axg_fclk_div4_div = {
326 .mult = 1, 351 .mult = 1,
327 .div = 4, 352 .div = 4,
328 .hw.init = &(struct clk_init_data){ 353 .hw.init = &(struct clk_init_data){
329 .name = "fclk_div4", 354 .name = "fclk_div4_div",
330 .ops = &clk_fixed_factor_ops, 355 .ops = &clk_fixed_factor_ops,
331 .parent_names = (const char *[]){ "fixed_pll" }, 356 .parent_names = (const char *[]){ "fixed_pll" },
332 .num_parents = 1, 357 .num_parents = 1,
333 }, 358 },
334}; 359};
335 360
336static struct clk_fixed_factor axg_fclk_div5 = { 361static struct clk_regmap axg_fclk_div4 = {
362 .data = &(struct clk_regmap_gate_data){
363 .offset = HHI_MPLL_CNTL6,
364 .bit_idx = 29,
365 },
366 .hw.init = &(struct clk_init_data){
367 .name = "fclk_div4",
368 .ops = &clk_regmap_gate_ops,
369 .parent_names = (const char *[]){ "fclk_div4_div" },
370 .num_parents = 1,
371 },
372};
373
374static struct clk_fixed_factor axg_fclk_div5_div = {
337 .mult = 1, 375 .mult = 1,
338 .div = 5, 376 .div = 5,
339 .hw.init = &(struct clk_init_data){ 377 .hw.init = &(struct clk_init_data){
340 .name = "fclk_div5", 378 .name = "fclk_div5_div",
341 .ops = &clk_fixed_factor_ops, 379 .ops = &clk_fixed_factor_ops,
342 .parent_names = (const char *[]){ "fixed_pll" }, 380 .parent_names = (const char *[]){ "fixed_pll" },
343 .num_parents = 1, 381 .num_parents = 1,
344 }, 382 },
345}; 383};
346 384
347static struct clk_fixed_factor axg_fclk_div7 = { 385static struct clk_regmap axg_fclk_div5 = {
386 .data = &(struct clk_regmap_gate_data){
387 .offset = HHI_MPLL_CNTL6,
388 .bit_idx = 30,
389 },
390 .hw.init = &(struct clk_init_data){
391 .name = "fclk_div5",
392 .ops = &clk_regmap_gate_ops,
393 .parent_names = (const char *[]){ "fclk_div5_div" },
394 .num_parents = 1,
395 },
396};
397
398static struct clk_fixed_factor axg_fclk_div7_div = {
348 .mult = 1, 399 .mult = 1,
349 .div = 7, 400 .div = 7,
350 .hw.init = &(struct clk_init_data){ 401 .hw.init = &(struct clk_init_data){
351 .name = "fclk_div7", 402 .name = "fclk_div7_div",
352 .ops = &clk_fixed_factor_ops, 403 .ops = &clk_fixed_factor_ops,
353 .parent_names = (const char *[]){ "fixed_pll" }, 404 .parent_names = (const char *[]){ "fixed_pll" },
354 .num_parents = 1, 405 .num_parents = 1,
355 }, 406 },
356}; 407};
357 408
358static struct meson_clk_mpll axg_mpll0 = { 409static struct clk_regmap axg_fclk_div7 = {
359 .sdm = { 410 .data = &(struct clk_regmap_gate_data){
360 .reg_off = HHI_MPLL_CNTL7, 411 .offset = HHI_MPLL_CNTL6,
361 .shift = 0, 412 .bit_idx = 31,
362 .width = 14,
363 }, 413 },
364 .sdm_en = { 414 .hw.init = &(struct clk_init_data){
365 .reg_off = HHI_MPLL_CNTL7, 415 .name = "fclk_div7",
366 .shift = 15, 416 .ops = &clk_regmap_gate_ops,
367 .width = 1, 417 .parent_names = (const char *[]){ "fclk_div7_div" },
418 .num_parents = 1,
368 }, 419 },
369 .n2 = { 420};
370 .reg_off = HHI_MPLL_CNTL7, 421
371 .shift = 16, 422static struct clk_regmap axg_mpll_prediv = {
372 .width = 9, 423 .data = &(struct clk_regmap_div_data){
424 .offset = HHI_MPLL_CNTL5,
425 .shift = 12,
426 .width = 1,
373 }, 427 },
374 .en = { 428 .hw.init = &(struct clk_init_data){
375 .reg_off = HHI_MPLL_CNTL7, 429 .name = "mpll_prediv",
376 .shift = 14, 430 .ops = &clk_regmap_divider_ro_ops,
377 .width = 1, 431 .parent_names = (const char *[]){ "fixed_pll" },
432 .num_parents = 1,
378 }, 433 },
379 .ssen = { 434};
380 .reg_off = HHI_MPLL_CNTL, 435
381 .shift = 25, 436static struct clk_regmap axg_mpll0_div = {
382 .width = 1, 437 .data = &(struct meson_clk_mpll_data){
438 .sdm = {
439 .reg_off = HHI_MPLL_CNTL7,
440 .shift = 0,
441 .width = 14,
442 },
443 .sdm_en = {
444 .reg_off = HHI_MPLL_CNTL7,
445 .shift = 15,
446 .width = 1,
447 },
448 .n2 = {
449 .reg_off = HHI_MPLL_CNTL7,
450 .shift = 16,
451 .width = 9,
452 },
453 .ssen = {
454 .reg_off = HHI_MPLL_CNTL,
455 .shift = 25,
456 .width = 1,
457 },
458 .misc = {
459 .reg_off = HHI_PLL_TOP_MISC,
460 .shift = 0,
461 .width = 1,
462 },
463 .lock = &meson_clk_lock,
383 }, 464 },
384 .lock = &meson_clk_lock,
385 .hw.init = &(struct clk_init_data){ 465 .hw.init = &(struct clk_init_data){
386 .name = "mpll0", 466 .name = "mpll0_div",
387 .ops = &meson_clk_mpll_ops, 467 .ops = &meson_clk_mpll_ops,
388 .parent_names = (const char *[]){ "fixed_pll" }, 468 .parent_names = (const char *[]){ "mpll_prediv" },
389 .num_parents = 1, 469 .num_parents = 1,
390 }, 470 },
391}; 471};
392 472
393static struct meson_clk_mpll axg_mpll1 = { 473static struct clk_regmap axg_mpll0 = {
394 .sdm = { 474 .data = &(struct clk_regmap_gate_data){
395 .reg_off = HHI_MPLL_CNTL8, 475 .offset = HHI_MPLL_CNTL7,
396 .shift = 0, 476 .bit_idx = 14,
397 .width = 14,
398 }, 477 },
399 .sdm_en = { 478 .hw.init = &(struct clk_init_data){
400 .reg_off = HHI_MPLL_CNTL8, 479 .name = "mpll0",
401 .shift = 15, 480 .ops = &clk_regmap_gate_ops,
402 .width = 1, 481 .parent_names = (const char *[]){ "mpll0_div" },
403 }, 482 .num_parents = 1,
404 .n2 = { 483 .flags = CLK_SET_RATE_PARENT,
405 .reg_off = HHI_MPLL_CNTL8,
406 .shift = 16,
407 .width = 9,
408 }, 484 },
409 .en = { 485};
410 .reg_off = HHI_MPLL_CNTL8, 486
411 .shift = 14, 487static struct clk_regmap axg_mpll1_div = {
412 .width = 1, 488 .data = &(struct meson_clk_mpll_data){
489 .sdm = {
490 .reg_off = HHI_MPLL_CNTL8,
491 .shift = 0,
492 .width = 14,
493 },
494 .sdm_en = {
495 .reg_off = HHI_MPLL_CNTL8,
496 .shift = 15,
497 .width = 1,
498 },
499 .n2 = {
500 .reg_off = HHI_MPLL_CNTL8,
501 .shift = 16,
502 .width = 9,
503 },
504 .misc = {
505 .reg_off = HHI_PLL_TOP_MISC,
506 .shift = 1,
507 .width = 1,
508 },
509 .lock = &meson_clk_lock,
413 }, 510 },
414 .lock = &meson_clk_lock,
415 .hw.init = &(struct clk_init_data){ 511 .hw.init = &(struct clk_init_data){
416 .name = "mpll1", 512 .name = "mpll1_div",
417 .ops = &meson_clk_mpll_ops, 513 .ops = &meson_clk_mpll_ops,
418 .parent_names = (const char *[]){ "fixed_pll" }, 514 .parent_names = (const char *[]){ "mpll_prediv" },
419 .num_parents = 1, 515 .num_parents = 1,
420 }, 516 },
421}; 517};
422 518
423static struct meson_clk_mpll axg_mpll2 = { 519static struct clk_regmap axg_mpll1 = {
424 .sdm = { 520 .data = &(struct clk_regmap_gate_data){
425 .reg_off = HHI_MPLL_CNTL9, 521 .offset = HHI_MPLL_CNTL8,
426 .shift = 0, 522 .bit_idx = 14,
427 .width = 14,
428 }, 523 },
429 .sdm_en = { 524 .hw.init = &(struct clk_init_data){
430 .reg_off = HHI_MPLL_CNTL9, 525 .name = "mpll1",
431 .shift = 15, 526 .ops = &clk_regmap_gate_ops,
432 .width = 1, 527 .parent_names = (const char *[]){ "mpll1_div" },
433 }, 528 .num_parents = 1,
434 .n2 = { 529 .flags = CLK_SET_RATE_PARENT,
435 .reg_off = HHI_MPLL_CNTL9,
436 .shift = 16,
437 .width = 9,
438 }, 530 },
439 .en = { 531};
440 .reg_off = HHI_MPLL_CNTL9, 532
441 .shift = 14, 533static struct clk_regmap axg_mpll2_div = {
442 .width = 1, 534 .data = &(struct meson_clk_mpll_data){
535 .sdm = {
536 .reg_off = HHI_MPLL_CNTL9,
537 .shift = 0,
538 .width = 14,
539 },
540 .sdm_en = {
541 .reg_off = HHI_MPLL_CNTL9,
542 .shift = 15,
543 .width = 1,
544 },
545 .n2 = {
546 .reg_off = HHI_MPLL_CNTL9,
547 .shift = 16,
548 .width = 9,
549 },
550 .misc = {
551 .reg_off = HHI_PLL_TOP_MISC,
552 .shift = 2,
553 .width = 1,
554 },
555 .lock = &meson_clk_lock,
443 }, 556 },
444 .lock = &meson_clk_lock,
445 .hw.init = &(struct clk_init_data){ 557 .hw.init = &(struct clk_init_data){
446 .name = "mpll2", 558 .name = "mpll2_div",
447 .ops = &meson_clk_mpll_ops, 559 .ops = &meson_clk_mpll_ops,
448 .parent_names = (const char *[]){ "fixed_pll" }, 560 .parent_names = (const char *[]){ "mpll_prediv" },
449 .num_parents = 1, 561 .num_parents = 1,
450 }, 562 },
451}; 563};
452 564
453static struct meson_clk_mpll axg_mpll3 = { 565static struct clk_regmap axg_mpll2 = {
454 .sdm = { 566 .data = &(struct clk_regmap_gate_data){
455 .reg_off = HHI_MPLL3_CNTL0, 567 .offset = HHI_MPLL_CNTL9,
456 .shift = 12, 568 .bit_idx = 14,
457 .width = 14,
458 }, 569 },
459 .sdm_en = { 570 .hw.init = &(struct clk_init_data){
460 .reg_off = HHI_MPLL3_CNTL0, 571 .name = "mpll2",
461 .shift = 11, 572 .ops = &clk_regmap_gate_ops,
462 .width = 1, 573 .parent_names = (const char *[]){ "mpll2_div" },
574 .num_parents = 1,
575 .flags = CLK_SET_RATE_PARENT,
576 },
577};
578
579static struct clk_regmap axg_mpll3_div = {
580 .data = &(struct meson_clk_mpll_data){
581 .sdm = {
582 .reg_off = HHI_MPLL3_CNTL0,
583 .shift = 12,
584 .width = 14,
585 },
586 .sdm_en = {
587 .reg_off = HHI_MPLL3_CNTL0,
588 .shift = 11,
589 .width = 1,
590 },
591 .n2 = {
592 .reg_off = HHI_MPLL3_CNTL0,
593 .shift = 2,
594 .width = 9,
595 },
596 .misc = {
597 .reg_off = HHI_PLL_TOP_MISC,
598 .shift = 3,
599 .width = 1,
600 },
601 .lock = &meson_clk_lock,
463 }, 602 },
464 .n2 = { 603 .hw.init = &(struct clk_init_data){
465 .reg_off = HHI_MPLL3_CNTL0, 604 .name = "mpll3_div",
466 .shift = 2, 605 .ops = &meson_clk_mpll_ops,
467 .width = 9, 606 .parent_names = (const char *[]){ "mpll_prediv" },
607 .num_parents = 1,
468 }, 608 },
469 .en = { 609};
470 .reg_off = HHI_MPLL3_CNTL0, 610
471 .shift = 0, 611static struct clk_regmap axg_mpll3 = {
472 .width = 1, 612 .data = &(struct clk_regmap_gate_data){
613 .offset = HHI_MPLL3_CNTL0,
614 .bit_idx = 0,
473 }, 615 },
474 .lock = &meson_clk_lock,
475 .hw.init = &(struct clk_init_data){ 616 .hw.init = &(struct clk_init_data){
476 .name = "mpll3", 617 .name = "mpll3",
477 .ops = &meson_clk_mpll_ops, 618 .ops = &clk_regmap_gate_ops,
478 .parent_names = (const char *[]){ "fixed_pll" }, 619 .parent_names = (const char *[]){ "mpll3_div" },
479 .num_parents = 1, 620 .num_parents = 1,
621 .flags = CLK_SET_RATE_PARENT,
480 }, 622 },
481}; 623};
482 624
483/*
484 * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers
485 * and should be modeled with their respective PLLs via the forthcoming
486 * coordinated clock rates feature
487 */
488static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; 625static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
489static const char * const clk81_parent_names[] = { 626static const char * const clk81_parent_names[] = {
490 "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4", 627 "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
491 "fclk_div3", "fclk_div5" 628 "fclk_div3", "fclk_div5"
492}; 629};
493 630
494static struct clk_mux axg_mpeg_clk_sel = { 631static struct clk_regmap axg_mpeg_clk_sel = {
495 .reg = (void *)HHI_MPEG_CLK_CNTL, 632 .data = &(struct clk_regmap_mux_data){
496 .mask = 0x7, 633 .offset = HHI_MPEG_CLK_CNTL,
497 .shift = 12, 634 .mask = 0x7,
498 .flags = CLK_MUX_READ_ONLY, 635 .shift = 12,
499 .table = mux_table_clk81, 636 .table = mux_table_clk81,
500 .lock = &meson_clk_lock, 637 },
501 .hw.init = &(struct clk_init_data){ 638 .hw.init = &(struct clk_init_data){
502 .name = "mpeg_clk_sel", 639 .name = "mpeg_clk_sel",
503 .ops = &clk_mux_ro_ops, 640 .ops = &clk_regmap_mux_ro_ops,
504 .parent_names = clk81_parent_names, 641 .parent_names = clk81_parent_names,
505 .num_parents = ARRAY_SIZE(clk81_parent_names), 642 .num_parents = ARRAY_SIZE(clk81_parent_names),
506 }, 643 },
507}; 644};
508 645
509static struct clk_divider axg_mpeg_clk_div = { 646static struct clk_regmap axg_mpeg_clk_div = {
510 .reg = (void *)HHI_MPEG_CLK_CNTL, 647 .data = &(struct clk_regmap_div_data){
511 .shift = 0, 648 .offset = HHI_MPEG_CLK_CNTL,
512 .width = 7, 649 .shift = 0,
513 .lock = &meson_clk_lock, 650 .width = 7,
651 },
514 .hw.init = &(struct clk_init_data){ 652 .hw.init = &(struct clk_init_data){
515 .name = "mpeg_clk_div", 653 .name = "mpeg_clk_div",
516 .ops = &clk_divider_ops, 654 .ops = &clk_regmap_divider_ops,
517 .parent_names = (const char *[]){ "mpeg_clk_sel" }, 655 .parent_names = (const char *[]){ "mpeg_clk_sel" },
518 .num_parents = 1, 656 .num_parents = 1,
519 .flags = CLK_SET_RATE_PARENT, 657 .flags = CLK_SET_RATE_PARENT,
520 }, 658 },
521}; 659};
522 660
523static struct clk_gate axg_clk81 = { 661static struct clk_regmap axg_clk81 = {
524 .reg = (void *)HHI_MPEG_CLK_CNTL, 662 .data = &(struct clk_regmap_gate_data){
525 .bit_idx = 7, 663 .offset = HHI_MPEG_CLK_CNTL,
526 .lock = &meson_clk_lock, 664 .bit_idx = 7,
665 },
527 .hw.init = &(struct clk_init_data){ 666 .hw.init = &(struct clk_init_data){
528 .name = "clk81", 667 .name = "clk81",
529 .ops = &clk_gate_ops, 668 .ops = &clk_regmap_gate_ops,
530 .parent_names = (const char *[]){ "mpeg_clk_div" }, 669 .parent_names = (const char *[]){ "mpeg_clk_div" },
531 .num_parents = 1, 670 .num_parents = 1,
532 .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), 671 .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
@@ -545,42 +684,45 @@ static const char * const axg_sd_emmc_clk0_parent_names[] = {
545}; 684};
546 685
547/* SDcard clock */ 686/* SDcard clock */
548static struct clk_mux axg_sd_emmc_b_clk0_sel = { 687static struct clk_regmap axg_sd_emmc_b_clk0_sel = {
549 .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 688 .data = &(struct clk_regmap_mux_data){
550 .mask = 0x7, 689 .offset = HHI_SD_EMMC_CLK_CNTL,
551 .shift = 25, 690 .mask = 0x7,
552 .lock = &meson_clk_lock, 691 .shift = 25,
692 },
553 .hw.init = &(struct clk_init_data) { 693 .hw.init = &(struct clk_init_data) {
554 .name = "sd_emmc_b_clk0_sel", 694 .name = "sd_emmc_b_clk0_sel",
555 .ops = &clk_mux_ops, 695 .ops = &clk_regmap_mux_ops,
556 .parent_names = axg_sd_emmc_clk0_parent_names, 696 .parent_names = axg_sd_emmc_clk0_parent_names,
557 .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names), 697 .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
558 .flags = CLK_SET_RATE_PARENT, 698 .flags = CLK_SET_RATE_PARENT,
559 }, 699 },
560}; 700};
561 701
562static struct clk_divider axg_sd_emmc_b_clk0_div = { 702static struct clk_regmap axg_sd_emmc_b_clk0_div = {
563 .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 703 .data = &(struct clk_regmap_div_data){
564 .shift = 16, 704 .offset = HHI_SD_EMMC_CLK_CNTL,
565 .width = 7, 705 .shift = 16,
566 .lock = &meson_clk_lock, 706 .width = 7,
567 .flags = CLK_DIVIDER_ROUND_CLOSEST, 707 .flags = CLK_DIVIDER_ROUND_CLOSEST,
708 },
568 .hw.init = &(struct clk_init_data) { 709 .hw.init = &(struct clk_init_data) {
569 .name = "sd_emmc_b_clk0_div", 710 .name = "sd_emmc_b_clk0_div",
570 .ops = &clk_divider_ops, 711 .ops = &clk_regmap_divider_ops,
571 .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, 712 .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
572 .num_parents = 1, 713 .num_parents = 1,
573 .flags = CLK_SET_RATE_PARENT, 714 .flags = CLK_SET_RATE_PARENT,
574 }, 715 },
575}; 716};
576 717
577static struct clk_gate axg_sd_emmc_b_clk0 = { 718static struct clk_regmap axg_sd_emmc_b_clk0 = {
578 .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 719 .data = &(struct clk_regmap_gate_data){
579 .bit_idx = 23, 720 .offset = HHI_SD_EMMC_CLK_CNTL,
580 .lock = &meson_clk_lock, 721 .bit_idx = 23,
722 },
581 .hw.init = &(struct clk_init_data){ 723 .hw.init = &(struct clk_init_data){
582 .name = "sd_emmc_b_clk0", 724 .name = "sd_emmc_b_clk0",
583 .ops = &clk_gate_ops, 725 .ops = &clk_regmap_gate_ops,
584 .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, 726 .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
585 .num_parents = 1, 727 .num_parents = 1,
586 .flags = CLK_SET_RATE_PARENT, 728 .flags = CLK_SET_RATE_PARENT,
@@ -588,42 +730,45 @@ static struct clk_gate axg_sd_emmc_b_clk0 = {
588}; 730};
589 731
590/* EMMC/NAND clock */ 732/* EMMC/NAND clock */
591static struct clk_mux axg_sd_emmc_c_clk0_sel = { 733static struct clk_regmap axg_sd_emmc_c_clk0_sel = {
592 .reg = (void *)HHI_NAND_CLK_CNTL, 734 .data = &(struct clk_regmap_mux_data){
593 .mask = 0x7, 735 .offset = HHI_NAND_CLK_CNTL,
594 .shift = 9, 736 .mask = 0x7,
595 .lock = &meson_clk_lock, 737 .shift = 9,
738 },
596 .hw.init = &(struct clk_init_data) { 739 .hw.init = &(struct clk_init_data) {
597 .name = "sd_emmc_c_clk0_sel", 740 .name = "sd_emmc_c_clk0_sel",
598 .ops = &clk_mux_ops, 741 .ops = &clk_regmap_mux_ops,
599 .parent_names = axg_sd_emmc_clk0_parent_names, 742 .parent_names = axg_sd_emmc_clk0_parent_names,
600 .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names), 743 .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
601 .flags = CLK_SET_RATE_PARENT, 744 .flags = CLK_SET_RATE_PARENT,
602 }, 745 },
603}; 746};
604 747
605static struct clk_divider axg_sd_emmc_c_clk0_div = { 748static struct clk_regmap axg_sd_emmc_c_clk0_div = {
606 .reg = (void *)HHI_NAND_CLK_CNTL, 749 .data = &(struct clk_regmap_div_data){
607 .shift = 0, 750 .offset = HHI_NAND_CLK_CNTL,
608 .width = 7, 751 .shift = 0,
609 .lock = &meson_clk_lock, 752 .width = 7,
610 .flags = CLK_DIVIDER_ROUND_CLOSEST, 753 .flags = CLK_DIVIDER_ROUND_CLOSEST,
754 },
611 .hw.init = &(struct clk_init_data) { 755 .hw.init = &(struct clk_init_data) {
612 .name = "sd_emmc_c_clk0_div", 756 .name = "sd_emmc_c_clk0_div",
613 .ops = &clk_divider_ops, 757 .ops = &clk_regmap_divider_ops,
614 .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, 758 .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
615 .num_parents = 1, 759 .num_parents = 1,
616 .flags = CLK_SET_RATE_PARENT, 760 .flags = CLK_SET_RATE_PARENT,
617 }, 761 },
618}; 762};
619 763
620static struct clk_gate axg_sd_emmc_c_clk0 = { 764static struct clk_regmap axg_sd_emmc_c_clk0 = {
621 .reg = (void *)HHI_NAND_CLK_CNTL, 765 .data = &(struct clk_regmap_gate_data){
622 .bit_idx = 7, 766 .offset = HHI_NAND_CLK_CNTL,
623 .lock = &meson_clk_lock, 767 .bit_idx = 7,
768 },
624 .hw.init = &(struct clk_init_data){ 769 .hw.init = &(struct clk_init_data){
625 .name = "sd_emmc_c_clk0", 770 .name = "sd_emmc_c_clk0",
626 .ops = &clk_gate_ops, 771 .ops = &clk_regmap_gate_ops,
627 .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, 772 .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
628 .num_parents = 1, 773 .num_parents = 1,
629 .flags = CLK_SET_RATE_PARENT, 774 .flags = CLK_SET_RATE_PARENT,
@@ -750,27 +895,24 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
750 [CLKID_SD_EMMC_C_CLK0_SEL] = &axg_sd_emmc_c_clk0_sel.hw, 895 [CLKID_SD_EMMC_C_CLK0_SEL] = &axg_sd_emmc_c_clk0_sel.hw,
751 [CLKID_SD_EMMC_C_CLK0_DIV] = &axg_sd_emmc_c_clk0_div.hw, 896 [CLKID_SD_EMMC_C_CLK0_DIV] = &axg_sd_emmc_c_clk0_div.hw,
752 [CLKID_SD_EMMC_C_CLK0] = &axg_sd_emmc_c_clk0.hw, 897 [CLKID_SD_EMMC_C_CLK0] = &axg_sd_emmc_c_clk0.hw,
898 [CLKID_MPLL0_DIV] = &axg_mpll0_div.hw,
899 [CLKID_MPLL1_DIV] = &axg_mpll1_div.hw,
900 [CLKID_MPLL2_DIV] = &axg_mpll2_div.hw,
901 [CLKID_MPLL3_DIV] = &axg_mpll3_div.hw,
902 [CLKID_HIFI_PLL] = &axg_hifi_pll.hw,
903 [CLKID_MPLL_PREDIV] = &axg_mpll_prediv.hw,
904 [CLKID_FCLK_DIV2_DIV] = &axg_fclk_div2_div.hw,
905 [CLKID_FCLK_DIV3_DIV] = &axg_fclk_div3_div.hw,
906 [CLKID_FCLK_DIV4_DIV] = &axg_fclk_div4_div.hw,
907 [CLKID_FCLK_DIV5_DIV] = &axg_fclk_div5_div.hw,
908 [CLKID_FCLK_DIV7_DIV] = &axg_fclk_div7_div.hw,
753 [NR_CLKS] = NULL, 909 [NR_CLKS] = NULL,
754 }, 910 },
755 .num = NR_CLKS, 911 .num = NR_CLKS,
756}; 912};
757 913
758/* Convenience tables to populate base addresses in .probe */ 914/* Convenience table to populate regmap in .probe */
759 915static struct clk_regmap *const axg_clk_regmaps[] = {
760static struct meson_clk_pll *const axg_clk_plls[] = {
761 &axg_fixed_pll,
762 &axg_sys_pll,
763 &axg_gp0_pll,
764};
765
766static struct meson_clk_mpll *const axg_clk_mplls[] = {
767 &axg_mpll0,
768 &axg_mpll1,
769 &axg_mpll2,
770 &axg_mpll3,
771};
772
773static struct clk_gate *const axg_clk_gates[] = {
774 &axg_clk81, 916 &axg_clk81,
775 &axg_ddr, 917 &axg_ddr,
776 &axg_audio_locker, 918 &axg_audio_locker,
@@ -818,113 +960,100 @@ static struct clk_gate *const axg_clk_gates[] = {
818 &axg_ao_i2c, 960 &axg_ao_i2c,
819 &axg_sd_emmc_b_clk0, 961 &axg_sd_emmc_b_clk0,
820 &axg_sd_emmc_c_clk0, 962 &axg_sd_emmc_c_clk0,
821};
822
823static struct clk_mux *const axg_clk_muxes[] = {
824 &axg_mpeg_clk_sel,
825 &axg_sd_emmc_b_clk0_sel,
826 &axg_sd_emmc_c_clk0_sel,
827};
828
829static struct clk_divider *const axg_clk_dividers[] = {
830 &axg_mpeg_clk_div, 963 &axg_mpeg_clk_div,
831 &axg_sd_emmc_b_clk0_div, 964 &axg_sd_emmc_b_clk0_div,
832 &axg_sd_emmc_c_clk0_div, 965 &axg_sd_emmc_c_clk0_div,
833}; 966 &axg_mpeg_clk_sel,
834 967 &axg_sd_emmc_b_clk0_sel,
835struct clkc_data { 968 &axg_sd_emmc_c_clk0_sel,
836 struct clk_gate *const *clk_gates; 969 &axg_mpll0,
837 unsigned int clk_gates_count; 970 &axg_mpll1,
838 struct meson_clk_mpll *const *clk_mplls; 971 &axg_mpll2,
839 unsigned int clk_mplls_count; 972 &axg_mpll3,
840 struct meson_clk_pll *const *clk_plls; 973 &axg_mpll0_div,
841 unsigned int clk_plls_count; 974 &axg_mpll1_div,
842 struct clk_mux *const *clk_muxes; 975 &axg_mpll2_div,
843 unsigned int clk_muxes_count; 976 &axg_mpll3_div,
844 struct clk_divider *const *clk_dividers; 977 &axg_fixed_pll,
845 unsigned int clk_dividers_count; 978 &axg_sys_pll,
846 struct clk_hw_onecell_data *hw_onecell_data; 979 &axg_gp0_pll,
847}; 980 &axg_hifi_pll,
848 981 &axg_mpll_prediv,
849static const struct clkc_data axg_clkc_data = { 982 &axg_fclk_div2,
850 .clk_gates = axg_clk_gates, 983 &axg_fclk_div3,
851 .clk_gates_count = ARRAY_SIZE(axg_clk_gates), 984 &axg_fclk_div4,
852 .clk_mplls = axg_clk_mplls, 985 &axg_fclk_div5,
853 .clk_mplls_count = ARRAY_SIZE(axg_clk_mplls), 986 &axg_fclk_div7,
854 .clk_plls = axg_clk_plls,
855 .clk_plls_count = ARRAY_SIZE(axg_clk_plls),
856 .clk_muxes = axg_clk_muxes,
857 .clk_muxes_count = ARRAY_SIZE(axg_clk_muxes),
858 .clk_dividers = axg_clk_dividers,
859 .clk_dividers_count = ARRAY_SIZE(axg_clk_dividers),
860 .hw_onecell_data = &axg_hw_onecell_data,
861}; 987};
862 988
863static const struct of_device_id clkc_match_table[] = { 989static const struct of_device_id clkc_match_table[] = {
864 { .compatible = "amlogic,axg-clkc", .data = &axg_clkc_data }, 990 { .compatible = "amlogic,axg-clkc" },
865 {} 991 {}
866}; 992};
867 993
994static const struct regmap_config clkc_regmap_config = {
995 .reg_bits = 32,
996 .val_bits = 32,
997 .reg_stride = 4,
998};
999
868static int axg_clkc_probe(struct platform_device *pdev) 1000static int axg_clkc_probe(struct platform_device *pdev)
869{ 1001{
870 struct device *dev = &pdev->dev; 1002 struct device *dev = &pdev->dev;
871 const struct clkc_data *clkc_data;
872 struct resource *res; 1003 struct resource *res;
873 void __iomem *clk_base; 1004 void __iomem *clk_base = NULL;
874 int ret, clkid, i; 1005 struct regmap *map;
875 1006 int ret, i;
876 clkc_data = of_device_get_match_data(&pdev->dev);
877 if (!clkc_data)
878 return -EINVAL;
879
880 /* Generic clocks and PLLs */
881 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
882 if (!res)
883 return -EINVAL;
884 clk_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
885 if (!clk_base) {
886 dev_err(&pdev->dev, "Unable to map clk base\n");
887 return -ENXIO;
888 }
889 1007
890 /* Populate base address for PLLs */ 1008 /* Get the hhi system controller node if available */
891 for (i = 0; i < clkc_data->clk_plls_count; i++) 1009 map = syscon_node_to_regmap(of_get_parent(dev->of_node));
892 clkc_data->clk_plls[i]->base = clk_base; 1010 if (IS_ERR(map)) {
1011 dev_err(dev,
1012 "failed to get HHI regmap - Trying obsolete regs\n");
893 1013
894 /* Populate base address for MPLLs */ 1014 /*
895 for (i = 0; i < clkc_data->clk_mplls_count; i++) 1015 * FIXME: HHI registers should be accessed through
896 clkc_data->clk_mplls[i]->base = clk_base; 1016 * the appropriate system controller. This is required because
1017 * there is more than just clocks in this register space
1018 *
1019 * This fallback method is only provided temporarily until
1020 * all the platform DTs are properly using the syscon node
1021 */
1022 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1023 if (!res)
1024 return -EINVAL;
897 1025
898 /* Populate base address for gates */
899 for (i = 0; i < clkc_data->clk_gates_count; i++)
900 clkc_data->clk_gates[i]->reg = clk_base +
901 (u64)clkc_data->clk_gates[i]->reg;
902 1026
903 /* Populate base address for muxes */ 1027 clk_base = devm_ioremap(dev, res->start, resource_size(res));
904 for (i = 0; i < clkc_data->clk_muxes_count; i++) 1028 if (!clk_base) {
905 clkc_data->clk_muxes[i]->reg = clk_base + 1029 dev_err(dev, "Unable to map clk base\n");
906 (u64)clkc_data->clk_muxes[i]->reg; 1030 return -ENXIO;
1031 }
1032
1033 map = devm_regmap_init_mmio(dev, clk_base,
1034 &clkc_regmap_config);
1035 if (IS_ERR(map))
1036 return PTR_ERR(map);
1037 }
907 1038
908 /* Populate base address for dividers */ 1039 /* Populate regmap for the regmap backed clocks */
909 for (i = 0; i < clkc_data->clk_dividers_count; i++) 1040 for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++)
910 clkc_data->clk_dividers[i]->reg = clk_base + 1041 axg_clk_regmaps[i]->map = map;
911 (u64)clkc_data->clk_dividers[i]->reg;
912 1042
913 for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) { 1043 for (i = 0; i < axg_hw_onecell_data.num; i++) {
914 /* array might be sparse */ 1044 /* array might be sparse */
915 if (!clkc_data->hw_onecell_data->hws[clkid]) 1045 if (!axg_hw_onecell_data.hws[i])
916 continue; 1046 continue;
917 1047
918 ret = devm_clk_hw_register(dev, 1048 ret = devm_clk_hw_register(dev, axg_hw_onecell_data.hws[i]);
919 clkc_data->hw_onecell_data->hws[clkid]);
920 if (ret) { 1049 if (ret) {
921 dev_err(&pdev->dev, "Clock registration failed\n"); 1050 dev_err(dev, "Clock registration failed\n");
922 return ret; 1051 return ret;
923 } 1052 }
924 } 1053 }
925 1054
926 return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, 1055 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
927 clkc_data->hw_onecell_data); 1056 &axg_hw_onecell_data);
928} 1057}
929 1058
930static struct platform_driver axg_driver = { 1059static struct platform_driver axg_driver = {
diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h
index ce0bafdb6b28..b421df6a7ea0 100644
--- a/drivers/clk/meson/axg.h
+++ b/drivers/clk/meson/axg.h
@@ -117,8 +117,18 @@
117#define CLKID_SD_EMMC_B_CLK0_DIV 62 117#define CLKID_SD_EMMC_B_CLK0_DIV 62
118#define CLKID_SD_EMMC_C_CLK0_SEL 63 118#define CLKID_SD_EMMC_C_CLK0_SEL 63
119#define CLKID_SD_EMMC_C_CLK0_DIV 64 119#define CLKID_SD_EMMC_C_CLK0_DIV 64
120#define CLKID_MPLL0_DIV 65
121#define CLKID_MPLL1_DIV 66
122#define CLKID_MPLL2_DIV 67
123#define CLKID_MPLL3_DIV 68
124#define CLKID_MPLL_PREDIV 70
125#define CLKID_FCLK_DIV2_DIV 71
126#define CLKID_FCLK_DIV3_DIV 72
127#define CLKID_FCLK_DIV4_DIV 73
128#define CLKID_FCLK_DIV5_DIV 74
129#define CLKID_FCLK_DIV7_DIV 75
120 130
121#define NR_CLKS 65 131#define NR_CLKS 76
122 132
123/* include the CLKIDs that have been made part of the DT binding */ 133/* include the CLKIDs that have been made part of the DT binding */
124#include <dt-bindings/clock/axg-clkc.h> 134#include <dt-bindings/clock/axg-clkc.h>
diff --git a/drivers/clk/meson/clk-audio-divider.c b/drivers/clk/meson/clk-audio-divider.c
index 6c07db06642d..f7ab5b1db342 100644
--- a/drivers/clk/meson/clk-audio-divider.c
+++ b/drivers/clk/meson/clk-audio-divider.c
@@ -28,8 +28,11 @@
28#include <linux/clk-provider.h> 28#include <linux/clk-provider.h>
29#include "clkc.h" 29#include "clkc.h"
30 30
31#define to_meson_clk_audio_divider(_hw) container_of(_hw, \ 31static inline struct meson_clk_audio_div_data *
32 struct meson_clk_audio_divider, hw) 32meson_clk_audio_div_data(struct clk_regmap *clk)
33{
34 return (struct meson_clk_audio_div_data *)clk->data;
35}
33 36
34static int _div_round(unsigned long parent_rate, unsigned long rate, 37static int _div_round(unsigned long parent_rate, unsigned long rate,
35 unsigned long flags) 38 unsigned long flags)
@@ -45,15 +48,9 @@ static int _get_val(unsigned long parent_rate, unsigned long rate)
45 return DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1; 48 return DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1;
46} 49}
47 50
48static int _valid_divider(struct clk_hw *hw, int divider) 51static int _valid_divider(unsigned int width, int divider)
49{ 52{
50 struct meson_clk_audio_divider *adiv = 53 int max_divider = 1 << width;
51 to_meson_clk_audio_divider(hw);
52 int max_divider;
53 u8 width;
54
55 width = adiv->div.width;
56 max_divider = 1 << width;
57 54
58 return clamp(divider, 1, max_divider); 55 return clamp(divider, 1, max_divider);
59} 56}
@@ -61,14 +58,11 @@ static int _valid_divider(struct clk_hw *hw, int divider)
61static unsigned long audio_divider_recalc_rate(struct clk_hw *hw, 58static unsigned long audio_divider_recalc_rate(struct clk_hw *hw,
62 unsigned long parent_rate) 59 unsigned long parent_rate)
63{ 60{
64 struct meson_clk_audio_divider *adiv = 61 struct clk_regmap *clk = to_clk_regmap(hw);
65 to_meson_clk_audio_divider(hw); 62 struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk);
66 struct parm *p; 63 unsigned long divider;
67 unsigned long reg, divider;
68 64
69 p = &adiv->div; 65 divider = meson_parm_read(clk->map, &adiv->div);
70 reg = readl(adiv->base + p->reg_off);
71 divider = PARM_GET(p->width, p->shift, reg) + 1;
72 66
73 return DIV_ROUND_UP_ULL((u64)parent_rate, divider); 67 return DIV_ROUND_UP_ULL((u64)parent_rate, divider);
74} 68}
@@ -77,14 +71,14 @@ static long audio_divider_round_rate(struct clk_hw *hw,
77 unsigned long rate, 71 unsigned long rate,
78 unsigned long *parent_rate) 72 unsigned long *parent_rate)
79{ 73{
80 struct meson_clk_audio_divider *adiv = 74 struct clk_regmap *clk = to_clk_regmap(hw);
81 to_meson_clk_audio_divider(hw); 75 struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk);
82 unsigned long max_prate; 76 unsigned long max_prate;
83 int divider; 77 int divider;
84 78
85 if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { 79 if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
86 divider = _div_round(*parent_rate, rate, adiv->flags); 80 divider = _div_round(*parent_rate, rate, adiv->flags);
87 divider = _valid_divider(hw, divider); 81 divider = _valid_divider(adiv->div.width, divider);
88 return DIV_ROUND_UP_ULL((u64)*parent_rate, divider); 82 return DIV_ROUND_UP_ULL((u64)*parent_rate, divider);
89 } 83 }
90 84
@@ -93,7 +87,7 @@ static long audio_divider_round_rate(struct clk_hw *hw,
93 87
94 /* Get the corresponding rounded down divider */ 88 /* Get the corresponding rounded down divider */
95 divider = max_prate / rate; 89 divider = max_prate / rate;
96 divider = _valid_divider(hw, divider); 90 divider = _valid_divider(adiv->div.width, divider);
97 91
98 /* Get actual rate of the parent */ 92 /* Get actual rate of the parent */
99 *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), 93 *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
@@ -106,28 +100,11 @@ static int audio_divider_set_rate(struct clk_hw *hw,
106 unsigned long rate, 100 unsigned long rate,
107 unsigned long parent_rate) 101 unsigned long parent_rate)
108{ 102{
109 struct meson_clk_audio_divider *adiv = 103 struct clk_regmap *clk = to_clk_regmap(hw);
110 to_meson_clk_audio_divider(hw); 104 struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk);
111 struct parm *p; 105 int val = _get_val(parent_rate, rate);
112 unsigned long reg, flags = 0; 106
113 int val; 107 meson_parm_write(clk->map, &adiv->div, val);
114
115 val = _get_val(parent_rate, rate);
116
117 if (adiv->lock)
118 spin_lock_irqsave(adiv->lock, flags);
119 else
120 __acquire(adiv->lock);
121
122 p = &adiv->div;
123 reg = readl(adiv->base + p->reg_off);
124 reg = PARM_SET(p->width, p->shift, reg, val);
125 writel(reg, adiv->base + p->reg_off);
126
127 if (adiv->lock)
128 spin_unlock_irqrestore(adiv->lock, flags);
129 else
130 __release(adiv->lock);
131 108
132 return 0; 109 return 0;
133} 110}
diff --git a/drivers/clk/meson/clk-cpu.c b/drivers/clk/meson/clk-cpu.c
deleted file mode 100644
index f8b2b7efd016..000000000000
--- a/drivers/clk/meson/clk-cpu.c
+++ /dev/null
@@ -1,178 +0,0 @@
1/*
2 * Copyright (c) 2015 Endless Mobile, Inc.
3 * Author: Carlo Caione <carlo@endlessm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * CPU clock path:
20 *
21 * +-[/N]-----|3|
22 * MUX2 +--[/3]-+----------|2| MUX1
23 * [sys_pll]---|1| |--[/2]------------|1|-|1|
24 * | |---+------------------|0| | |----- [a5_clk]
25 * +--|0| | |
26 * [xtal]---+-------------------------------|0|
27 *
28 *
29 *
30 */
31
32#include <linux/delay.h>
33#include <linux/err.h>
34#include <linux/io.h>
35#include <linux/module.h>
36#include <linux/of_address.h>
37#include <linux/slab.h>
38#include <linux/clk.h>
39#include <linux/clk-provider.h>
40
41#define MESON_CPU_CLK_CNTL1 0x00
42#define MESON_CPU_CLK_CNTL 0x40
43
44#define MESON_CPU_CLK_MUX1 BIT(7)
45#define MESON_CPU_CLK_MUX2 BIT(0)
46
47#define MESON_N_WIDTH 9
48#define MESON_N_SHIFT 20
49#define MESON_SEL_WIDTH 2
50#define MESON_SEL_SHIFT 2
51
52#include "clkc.h"
53
54#define to_meson_clk_cpu_hw(_hw) container_of(_hw, struct meson_clk_cpu, hw)
55#define to_meson_clk_cpu_nb(_nb) container_of(_nb, struct meson_clk_cpu, clk_nb)
56
57static long meson_clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
58 unsigned long *prate)
59{
60 struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
61
62 return divider_round_rate(hw, rate, prate, clk_cpu->div_table,
63 MESON_N_WIDTH, CLK_DIVIDER_ROUND_CLOSEST);
64}
65
66static int meson_clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
67 unsigned long parent_rate)
68{
69 struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
70 unsigned int div, sel, N = 0;
71 u32 reg;
72
73 div = DIV_ROUND_UP(parent_rate, rate);
74
75 if (div <= 3) {
76 sel = div - 1;
77 } else {
78 sel = 3;
79 N = div / 2;
80 }
81
82 reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
83 reg = PARM_SET(MESON_N_WIDTH, MESON_N_SHIFT, reg, N);
84 writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
85
86 reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
87 reg = PARM_SET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg, sel);
88 writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
89
90 return 0;
91}
92
93static unsigned long meson_clk_cpu_recalc_rate(struct clk_hw *hw,
94 unsigned long parent_rate)
95{
96 struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
97 unsigned int N, sel;
98 unsigned int div = 1;
99 u32 reg;
100
101 reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
102 N = PARM_GET(MESON_N_WIDTH, MESON_N_SHIFT, reg);
103
104 reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
105 sel = PARM_GET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg);
106
107 if (sel < 3)
108 div = sel + 1;
109 else
110 div = 2 * N;
111
112 return parent_rate / div;
113}
114
115/* FIXME MUX1 & MUX2 should be struct clk_hw objects */
116static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu,
117 struct clk_notifier_data *ndata)
118{
119 u32 cpu_clk_cntl;
120
121 /* switch MUX1 to xtal */
122 cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
123 + MESON_CPU_CLK_CNTL);
124 cpu_clk_cntl &= ~MESON_CPU_CLK_MUX1;
125 writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
126 + MESON_CPU_CLK_CNTL);
127 udelay(100);
128
129 /* switch MUX2 to sys-pll */
130 cpu_clk_cntl |= MESON_CPU_CLK_MUX2;
131 writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
132 + MESON_CPU_CLK_CNTL);
133
134 return 0;
135}
136
137/* FIXME MUX1 & MUX2 should be struct clk_hw objects */
138static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu,
139 struct clk_notifier_data *ndata)
140{
141 u32 cpu_clk_cntl;
142
143 /* switch MUX1 to divisors' output */
144 cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
145 + MESON_CPU_CLK_CNTL);
146 cpu_clk_cntl |= MESON_CPU_CLK_MUX1;
147 writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
148 + MESON_CPU_CLK_CNTL);
149 udelay(100);
150
151 return 0;
152}
153
154/*
155 * This clock notifier is called when the frequency of the of the parent
156 * PLL clock is to be changed. We use the xtal input as temporary parent
157 * while the PLL frequency is stabilized.
158 */
159int meson_clk_cpu_notifier_cb(struct notifier_block *nb,
160 unsigned long event, void *data)
161{
162 struct clk_notifier_data *ndata = data;
163 struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_nb(nb);
164 int ret = 0;
165
166 if (event == PRE_RATE_CHANGE)
167 ret = meson_clk_cpu_pre_rate_change(clk_cpu, ndata);
168 else if (event == POST_RATE_CHANGE)
169 ret = meson_clk_cpu_post_rate_change(clk_cpu, ndata);
170
171 return notifier_from_errno(ret);
172}
173
174const struct clk_ops meson_clk_cpu_ops = {
175 .recalc_rate = meson_clk_cpu_recalc_rate,
176 .round_rate = meson_clk_cpu_round_rate,
177 .set_rate = meson_clk_cpu_set_rate,
178};
diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
index 5144360e2c80..0df1227b65b3 100644
--- a/drivers/clk/meson/clk-mpll.c
+++ b/drivers/clk/meson/clk-mpll.c
@@ -68,11 +68,15 @@
68#define N2_MIN 4 68#define N2_MIN 4
69#define N2_MAX 511 69#define N2_MAX 511
70 70
71#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw) 71static inline struct meson_clk_mpll_data *
72meson_clk_mpll_data(struct clk_regmap *clk)
73{
74 return (struct meson_clk_mpll_data *)clk->data;
75}
72 76
73static long rate_from_params(unsigned long parent_rate, 77static long rate_from_params(unsigned long parent_rate,
74 unsigned long sdm, 78 unsigned int sdm,
75 unsigned long n2) 79 unsigned int n2)
76{ 80{
77 unsigned long divisor = (SDM_DEN * n2) + sdm; 81 unsigned long divisor = (SDM_DEN * n2) + sdm;
78 82
@@ -84,8 +88,8 @@ static long rate_from_params(unsigned long parent_rate,
84 88
85static void params_from_rate(unsigned long requested_rate, 89static void params_from_rate(unsigned long requested_rate,
86 unsigned long parent_rate, 90 unsigned long parent_rate,
87 unsigned long *sdm, 91 unsigned int *sdm,
88 unsigned long *n2) 92 unsigned int *n2)
89{ 93{
90 uint64_t div = parent_rate; 94 uint64_t div = parent_rate;
91 unsigned long rem = do_div(div, requested_rate); 95 unsigned long rem = do_div(div, requested_rate);
@@ -105,31 +109,23 @@ static void params_from_rate(unsigned long requested_rate,
105static unsigned long mpll_recalc_rate(struct clk_hw *hw, 109static unsigned long mpll_recalc_rate(struct clk_hw *hw,
106 unsigned long parent_rate) 110 unsigned long parent_rate)
107{ 111{
108 struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); 112 struct clk_regmap *clk = to_clk_regmap(hw);
109 struct parm *p; 113 struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
110 unsigned long reg, sdm, n2; 114 unsigned int sdm, n2;
111 long rate; 115 long rate;
112 116
113 p = &mpll->sdm; 117 sdm = meson_parm_read(clk->map, &mpll->sdm);
114 reg = readl(mpll->base + p->reg_off); 118 n2 = meson_parm_read(clk->map, &mpll->n2);
115 sdm = PARM_GET(p->width, p->shift, reg);
116
117 p = &mpll->n2;
118 reg = readl(mpll->base + p->reg_off);
119 n2 = PARM_GET(p->width, p->shift, reg);
120 119
121 rate = rate_from_params(parent_rate, sdm, n2); 120 rate = rate_from_params(parent_rate, sdm, n2);
122 if (rate < 0) 121 return rate < 0 ? 0 : rate;
123 return 0;
124
125 return rate;
126} 122}
127 123
128static long mpll_round_rate(struct clk_hw *hw, 124static long mpll_round_rate(struct clk_hw *hw,
129 unsigned long rate, 125 unsigned long rate,
130 unsigned long *parent_rate) 126 unsigned long *parent_rate)
131{ 127{
132 unsigned long sdm, n2; 128 unsigned int sdm, n2;
133 129
134 params_from_rate(rate, *parent_rate, &sdm, &n2); 130 params_from_rate(rate, *parent_rate, &sdm, &n2);
135 return rate_from_params(*parent_rate, sdm, n2); 131 return rate_from_params(*parent_rate, sdm, n2);
@@ -139,9 +135,9 @@ static int mpll_set_rate(struct clk_hw *hw,
139 unsigned long rate, 135 unsigned long rate,
140 unsigned long parent_rate) 136 unsigned long parent_rate)
141{ 137{
142 struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); 138 struct clk_regmap *clk = to_clk_regmap(hw);
143 struct parm *p; 139 struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
144 unsigned long reg, sdm, n2; 140 unsigned int sdm, n2;
145 unsigned long flags = 0; 141 unsigned long flags = 0;
146 142
147 params_from_rate(rate, parent_rate, &sdm, &n2); 143 params_from_rate(rate, parent_rate, &sdm, &n2);
@@ -151,97 +147,36 @@ static int mpll_set_rate(struct clk_hw *hw,
151 else 147 else
152 __acquire(mpll->lock); 148 __acquire(mpll->lock);
153 149
154 p = &mpll->sdm; 150 /* Enable and set the fractional part */
155 reg = readl(mpll->base + p->reg_off); 151 meson_parm_write(clk->map, &mpll->sdm, sdm);
156 reg = PARM_SET(p->width, p->shift, reg, sdm); 152 meson_parm_write(clk->map, &mpll->sdm_en, 1);
157 writel(reg, mpll->base + p->reg_off);
158
159 p = &mpll->sdm_en;
160 reg = readl(mpll->base + p->reg_off);
161 reg = PARM_SET(p->width, p->shift, reg, 1);
162 writel(reg, mpll->base + p->reg_off);
163
164 p = &mpll->ssen;
165 if (p->width != 0) {
166 reg = readl(mpll->base + p->reg_off);
167 reg = PARM_SET(p->width, p->shift, reg, 1);
168 writel(reg, mpll->base + p->reg_off);
169 }
170
171 p = &mpll->n2;
172 reg = readl(mpll->base + p->reg_off);
173 reg = PARM_SET(p->width, p->shift, reg, n2);
174 writel(reg, mpll->base + p->reg_off);
175
176 if (mpll->lock)
177 spin_unlock_irqrestore(mpll->lock, flags);
178 else
179 __release(mpll->lock);
180
181 return 0;
182}
183 153
184static void mpll_enable_core(struct clk_hw *hw, int enable) 154 /* Set additional fractional part enable if required */
185{ 155 if (MESON_PARM_APPLICABLE(&mpll->ssen))
186 struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); 156 meson_parm_write(clk->map, &mpll->ssen, 1);
187 struct parm *p;
188 unsigned long reg;
189 unsigned long flags = 0;
190 157
191 if (mpll->lock) 158 /* Set the integer divider part */
192 spin_lock_irqsave(mpll->lock, flags); 159 meson_parm_write(clk->map, &mpll->n2, n2);
193 else
194 __acquire(mpll->lock);
195 160
196 p = &mpll->en; 161 /* Set the magic misc bit if required */
197 reg = readl(mpll->base + p->reg_off); 162 if (MESON_PARM_APPLICABLE(&mpll->misc))
198 reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0); 163 meson_parm_write(clk->map, &mpll->misc, 1);
199 writel(reg, mpll->base + p->reg_off);
200 164
201 if (mpll->lock) 165 if (mpll->lock)
202 spin_unlock_irqrestore(mpll->lock, flags); 166 spin_unlock_irqrestore(mpll->lock, flags);
203 else 167 else
204 __release(mpll->lock); 168 __release(mpll->lock);
205}
206
207
208static int mpll_enable(struct clk_hw *hw)
209{
210 mpll_enable_core(hw, 1);
211 169
212 return 0; 170 return 0;
213} 171}
214 172
215static void mpll_disable(struct clk_hw *hw)
216{
217 mpll_enable_core(hw, 0);
218}
219
220static int mpll_is_enabled(struct clk_hw *hw)
221{
222 struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
223 struct parm *p;
224 unsigned long reg;
225 int en;
226
227 p = &mpll->en;
228 reg = readl(mpll->base + p->reg_off);
229 en = PARM_GET(p->width, p->shift, reg);
230
231 return en;
232}
233
234const struct clk_ops meson_clk_mpll_ro_ops = { 173const struct clk_ops meson_clk_mpll_ro_ops = {
235 .recalc_rate = mpll_recalc_rate, 174 .recalc_rate = mpll_recalc_rate,
236 .round_rate = mpll_round_rate, 175 .round_rate = mpll_round_rate,
237 .is_enabled = mpll_is_enabled,
238}; 176};
239 177
240const struct clk_ops meson_clk_mpll_ops = { 178const struct clk_ops meson_clk_mpll_ops = {
241 .recalc_rate = mpll_recalc_rate, 179 .recalc_rate = mpll_recalc_rate,
242 .round_rate = mpll_round_rate, 180 .round_rate = mpll_round_rate,
243 .set_rate = mpll_set_rate, 181 .set_rate = mpll_set_rate,
244 .enable = mpll_enable,
245 .disable = mpll_disable,
246 .is_enabled = mpll_is_enabled,
247}; 182};
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 01341553f50b..65a7bd903551 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -2,6 +2,9 @@
2 * Copyright (c) 2015 Endless Mobile, Inc. 2 * Copyright (c) 2015 Endless Mobile, Inc.
3 * Author: Carlo Caione <carlo@endlessm.com> 3 * Author: Carlo Caione <carlo@endlessm.com>
4 * 4 *
5 * Copyright (c) 2018 Baylibre, SAS.
6 * Author: Jerome Brunet <jbrunet@baylibre.com>
7 *
5 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License, 9 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation. 10 * version 2, as published by the Free Software Foundation.
@@ -27,13 +30,14 @@
27 * | | 30 * | |
28 * FREF VCO 31 * FREF VCO
29 * 32 *
30 * out = (in * M / N) >> OD 33 * out = in * (m + frac / frac_max) / (n << sum(ods))
31 */ 34 */
32 35
33#include <linux/clk-provider.h> 36#include <linux/clk-provider.h>
34#include <linux/delay.h> 37#include <linux/delay.h>
35#include <linux/err.h> 38#include <linux/err.h>
36#include <linux/io.h> 39#include <linux/io.h>
40#include <linux/math64.h>
37#include <linux/module.h> 41#include <linux/module.h>
38#include <linux/of_address.h> 42#include <linux/of_address.h>
39#include <linux/slab.h> 43#include <linux/slab.h>
@@ -41,209 +45,213 @@
41 45
42#include "clkc.h" 46#include "clkc.h"
43 47
44#define MESON_PLL_RESET BIT(29) 48static inline struct meson_clk_pll_data *
45#define MESON_PLL_LOCK BIT(31) 49meson_clk_pll_data(struct clk_regmap *clk)
46
47#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
48
49static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
50 unsigned long parent_rate)
51{ 50{
52 struct meson_clk_pll *pll = to_meson_clk_pll(hw); 51 return (struct meson_clk_pll_data *)clk->data;
53 struct parm *p;
54 unsigned long parent_rate_mhz = parent_rate / 1000000;
55 unsigned long rate_mhz;
56 u16 n, m, frac = 0, od, od2 = 0;
57 u32 reg;
58
59 p = &pll->n;
60 reg = readl(pll->base + p->reg_off);
61 n = PARM_GET(p->width, p->shift, reg);
62
63 p = &pll->m;
64 reg = readl(pll->base + p->reg_off);
65 m = PARM_GET(p->width, p->shift, reg);
66
67 p = &pll->od;
68 reg = readl(pll->base + p->reg_off);
69 od = PARM_GET(p->width, p->shift, reg);
70
71 p = &pll->od2;
72 if (p->width) {
73 reg = readl(pll->base + p->reg_off);
74 od2 = PARM_GET(p->width, p->shift, reg);
75 }
76
77 p = &pll->frac;
78 if (p->width) {
79 reg = readl(pll->base + p->reg_off);
80 frac = PARM_GET(p->width, p->shift, reg);
81 rate_mhz = (parent_rate_mhz * m + \
82 (parent_rate_mhz * frac >> 12)) * 2 / n;
83 rate_mhz = rate_mhz >> od >> od2;
84 } else
85 rate_mhz = (parent_rate_mhz * m / n) >> od >> od2;
86
87 return rate_mhz * 1000000;
88} 52}
89 53
90static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, 54static unsigned long __pll_params_to_rate(unsigned long parent_rate,
91 unsigned long *parent_rate) 55 const struct pll_rate_table *pllt,
56 u16 frac,
57 struct meson_clk_pll_data *pll)
92{ 58{
93 struct meson_clk_pll *pll = to_meson_clk_pll(hw); 59 u64 rate = (u64)parent_rate * pllt->m;
94 const struct pll_rate_table *rate_table = pll->rate_table; 60 unsigned int od = pllt->od + pllt->od2 + pllt->od3;
95 int i;
96 61
97 for (i = 0; i < pll->rate_count; i++) { 62 if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
98 if (rate <= rate_table[i].rate) 63 u64 frac_rate = (u64)parent_rate * frac;
99 return rate_table[i].rate; 64
65 rate += DIV_ROUND_UP_ULL(frac_rate,
66 (1 << pll->frac.width));
100 } 67 }
101 68
102 /* else return the smallest value */ 69 return DIV_ROUND_UP_ULL(rate, pllt->n << od);
103 return rate_table[0].rate;
104} 70}
105 71
106static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_pll *pll, 72static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
107 unsigned long rate) 73 unsigned long parent_rate)
108{ 74{
109 const struct pll_rate_table *rate_table = pll->rate_table; 75 struct clk_regmap *clk = to_clk_regmap(hw);
110 int i; 76 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
77 struct pll_rate_table pllt;
78 u16 frac;
111 79
112 for (i = 0; i < pll->rate_count; i++) { 80 pllt.n = meson_parm_read(clk->map, &pll->n);
113 if (rate == rate_table[i].rate) 81 pllt.m = meson_parm_read(clk->map, &pll->m);
114 return &rate_table[i]; 82 pllt.od = meson_parm_read(clk->map, &pll->od);
115 } 83
116 return NULL; 84 pllt.od2 = MESON_PARM_APPLICABLE(&pll->od2) ?
85 meson_parm_read(clk->map, &pll->od2) :
86 0;
87
88 pllt.od3 = MESON_PARM_APPLICABLE(&pll->od3) ?
89 meson_parm_read(clk->map, &pll->od3) :
90 0;
91
92 frac = MESON_PARM_APPLICABLE(&pll->frac) ?
93 meson_parm_read(clk->map, &pll->frac) :
94 0;
95
96 return __pll_params_to_rate(parent_rate, &pllt, frac, pll);
117} 97}
118 98
119/* Specific wait loop for GXL/GXM GP0 PLL */ 99static u16 __pll_params_with_frac(unsigned long rate,
120static int meson_clk_pll_wait_lock_reset(struct meson_clk_pll *pll, 100 unsigned long parent_rate,
121 struct parm *p_n) 101 const struct pll_rate_table *pllt,
102 struct meson_clk_pll_data *pll)
122{ 103{
123 int delay = 100; 104 u16 frac_max = (1 << pll->frac.width);
124 u32 reg; 105 u64 val = (u64)rate * pllt->n;
125 106
126 while (delay > 0) { 107 val <<= pllt->od + pllt->od2 + pllt->od3;
127 reg = readl(pll->base + p_n->reg_off);
128 writel(reg | MESON_PLL_RESET, pll->base + p_n->reg_off);
129 udelay(10);
130 writel(reg & ~MESON_PLL_RESET, pll->base + p_n->reg_off);
131 108
132 /* This delay comes from AMLogic tree clk-gp0-gxl driver */ 109 if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
133 mdelay(1); 110 val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
111 else
112 val = div_u64(val * frac_max, parent_rate);
134 113
135 reg = readl(pll->base + p_n->reg_off); 114 val -= pllt->m * frac_max;
136 if (reg & MESON_PLL_LOCK) 115
137 return 0; 116 return min((u16)val, (u16)(frac_max - 1));
138 delay--; 117}
118
119static const struct pll_rate_table *
120meson_clk_get_pll_settings(unsigned long rate,
121 struct meson_clk_pll_data *pll)
122{
123 const struct pll_rate_table *table = pll->table;
124 unsigned int i = 0;
125
126 if (!table)
127 return NULL;
128
129 /* Find the first table element exceeding rate */
130 while (table[i].rate && table[i].rate <= rate)
131 i++;
132
133 if (i != 0) {
134 if (MESON_PARM_APPLICABLE(&pll->frac) ||
135 !(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
136 (abs(rate - table[i - 1].rate) <
137 abs(rate - table[i].rate)))
138 i--;
139 } 139 }
140 return -ETIMEDOUT; 140
141 return (struct pll_rate_table *)&table[i];
141} 142}
142 143
143static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll, 144static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
144 struct parm *p_n) 145 unsigned long *parent_rate)
145{ 146{
146 int delay = 24000000; 147 struct clk_regmap *clk = to_clk_regmap(hw);
147 u32 reg; 148 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
149 const struct pll_rate_table *pllt =
150 meson_clk_get_pll_settings(rate, pll);
151 u16 frac;
152
153 if (!pllt)
154 return meson_clk_pll_recalc_rate(hw, *parent_rate);
155
156 if (!MESON_PARM_APPLICABLE(&pll->frac)
157 || rate == pllt->rate)
158 return pllt->rate;
159
160 /*
161 * The rate provided by the setting is not an exact match, let's
162 * try to improve the result using the fractional parameter
163 */
164 frac = __pll_params_with_frac(rate, *parent_rate, pllt, pll);
165
166 return __pll_params_to_rate(*parent_rate, pllt, frac, pll);
167}
148 168
149 while (delay > 0) { 169static int meson_clk_pll_wait_lock(struct clk_hw *hw)
150 reg = readl(pll->base + p_n->reg_off); 170{
171 struct clk_regmap *clk = to_clk_regmap(hw);
172 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
173 int delay = 24000000;
151 174
152 if (reg & MESON_PLL_LOCK) 175 do {
176 /* Is the clock locked now ? */
177 if (meson_parm_read(clk->map, &pll->l))
153 return 0; 178 return 0;
179
154 delay--; 180 delay--;
155 } 181 } while (delay > 0);
182
156 return -ETIMEDOUT; 183 return -ETIMEDOUT;
157} 184}
158 185
159static void meson_clk_pll_init_params(struct meson_clk_pll *pll) 186static void meson_clk_pll_init(struct clk_hw *hw)
160{ 187{
161 int i; 188 struct clk_regmap *clk = to_clk_regmap(hw);
162 189 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
163 for (i = 0 ; i < pll->params.params_count ; ++i) 190
164 writel(pll->params.params_table[i].value, 191 if (pll->init_count) {
165 pll->base + pll->params.params_table[i].reg_off); 192 meson_parm_write(clk->map, &pll->rst, 1);
193 regmap_multi_reg_write(clk->map, pll->init_regs,
194 pll->init_count);
195 meson_parm_write(clk->map, &pll->rst, 0);
196 }
166} 197}
167 198
168static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, 199static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
169 unsigned long parent_rate) 200 unsigned long parent_rate)
170{ 201{
171 struct meson_clk_pll *pll = to_meson_clk_pll(hw); 202 struct clk_regmap *clk = to_clk_regmap(hw);
172 struct parm *p; 203 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
173 const struct pll_rate_table *rate_set; 204 const struct pll_rate_table *pllt;
174 unsigned long old_rate; 205 unsigned long old_rate;
175 int ret = 0; 206 u16 frac = 0;
176 u32 reg;
177 207
178 if (parent_rate == 0 || rate == 0) 208 if (parent_rate == 0 || rate == 0)
179 return -EINVAL; 209 return -EINVAL;
180 210
181 old_rate = rate; 211 old_rate = rate;
182 212
183 rate_set = meson_clk_get_pll_settings(pll, rate); 213 pllt = meson_clk_get_pll_settings(rate, pll);
184 if (!rate_set) 214 if (!pllt)
185 return -EINVAL; 215 return -EINVAL;
186 216
187 /* Initialize the PLL in a clean state if specified */ 217 /* Put the pll in reset to write the params */
188 if (pll->params.params_count) 218 meson_parm_write(clk->map, &pll->rst, 1);
189 meson_clk_pll_init_params(pll);
190
191 /* PLL reset */
192 p = &pll->n;
193 reg = readl(pll->base + p->reg_off);
194 /* If no_init_reset is provided, avoid resetting at this point */
195 if (!pll->params.no_init_reset)
196 writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
197
198 reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
199 writel(reg, pll->base + p->reg_off);
200
201 p = &pll->m;
202 reg = readl(pll->base + p->reg_off);
203 reg = PARM_SET(p->width, p->shift, reg, rate_set->m);
204 writel(reg, pll->base + p->reg_off);
205
206 p = &pll->od;
207 reg = readl(pll->base + p->reg_off);
208 reg = PARM_SET(p->width, p->shift, reg, rate_set->od);
209 writel(reg, pll->base + p->reg_off);
210
211 p = &pll->od2;
212 if (p->width) {
213 reg = readl(pll->base + p->reg_off);
214 reg = PARM_SET(p->width, p->shift, reg, rate_set->od2);
215 writel(reg, pll->base + p->reg_off);
216 }
217 219
218 p = &pll->frac; 220 meson_parm_write(clk->map, &pll->n, pllt->n);
219 if (p->width) { 221 meson_parm_write(clk->map, &pll->m, pllt->m);
220 reg = readl(pll->base + p->reg_off); 222 meson_parm_write(clk->map, &pll->od, pllt->od);
221 reg = PARM_SET(p->width, p->shift, reg, rate_set->frac); 223
222 writel(reg, pll->base + p->reg_off); 224 if (MESON_PARM_APPLICABLE(&pll->od2))
223 } 225 meson_parm_write(clk->map, &pll->od2, pllt->od2);
226
227 if (MESON_PARM_APPLICABLE(&pll->od3))
228 meson_parm_write(clk->map, &pll->od3, pllt->od3);
224 229
225 p = &pll->n; 230 if (MESON_PARM_APPLICABLE(&pll->frac)) {
226 /* If clear_reset_for_lock is provided, remove the reset bit here */ 231 frac = __pll_params_with_frac(rate, parent_rate, pllt, pll);
227 if (pll->params.clear_reset_for_lock) { 232 meson_parm_write(clk->map, &pll->frac, frac);
228 reg = readl(pll->base + p->reg_off);
229 writel(reg & ~MESON_PLL_RESET, pll->base + p->reg_off);
230 } 233 }
231 234
232 /* If reset_lock_loop, use a special loop including resetting */ 235 /* make sure the reset is cleared at this point */
233 if (pll->params.reset_lock_loop) 236 meson_parm_write(clk->map, &pll->rst, 0);
234 ret = meson_clk_pll_wait_lock_reset(pll, p); 237
235 else 238 if (meson_clk_pll_wait_lock(hw)) {
236 ret = meson_clk_pll_wait_lock(pll, p);
237 if (ret) {
238 pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", 239 pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
239 __func__, old_rate); 240 __func__, old_rate);
241 /*
242 * FIXME: Do we really need/want this HACK ?
243 * It looks unsafe. what happens if the clock gets into a
244 * broken state and we can't lock back on the old_rate ? Looks
245 * like an infinite recursion is possible
246 */
240 meson_clk_pll_set_rate(hw, old_rate, parent_rate); 247 meson_clk_pll_set_rate(hw, old_rate, parent_rate);
241 } 248 }
242 249
243 return ret; 250 return 0;
244} 251}
245 252
246const struct clk_ops meson_clk_pll_ops = { 253const struct clk_ops meson_clk_pll_ops = {
254 .init = meson_clk_pll_init,
247 .recalc_rate = meson_clk_pll_recalc_rate, 255 .recalc_rate = meson_clk_pll_recalc_rate,
248 .round_rate = meson_clk_pll_round_rate, 256 .round_rate = meson_clk_pll_round_rate,
249 .set_rate = meson_clk_pll_set_rate, 257 .set_rate = meson_clk_pll_set_rate,
diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c
new file mode 100644
index 000000000000..3645fdb62343
--- /dev/null
+++ b/drivers/clk/meson/clk-regmap.c
@@ -0,0 +1,166 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 BayLibre, SAS.
3// Author: Jerome Brunet <jbrunet@baylibre.com>
4
5#include "clk-regmap.h"
6
7static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable)
8{
9 struct clk_regmap *clk = to_clk_regmap(hw);
10 struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
11 int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
12
13 set ^= enable;
14
15 return regmap_update_bits(clk->map, gate->offset, BIT(gate->bit_idx),
16 set ? BIT(gate->bit_idx) : 0);
17}
18
19static int clk_regmap_gate_enable(struct clk_hw *hw)
20{
21 return clk_regmap_gate_endisable(hw, 1);
22}
23
24static void clk_regmap_gate_disable(struct clk_hw *hw)
25{
26 clk_regmap_gate_endisable(hw, 0);
27}
28
29static int clk_regmap_gate_is_enabled(struct clk_hw *hw)
30{
31 struct clk_regmap *clk = to_clk_regmap(hw);
32 struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
33 unsigned int val;
34
35 regmap_read(clk->map, gate->offset, &val);
36 if (gate->flags & CLK_GATE_SET_TO_DISABLE)
37 val ^= BIT(gate->bit_idx);
38
39 val &= BIT(gate->bit_idx);
40
41 return val ? 1 : 0;
42}
43
44const struct clk_ops clk_regmap_gate_ops = {
45 .enable = clk_regmap_gate_enable,
46 .disable = clk_regmap_gate_disable,
47 .is_enabled = clk_regmap_gate_is_enabled,
48};
49EXPORT_SYMBOL_GPL(clk_regmap_gate_ops);
50
51static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw,
52 unsigned long prate)
53{
54 struct clk_regmap *clk = to_clk_regmap(hw);
55 struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
56 unsigned int val;
57 int ret;
58
59 ret = regmap_read(clk->map, div->offset, &val);
60 if (ret)
61 /* Gives a hint that something is wrong */
62 return 0;
63
64 val >>= div->shift;
65 val &= clk_div_mask(div->width);
66 return divider_recalc_rate(hw, prate, val, div->table, div->flags,
67 div->width);
68}
69
70static long clk_regmap_div_round_rate(struct clk_hw *hw, unsigned long rate,
71 unsigned long *prate)
72{
73 struct clk_regmap *clk = to_clk_regmap(hw);
74 struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
75 unsigned int val;
76 int ret;
77
78 /* if read only, just return current value */
79 if (div->flags & CLK_DIVIDER_READ_ONLY) {
80 ret = regmap_read(clk->map, div->offset, &val);
81 if (ret)
82 /* Gives a hint that something is wrong */
83 return 0;
84
85 val >>= div->shift;
86 val &= clk_div_mask(div->width);
87
88 return divider_ro_round_rate(hw, rate, prate, div->table,
89 div->width, div->flags, val);
90 }
91
92 return divider_round_rate(hw, rate, prate, div->table, div->width,
93 div->flags);
94}
95
96static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate,
97 unsigned long parent_rate)
98{
99 struct clk_regmap *clk = to_clk_regmap(hw);
100 struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
101 unsigned int val;
102 int ret;
103
104 ret = divider_get_val(rate, parent_rate, div->table, div->width,
105 div->flags);
106 if (ret < 0)
107 return ret;
108
109 val = (unsigned int)ret << div->shift;
110 return regmap_update_bits(clk->map, div->offset,
111 clk_div_mask(div->width) << div->shift, val);
112};
113
114/* Would prefer clk_regmap_div_ro_ops but clashes with qcom */
115
116const struct clk_ops clk_regmap_divider_ops = {
117 .recalc_rate = clk_regmap_div_recalc_rate,
118 .round_rate = clk_regmap_div_round_rate,
119 .set_rate = clk_regmap_div_set_rate,
120};
121EXPORT_SYMBOL_GPL(clk_regmap_divider_ops);
122
123const struct clk_ops clk_regmap_divider_ro_ops = {
124 .recalc_rate = clk_regmap_div_recalc_rate,
125 .round_rate = clk_regmap_div_round_rate,
126};
127EXPORT_SYMBOL_GPL(clk_regmap_divider_ro_ops);
128
129static u8 clk_regmap_mux_get_parent(struct clk_hw *hw)
130{
131 struct clk_regmap *clk = to_clk_regmap(hw);
132 struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk);
133 unsigned int val;
134 int ret;
135
136 ret = regmap_read(clk->map, mux->offset, &val);
137 if (ret)
138 return ret;
139
140 val >>= mux->shift;
141 val &= mux->mask;
142 return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
143}
144
145static int clk_regmap_mux_set_parent(struct clk_hw *hw, u8 index)
146{
147 struct clk_regmap *clk = to_clk_regmap(hw);
148 struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk);
149 unsigned int val = clk_mux_index_to_val(mux->table, mux->flags, index);
150
151 return regmap_update_bits(clk->map, mux->offset,
152 mux->mask << mux->shift,
153 val << mux->shift);
154}
155
156const struct clk_ops clk_regmap_mux_ops = {
157 .get_parent = clk_regmap_mux_get_parent,
158 .set_parent = clk_regmap_mux_set_parent,
159 .determine_rate = __clk_mux_determine_rate,
160};
161EXPORT_SYMBOL_GPL(clk_regmap_mux_ops);
162
163const struct clk_ops clk_regmap_mux_ro_ops = {
164 .get_parent = clk_regmap_mux_get_parent,
165};
166EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops);
diff --git a/drivers/clk/meson/clk-regmap.h b/drivers/clk/meson/clk-regmap.h
new file mode 100644
index 000000000000..627c888026d7
--- /dev/null
+++ b/drivers/clk/meson/clk-regmap.h
@@ -0,0 +1,111 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 BayLibre, SAS.
3// Author: Jerome Brunet <jbrunet@baylibre.com>
4
5#ifndef __CLK_REGMAP_H
6#define __CLK_REGMAP_H
7
8#include <linux/clk-provider.h>
9#include <linux/regmap.h>
10
11/**
12 * struct clk_regmap - regmap backed clock
13 *
14 * @hw: handle between common and hardware-specific interfaces
15 * @map: pointer to the regmap structure controlling the clock
16 * @data: data specific to the clock type
17 *
18 * Clock which is controlled by regmap backed registers. The actual type of
19 * of the clock is controlled by the clock_ops and data.
20 */
21struct clk_regmap {
22 struct clk_hw hw;
23 struct regmap *map;
24 void *data;
25};
26
27#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw)
28
29/**
30 * struct clk_regmap_gate_data - regmap backed gate specific data
31 *
32 * @offset: offset of the register controlling gate
33 * @bit_idx: single bit controlling gate
34 * @flags: hardware-specific flags
35 *
36 * Flags:
37 * Same as clk_gate except CLK_GATE_HIWORD_MASK which is ignored
38 */
39struct clk_regmap_gate_data {
40 unsigned int offset;
41 u8 bit_idx;
42 u8 flags;
43};
44
45static inline struct clk_regmap_gate_data *
46clk_get_regmap_gate_data(struct clk_regmap *clk)
47{
48 return (struct clk_regmap_gate_data *)clk->data;
49}
50
51extern const struct clk_ops clk_regmap_gate_ops;
52
53/**
54 * struct clk_regmap_div_data - regmap backed adjustable divider specific data
55 *
56 * @offset: offset of the register controlling the divider
57 * @shift: shift to the divider bit field
58 * @width: width of the divider bit field
59 * @table: array of value/divider pairs, last entry should have div = 0
60 *
61 * Flags:
62 * Same as clk_divider except CLK_DIVIDER_HIWORD_MASK which is ignored
63 */
64struct clk_regmap_div_data {
65 unsigned int offset;
66 u8 shift;
67 u8 width;
68 u8 flags;
69 const struct clk_div_table *table;
70};
71
72static inline struct clk_regmap_div_data *
73clk_get_regmap_div_data(struct clk_regmap *clk)
74{
75 return (struct clk_regmap_div_data *)clk->data;
76}
77
78extern const struct clk_ops clk_regmap_divider_ops;
79extern const struct clk_ops clk_regmap_divider_ro_ops;
80
81/**
82 * struct clk_regmap_mux_data - regmap backed multiplexer clock specific data
83 *
84 * @hw: handle between common and hardware-specific interfaces
85 * @offset: offset of theregister controlling multiplexer
86 * @table: array of parent indexed register values
87 * @shift: shift to multiplexer bit field
88 * @mask: mask of mutliplexer bit field
89 * @flags: hardware-specific flags
90 *
91 * Flags:
92 * Same as clk_divider except CLK_MUX_HIWORD_MASK which is ignored
93 */
94struct clk_regmap_mux_data {
95 unsigned int offset;
96 u32 *table;
97 u32 mask;
98 u8 shift;
99 u8 flags;
100};
101
102static inline struct clk_regmap_mux_data *
103clk_get_regmap_mux_data(struct clk_regmap *clk)
104{
105 return (struct clk_regmap_mux_data *)clk->data;
106}
107
108extern const struct clk_ops clk_regmap_mux_ops;
109extern const struct clk_ops clk_regmap_mux_ro_ops;
110
111#endif /* __CLK_REGMAP_H */
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index c2ff0520ce53..8fe73c4edca8 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -18,6 +18,9 @@
18#ifndef __CLKC_H 18#ifndef __CLKC_H
19#define __CLKC_H 19#define __CLKC_H
20 20
21#include <linux/clk-provider.h>
22#include "clk-regmap.h"
23
21#define PMASK(width) GENMASK(width - 1, 0) 24#define PMASK(width) GENMASK(width - 1, 0)
22#define SETPMASK(width, shift) GENMASK(shift + width - 1, shift) 25#define SETPMASK(width, shift) GENMASK(shift + width - 1, shift)
23#define CLRPMASK(width, shift) (~SETPMASK(width, shift)) 26#define CLRPMASK(width, shift) (~SETPMASK(width, shift))
@@ -35,13 +38,29 @@ struct parm {
35 u8 width; 38 u8 width;
36}; 39};
37 40
41static inline unsigned int meson_parm_read(struct regmap *map, struct parm *p)
42{
43 unsigned int val;
44
45 regmap_read(map, p->reg_off, &val);
46 return PARM_GET(p->width, p->shift, val);
47}
48
49static inline void meson_parm_write(struct regmap *map, struct parm *p,
50 unsigned int val)
51{
52 regmap_update_bits(map, p->reg_off, SETPMASK(p->width, p->shift),
53 val << p->shift);
54}
55
56
38struct pll_rate_table { 57struct pll_rate_table {
39 unsigned long rate; 58 unsigned long rate;
40 u16 m; 59 u16 m;
41 u16 n; 60 u16 n;
42 u16 od; 61 u16 od;
43 u16 od2; 62 u16 od2;
44 u16 frac; 63 u16 od3;
45}; 64};
46 65
47#define PLL_RATE(_r, _m, _n, _od) \ 66#define PLL_RATE(_r, _m, _n, _od) \
@@ -50,97 +69,53 @@ struct pll_rate_table {
50 .m = (_m), \ 69 .m = (_m), \
51 .n = (_n), \ 70 .n = (_n), \
52 .od = (_od), \ 71 .od = (_od), \
53 } \
54
55#define PLL_FRAC_RATE(_r, _m, _n, _od, _od2, _frac) \
56 { \
57 .rate = (_r), \
58 .m = (_m), \
59 .n = (_n), \
60 .od = (_od), \
61 .od2 = (_od2), \
62 .frac = (_frac), \
63 } \
64
65struct pll_params_table {
66 unsigned int reg_off;
67 unsigned int value;
68};
69
70#define PLL_PARAM(_reg, _val) \
71 { \
72 .reg_off = (_reg), \
73 .value = (_val), \
74 } 72 }
75 73
76struct pll_setup_params { 74#define CLK_MESON_PLL_ROUND_CLOSEST BIT(0)
77 struct pll_params_table *params_table;
78 unsigned int params_count;
79 /* Workaround for GP0, do not reset before configuring */
80 bool no_init_reset;
81 /* Workaround for GP0, unreset right before checking for lock */
82 bool clear_reset_for_lock;
83 /* Workaround for GXL GP0, reset in the lock checking loop */
84 bool reset_lock_loop;
85};
86 75
87struct meson_clk_pll { 76struct meson_clk_pll_data {
88 struct clk_hw hw;
89 void __iomem *base;
90 struct parm m; 77 struct parm m;
91 struct parm n; 78 struct parm n;
92 struct parm frac; 79 struct parm frac;
93 struct parm od; 80 struct parm od;
94 struct parm od2; 81 struct parm od2;
95 const struct pll_setup_params params; 82 struct parm od3;
96 const struct pll_rate_table *rate_table; 83 struct parm l;
97 unsigned int rate_count; 84 struct parm rst;
98 spinlock_t *lock; 85 const struct reg_sequence *init_regs;
86 unsigned int init_count;
87 const struct pll_rate_table *table;
88 u8 flags;
99}; 89};
100 90
101#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) 91#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
102 92
103struct meson_clk_cpu { 93struct meson_clk_mpll_data {
104 struct clk_hw hw;
105 void __iomem *base;
106 u16 reg_off;
107 struct notifier_block clk_nb;
108 const struct clk_div_table *div_table;
109};
110
111int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event,
112 void *data);
113
114struct meson_clk_mpll {
115 struct clk_hw hw;
116 void __iomem *base;
117 struct parm sdm; 94 struct parm sdm;
118 struct parm sdm_en; 95 struct parm sdm_en;
119 struct parm n2; 96 struct parm n2;
120 struct parm en;
121 struct parm ssen; 97 struct parm ssen;
98 struct parm misc;
122 spinlock_t *lock; 99 spinlock_t *lock;
123}; 100};
124 101
125struct meson_clk_audio_divider { 102struct meson_clk_audio_div_data {
126 struct clk_hw hw;
127 void __iomem *base;
128 struct parm div; 103 struct parm div;
129 u8 flags; 104 u8 flags;
130 spinlock_t *lock;
131}; 105};
132 106
133#define MESON_GATE(_name, _reg, _bit) \ 107#define MESON_GATE(_name, _reg, _bit) \
134struct clk_gate _name = { \ 108struct clk_regmap _name = { \
135 .reg = (void __iomem *) _reg, \ 109 .data = &(struct clk_regmap_gate_data){ \
136 .bit_idx = (_bit), \ 110 .offset = (_reg), \
137 .lock = &meson_clk_lock, \ 111 .bit_idx = (_bit), \
138 .hw.init = &(struct clk_init_data) { \ 112 }, \
139 .name = #_name, \ 113 .hw.init = &(struct clk_init_data) { \
140 .ops = &clk_gate_ops, \ 114 .name = #_name, \
115 .ops = &clk_regmap_gate_ops, \
141 .parent_names = (const char *[]){ "clk81" }, \ 116 .parent_names = (const char *[]){ "clk81" }, \
142 .num_parents = 1, \ 117 .num_parents = 1, \
143 .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ 118 .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
144 }, \ 119 }, \
145}; 120};
146 121
diff --git a/drivers/clk/meson/gxbb-aoclk-regmap.c b/drivers/clk/meson/gxbb-aoclk-regmap.c
deleted file mode 100644
index 2515fbfa0467..000000000000
--- a/drivers/clk/meson/gxbb-aoclk-regmap.c
+++ /dev/null
@@ -1,46 +0,0 @@
1/*
2 * Copyright (c) 2017 BayLibre, SAS.
3 * Author: Neil Armstrong <narmstrong@baylibre.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <linux/clk-provider.h>
9#include <linux/bitfield.h>
10#include <linux/regmap.h>
11#include "gxbb-aoclk.h"
12
13static int aoclk_gate_regmap_enable(struct clk_hw *hw)
14{
15 struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw);
16
17 return regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0,
18 BIT(gate->bit_idx), BIT(gate->bit_idx));
19}
20
21static void aoclk_gate_regmap_disable(struct clk_hw *hw)
22{
23 struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw);
24
25 regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0,
26 BIT(gate->bit_idx), 0);
27}
28
29static int aoclk_gate_regmap_is_enabled(struct clk_hw *hw)
30{
31 struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw);
32 unsigned int val;
33 int ret;
34
35 ret = regmap_read(gate->regmap, AO_RTI_GEN_CNTL_REG0, &val);
36 if (ret)
37 return ret;
38
39 return (val & BIT(gate->bit_idx)) != 0;
40}
41
42const struct clk_ops meson_aoclk_gate_regmap_ops = {
43 .enable = aoclk_gate_regmap_enable,
44 .disable = aoclk_gate_regmap_disable,
45 .is_enabled = aoclk_gate_regmap_is_enabled,
46};
diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c
index 6c161e0a8e59..9ec23ae9a219 100644
--- a/drivers/clk/meson/gxbb-aoclk.c
+++ b/drivers/clk/meson/gxbb-aoclk.c
@@ -62,10 +62,9 @@
62#include <linux/delay.h> 62#include <linux/delay.h>
63#include <dt-bindings/clock/gxbb-aoclkc.h> 63#include <dt-bindings/clock/gxbb-aoclkc.h>
64#include <dt-bindings/reset/gxbb-aoclkc.h> 64#include <dt-bindings/reset/gxbb-aoclkc.h>
65#include "clk-regmap.h"
65#include "gxbb-aoclk.h" 66#include "gxbb-aoclk.h"
66 67
67static DEFINE_SPINLOCK(gxbb_aoclk_lock);
68
69struct gxbb_aoclk_reset_controller { 68struct gxbb_aoclk_reset_controller {
70 struct reset_controller_dev reset; 69 struct reset_controller_dev reset;
71 unsigned int *data; 70 unsigned int *data;
@@ -87,12 +86,14 @@ static const struct reset_control_ops gxbb_aoclk_reset_ops = {
87}; 86};
88 87
89#define GXBB_AO_GATE(_name, _bit) \ 88#define GXBB_AO_GATE(_name, _bit) \
90static struct aoclk_gate_regmap _name##_ao = { \ 89static struct clk_regmap _name##_ao = { \
91 .bit_idx = (_bit), \ 90 .data = &(struct clk_regmap_gate_data) { \
92 .lock = &gxbb_aoclk_lock, \ 91 .offset = AO_RTI_GEN_CNTL_REG0, \
92 .bit_idx = (_bit), \
93 }, \
93 .hw.init = &(struct clk_init_data) { \ 94 .hw.init = &(struct clk_init_data) { \
94 .name = #_name "_ao", \ 95 .name = #_name "_ao", \
95 .ops = &meson_aoclk_gate_regmap_ops, \ 96 .ops = &clk_regmap_gate_ops, \
96 .parent_names = (const char *[]){ "clk81" }, \ 97 .parent_names = (const char *[]){ "clk81" }, \
97 .num_parents = 1, \ 98 .num_parents = 1, \
98 .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ 99 .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
@@ -107,7 +108,6 @@ GXBB_AO_GATE(uart2, 5);
107GXBB_AO_GATE(ir_blaster, 6); 108GXBB_AO_GATE(ir_blaster, 6);
108 109
109static struct aoclk_cec_32k cec_32k_ao = { 110static struct aoclk_cec_32k cec_32k_ao = {
110 .lock = &gxbb_aoclk_lock,
111 .hw.init = &(struct clk_init_data) { 111 .hw.init = &(struct clk_init_data) {
112 .name = "cec_32k_ao", 112 .name = "cec_32k_ao",
113 .ops = &meson_aoclk_cec_32k_ops, 113 .ops = &meson_aoclk_cec_32k_ops,
@@ -126,7 +126,7 @@ static unsigned int gxbb_aoclk_reset[] = {
126 [RESET_AO_IR_BLASTER] = 23, 126 [RESET_AO_IR_BLASTER] = 23,
127}; 127};
128 128
129static struct aoclk_gate_regmap *gxbb_aoclk_gate[] = { 129static struct clk_regmap *gxbb_aoclk_gate[] = {
130 [CLKID_AO_REMOTE] = &remote_ao, 130 [CLKID_AO_REMOTE] = &remote_ao,
131 [CLKID_AO_I2C_MASTER] = &i2c_master_ao, 131 [CLKID_AO_I2C_MASTER] = &i2c_master_ao,
132 [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao, 132 [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao,
@@ -177,10 +177,10 @@ static int gxbb_aoclkc_probe(struct platform_device *pdev)
177 * Populate regmap and register all clks 177 * Populate regmap and register all clks
178 */ 178 */
179 for (clkid = 0; clkid < ARRAY_SIZE(gxbb_aoclk_gate); clkid++) { 179 for (clkid = 0; clkid < ARRAY_SIZE(gxbb_aoclk_gate); clkid++) {
180 gxbb_aoclk_gate[clkid]->regmap = regmap; 180 gxbb_aoclk_gate[clkid]->map = regmap;
181 181
182 ret = devm_clk_hw_register(dev, 182 ret = devm_clk_hw_register(dev,
183 gxbb_aoclk_onecell_data.hws[clkid]); 183 gxbb_aoclk_onecell_data.hws[clkid]);
184 if (ret) 184 if (ret)
185 return ret; 185 return ret;
186 } 186 }
diff --git a/drivers/clk/meson/gxbb-aoclk.h b/drivers/clk/meson/gxbb-aoclk.h
index e8604c8f7eee..0be78383f257 100644
--- a/drivers/clk/meson/gxbb-aoclk.h
+++ b/drivers/clk/meson/gxbb-aoclk.h
@@ -17,22 +17,11 @@
17#define AO_RTC_ALT_CLK_CNTL0 0x94 17#define AO_RTC_ALT_CLK_CNTL0 0x94
18#define AO_RTC_ALT_CLK_CNTL1 0x98 18#define AO_RTC_ALT_CLK_CNTL1 0x98
19 19
20struct aoclk_gate_regmap {
21 struct clk_hw hw;
22 unsigned bit_idx;
23 struct regmap *regmap;
24 spinlock_t *lock;
25};
26
27#define to_aoclk_gate_regmap(_hw) \
28 container_of(_hw, struct aoclk_gate_regmap, hw)
29
30extern const struct clk_ops meson_aoclk_gate_regmap_ops; 20extern const struct clk_ops meson_aoclk_gate_regmap_ops;
31 21
32struct aoclk_cec_32k { 22struct aoclk_cec_32k {
33 struct clk_hw hw; 23 struct clk_hw hw;
34 struct regmap *regmap; 24 struct regmap *regmap;
35 spinlock_t *lock;
36}; 25};
37 26
38#define to_aoclk_cec_32k(_hw) container_of(_hw, struct aoclk_cec_32k, hw) 27#define to_aoclk_cec_32k(_hw) container_of(_hw, struct aoclk_cec_32k, hw)
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index af24455af5b4..b1e4d9557610 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -19,108 +19,19 @@
19 19
20#include <linux/clk.h> 20#include <linux/clk.h>
21#include <linux/clk-provider.h> 21#include <linux/clk-provider.h>
22#include <linux/init.h>
22#include <linux/of_address.h> 23#include <linux/of_address.h>
23#include <linux/of_device.h> 24#include <linux/of_device.h>
25#include <linux/mfd/syscon.h>
24#include <linux/platform_device.h> 26#include <linux/platform_device.h>
25#include <linux/init.h> 27#include <linux/regmap.h>
26 28
27#include "clkc.h" 29#include "clkc.h"
28#include "gxbb.h" 30#include "gxbb.h"
31#include "clk-regmap.h"
29 32
30static DEFINE_SPINLOCK(meson_clk_lock); 33static DEFINE_SPINLOCK(meson_clk_lock);
31 34
32static const struct pll_rate_table sys_pll_rate_table[] = {
33 PLL_RATE(24000000, 56, 1, 2),
34 PLL_RATE(48000000, 64, 1, 2),
35 PLL_RATE(72000000, 72, 1, 2),
36 PLL_RATE(96000000, 64, 1, 2),
37 PLL_RATE(120000000, 80, 1, 2),
38 PLL_RATE(144000000, 96, 1, 2),
39 PLL_RATE(168000000, 56, 1, 1),
40 PLL_RATE(192000000, 64, 1, 1),
41 PLL_RATE(216000000, 72, 1, 1),
42 PLL_RATE(240000000, 80, 1, 1),
43 PLL_RATE(264000000, 88, 1, 1),
44 PLL_RATE(288000000, 96, 1, 1),
45 PLL_RATE(312000000, 52, 1, 2),
46 PLL_RATE(336000000, 56, 1, 2),
47 PLL_RATE(360000000, 60, 1, 2),
48 PLL_RATE(384000000, 64, 1, 2),
49 PLL_RATE(408000000, 68, 1, 2),
50 PLL_RATE(432000000, 72, 1, 2),
51 PLL_RATE(456000000, 76, 1, 2),
52 PLL_RATE(480000000, 80, 1, 2),
53 PLL_RATE(504000000, 84, 1, 2),
54 PLL_RATE(528000000, 88, 1, 2),
55 PLL_RATE(552000000, 92, 1, 2),
56 PLL_RATE(576000000, 96, 1, 2),
57 PLL_RATE(600000000, 50, 1, 1),
58 PLL_RATE(624000000, 52, 1, 1),
59 PLL_RATE(648000000, 54, 1, 1),
60 PLL_RATE(672000000, 56, 1, 1),
61 PLL_RATE(696000000, 58, 1, 1),
62 PLL_RATE(720000000, 60, 1, 1),
63 PLL_RATE(744000000, 62, 1, 1),
64 PLL_RATE(768000000, 64, 1, 1),
65 PLL_RATE(792000000, 66, 1, 1),
66 PLL_RATE(816000000, 68, 1, 1),
67 PLL_RATE(840000000, 70, 1, 1),
68 PLL_RATE(864000000, 72, 1, 1),
69 PLL_RATE(888000000, 74, 1, 1),
70 PLL_RATE(912000000, 76, 1, 1),
71 PLL_RATE(936000000, 78, 1, 1),
72 PLL_RATE(960000000, 80, 1, 1),
73 PLL_RATE(984000000, 82, 1, 1),
74 PLL_RATE(1008000000, 84, 1, 1),
75 PLL_RATE(1032000000, 86, 1, 1),
76 PLL_RATE(1056000000, 88, 1, 1),
77 PLL_RATE(1080000000, 90, 1, 1),
78 PLL_RATE(1104000000, 92, 1, 1),
79 PLL_RATE(1128000000, 94, 1, 1),
80 PLL_RATE(1152000000, 96, 1, 1),
81 PLL_RATE(1176000000, 98, 1, 1),
82 PLL_RATE(1200000000, 50, 1, 0),
83 PLL_RATE(1224000000, 51, 1, 0),
84 PLL_RATE(1248000000, 52, 1, 0),
85 PLL_RATE(1272000000, 53, 1, 0),
86 PLL_RATE(1296000000, 54, 1, 0),
87 PLL_RATE(1320000000, 55, 1, 0),
88 PLL_RATE(1344000000, 56, 1, 0),
89 PLL_RATE(1368000000, 57, 1, 0),
90 PLL_RATE(1392000000, 58, 1, 0),
91 PLL_RATE(1416000000, 59, 1, 0),
92 PLL_RATE(1440000000, 60, 1, 0),
93 PLL_RATE(1464000000, 61, 1, 0),
94 PLL_RATE(1488000000, 62, 1, 0),
95 PLL_RATE(1512000000, 63, 1, 0),
96 PLL_RATE(1536000000, 64, 1, 0),
97 PLL_RATE(1560000000, 65, 1, 0),
98 PLL_RATE(1584000000, 66, 1, 0),
99 PLL_RATE(1608000000, 67, 1, 0),
100 PLL_RATE(1632000000, 68, 1, 0),
101 PLL_RATE(1656000000, 68, 1, 0),
102 PLL_RATE(1680000000, 68, 1, 0),
103 PLL_RATE(1704000000, 68, 1, 0),
104 PLL_RATE(1728000000, 69, 1, 0),
105 PLL_RATE(1752000000, 69, 1, 0),
106 PLL_RATE(1776000000, 69, 1, 0),
107 PLL_RATE(1800000000, 69, 1, 0),
108 PLL_RATE(1824000000, 70, 1, 0),
109 PLL_RATE(1848000000, 70, 1, 0),
110 PLL_RATE(1872000000, 70, 1, 0),
111 PLL_RATE(1896000000, 70, 1, 0),
112 PLL_RATE(1920000000, 71, 1, 0),
113 PLL_RATE(1944000000, 71, 1, 0),
114 PLL_RATE(1968000000, 71, 1, 0),
115 PLL_RATE(1992000000, 71, 1, 0),
116 PLL_RATE(2016000000, 72, 1, 0),
117 PLL_RATE(2040000000, 72, 1, 0),
118 PLL_RATE(2064000000, 72, 1, 0),
119 PLL_RATE(2088000000, 72, 1, 0),
120 PLL_RATE(2112000000, 73, 1, 0),
121 { /* sentinel */ },
122};
123
124static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = { 35static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
125 PLL_RATE(96000000, 32, 1, 3), 36 PLL_RATE(96000000, 32, 1, 3),
126 PLL_RATE(99000000, 33, 1, 3), 37 PLL_RATE(99000000, 33, 1, 3),
@@ -278,23 +189,39 @@ static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
278 { /* sentinel */ }, 189 { /* sentinel */ },
279}; 190};
280 191
281static struct meson_clk_pll gxbb_fixed_pll = { 192static struct clk_regmap gxbb_fixed_pll = {
282 .m = { 193 .data = &(struct meson_clk_pll_data){
283 .reg_off = HHI_MPLL_CNTL, 194 .m = {
284 .shift = 0, 195 .reg_off = HHI_MPLL_CNTL,
285 .width = 9, 196 .shift = 0,
197 .width = 9,
198 },
199 .n = {
200 .reg_off = HHI_MPLL_CNTL,
201 .shift = 9,
202 .width = 5,
203 },
204 .od = {
205 .reg_off = HHI_MPLL_CNTL,
206 .shift = 16,
207 .width = 2,
208 },
209 .frac = {
210 .reg_off = HHI_MPLL_CNTL2,
211 .shift = 0,
212 .width = 12,
213 },
214 .l = {
215 .reg_off = HHI_MPLL_CNTL,
216 .shift = 31,
217 .width = 1,
218 },
219 .rst = {
220 .reg_off = HHI_MPLL_CNTL,
221 .shift = 29,
222 .width = 1,
223 },
286 }, 224 },
287 .n = {
288 .reg_off = HHI_MPLL_CNTL,
289 .shift = 9,
290 .width = 5,
291 },
292 .od = {
293 .reg_off = HHI_MPLL_CNTL,
294 .shift = 16,
295 .width = 2,
296 },
297 .lock = &meson_clk_lock,
298 .hw.init = &(struct clk_init_data){ 225 .hw.init = &(struct clk_init_data){
299 .name = "fixed_pll", 226 .name = "fixed_pll",
300 .ops = &meson_clk_pll_ro_ops, 227 .ops = &meson_clk_pll_ro_ops,
@@ -304,33 +231,118 @@ static struct meson_clk_pll gxbb_fixed_pll = {
304 }, 231 },
305}; 232};
306 233
307static struct meson_clk_pll gxbb_hdmi_pll = { 234static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
308 .m = { 235 .mult = 2,
309 .reg_off = HHI_HDMI_PLL_CNTL, 236 .div = 1,
310 .shift = 0, 237 .hw.init = &(struct clk_init_data){
311 .width = 9, 238 .name = "hdmi_pll_pre_mult",
312 }, 239 .ops = &clk_fixed_factor_ops,
313 .n = { 240 .parent_names = (const char *[]){ "xtal" },
314 .reg_off = HHI_HDMI_PLL_CNTL, 241 .num_parents = 1,
315 .shift = 9,
316 .width = 5,
317 }, 242 },
318 .frac = { 243};
319 .reg_off = HHI_HDMI_PLL_CNTL2, 244
320 .shift = 0, 245static struct clk_regmap gxbb_hdmi_pll = {
321 .width = 12, 246 .data = &(struct meson_clk_pll_data){
247 .m = {
248 .reg_off = HHI_HDMI_PLL_CNTL,
249 .shift = 0,
250 .width = 9,
251 },
252 .n = {
253 .reg_off = HHI_HDMI_PLL_CNTL,
254 .shift = 9,
255 .width = 5,
256 },
257 .frac = {
258 .reg_off = HHI_HDMI_PLL_CNTL2,
259 .shift = 0,
260 .width = 12,
261 },
262 .od = {
263 .reg_off = HHI_HDMI_PLL_CNTL2,
264 .shift = 16,
265 .width = 2,
266 },
267 .od2 = {
268 .reg_off = HHI_HDMI_PLL_CNTL2,
269 .shift = 22,
270 .width = 2,
271 },
272 .od3 = {
273 .reg_off = HHI_HDMI_PLL_CNTL2,
274 .shift = 18,
275 .width = 2,
276 },
277 .l = {
278 .reg_off = HHI_HDMI_PLL_CNTL,
279 .shift = 31,
280 .width = 1,
281 },
282 .rst = {
283 .reg_off = HHI_HDMI_PLL_CNTL,
284 .shift = 28,
285 .width = 1,
286 },
322 }, 287 },
323 .od = { 288 .hw.init = &(struct clk_init_data){
324 .reg_off = HHI_HDMI_PLL_CNTL2, 289 .name = "hdmi_pll",
325 .shift = 16, 290 .ops = &meson_clk_pll_ro_ops,
326 .width = 2, 291 .parent_names = (const char *[]){ "hdmi_pll_pre_mult" },
292 .num_parents = 1,
293 .flags = CLK_GET_RATE_NOCACHE,
327 }, 294 },
328 .od2 = { 295};
329 .reg_off = HHI_HDMI_PLL_CNTL2, 296
330 .shift = 22, 297static struct clk_regmap gxl_hdmi_pll = {
331 .width = 2, 298 .data = &(struct meson_clk_pll_data){
299 .m = {
300 .reg_off = HHI_HDMI_PLL_CNTL,
301 .shift = 0,
302 .width = 9,
303 },
304 .n = {
305 .reg_off = HHI_HDMI_PLL_CNTL,
306 .shift = 9,
307 .width = 5,
308 },
309 .frac = {
310 /*
311 * On gxl, there is a register shift due to
312 * HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
313 * so we compute the register offset based on the PLL
314 * base to get it right
315 */
316 .reg_off = HHI_HDMI_PLL_CNTL + 4,
317 .shift = 0,
318 .width = 12,
319 },
320 .od = {
321 .reg_off = HHI_HDMI_PLL_CNTL + 8,
322 .shift = 21,
323 .width = 2,
324 },
325 .od2 = {
326 .reg_off = HHI_HDMI_PLL_CNTL + 8,
327 .shift = 23,
328 .width = 2,
329 },
330 .od3 = {
331 .reg_off = HHI_HDMI_PLL_CNTL + 8,
332 .shift = 19,
333 .width = 2,
334 },
335 .l = {
336 .reg_off = HHI_HDMI_PLL_CNTL,
337 .shift = 31,
338 .width = 1,
339 },
340 .rst = {
341 .reg_off = HHI_HDMI_PLL_CNTL,
342 .shift = 29,
343 .width = 1,
344 },
332 }, 345 },
333 .lock = &meson_clk_lock,
334 .hw.init = &(struct clk_init_data){ 346 .hw.init = &(struct clk_init_data){
335 .name = "hdmi_pll", 347 .name = "hdmi_pll",
336 .ops = &meson_clk_pll_ro_ops, 348 .ops = &meson_clk_pll_ro_ops,
@@ -340,25 +352,34 @@ static struct meson_clk_pll gxbb_hdmi_pll = {
340 }, 352 },
341}; 353};
342 354
343static struct meson_clk_pll gxbb_sys_pll = { 355static struct clk_regmap gxbb_sys_pll = {
344 .m = { 356 .data = &(struct meson_clk_pll_data){
345 .reg_off = HHI_SYS_PLL_CNTL, 357 .m = {
346 .shift = 0, 358 .reg_off = HHI_SYS_PLL_CNTL,
347 .width = 9, 359 .shift = 0,
348 }, 360 .width = 9,
349 .n = { 361 },
350 .reg_off = HHI_SYS_PLL_CNTL, 362 .n = {
351 .shift = 9, 363 .reg_off = HHI_SYS_PLL_CNTL,
352 .width = 5, 364 .shift = 9,
365 .width = 5,
366 },
367 .od = {
368 .reg_off = HHI_SYS_PLL_CNTL,
369 .shift = 10,
370 .width = 2,
371 },
372 .l = {
373 .reg_off = HHI_SYS_PLL_CNTL,
374 .shift = 31,
375 .width = 1,
376 },
377 .rst = {
378 .reg_off = HHI_SYS_PLL_CNTL,
379 .shift = 29,
380 .width = 1,
381 },
353 }, 382 },
354 .od = {
355 .reg_off = HHI_SYS_PLL_CNTL,
356 .shift = 10,
357 .width = 2,
358 },
359 .rate_table = sys_pll_rate_table,
360 .rate_count = ARRAY_SIZE(sys_pll_rate_table),
361 .lock = &meson_clk_lock,
362 .hw.init = &(struct clk_init_data){ 383 .hw.init = &(struct clk_init_data){
363 .name = "sys_pll", 384 .name = "sys_pll",
364 .ops = &meson_clk_pll_ro_ops, 385 .ops = &meson_clk_pll_ro_ops,
@@ -368,38 +389,44 @@ static struct meson_clk_pll gxbb_sys_pll = {
368 }, 389 },
369}; 390};
370 391
371struct pll_params_table gxbb_gp0_params_table[] = { 392static const struct reg_sequence gxbb_gp0_init_regs[] = {
372 PLL_PARAM(HHI_GP0_PLL_CNTL, 0x6a000228), 393 { .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 },
373 PLL_PARAM(HHI_GP0_PLL_CNTL2, 0x69c80000), 394 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 },
374 PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a5590c4), 395 { .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d },
375 PLL_PARAM(HHI_GP0_PLL_CNTL4, 0x0000500d), 396 { .reg = HHI_GP0_PLL_CNTL, .def = 0x4a000228 },
376}; 397};
377 398
378static struct meson_clk_pll gxbb_gp0_pll = { 399static struct clk_regmap gxbb_gp0_pll = {
379 .m = { 400 .data = &(struct meson_clk_pll_data){
380 .reg_off = HHI_GP0_PLL_CNTL, 401 .m = {
381 .shift = 0, 402 .reg_off = HHI_GP0_PLL_CNTL,
382 .width = 9, 403 .shift = 0,
383 }, 404 .width = 9,
384 .n = { 405 },
385 .reg_off = HHI_GP0_PLL_CNTL, 406 .n = {
386 .shift = 9, 407 .reg_off = HHI_GP0_PLL_CNTL,
387 .width = 5, 408 .shift = 9,
388 }, 409 .width = 5,
389 .od = { 410 },
390 .reg_off = HHI_GP0_PLL_CNTL, 411 .od = {
391 .shift = 16, 412 .reg_off = HHI_GP0_PLL_CNTL,
392 .width = 2, 413 .shift = 16,
393 }, 414 .width = 2,
394 .params = { 415 },
395 .params_table = gxbb_gp0_params_table, 416 .l = {
396 .params_count = ARRAY_SIZE(gxbb_gp0_params_table), 417 .reg_off = HHI_GP0_PLL_CNTL,
397 .no_init_reset = true, 418 .shift = 31,
398 .clear_reset_for_lock = true, 419 .width = 1,
420 },
421 .rst = {
422 .reg_off = HHI_GP0_PLL_CNTL,
423 .shift = 29,
424 .width = 1,
425 },
426 .table = gxbb_gp0_pll_rate_table,
427 .init_regs = gxbb_gp0_init_regs,
428 .init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
399 }, 429 },
400 .rate_table = gxbb_gp0_pll_rate_table,
401 .rate_count = ARRAY_SIZE(gxbb_gp0_pll_rate_table),
402 .lock = &meson_clk_lock,
403 .hw.init = &(struct clk_init_data){ 430 .hw.init = &(struct clk_init_data){
404 .name = "gp0_pll", 431 .name = "gp0_pll",
405 .ops = &meson_clk_pll_ops, 432 .ops = &meson_clk_pll_ops,
@@ -409,40 +436,51 @@ static struct meson_clk_pll gxbb_gp0_pll = {
409 }, 436 },
410}; 437};
411 438
412struct pll_params_table gxl_gp0_params_table[] = { 439static const struct reg_sequence gxl_gp0_init_regs[] = {
413 PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250), 440 { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084b000 },
414 PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000), 441 { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be },
415 PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be), 442 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
416 PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288), 443 { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
417 PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d), 444 { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
418 PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000), 445 { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
419}; 446};
420 447
421static struct meson_clk_pll gxl_gp0_pll = { 448static struct clk_regmap gxl_gp0_pll = {
422 .m = { 449 .data = &(struct meson_clk_pll_data){
423 .reg_off = HHI_GP0_PLL_CNTL, 450 .m = {
424 .shift = 0, 451 .reg_off = HHI_GP0_PLL_CNTL,
425 .width = 9, 452 .shift = 0,
426 }, 453 .width = 9,
427 .n = { 454 },
428 .reg_off = HHI_GP0_PLL_CNTL, 455 .n = {
429 .shift = 9, 456 .reg_off = HHI_GP0_PLL_CNTL,
430 .width = 5, 457 .shift = 9,
431 }, 458 .width = 5,
432 .od = { 459 },
433 .reg_off = HHI_GP0_PLL_CNTL, 460 .od = {
434 .shift = 16, 461 .reg_off = HHI_GP0_PLL_CNTL,
435 .width = 2, 462 .shift = 16,
463 .width = 2,
464 },
465 .frac = {
466 .reg_off = HHI_GP0_PLL_CNTL1,
467 .shift = 0,
468 .width = 10,
469 },
470 .l = {
471 .reg_off = HHI_GP0_PLL_CNTL,
472 .shift = 31,
473 .width = 1,
474 },
475 .rst = {
476 .reg_off = HHI_GP0_PLL_CNTL,
477 .shift = 29,
478 .width = 1,
479 },
480 .table = gxl_gp0_pll_rate_table,
481 .init_regs = gxl_gp0_init_regs,
482 .init_count = ARRAY_SIZE(gxl_gp0_init_regs),
436 }, 483 },
437 .params = {
438 .params_table = gxl_gp0_params_table,
439 .params_count = ARRAY_SIZE(gxl_gp0_params_table),
440 .no_init_reset = true,
441 .reset_lock_loop = true,
442 },
443 .rate_table = gxl_gp0_pll_rate_table,
444 .rate_count = ARRAY_SIZE(gxl_gp0_pll_rate_table),
445 .lock = &meson_clk_lock,
446 .hw.init = &(struct clk_init_data){ 484 .hw.init = &(struct clk_init_data){
447 .name = "gp0_pll", 485 .name = "gp0_pll",
448 .ops = &meson_clk_pll_ops, 486 .ops = &meson_clk_pll_ops,
@@ -452,161 +490,267 @@ static struct meson_clk_pll gxl_gp0_pll = {
452 }, 490 },
453}; 491};
454 492
455static struct clk_fixed_factor gxbb_fclk_div2 = { 493static struct clk_fixed_factor gxbb_fclk_div2_div = {
456 .mult = 1, 494 .mult = 1,
457 .div = 2, 495 .div = 2,
458 .hw.init = &(struct clk_init_data){ 496 .hw.init = &(struct clk_init_data){
459 .name = "fclk_div2", 497 .name = "fclk_div2_div",
460 .ops = &clk_fixed_factor_ops, 498 .ops = &clk_fixed_factor_ops,
461 .parent_names = (const char *[]){ "fixed_pll" }, 499 .parent_names = (const char *[]){ "fixed_pll" },
462 .num_parents = 1, 500 .num_parents = 1,
463 }, 501 },
464}; 502};
465 503
466static struct clk_fixed_factor gxbb_fclk_div3 = { 504static struct clk_regmap gxbb_fclk_div2 = {
505 .data = &(struct clk_regmap_gate_data){
506 .offset = HHI_MPLL_CNTL6,
507 .bit_idx = 27,
508 },
509 .hw.init = &(struct clk_init_data){
510 .name = "fclk_div2",
511 .ops = &clk_regmap_gate_ops,
512 .parent_names = (const char *[]){ "fclk_div2_div" },
513 .num_parents = 1,
514 },
515};
516
517static struct clk_fixed_factor gxbb_fclk_div3_div = {
467 .mult = 1, 518 .mult = 1,
468 .div = 3, 519 .div = 3,
469 .hw.init = &(struct clk_init_data){ 520 .hw.init = &(struct clk_init_data){
470 .name = "fclk_div3", 521 .name = "fclk_div3_div",
471 .ops = &clk_fixed_factor_ops, 522 .ops = &clk_fixed_factor_ops,
472 .parent_names = (const char *[]){ "fixed_pll" }, 523 .parent_names = (const char *[]){ "fixed_pll" },
473 .num_parents = 1, 524 .num_parents = 1,
474 }, 525 },
475}; 526};
476 527
477static struct clk_fixed_factor gxbb_fclk_div4 = { 528static struct clk_regmap gxbb_fclk_div3 = {
529 .data = &(struct clk_regmap_gate_data){
530 .offset = HHI_MPLL_CNTL6,
531 .bit_idx = 28,
532 },
533 .hw.init = &(struct clk_init_data){
534 .name = "fclk_div3",
535 .ops = &clk_regmap_gate_ops,
536 .parent_names = (const char *[]){ "fclk_div3_div" },
537 .num_parents = 1,
538 },
539};
540
541static struct clk_fixed_factor gxbb_fclk_div4_div = {
478 .mult = 1, 542 .mult = 1,
479 .div = 4, 543 .div = 4,
480 .hw.init = &(struct clk_init_data){ 544 .hw.init = &(struct clk_init_data){
481 .name = "fclk_div4", 545 .name = "fclk_div4_div",
482 .ops = &clk_fixed_factor_ops, 546 .ops = &clk_fixed_factor_ops,
483 .parent_names = (const char *[]){ "fixed_pll" }, 547 .parent_names = (const char *[]){ "fixed_pll" },
484 .num_parents = 1, 548 .num_parents = 1,
485 }, 549 },
486}; 550};
487 551
488static struct clk_fixed_factor gxbb_fclk_div5 = { 552static struct clk_regmap gxbb_fclk_div4 = {
553 .data = &(struct clk_regmap_gate_data){
554 .offset = HHI_MPLL_CNTL6,
555 .bit_idx = 29,
556 },
557 .hw.init = &(struct clk_init_data){
558 .name = "fclk_div4",
559 .ops = &clk_regmap_gate_ops,
560 .parent_names = (const char *[]){ "fclk_div4_div" },
561 .num_parents = 1,
562 },
563};
564
565static struct clk_fixed_factor gxbb_fclk_div5_div = {
489 .mult = 1, 566 .mult = 1,
490 .div = 5, 567 .div = 5,
491 .hw.init = &(struct clk_init_data){ 568 .hw.init = &(struct clk_init_data){
492 .name = "fclk_div5", 569 .name = "fclk_div5_div",
493 .ops = &clk_fixed_factor_ops, 570 .ops = &clk_fixed_factor_ops,
494 .parent_names = (const char *[]){ "fixed_pll" }, 571 .parent_names = (const char *[]){ "fixed_pll" },
495 .num_parents = 1, 572 .num_parents = 1,
496 }, 573 },
497}; 574};
498 575
499static struct clk_fixed_factor gxbb_fclk_div7 = { 576static struct clk_regmap gxbb_fclk_div5 = {
577 .data = &(struct clk_regmap_gate_data){
578 .offset = HHI_MPLL_CNTL6,
579 .bit_idx = 30,
580 },
581 .hw.init = &(struct clk_init_data){
582 .name = "fclk_div5",
583 .ops = &clk_regmap_gate_ops,
584 .parent_names = (const char *[]){ "fclk_div5_div" },
585 .num_parents = 1,
586 },
587};
588
589static struct clk_fixed_factor gxbb_fclk_div7_div = {
500 .mult = 1, 590 .mult = 1,
501 .div = 7, 591 .div = 7,
502 .hw.init = &(struct clk_init_data){ 592 .hw.init = &(struct clk_init_data){
503 .name = "fclk_div7", 593 .name = "fclk_div7_div",
504 .ops = &clk_fixed_factor_ops, 594 .ops = &clk_fixed_factor_ops,
505 .parent_names = (const char *[]){ "fixed_pll" }, 595 .parent_names = (const char *[]){ "fixed_pll" },
506 .num_parents = 1, 596 .num_parents = 1,
507 }, 597 },
508}; 598};
509 599
510static struct meson_clk_mpll gxbb_mpll0 = { 600static struct clk_regmap gxbb_fclk_div7 = {
511 .sdm = { 601 .data = &(struct clk_regmap_gate_data){
512 .reg_off = HHI_MPLL_CNTL7, 602 .offset = HHI_MPLL_CNTL6,
513 .shift = 0, 603 .bit_idx = 31,
514 .width = 14,
515 }, 604 },
516 .sdm_en = { 605 .hw.init = &(struct clk_init_data){
517 .reg_off = HHI_MPLL_CNTL7, 606 .name = "fclk_div7",
518 .shift = 15, 607 .ops = &clk_regmap_gate_ops,
519 .width = 1, 608 .parent_names = (const char *[]){ "fclk_div7_div" },
609 .num_parents = 1,
520 }, 610 },
521 .n2 = { 611};
522 .reg_off = HHI_MPLL_CNTL7, 612
523 .shift = 16, 613static struct clk_regmap gxbb_mpll_prediv = {
524 .width = 9, 614 .data = &(struct clk_regmap_div_data){
615 .offset = HHI_MPLL_CNTL5,
616 .shift = 12,
617 .width = 1,
525 }, 618 },
526 .en = { 619 .hw.init = &(struct clk_init_data){
527 .reg_off = HHI_MPLL_CNTL7, 620 .name = "mpll_prediv",
528 .shift = 14, 621 .ops = &clk_regmap_divider_ro_ops,
529 .width = 1, 622 .parent_names = (const char *[]){ "fixed_pll" },
623 .num_parents = 1,
530 }, 624 },
531 .ssen = { 625};
532 .reg_off = HHI_MPLL_CNTL, 626
533 .shift = 25, 627static struct clk_regmap gxbb_mpll0_div = {
534 .width = 1, 628 .data = &(struct meson_clk_mpll_data){
629 .sdm = {
630 .reg_off = HHI_MPLL_CNTL7,
631 .shift = 0,
632 .width = 14,
633 },
634 .sdm_en = {
635 .reg_off = HHI_MPLL_CNTL7,
636 .shift = 15,
637 .width = 1,
638 },
639 .n2 = {
640 .reg_off = HHI_MPLL_CNTL7,
641 .shift = 16,
642 .width = 9,
643 },
644 .ssen = {
645 .reg_off = HHI_MPLL_CNTL,
646 .shift = 25,
647 .width = 1,
648 },
649 .lock = &meson_clk_lock,
535 }, 650 },
536 .lock = &meson_clk_lock,
537 .hw.init = &(struct clk_init_data){ 651 .hw.init = &(struct clk_init_data){
538 .name = "mpll0", 652 .name = "mpll0_div",
539 .ops = &meson_clk_mpll_ops, 653 .ops = &meson_clk_mpll_ops,
540 .parent_names = (const char *[]){ "fixed_pll" }, 654 .parent_names = (const char *[]){ "mpll_prediv" },
541 .num_parents = 1, 655 .num_parents = 1,
542 }, 656 },
543}; 657};
544 658
545static struct meson_clk_mpll gxbb_mpll1 = { 659static struct clk_regmap gxbb_mpll0 = {
546 .sdm = { 660 .data = &(struct clk_regmap_gate_data){
547 .reg_off = HHI_MPLL_CNTL8, 661 .offset = HHI_MPLL_CNTL7,
548 .shift = 0, 662 .bit_idx = 14,
549 .width = 14,
550 },
551 .sdm_en = {
552 .reg_off = HHI_MPLL_CNTL8,
553 .shift = 15,
554 .width = 1,
555 }, 663 },
556 .n2 = { 664 .hw.init = &(struct clk_init_data){
557 .reg_off = HHI_MPLL_CNTL8, 665 .name = "mpll0",
558 .shift = 16, 666 .ops = &clk_regmap_gate_ops,
559 .width = 9, 667 .parent_names = (const char *[]){ "mpll0_div" },
668 .num_parents = 1,
669 .flags = CLK_SET_RATE_PARENT,
560 }, 670 },
561 .en = { 671};
562 .reg_off = HHI_MPLL_CNTL8, 672
563 .shift = 14, 673static struct clk_regmap gxbb_mpll1_div = {
564 .width = 1, 674 .data = &(struct meson_clk_mpll_data){
675 .sdm = {
676 .reg_off = HHI_MPLL_CNTL8,
677 .shift = 0,
678 .width = 14,
679 },
680 .sdm_en = {
681 .reg_off = HHI_MPLL_CNTL8,
682 .shift = 15,
683 .width = 1,
684 },
685 .n2 = {
686 .reg_off = HHI_MPLL_CNTL8,
687 .shift = 16,
688 .width = 9,
689 },
690 .lock = &meson_clk_lock,
565 }, 691 },
566 .lock = &meson_clk_lock,
567 .hw.init = &(struct clk_init_data){ 692 .hw.init = &(struct clk_init_data){
568 .name = "mpll1", 693 .name = "mpll1_div",
569 .ops = &meson_clk_mpll_ops, 694 .ops = &meson_clk_mpll_ops,
570 .parent_names = (const char *[]){ "fixed_pll" }, 695 .parent_names = (const char *[]){ "mpll_prediv" },
571 .num_parents = 1, 696 .num_parents = 1,
572 }, 697 },
573}; 698};
574 699
575static struct meson_clk_mpll gxbb_mpll2 = { 700static struct clk_regmap gxbb_mpll1 = {
576 .sdm = { 701 .data = &(struct clk_regmap_gate_data){
577 .reg_off = HHI_MPLL_CNTL9, 702 .offset = HHI_MPLL_CNTL8,
578 .shift = 0, 703 .bit_idx = 14,
579 .width = 14,
580 },
581 .sdm_en = {
582 .reg_off = HHI_MPLL_CNTL9,
583 .shift = 15,
584 .width = 1,
585 }, 704 },
586 .n2 = { 705 .hw.init = &(struct clk_init_data){
587 .reg_off = HHI_MPLL_CNTL9, 706 .name = "mpll1",
588 .shift = 16, 707 .ops = &clk_regmap_gate_ops,
589 .width = 9, 708 .parent_names = (const char *[]){ "mpll1_div" },
709 .num_parents = 1,
710 .flags = CLK_SET_RATE_PARENT,
590 }, 711 },
591 .en = { 712};
592 .reg_off = HHI_MPLL_CNTL9, 713
593 .shift = 14, 714static struct clk_regmap gxbb_mpll2_div = {
594 .width = 1, 715 .data = &(struct meson_clk_mpll_data){
716 .sdm = {
717 .reg_off = HHI_MPLL_CNTL9,
718 .shift = 0,
719 .width = 14,
720 },
721 .sdm_en = {
722 .reg_off = HHI_MPLL_CNTL9,
723 .shift = 15,
724 .width = 1,
725 },
726 .n2 = {
727 .reg_off = HHI_MPLL_CNTL9,
728 .shift = 16,
729 .width = 9,
730 },
731 .lock = &meson_clk_lock,
595 }, 732 },
596 .lock = &meson_clk_lock,
597 .hw.init = &(struct clk_init_data){ 733 .hw.init = &(struct clk_init_data){
598 .name = "mpll2", 734 .name = "mpll2_div",
599 .ops = &meson_clk_mpll_ops, 735 .ops = &meson_clk_mpll_ops,
600 .parent_names = (const char *[]){ "fixed_pll" }, 736 .parent_names = (const char *[]){ "mpll_prediv" },
601 .num_parents = 1, 737 .num_parents = 1,
602 }, 738 },
603}; 739};
604 740
605/* 741static struct clk_regmap gxbb_mpll2 = {
606 * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers 742 .data = &(struct clk_regmap_gate_data){
607 * and should be modeled with their respective PLLs via the forthcoming 743 .offset = HHI_MPLL_CNTL9,
608 * coordinated clock rates feature 744 .bit_idx = 14,
609 */ 745 },
746 .hw.init = &(struct clk_init_data){
747 .name = "mpll2",
748 .ops = &clk_regmap_gate_ops,
749 .parent_names = (const char *[]){ "mpll2_div" },
750 .num_parents = 1,
751 .flags = CLK_SET_RATE_PARENT,
752 },
753};
610 754
611static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; 755static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
612static const char * const clk81_parent_names[] = { 756static const char * const clk81_parent_names[] = {
@@ -614,16 +758,16 @@ static const char * const clk81_parent_names[] = {
614 "fclk_div3", "fclk_div5" 758 "fclk_div3", "fclk_div5"
615}; 759};
616 760
617static struct clk_mux gxbb_mpeg_clk_sel = { 761static struct clk_regmap gxbb_mpeg_clk_sel = {
618 .reg = (void *)HHI_MPEG_CLK_CNTL, 762 .data = &(struct clk_regmap_mux_data){
619 .mask = 0x7, 763 .offset = HHI_MPEG_CLK_CNTL,
620 .shift = 12, 764 .mask = 0x7,
621 .flags = CLK_MUX_READ_ONLY, 765 .shift = 12,
622 .table = mux_table_clk81, 766 .table = mux_table_clk81,
623 .lock = &meson_clk_lock, 767 },
624 .hw.init = &(struct clk_init_data){ 768 .hw.init = &(struct clk_init_data){
625 .name = "mpeg_clk_sel", 769 .name = "mpeg_clk_sel",
626 .ops = &clk_mux_ro_ops, 770 .ops = &clk_regmap_mux_ro_ops,
627 /* 771 /*
628 * bits 14:12 selects from 8 possible parents: 772 * bits 14:12 selects from 8 possible parents:
629 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2, 773 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
@@ -631,72 +775,75 @@ static struct clk_mux gxbb_mpeg_clk_sel = {
631 */ 775 */
632 .parent_names = clk81_parent_names, 776 .parent_names = clk81_parent_names,
633 .num_parents = ARRAY_SIZE(clk81_parent_names), 777 .num_parents = ARRAY_SIZE(clk81_parent_names),
634 .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
635 }, 778 },
636}; 779};
637 780
638static struct clk_divider gxbb_mpeg_clk_div = { 781static struct clk_regmap gxbb_mpeg_clk_div = {
639 .reg = (void *)HHI_MPEG_CLK_CNTL, 782 .data = &(struct clk_regmap_div_data){
640 .shift = 0, 783 .offset = HHI_MPEG_CLK_CNTL,
641 .width = 7, 784 .shift = 0,
642 .lock = &meson_clk_lock, 785 .width = 7,
786 },
643 .hw.init = &(struct clk_init_data){ 787 .hw.init = &(struct clk_init_data){
644 .name = "mpeg_clk_div", 788 .name = "mpeg_clk_div",
645 .ops = &clk_divider_ops, 789 .ops = &clk_regmap_divider_ro_ops,
646 .parent_names = (const char *[]){ "mpeg_clk_sel" }, 790 .parent_names = (const char *[]){ "mpeg_clk_sel" },
647 .num_parents = 1, 791 .num_parents = 1,
648 .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
649 }, 792 },
650}; 793};
651 794
652/* the mother of dragons^W gates */ 795/* the mother of dragons gates */
653static struct clk_gate gxbb_clk81 = { 796static struct clk_regmap gxbb_clk81 = {
654 .reg = (void *)HHI_MPEG_CLK_CNTL, 797 .data = &(struct clk_regmap_gate_data){
655 .bit_idx = 7, 798 .offset = HHI_MPEG_CLK_CNTL,
656 .lock = &meson_clk_lock, 799 .bit_idx = 7,
800 },
657 .hw.init = &(struct clk_init_data){ 801 .hw.init = &(struct clk_init_data){
658 .name = "clk81", 802 .name = "clk81",
659 .ops = &clk_gate_ops, 803 .ops = &clk_regmap_gate_ops,
660 .parent_names = (const char *[]){ "mpeg_clk_div" }, 804 .parent_names = (const char *[]){ "mpeg_clk_div" },
661 .num_parents = 1, 805 .num_parents = 1,
662 .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), 806 .flags = CLK_IS_CRITICAL,
663 }, 807 },
664}; 808};
665 809
666static struct clk_mux gxbb_sar_adc_clk_sel = { 810static struct clk_regmap gxbb_sar_adc_clk_sel = {
667 .reg = (void *)HHI_SAR_CLK_CNTL, 811 .data = &(struct clk_regmap_mux_data){
668 .mask = 0x3, 812 .offset = HHI_SAR_CLK_CNTL,
669 .shift = 9, 813 .mask = 0x3,
670 .lock = &meson_clk_lock, 814 .shift = 9,
815 },
671 .hw.init = &(struct clk_init_data){ 816 .hw.init = &(struct clk_init_data){
672 .name = "sar_adc_clk_sel", 817 .name = "sar_adc_clk_sel",
673 .ops = &clk_mux_ops, 818 .ops = &clk_regmap_mux_ops,
674 /* NOTE: The datasheet doesn't list the parents for bit 10 */ 819 /* NOTE: The datasheet doesn't list the parents for bit 10 */
675 .parent_names = (const char *[]){ "xtal", "clk81", }, 820 .parent_names = (const char *[]){ "xtal", "clk81", },
676 .num_parents = 2, 821 .num_parents = 2,
677 }, 822 },
678}; 823};
679 824
680static struct clk_divider gxbb_sar_adc_clk_div = { 825static struct clk_regmap gxbb_sar_adc_clk_div = {
681 .reg = (void *)HHI_SAR_CLK_CNTL, 826 .data = &(struct clk_regmap_div_data){
682 .shift = 0, 827 .offset = HHI_SAR_CLK_CNTL,
683 .width = 8, 828 .shift = 0,
684 .lock = &meson_clk_lock, 829 .width = 8,
830 },
685 .hw.init = &(struct clk_init_data){ 831 .hw.init = &(struct clk_init_data){
686 .name = "sar_adc_clk_div", 832 .name = "sar_adc_clk_div",
687 .ops = &clk_divider_ops, 833 .ops = &clk_regmap_divider_ops,
688 .parent_names = (const char *[]){ "sar_adc_clk_sel" }, 834 .parent_names = (const char *[]){ "sar_adc_clk_sel" },
689 .num_parents = 1, 835 .num_parents = 1,
690 }, 836 },
691}; 837};
692 838
693static struct clk_gate gxbb_sar_adc_clk = { 839static struct clk_regmap gxbb_sar_adc_clk = {
694 .reg = (void *)HHI_SAR_CLK_CNTL, 840 .data = &(struct clk_regmap_gate_data){
695 .bit_idx = 8, 841 .offset = HHI_SAR_CLK_CNTL,
696 .lock = &meson_clk_lock, 842 .bit_idx = 8,
843 },
697 .hw.init = &(struct clk_init_data){ 844 .hw.init = &(struct clk_init_data){
698 .name = "sar_adc_clk", 845 .name = "sar_adc_clk",
699 .ops = &clk_gate_ops, 846 .ops = &clk_regmap_gate_ops,
700 .parent_names = (const char *[]){ "sar_adc_clk_div" }, 847 .parent_names = (const char *[]){ "sar_adc_clk_div" },
701 .num_parents = 1, 848 .num_parents = 1,
702 .flags = CLK_SET_RATE_PARENT, 849 .flags = CLK_SET_RATE_PARENT,
@@ -708,21 +855,20 @@ static struct clk_gate gxbb_sar_adc_clk = {
708 * muxed by a glitch-free switch. 855 * muxed by a glitch-free switch.
709 */ 856 */
710 857
711static u32 mux_table_mali_0_1[] = {0, 1, 2, 3, 4, 5, 6, 7};
712static const char * const gxbb_mali_0_1_parent_names[] = { 858static const char * const gxbb_mali_0_1_parent_names[] = {
713 "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7", 859 "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
714 "fclk_div4", "fclk_div3", "fclk_div5" 860 "fclk_div4", "fclk_div3", "fclk_div5"
715}; 861};
716 862
717static struct clk_mux gxbb_mali_0_sel = { 863static struct clk_regmap gxbb_mali_0_sel = {
718 .reg = (void *)HHI_MALI_CLK_CNTL, 864 .data = &(struct clk_regmap_mux_data){
719 .mask = 0x7, 865 .offset = HHI_MALI_CLK_CNTL,
720 .shift = 9, 866 .mask = 0x7,
721 .table = mux_table_mali_0_1, 867 .shift = 9,
722 .lock = &meson_clk_lock, 868 },
723 .hw.init = &(struct clk_init_data){ 869 .hw.init = &(struct clk_init_data){
724 .name = "mali_0_sel", 870 .name = "mali_0_sel",
725 .ops = &clk_mux_ops, 871 .ops = &clk_regmap_mux_ops,
726 /* 872 /*
727 * bits 10:9 selects from 8 possible parents: 873 * bits 10:9 selects from 8 possible parents:
728 * xtal, gp0_pll, mpll2, mpll1, fclk_div7, 874 * xtal, gp0_pll, mpll2, mpll1, fclk_div7,
@@ -734,42 +880,44 @@ static struct clk_mux gxbb_mali_0_sel = {
734 }, 880 },
735}; 881};
736 882
737static struct clk_divider gxbb_mali_0_div = { 883static struct clk_regmap gxbb_mali_0_div = {
738 .reg = (void *)HHI_MALI_CLK_CNTL, 884 .data = &(struct clk_regmap_div_data){
739 .shift = 0, 885 .offset = HHI_MALI_CLK_CNTL,
740 .width = 7, 886 .shift = 0,
741 .lock = &meson_clk_lock, 887 .width = 7,
888 },
742 .hw.init = &(struct clk_init_data){ 889 .hw.init = &(struct clk_init_data){
743 .name = "mali_0_div", 890 .name = "mali_0_div",
744 .ops = &clk_divider_ops, 891 .ops = &clk_regmap_divider_ops,
745 .parent_names = (const char *[]){ "mali_0_sel" }, 892 .parent_names = (const char *[]){ "mali_0_sel" },
746 .num_parents = 1, 893 .num_parents = 1,
747 .flags = CLK_SET_RATE_NO_REPARENT, 894 .flags = CLK_SET_RATE_NO_REPARENT,
748 }, 895 },
749}; 896};
750 897
751static struct clk_gate gxbb_mali_0 = { 898static struct clk_regmap gxbb_mali_0 = {
752 .reg = (void *)HHI_MALI_CLK_CNTL, 899 .data = &(struct clk_regmap_gate_data){
753 .bit_idx = 8, 900 .offset = HHI_MALI_CLK_CNTL,
754 .lock = &meson_clk_lock, 901 .bit_idx = 8,
902 },
755 .hw.init = &(struct clk_init_data){ 903 .hw.init = &(struct clk_init_data){
756 .name = "mali_0", 904 .name = "mali_0",
757 .ops = &clk_gate_ops, 905 .ops = &clk_regmap_gate_ops,
758 .parent_names = (const char *[]){ "mali_0_div" }, 906 .parent_names = (const char *[]){ "mali_0_div" },
759 .num_parents = 1, 907 .num_parents = 1,
760 .flags = CLK_SET_RATE_PARENT, 908 .flags = CLK_SET_RATE_PARENT,
761 }, 909 },
762}; 910};
763 911
764static struct clk_mux gxbb_mali_1_sel = { 912static struct clk_regmap gxbb_mali_1_sel = {
765 .reg = (void *)HHI_MALI_CLK_CNTL, 913 .data = &(struct clk_regmap_mux_data){
766 .mask = 0x7, 914 .offset = HHI_MALI_CLK_CNTL,
767 .shift = 25, 915 .mask = 0x7,
768 .table = mux_table_mali_0_1, 916 .shift = 25,
769 .lock = &meson_clk_lock, 917 },
770 .hw.init = &(struct clk_init_data){ 918 .hw.init = &(struct clk_init_data){
771 .name = "mali_1_sel", 919 .name = "mali_1_sel",
772 .ops = &clk_mux_ops, 920 .ops = &clk_regmap_mux_ops,
773 /* 921 /*
774 * bits 10:9 selects from 8 possible parents: 922 * bits 10:9 selects from 8 possible parents:
775 * xtal, gp0_pll, mpll2, mpll1, fclk_div7, 923 * xtal, gp0_pll, mpll2, mpll1, fclk_div7,
@@ -781,77 +929,79 @@ static struct clk_mux gxbb_mali_1_sel = {
781 }, 929 },
782}; 930};
783 931
784static struct clk_divider gxbb_mali_1_div = { 932static struct clk_regmap gxbb_mali_1_div = {
785 .reg = (void *)HHI_MALI_CLK_CNTL, 933 .data = &(struct clk_regmap_div_data){
786 .shift = 16, 934 .offset = HHI_MALI_CLK_CNTL,
787 .width = 7, 935 .shift = 16,
788 .lock = &meson_clk_lock, 936 .width = 7,
937 },
789 .hw.init = &(struct clk_init_data){ 938 .hw.init = &(struct clk_init_data){
790 .name = "mali_1_div", 939 .name = "mali_1_div",
791 .ops = &clk_divider_ops, 940 .ops = &clk_regmap_divider_ops,
792 .parent_names = (const char *[]){ "mali_1_sel" }, 941 .parent_names = (const char *[]){ "mali_1_sel" },
793 .num_parents = 1, 942 .num_parents = 1,
794 .flags = CLK_SET_RATE_NO_REPARENT, 943 .flags = CLK_SET_RATE_NO_REPARENT,
795 }, 944 },
796}; 945};
797 946
798static struct clk_gate gxbb_mali_1 = { 947static struct clk_regmap gxbb_mali_1 = {
799 .reg = (void *)HHI_MALI_CLK_CNTL, 948 .data = &(struct clk_regmap_gate_data){
800 .bit_idx = 24, 949 .offset = HHI_MALI_CLK_CNTL,
801 .lock = &meson_clk_lock, 950 .bit_idx = 24,
951 },
802 .hw.init = &(struct clk_init_data){ 952 .hw.init = &(struct clk_init_data){
803 .name = "mali_1", 953 .name = "mali_1",
804 .ops = &clk_gate_ops, 954 .ops = &clk_regmap_gate_ops,
805 .parent_names = (const char *[]){ "mali_1_div" }, 955 .parent_names = (const char *[]){ "mali_1_div" },
806 .num_parents = 1, 956 .num_parents = 1,
807 .flags = CLK_SET_RATE_PARENT, 957 .flags = CLK_SET_RATE_PARENT,
808 }, 958 },
809}; 959};
810 960
811static u32 mux_table_mali[] = {0, 1};
812static const char * const gxbb_mali_parent_names[] = { 961static const char * const gxbb_mali_parent_names[] = {
813 "mali_0", "mali_1" 962 "mali_0", "mali_1"
814}; 963};
815 964
816static struct clk_mux gxbb_mali = { 965static struct clk_regmap gxbb_mali = {
817 .reg = (void *)HHI_MALI_CLK_CNTL, 966 .data = &(struct clk_regmap_mux_data){
818 .mask = 1, 967 .offset = HHI_MALI_CLK_CNTL,
819 .shift = 31, 968 .mask = 1,
820 .table = mux_table_mali, 969 .shift = 31,
821 .lock = &meson_clk_lock, 970 },
822 .hw.init = &(struct clk_init_data){ 971 .hw.init = &(struct clk_init_data){
823 .name = "mali", 972 .name = "mali",
824 .ops = &clk_mux_ops, 973 .ops = &clk_regmap_mux_ops,
825 .parent_names = gxbb_mali_parent_names, 974 .parent_names = gxbb_mali_parent_names,
826 .num_parents = 2, 975 .num_parents = 2,
827 .flags = CLK_SET_RATE_NO_REPARENT, 976 .flags = CLK_SET_RATE_NO_REPARENT,
828 }, 977 },
829}; 978};
830 979
831static struct clk_mux gxbb_cts_amclk_sel = { 980static struct clk_regmap gxbb_cts_amclk_sel = {
832 .reg = (void *) HHI_AUD_CLK_CNTL, 981 .data = &(struct clk_regmap_mux_data){
833 .mask = 0x3, 982 .offset = HHI_AUD_CLK_CNTL,
834 .shift = 9, 983 .mask = 0x3,
835 /* Default parent unknown (register reset value: 0) */ 984 .shift = 9,
836 .table = (u32[]){ 1, 2, 3 }, 985 .table = (u32[]){ 1, 2, 3 },
837 .lock = &meson_clk_lock, 986 },
838 .hw.init = &(struct clk_init_data){ 987 .hw.init = &(struct clk_init_data){
839 .name = "cts_amclk_sel", 988 .name = "cts_amclk_sel",
840 .ops = &clk_mux_ops, 989 .ops = &clk_regmap_mux_ops,
841 .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" }, 990 .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
842 .num_parents = 3, 991 .num_parents = 3,
843 .flags = CLK_SET_RATE_PARENT, 992 .flags = CLK_SET_RATE_PARENT,
844 }, 993 },
845}; 994};
846 995
847static struct meson_clk_audio_divider gxbb_cts_amclk_div = { 996static struct clk_regmap gxbb_cts_amclk_div = {
848 .div = { 997 .data = &(struct meson_clk_audio_div_data){
849 .reg_off = HHI_AUD_CLK_CNTL, 998 .div = {
850 .shift = 0, 999 .reg_off = HHI_AUD_CLK_CNTL,
851 .width = 8, 1000 .shift = 0,
1001 .width = 8,
1002 },
1003 .flags = CLK_DIVIDER_ROUND_CLOSEST,
852 }, 1004 },
853 .flags = CLK_DIVIDER_ROUND_CLOSEST,
854 .lock = &meson_clk_lock,
855 .hw.init = &(struct clk_init_data){ 1005 .hw.init = &(struct clk_init_data){
856 .name = "cts_amclk_div", 1006 .name = "cts_amclk_div",
857 .ops = &meson_clk_audio_divider_ops, 1007 .ops = &meson_clk_audio_divider_ops,
@@ -861,71 +1011,75 @@ static struct meson_clk_audio_divider gxbb_cts_amclk_div = {
861 }, 1011 },
862}; 1012};
863 1013
864static struct clk_gate gxbb_cts_amclk = { 1014static struct clk_regmap gxbb_cts_amclk = {
865 .reg = (void *) HHI_AUD_CLK_CNTL, 1015 .data = &(struct clk_regmap_gate_data){
866 .bit_idx = 8, 1016 .offset = HHI_AUD_CLK_CNTL,
867 .lock = &meson_clk_lock, 1017 .bit_idx = 8,
1018 },
868 .hw.init = &(struct clk_init_data){ 1019 .hw.init = &(struct clk_init_data){
869 .name = "cts_amclk", 1020 .name = "cts_amclk",
870 .ops = &clk_gate_ops, 1021 .ops = &clk_regmap_gate_ops,
871 .parent_names = (const char *[]){ "cts_amclk_div" }, 1022 .parent_names = (const char *[]){ "cts_amclk_div" },
872 .num_parents = 1, 1023 .num_parents = 1,
873 .flags = CLK_SET_RATE_PARENT, 1024 .flags = CLK_SET_RATE_PARENT,
874 }, 1025 },
875}; 1026};
876 1027
877static struct clk_mux gxbb_cts_mclk_i958_sel = { 1028static struct clk_regmap gxbb_cts_mclk_i958_sel = {
878 .reg = (void *)HHI_AUD_CLK_CNTL2, 1029 .data = &(struct clk_regmap_mux_data){
879 .mask = 0x3, 1030 .offset = HHI_AUD_CLK_CNTL2,
880 .shift = 25, 1031 .mask = 0x3,
881 /* Default parent unknown (register reset value: 0) */ 1032 .shift = 25,
882 .table = (u32[]){ 1, 2, 3 }, 1033 .table = (u32[]){ 1, 2, 3 },
883 .lock = &meson_clk_lock, 1034 },
884 .hw.init = &(struct clk_init_data) { 1035 .hw.init = &(struct clk_init_data) {
885 .name = "cts_mclk_i958_sel", 1036 .name = "cts_mclk_i958_sel",
886 .ops = &clk_mux_ops, 1037 .ops = &clk_regmap_mux_ops,
887 .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" }, 1038 .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
888 .num_parents = 3, 1039 .num_parents = 3,
889 .flags = CLK_SET_RATE_PARENT, 1040 .flags = CLK_SET_RATE_PARENT,
890 }, 1041 },
891}; 1042};
892 1043
893static struct clk_divider gxbb_cts_mclk_i958_div = { 1044static struct clk_regmap gxbb_cts_mclk_i958_div = {
894 .reg = (void *)HHI_AUD_CLK_CNTL2, 1045 .data = &(struct clk_regmap_div_data){
895 .shift = 16, 1046 .offset = HHI_AUD_CLK_CNTL2,
896 .width = 8, 1047 .shift = 16,
897 .lock = &meson_clk_lock, 1048 .width = 8,
898 .flags = CLK_DIVIDER_ROUND_CLOSEST, 1049 .flags = CLK_DIVIDER_ROUND_CLOSEST,
1050 },
899 .hw.init = &(struct clk_init_data) { 1051 .hw.init = &(struct clk_init_data) {
900 .name = "cts_mclk_i958_div", 1052 .name = "cts_mclk_i958_div",
901 .ops = &clk_divider_ops, 1053 .ops = &clk_regmap_divider_ops,
902 .parent_names = (const char *[]){ "cts_mclk_i958_sel" }, 1054 .parent_names = (const char *[]){ "cts_mclk_i958_sel" },
903 .num_parents = 1, 1055 .num_parents = 1,
904 .flags = CLK_SET_RATE_PARENT, 1056 .flags = CLK_SET_RATE_PARENT,
905 }, 1057 },
906}; 1058};
907 1059
908static struct clk_gate gxbb_cts_mclk_i958 = { 1060static struct clk_regmap gxbb_cts_mclk_i958 = {
909 .reg = (void *)HHI_AUD_CLK_CNTL2, 1061 .data = &(struct clk_regmap_gate_data){
910 .bit_idx = 24, 1062 .offset = HHI_AUD_CLK_CNTL2,
911 .lock = &meson_clk_lock, 1063 .bit_idx = 24,
1064 },
912 .hw.init = &(struct clk_init_data){ 1065 .hw.init = &(struct clk_init_data){
913 .name = "cts_mclk_i958", 1066 .name = "cts_mclk_i958",
914 .ops = &clk_gate_ops, 1067 .ops = &clk_regmap_gate_ops,
915 .parent_names = (const char *[]){ "cts_mclk_i958_div" }, 1068 .parent_names = (const char *[]){ "cts_mclk_i958_div" },
916 .num_parents = 1, 1069 .num_parents = 1,
917 .flags = CLK_SET_RATE_PARENT, 1070 .flags = CLK_SET_RATE_PARENT,
918 }, 1071 },
919}; 1072};
920 1073
921static struct clk_mux gxbb_cts_i958 = { 1074static struct clk_regmap gxbb_cts_i958 = {
922 .reg = (void *)HHI_AUD_CLK_CNTL2, 1075 .data = &(struct clk_regmap_mux_data){
923 .mask = 0x1, 1076 .offset = HHI_AUD_CLK_CNTL2,
924 .shift = 27, 1077 .mask = 0x1,
925 .lock = &meson_clk_lock, 1078 .shift = 27,
926 .hw.init = &(struct clk_init_data){ 1079 },
1080 .hw.init = &(struct clk_init_data){
927 .name = "cts_i958", 1081 .name = "cts_i958",
928 .ops = &clk_mux_ops, 1082 .ops = &clk_regmap_mux_ops,
929 .parent_names = (const char *[]){ "cts_amclk", "cts_mclk_i958" }, 1083 .parent_names = (const char *[]){ "cts_amclk", "cts_mclk_i958" },
930 .num_parents = 2, 1084 .num_parents = 2,
931 /* 1085 /*
@@ -936,27 +1090,29 @@ static struct clk_mux gxbb_cts_i958 = {
936 }, 1090 },
937}; 1091};
938 1092
939static struct clk_divider gxbb_32k_clk_div = { 1093static struct clk_regmap gxbb_32k_clk_div = {
940 .reg = (void *)HHI_32K_CLK_CNTL, 1094 .data = &(struct clk_regmap_div_data){
941 .shift = 0, 1095 .offset = HHI_32K_CLK_CNTL,
942 .width = 14, 1096 .shift = 0,
943 .lock = &meson_clk_lock, 1097 .width = 14,
1098 },
944 .hw.init = &(struct clk_init_data){ 1099 .hw.init = &(struct clk_init_data){
945 .name = "32k_clk_div", 1100 .name = "32k_clk_div",
946 .ops = &clk_divider_ops, 1101 .ops = &clk_regmap_divider_ops,
947 .parent_names = (const char *[]){ "32k_clk_sel" }, 1102 .parent_names = (const char *[]){ "32k_clk_sel" },
948 .num_parents = 1, 1103 .num_parents = 1,
949 .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST, 1104 .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST,
950 }, 1105 },
951}; 1106};
952 1107
953static struct clk_gate gxbb_32k_clk = { 1108static struct clk_regmap gxbb_32k_clk = {
954 .reg = (void *)HHI_32K_CLK_CNTL, 1109 .data = &(struct clk_regmap_gate_data){
955 .bit_idx = 15, 1110 .offset = HHI_32K_CLK_CNTL,
956 .lock = &meson_clk_lock, 1111 .bit_idx = 15,
1112 },
957 .hw.init = &(struct clk_init_data){ 1113 .hw.init = &(struct clk_init_data){
958 .name = "32k_clk", 1114 .name = "32k_clk",
959 .ops = &clk_gate_ops, 1115 .ops = &clk_regmap_gate_ops,
960 .parent_names = (const char *[]){ "32k_clk_div" }, 1116 .parent_names = (const char *[]){ "32k_clk_div" },
961 .num_parents = 1, 1117 .num_parents = 1,
962 .flags = CLK_SET_RATE_PARENT, 1118 .flags = CLK_SET_RATE_PARENT,
@@ -967,14 +1123,15 @@ static const char * const gxbb_32k_clk_parent_names[] = {
967 "xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5" 1123 "xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5"
968}; 1124};
969 1125
970static struct clk_mux gxbb_32k_clk_sel = { 1126static struct clk_regmap gxbb_32k_clk_sel = {
971 .reg = (void *)HHI_32K_CLK_CNTL, 1127 .data = &(struct clk_regmap_mux_data){
972 .mask = 0x3, 1128 .offset = HHI_32K_CLK_CNTL,
973 .shift = 16, 1129 .mask = 0x3,
974 .lock = &meson_clk_lock, 1130 .shift = 16,
975 .hw.init = &(struct clk_init_data){ 1131 },
1132 .hw.init = &(struct clk_init_data){
976 .name = "32k_clk_sel", 1133 .name = "32k_clk_sel",
977 .ops = &clk_mux_ops, 1134 .ops = &clk_regmap_mux_ops,
978 .parent_names = gxbb_32k_clk_parent_names, 1135 .parent_names = gxbb_32k_clk_parent_names,
979 .num_parents = 4, 1136 .num_parents = 4,
980 .flags = CLK_SET_RATE_PARENT, 1137 .flags = CLK_SET_RATE_PARENT,
@@ -993,42 +1150,45 @@ static const char * const gxbb_sd_emmc_clk0_parent_names[] = {
993}; 1150};
994 1151
995/* SDIO clock */ 1152/* SDIO clock */
996static struct clk_mux gxbb_sd_emmc_a_clk0_sel = { 1153static struct clk_regmap gxbb_sd_emmc_a_clk0_sel = {
997 .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1154 .data = &(struct clk_regmap_mux_data){
998 .mask = 0x7, 1155 .offset = HHI_SD_EMMC_CLK_CNTL,
999 .shift = 9, 1156 .mask = 0x7,
1000 .lock = &meson_clk_lock, 1157 .shift = 9,
1158 },
1001 .hw.init = &(struct clk_init_data) { 1159 .hw.init = &(struct clk_init_data) {
1002 .name = "sd_emmc_a_clk0_sel", 1160 .name = "sd_emmc_a_clk0_sel",
1003 .ops = &clk_mux_ops, 1161 .ops = &clk_regmap_mux_ops,
1004 .parent_names = gxbb_sd_emmc_clk0_parent_names, 1162 .parent_names = gxbb_sd_emmc_clk0_parent_names,
1005 .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), 1163 .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
1006 .flags = CLK_SET_RATE_PARENT, 1164 .flags = CLK_SET_RATE_PARENT,
1007 }, 1165 },
1008}; 1166};
1009 1167
1010static struct clk_divider gxbb_sd_emmc_a_clk0_div = { 1168static struct clk_regmap gxbb_sd_emmc_a_clk0_div = {
1011 .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1169 .data = &(struct clk_regmap_div_data){
1012 .shift = 0, 1170 .offset = HHI_SD_EMMC_CLK_CNTL,
1013 .width = 7, 1171 .shift = 0,
1014 .lock = &meson_clk_lock, 1172 .width = 7,
1015 .flags = CLK_DIVIDER_ROUND_CLOSEST, 1173 .flags = CLK_DIVIDER_ROUND_CLOSEST,
1174 },
1016 .hw.init = &(struct clk_init_data) { 1175 .hw.init = &(struct clk_init_data) {
1017 .name = "sd_emmc_a_clk0_div", 1176 .name = "sd_emmc_a_clk0_div",
1018 .ops = &clk_divider_ops, 1177 .ops = &clk_regmap_divider_ops,
1019 .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" }, 1178 .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" },
1020 .num_parents = 1, 1179 .num_parents = 1,
1021 .flags = CLK_SET_RATE_PARENT, 1180 .flags = CLK_SET_RATE_PARENT,
1022 }, 1181 },
1023}; 1182};
1024 1183
1025static struct clk_gate gxbb_sd_emmc_a_clk0 = { 1184static struct clk_regmap gxbb_sd_emmc_a_clk0 = {
1026 .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1185 .data = &(struct clk_regmap_gate_data){
1027 .bit_idx = 7, 1186 .offset = HHI_SD_EMMC_CLK_CNTL,
1028 .lock = &meson_clk_lock, 1187 .bit_idx = 7,
1188 },
1029 .hw.init = &(struct clk_init_data){ 1189 .hw.init = &(struct clk_init_data){
1030 .name = "sd_emmc_a_clk0", 1190 .name = "sd_emmc_a_clk0",
1031 .ops = &clk_gate_ops, 1191 .ops = &clk_regmap_gate_ops,
1032 .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" }, 1192 .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" },
1033 .num_parents = 1, 1193 .num_parents = 1,
1034 .flags = CLK_SET_RATE_PARENT, 1194 .flags = CLK_SET_RATE_PARENT,
@@ -1036,42 +1196,45 @@ static struct clk_gate gxbb_sd_emmc_a_clk0 = {
1036}; 1196};
1037 1197
1038/* SDcard clock */ 1198/* SDcard clock */
1039static struct clk_mux gxbb_sd_emmc_b_clk0_sel = { 1199static struct clk_regmap gxbb_sd_emmc_b_clk0_sel = {
1040 .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1200 .data = &(struct clk_regmap_mux_data){
1041 .mask = 0x7, 1201 .offset = HHI_SD_EMMC_CLK_CNTL,
1042 .shift = 25, 1202 .mask = 0x7,
1043 .lock = &meson_clk_lock, 1203 .shift = 25,
1204 },
1044 .hw.init = &(struct clk_init_data) { 1205 .hw.init = &(struct clk_init_data) {
1045 .name = "sd_emmc_b_clk0_sel", 1206 .name = "sd_emmc_b_clk0_sel",
1046 .ops = &clk_mux_ops, 1207 .ops = &clk_regmap_mux_ops,
1047 .parent_names = gxbb_sd_emmc_clk0_parent_names, 1208 .parent_names = gxbb_sd_emmc_clk0_parent_names,
1048 .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), 1209 .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
1049 .flags = CLK_SET_RATE_PARENT, 1210 .flags = CLK_SET_RATE_PARENT,
1050 }, 1211 },
1051}; 1212};
1052 1213
1053static struct clk_divider gxbb_sd_emmc_b_clk0_div = { 1214static struct clk_regmap gxbb_sd_emmc_b_clk0_div = {
1054 .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1215 .data = &(struct clk_regmap_div_data){
1055 .shift = 16, 1216 .offset = HHI_SD_EMMC_CLK_CNTL,
1056 .width = 7, 1217 .shift = 16,
1057 .lock = &meson_clk_lock, 1218 .width = 7,
1058 .flags = CLK_DIVIDER_ROUND_CLOSEST, 1219 .flags = CLK_DIVIDER_ROUND_CLOSEST,
1220 },
1059 .hw.init = &(struct clk_init_data) { 1221 .hw.init = &(struct clk_init_data) {
1060 .name = "sd_emmc_b_clk0_div", 1222 .name = "sd_emmc_b_clk0_div",
1061 .ops = &clk_divider_ops, 1223 .ops = &clk_regmap_divider_ops,
1062 .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, 1224 .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
1063 .num_parents = 1, 1225 .num_parents = 1,
1064 .flags = CLK_SET_RATE_PARENT, 1226 .flags = CLK_SET_RATE_PARENT,
1065 }, 1227 },
1066}; 1228};
1067 1229
1068static struct clk_gate gxbb_sd_emmc_b_clk0 = { 1230static struct clk_regmap gxbb_sd_emmc_b_clk0 = {
1069 .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1231 .data = &(struct clk_regmap_gate_data){
1070 .bit_idx = 23, 1232 .offset = HHI_SD_EMMC_CLK_CNTL,
1071 .lock = &meson_clk_lock, 1233 .bit_idx = 23,
1234 },
1072 .hw.init = &(struct clk_init_data){ 1235 .hw.init = &(struct clk_init_data){
1073 .name = "sd_emmc_b_clk0", 1236 .name = "sd_emmc_b_clk0",
1074 .ops = &clk_gate_ops, 1237 .ops = &clk_regmap_gate_ops,
1075 .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, 1238 .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
1076 .num_parents = 1, 1239 .num_parents = 1,
1077 .flags = CLK_SET_RATE_PARENT, 1240 .flags = CLK_SET_RATE_PARENT,
@@ -1079,42 +1242,45 @@ static struct clk_gate gxbb_sd_emmc_b_clk0 = {
1079}; 1242};
1080 1243
1081/* EMMC/NAND clock */ 1244/* EMMC/NAND clock */
1082static struct clk_mux gxbb_sd_emmc_c_clk0_sel = { 1245static struct clk_regmap gxbb_sd_emmc_c_clk0_sel = {
1083 .reg = (void *)HHI_NAND_CLK_CNTL, 1246 .data = &(struct clk_regmap_mux_data){
1084 .mask = 0x7, 1247 .offset = HHI_NAND_CLK_CNTL,
1085 .shift = 9, 1248 .mask = 0x7,
1086 .lock = &meson_clk_lock, 1249 .shift = 9,
1250 },
1087 .hw.init = &(struct clk_init_data) { 1251 .hw.init = &(struct clk_init_data) {
1088 .name = "sd_emmc_c_clk0_sel", 1252 .name = "sd_emmc_c_clk0_sel",
1089 .ops = &clk_mux_ops, 1253 .ops = &clk_regmap_mux_ops,
1090 .parent_names = gxbb_sd_emmc_clk0_parent_names, 1254 .parent_names = gxbb_sd_emmc_clk0_parent_names,
1091 .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), 1255 .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
1092 .flags = CLK_SET_RATE_PARENT, 1256 .flags = CLK_SET_RATE_PARENT,
1093 }, 1257 },
1094}; 1258};
1095 1259
1096static struct clk_divider gxbb_sd_emmc_c_clk0_div = { 1260static struct clk_regmap gxbb_sd_emmc_c_clk0_div = {
1097 .reg = (void *)HHI_NAND_CLK_CNTL, 1261 .data = &(struct clk_regmap_div_data){
1098 .shift = 0, 1262 .offset = HHI_NAND_CLK_CNTL,
1099 .width = 7, 1263 .shift = 0,
1100 .lock = &meson_clk_lock, 1264 .width = 7,
1101 .flags = CLK_DIVIDER_ROUND_CLOSEST, 1265 .flags = CLK_DIVIDER_ROUND_CLOSEST,
1266 },
1102 .hw.init = &(struct clk_init_data) { 1267 .hw.init = &(struct clk_init_data) {
1103 .name = "sd_emmc_c_clk0_div", 1268 .name = "sd_emmc_c_clk0_div",
1104 .ops = &clk_divider_ops, 1269 .ops = &clk_regmap_divider_ops,
1105 .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, 1270 .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
1106 .num_parents = 1, 1271 .num_parents = 1,
1107 .flags = CLK_SET_RATE_PARENT, 1272 .flags = CLK_SET_RATE_PARENT,
1108 }, 1273 },
1109}; 1274};
1110 1275
1111static struct clk_gate gxbb_sd_emmc_c_clk0 = { 1276static struct clk_regmap gxbb_sd_emmc_c_clk0 = {
1112 .reg = (void *)HHI_NAND_CLK_CNTL, 1277 .data = &(struct clk_regmap_gate_data){
1113 .bit_idx = 7, 1278 .offset = HHI_NAND_CLK_CNTL,
1114 .lock = &meson_clk_lock, 1279 .bit_idx = 7,
1280 },
1115 .hw.init = &(struct clk_init_data){ 1281 .hw.init = &(struct clk_init_data){
1116 .name = "sd_emmc_c_clk0", 1282 .name = "sd_emmc_c_clk0",
1117 .ops = &clk_gate_ops, 1283 .ops = &clk_regmap_gate_ops,
1118 .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, 1284 .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
1119 .num_parents = 1, 1285 .num_parents = 1,
1120 .flags = CLK_SET_RATE_PARENT, 1286 .flags = CLK_SET_RATE_PARENT,
@@ -1123,20 +1289,19 @@ static struct clk_gate gxbb_sd_emmc_c_clk0 = {
1123 1289
1124/* VPU Clock */ 1290/* VPU Clock */
1125 1291
1126static u32 mux_table_vpu[] = {0, 1, 2, 3};
1127static const char * const gxbb_vpu_parent_names[] = { 1292static const char * const gxbb_vpu_parent_names[] = {
1128 "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" 1293 "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
1129}; 1294};
1130 1295
1131static struct clk_mux gxbb_vpu_0_sel = { 1296static struct clk_regmap gxbb_vpu_0_sel = {
1132 .reg = (void *)HHI_VPU_CLK_CNTL, 1297 .data = &(struct clk_regmap_mux_data){
1133 .mask = 0x3, 1298 .offset = HHI_VPU_CLK_CNTL,
1134 .shift = 9, 1299 .mask = 0x3,
1135 .lock = &meson_clk_lock, 1300 .shift = 9,
1136 .table = mux_table_vpu, 1301 },
1137 .hw.init = &(struct clk_init_data){ 1302 .hw.init = &(struct clk_init_data){
1138 .name = "vpu_0_sel", 1303 .name = "vpu_0_sel",
1139 .ops = &clk_mux_ops, 1304 .ops = &clk_regmap_mux_ops,
1140 /* 1305 /*
1141 * bits 9:10 selects from 4 possible parents: 1306 * bits 9:10 selects from 4 possible parents:
1142 * fclk_div4, fclk_div3, fclk_div5, fclk_div7, 1307 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
@@ -1147,42 +1312,44 @@ static struct clk_mux gxbb_vpu_0_sel = {
1147 }, 1312 },
1148}; 1313};
1149 1314
1150static struct clk_divider gxbb_vpu_0_div = { 1315static struct clk_regmap gxbb_vpu_0_div = {
1151 .reg = (void *)HHI_VPU_CLK_CNTL, 1316 .data = &(struct clk_regmap_div_data){
1152 .shift = 0, 1317 .offset = HHI_VPU_CLK_CNTL,
1153 .width = 7, 1318 .shift = 0,
1154 .lock = &meson_clk_lock, 1319 .width = 7,
1320 },
1155 .hw.init = &(struct clk_init_data){ 1321 .hw.init = &(struct clk_init_data){
1156 .name = "vpu_0_div", 1322 .name = "vpu_0_div",
1157 .ops = &clk_divider_ops, 1323 .ops = &clk_regmap_divider_ops,
1158 .parent_names = (const char *[]){ "vpu_0_sel" }, 1324 .parent_names = (const char *[]){ "vpu_0_sel" },
1159 .num_parents = 1, 1325 .num_parents = 1,
1160 .flags = CLK_SET_RATE_PARENT, 1326 .flags = CLK_SET_RATE_PARENT,
1161 }, 1327 },
1162}; 1328};
1163 1329
1164static struct clk_gate gxbb_vpu_0 = { 1330static struct clk_regmap gxbb_vpu_0 = {
1165 .reg = (void *)HHI_VPU_CLK_CNTL, 1331 .data = &(struct clk_regmap_gate_data){
1166 .bit_idx = 8, 1332 .offset = HHI_VPU_CLK_CNTL,
1167 .lock = &meson_clk_lock, 1333 .bit_idx = 8,
1334 },
1168 .hw.init = &(struct clk_init_data) { 1335 .hw.init = &(struct clk_init_data) {
1169 .name = "vpu_0", 1336 .name = "vpu_0",
1170 .ops = &clk_gate_ops, 1337 .ops = &clk_regmap_gate_ops,
1171 .parent_names = (const char *[]){ "vpu_0_div" }, 1338 .parent_names = (const char *[]){ "vpu_0_div" },
1172 .num_parents = 1, 1339 .num_parents = 1,
1173 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 1340 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1174 }, 1341 },
1175}; 1342};
1176 1343
1177static struct clk_mux gxbb_vpu_1_sel = { 1344static struct clk_regmap gxbb_vpu_1_sel = {
1178 .reg = (void *)HHI_VPU_CLK_CNTL, 1345 .data = &(struct clk_regmap_mux_data){
1179 .mask = 0x3, 1346 .offset = HHI_VPU_CLK_CNTL,
1180 .shift = 25, 1347 .mask = 0x3,
1181 .lock = &meson_clk_lock, 1348 .shift = 25,
1182 .table = mux_table_vpu, 1349 },
1183 .hw.init = &(struct clk_init_data){ 1350 .hw.init = &(struct clk_init_data){
1184 .name = "vpu_1_sel", 1351 .name = "vpu_1_sel",
1185 .ops = &clk_mux_ops, 1352 .ops = &clk_regmap_mux_ops,
1186 /* 1353 /*
1187 * bits 25:26 selects from 4 possible parents: 1354 * bits 25:26 selects from 4 possible parents:
1188 * fclk_div4, fclk_div3, fclk_div5, fclk_div7, 1355 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
@@ -1193,41 +1360,44 @@ static struct clk_mux gxbb_vpu_1_sel = {
1193 }, 1360 },
1194}; 1361};
1195 1362
1196static struct clk_divider gxbb_vpu_1_div = { 1363static struct clk_regmap gxbb_vpu_1_div = {
1197 .reg = (void *)HHI_VPU_CLK_CNTL, 1364 .data = &(struct clk_regmap_div_data){
1198 .shift = 16, 1365 .offset = HHI_VPU_CLK_CNTL,
1199 .width = 7, 1366 .shift = 16,
1200 .lock = &meson_clk_lock, 1367 .width = 7,
1368 },
1201 .hw.init = &(struct clk_init_data){ 1369 .hw.init = &(struct clk_init_data){
1202 .name = "vpu_1_div", 1370 .name = "vpu_1_div",
1203 .ops = &clk_divider_ops, 1371 .ops = &clk_regmap_divider_ops,
1204 .parent_names = (const char *[]){ "vpu_1_sel" }, 1372 .parent_names = (const char *[]){ "vpu_1_sel" },
1205 .num_parents = 1, 1373 .num_parents = 1,
1206 .flags = CLK_SET_RATE_PARENT, 1374 .flags = CLK_SET_RATE_PARENT,
1207 }, 1375 },
1208}; 1376};
1209 1377
1210static struct clk_gate gxbb_vpu_1 = { 1378static struct clk_regmap gxbb_vpu_1 = {
1211 .reg = (void *)HHI_VPU_CLK_CNTL, 1379 .data = &(struct clk_regmap_gate_data){
1212 .bit_idx = 24, 1380 .offset = HHI_VPU_CLK_CNTL,
1213 .lock = &meson_clk_lock, 1381 .bit_idx = 24,
1382 },
1214 .hw.init = &(struct clk_init_data) { 1383 .hw.init = &(struct clk_init_data) {
1215 .name = "vpu_1", 1384 .name = "vpu_1",
1216 .ops = &clk_gate_ops, 1385 .ops = &clk_regmap_gate_ops,
1217 .parent_names = (const char *[]){ "vpu_1_div" }, 1386 .parent_names = (const char *[]){ "vpu_1_div" },
1218 .num_parents = 1, 1387 .num_parents = 1,
1219 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 1388 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1220 }, 1389 },
1221}; 1390};
1222 1391
1223static struct clk_mux gxbb_vpu = { 1392static struct clk_regmap gxbb_vpu = {
1224 .reg = (void *)HHI_VPU_CLK_CNTL, 1393 .data = &(struct clk_regmap_mux_data){
1225 .mask = 1, 1394 .offset = HHI_VPU_CLK_CNTL,
1226 .shift = 31, 1395 .mask = 1,
1227 .lock = &meson_clk_lock, 1396 .shift = 31,
1397 },
1228 .hw.init = &(struct clk_init_data){ 1398 .hw.init = &(struct clk_init_data){
1229 .name = "vpu", 1399 .name = "vpu",
1230 .ops = &clk_mux_ops, 1400 .ops = &clk_regmap_mux_ops,
1231 /* 1401 /*
1232 * bit 31 selects from 2 possible parents: 1402 * bit 31 selects from 2 possible parents:
1233 * vpu_0 or vpu_1 1403 * vpu_0 or vpu_1
@@ -1240,20 +1410,19 @@ static struct clk_mux gxbb_vpu = {
1240 1410
1241/* VAPB Clock */ 1411/* VAPB Clock */
1242 1412
1243static u32 mux_table_vapb[] = {0, 1, 2, 3};
1244static const char * const gxbb_vapb_parent_names[] = { 1413static const char * const gxbb_vapb_parent_names[] = {
1245 "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" 1414 "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
1246}; 1415};
1247 1416
1248static struct clk_mux gxbb_vapb_0_sel = { 1417static struct clk_regmap gxbb_vapb_0_sel = {
1249 .reg = (void *)HHI_VAPBCLK_CNTL, 1418 .data = &(struct clk_regmap_mux_data){
1250 .mask = 0x3, 1419 .offset = HHI_VAPBCLK_CNTL,
1251 .shift = 9, 1420 .mask = 0x3,
1252 .lock = &meson_clk_lock, 1421 .shift = 9,
1253 .table = mux_table_vapb, 1422 },
1254 .hw.init = &(struct clk_init_data){ 1423 .hw.init = &(struct clk_init_data){
1255 .name = "vapb_0_sel", 1424 .name = "vapb_0_sel",
1256 .ops = &clk_mux_ops, 1425 .ops = &clk_regmap_mux_ops,
1257 /* 1426 /*
1258 * bits 9:10 selects from 4 possible parents: 1427 * bits 9:10 selects from 4 possible parents:
1259 * fclk_div4, fclk_div3, fclk_div5, fclk_div7, 1428 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
@@ -1264,42 +1433,44 @@ static struct clk_mux gxbb_vapb_0_sel = {
1264 }, 1433 },
1265}; 1434};
1266 1435
1267static struct clk_divider gxbb_vapb_0_div = { 1436static struct clk_regmap gxbb_vapb_0_div = {
1268 .reg = (void *)HHI_VAPBCLK_CNTL, 1437 .data = &(struct clk_regmap_div_data){
1269 .shift = 0, 1438 .offset = HHI_VAPBCLK_CNTL,
1270 .width = 7, 1439 .shift = 0,
1271 .lock = &meson_clk_lock, 1440 .width = 7,
1441 },
1272 .hw.init = &(struct clk_init_data){ 1442 .hw.init = &(struct clk_init_data){
1273 .name = "vapb_0_div", 1443 .name = "vapb_0_div",
1274 .ops = &clk_divider_ops, 1444 .ops = &clk_regmap_divider_ops,
1275 .parent_names = (const char *[]){ "vapb_0_sel" }, 1445 .parent_names = (const char *[]){ "vapb_0_sel" },
1276 .num_parents = 1, 1446 .num_parents = 1,
1277 .flags = CLK_SET_RATE_PARENT, 1447 .flags = CLK_SET_RATE_PARENT,
1278 }, 1448 },
1279}; 1449};
1280 1450
1281static struct clk_gate gxbb_vapb_0 = { 1451static struct clk_regmap gxbb_vapb_0 = {
1282 .reg = (void *)HHI_VAPBCLK_CNTL, 1452 .data = &(struct clk_regmap_gate_data){
1283 .bit_idx = 8, 1453 .offset = HHI_VAPBCLK_CNTL,
1284 .lock = &meson_clk_lock, 1454 .bit_idx = 8,
1455 },
1285 .hw.init = &(struct clk_init_data) { 1456 .hw.init = &(struct clk_init_data) {
1286 .name = "vapb_0", 1457 .name = "vapb_0",
1287 .ops = &clk_gate_ops, 1458 .ops = &clk_regmap_gate_ops,
1288 .parent_names = (const char *[]){ "vapb_0_div" }, 1459 .parent_names = (const char *[]){ "vapb_0_div" },
1289 .num_parents = 1, 1460 .num_parents = 1,
1290 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 1461 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1291 }, 1462 },
1292}; 1463};
1293 1464
1294static struct clk_mux gxbb_vapb_1_sel = { 1465static struct clk_regmap gxbb_vapb_1_sel = {
1295 .reg = (void *)HHI_VAPBCLK_CNTL, 1466 .data = &(struct clk_regmap_mux_data){
1296 .mask = 0x3, 1467 .offset = HHI_VAPBCLK_CNTL,
1297 .shift = 25, 1468 .mask = 0x3,
1298 .lock = &meson_clk_lock, 1469 .shift = 25,
1299 .table = mux_table_vapb, 1470 },
1300 .hw.init = &(struct clk_init_data){ 1471 .hw.init = &(struct clk_init_data){
1301 .name = "vapb_1_sel", 1472 .name = "vapb_1_sel",
1302 .ops = &clk_mux_ops, 1473 .ops = &clk_regmap_mux_ops,
1303 /* 1474 /*
1304 * bits 25:26 selects from 4 possible parents: 1475 * bits 25:26 selects from 4 possible parents:
1305 * fclk_div4, fclk_div3, fclk_div5, fclk_div7, 1476 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
@@ -1310,41 +1481,44 @@ static struct clk_mux gxbb_vapb_1_sel = {
1310 }, 1481 },
1311}; 1482};
1312 1483
1313static struct clk_divider gxbb_vapb_1_div = { 1484static struct clk_regmap gxbb_vapb_1_div = {
1314 .reg = (void *)HHI_VAPBCLK_CNTL, 1485 .data = &(struct clk_regmap_div_data){
1315 .shift = 16, 1486 .offset = HHI_VAPBCLK_CNTL,
1316 .width = 7, 1487 .shift = 16,
1317 .lock = &meson_clk_lock, 1488 .width = 7,
1489 },
1318 .hw.init = &(struct clk_init_data){ 1490 .hw.init = &(struct clk_init_data){
1319 .name = "vapb_1_div", 1491 .name = "vapb_1_div",
1320 .ops = &clk_divider_ops, 1492 .ops = &clk_regmap_divider_ops,
1321 .parent_names = (const char *[]){ "vapb_1_sel" }, 1493 .parent_names = (const char *[]){ "vapb_1_sel" },
1322 .num_parents = 1, 1494 .num_parents = 1,
1323 .flags = CLK_SET_RATE_PARENT, 1495 .flags = CLK_SET_RATE_PARENT,
1324 }, 1496 },
1325}; 1497};
1326 1498
1327static struct clk_gate gxbb_vapb_1 = { 1499static struct clk_regmap gxbb_vapb_1 = {
1328 .reg = (void *)HHI_VAPBCLK_CNTL, 1500 .data = &(struct clk_regmap_gate_data){
1329 .bit_idx = 24, 1501 .offset = HHI_VAPBCLK_CNTL,
1330 .lock = &meson_clk_lock, 1502 .bit_idx = 24,
1503 },
1331 .hw.init = &(struct clk_init_data) { 1504 .hw.init = &(struct clk_init_data) {
1332 .name = "vapb_1", 1505 .name = "vapb_1",
1333 .ops = &clk_gate_ops, 1506 .ops = &clk_regmap_gate_ops,
1334 .parent_names = (const char *[]){ "vapb_1_div" }, 1507 .parent_names = (const char *[]){ "vapb_1_div" },
1335 .num_parents = 1, 1508 .num_parents = 1,
1336 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 1509 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1337 }, 1510 },
1338}; 1511};
1339 1512
1340static struct clk_mux gxbb_vapb_sel = { 1513static struct clk_regmap gxbb_vapb_sel = {
1341 .reg = (void *)HHI_VAPBCLK_CNTL, 1514 .data = &(struct clk_regmap_mux_data){
1342 .mask = 1, 1515 .offset = HHI_VAPBCLK_CNTL,
1343 .shift = 31, 1516 .mask = 1,
1344 .lock = &meson_clk_lock, 1517 .shift = 31,
1518 },
1345 .hw.init = &(struct clk_init_data){ 1519 .hw.init = &(struct clk_init_data){
1346 .name = "vapb_sel", 1520 .name = "vapb_sel",
1347 .ops = &clk_mux_ops, 1521 .ops = &clk_regmap_mux_ops,
1348 /* 1522 /*
1349 * bit 31 selects from 2 possible parents: 1523 * bit 31 selects from 2 possible parents:
1350 * vapb_0 or vapb_1 1524 * vapb_0 or vapb_1
@@ -1355,13 +1529,14 @@ static struct clk_mux gxbb_vapb_sel = {
1355 }, 1529 },
1356}; 1530};
1357 1531
1358static struct clk_gate gxbb_vapb = { 1532static struct clk_regmap gxbb_vapb = {
1359 .reg = (void *)HHI_VAPBCLK_CNTL, 1533 .data = &(struct clk_regmap_gate_data){
1360 .bit_idx = 30, 1534 .offset = HHI_VAPBCLK_CNTL,
1361 .lock = &meson_clk_lock, 1535 .bit_idx = 30,
1536 },
1362 .hw.init = &(struct clk_init_data) { 1537 .hw.init = &(struct clk_init_data) {
1363 .name = "vapb", 1538 .name = "vapb",
1364 .ops = &clk_gate_ops, 1539 .ops = &clk_regmap_gate_ops,
1365 .parent_names = (const char *[]){ "vapb_sel" }, 1540 .parent_names = (const char *[]){ "vapb_sel" },
1366 .num_parents = 1, 1541 .num_parents = 1,
1367 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 1542 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
@@ -1601,6 +1776,16 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
1601 [CLKID_VAPB_1] = &gxbb_vapb_1.hw, 1776 [CLKID_VAPB_1] = &gxbb_vapb_1.hw,
1602 [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw, 1777 [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw,
1603 [CLKID_VAPB] = &gxbb_vapb.hw, 1778 [CLKID_VAPB] = &gxbb_vapb.hw,
1779 [CLKID_HDMI_PLL_PRE_MULT] = &gxbb_hdmi_pll_pre_mult.hw,
1780 [CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw,
1781 [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw,
1782 [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw,
1783 [CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw,
1784 [CLKID_FCLK_DIV2_DIV] = &gxbb_fclk_div2_div.hw,
1785 [CLKID_FCLK_DIV3_DIV] = &gxbb_fclk_div3_div.hw,
1786 [CLKID_FCLK_DIV4_DIV] = &gxbb_fclk_div4_div.hw,
1787 [CLKID_FCLK_DIV5_DIV] = &gxbb_fclk_div5_div.hw,
1788 [CLKID_FCLK_DIV7_DIV] = &gxbb_fclk_div7_div.hw,
1604 [NR_CLKS] = NULL, 1789 [NR_CLKS] = NULL,
1605 }, 1790 },
1606 .num = NR_CLKS, 1791 .num = NR_CLKS,
@@ -1609,7 +1794,7 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
1609static struct clk_hw_onecell_data gxl_hw_onecell_data = { 1794static struct clk_hw_onecell_data gxl_hw_onecell_data = {
1610 .hws = { 1795 .hws = {
1611 [CLKID_SYS_PLL] = &gxbb_sys_pll.hw, 1796 [CLKID_SYS_PLL] = &gxbb_sys_pll.hw,
1612 [CLKID_HDMI_PLL] = &gxbb_hdmi_pll.hw, 1797 [CLKID_HDMI_PLL] = &gxl_hdmi_pll.hw,
1613 [CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw, 1798 [CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw,
1614 [CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw, 1799 [CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw,
1615 [CLKID_FCLK_DIV3] = &gxbb_fclk_div3.hw, 1800 [CLKID_FCLK_DIV3] = &gxbb_fclk_div3.hw,
@@ -1748,34 +1933,31 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
1748 [CLKID_VAPB_1] = &gxbb_vapb_1.hw, 1933 [CLKID_VAPB_1] = &gxbb_vapb_1.hw,
1749 [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw, 1934 [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw,
1750 [CLKID_VAPB] = &gxbb_vapb.hw, 1935 [CLKID_VAPB] = &gxbb_vapb.hw,
1936 [CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw,
1937 [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw,
1938 [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw,
1939 [CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw,
1940 [CLKID_FCLK_DIV2_DIV] = &gxbb_fclk_div2_div.hw,
1941 [CLKID_FCLK_DIV3_DIV] = &gxbb_fclk_div3_div.hw,
1942 [CLKID_FCLK_DIV4_DIV] = &gxbb_fclk_div4_div.hw,
1943 [CLKID_FCLK_DIV5_DIV] = &gxbb_fclk_div5_div.hw,
1944 [CLKID_FCLK_DIV7_DIV] = &gxbb_fclk_div7_div.hw,
1751 [NR_CLKS] = NULL, 1945 [NR_CLKS] = NULL,
1752 }, 1946 },
1753 .num = NR_CLKS, 1947 .num = NR_CLKS,
1754}; 1948};
1755 1949
1756/* Convenience tables to populate base addresses in .probe */ 1950static struct clk_regmap *const gxbb_clk_regmaps[] = {
1757
1758static struct meson_clk_pll *const gxbb_clk_plls[] = {
1759 &gxbb_fixed_pll,
1760 &gxbb_hdmi_pll,
1761 &gxbb_sys_pll,
1762 &gxbb_gp0_pll, 1951 &gxbb_gp0_pll,
1763};
1764
1765static struct meson_clk_pll *const gxl_clk_plls[] = {
1766 &gxbb_fixed_pll,
1767 &gxbb_hdmi_pll, 1952 &gxbb_hdmi_pll,
1768 &gxbb_sys_pll,
1769 &gxl_gp0_pll,
1770}; 1953};
1771 1954
1772static struct meson_clk_mpll *const gxbb_clk_mplls[] = { 1955static struct clk_regmap *const gxl_clk_regmaps[] = {
1773 &gxbb_mpll0, 1956 &gxl_gp0_pll,
1774 &gxbb_mpll1, 1957 &gxl_hdmi_pll,
1775 &gxbb_mpll2,
1776}; 1958};
1777 1959
1778static struct clk_gate *const gxbb_clk_gates[] = { 1960static struct clk_regmap *const gx_clk_regmaps[] = {
1779 &gxbb_clk81, 1961 &gxbb_clk81,
1780 &gxbb_ddr, 1962 &gxbb_ddr,
1781 &gxbb_dos, 1963 &gxbb_dos,
@@ -1872,9 +2054,19 @@ static struct clk_gate *const gxbb_clk_gates[] = {
1872 &gxbb_vapb_0, 2054 &gxbb_vapb_0,
1873 &gxbb_vapb_1, 2055 &gxbb_vapb_1,
1874 &gxbb_vapb, 2056 &gxbb_vapb,
1875}; 2057 &gxbb_mpeg_clk_div,
1876 2058 &gxbb_sar_adc_clk_div,
1877static struct clk_mux *const gxbb_clk_muxes[] = { 2059 &gxbb_mali_0_div,
2060 &gxbb_mali_1_div,
2061 &gxbb_cts_mclk_i958_div,
2062 &gxbb_32k_clk_div,
2063 &gxbb_sd_emmc_a_clk0_div,
2064 &gxbb_sd_emmc_b_clk0_div,
2065 &gxbb_sd_emmc_c_clk0_div,
2066 &gxbb_vpu_0_div,
2067 &gxbb_vpu_1_div,
2068 &gxbb_vapb_0_div,
2069 &gxbb_vapb_1_div,
1878 &gxbb_mpeg_clk_sel, 2070 &gxbb_mpeg_clk_sel,
1879 &gxbb_sar_adc_clk_sel, 2071 &gxbb_sar_adc_clk_sel,
1880 &gxbb_mali_0_sel, 2072 &gxbb_mali_0_sel,
@@ -1893,73 +2085,38 @@ static struct clk_mux *const gxbb_clk_muxes[] = {
1893 &gxbb_vapb_0_sel, 2085 &gxbb_vapb_0_sel,
1894 &gxbb_vapb_1_sel, 2086 &gxbb_vapb_1_sel,
1895 &gxbb_vapb_sel, 2087 &gxbb_vapb_sel,
1896}; 2088 &gxbb_mpll0,
1897 2089 &gxbb_mpll1,
1898static struct clk_divider *const gxbb_clk_dividers[] = { 2090 &gxbb_mpll2,
1899 &gxbb_mpeg_clk_div, 2091 &gxbb_mpll0_div,
1900 &gxbb_sar_adc_clk_div, 2092 &gxbb_mpll1_div,
1901 &gxbb_mali_0_div, 2093 &gxbb_mpll2_div,
1902 &gxbb_mali_1_div,
1903 &gxbb_cts_mclk_i958_div,
1904 &gxbb_32k_clk_div,
1905 &gxbb_sd_emmc_a_clk0_div,
1906 &gxbb_sd_emmc_b_clk0_div,
1907 &gxbb_sd_emmc_c_clk0_div,
1908 &gxbb_vpu_0_div,
1909 &gxbb_vpu_1_div,
1910 &gxbb_vapb_0_div,
1911 &gxbb_vapb_1_div,
1912};
1913
1914static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = {
1915 &gxbb_cts_amclk_div, 2094 &gxbb_cts_amclk_div,
2095 &gxbb_fixed_pll,
2096 &gxbb_sys_pll,
2097 &gxbb_mpll_prediv,
2098 &gxbb_fclk_div2,
2099 &gxbb_fclk_div3,
2100 &gxbb_fclk_div4,
2101 &gxbb_fclk_div5,
2102 &gxbb_fclk_div7,
1916}; 2103};
1917 2104
1918struct clkc_data { 2105struct clkc_data {
1919 struct clk_gate *const *clk_gates; 2106 struct clk_regmap *const *regmap_clks;
1920 unsigned int clk_gates_count; 2107 unsigned int regmap_clks_count;
1921 struct meson_clk_mpll *const *clk_mplls;
1922 unsigned int clk_mplls_count;
1923 struct meson_clk_pll *const *clk_plls;
1924 unsigned int clk_plls_count;
1925 struct clk_mux *const *clk_muxes;
1926 unsigned int clk_muxes_count;
1927 struct clk_divider *const *clk_dividers;
1928 unsigned int clk_dividers_count;
1929 struct meson_clk_audio_divider *const *clk_audio_dividers;
1930 unsigned int clk_audio_dividers_count;
1931 struct clk_hw_onecell_data *hw_onecell_data; 2108 struct clk_hw_onecell_data *hw_onecell_data;
1932}; 2109};
1933 2110
1934static const struct clkc_data gxbb_clkc_data = { 2111static const struct clkc_data gxbb_clkc_data = {
1935 .clk_gates = gxbb_clk_gates, 2112 .regmap_clks = gxbb_clk_regmaps,
1936 .clk_gates_count = ARRAY_SIZE(gxbb_clk_gates), 2113 .regmap_clks_count = ARRAY_SIZE(gxbb_clk_regmaps),
1937 .clk_mplls = gxbb_clk_mplls,
1938 .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls),
1939 .clk_plls = gxbb_clk_plls,
1940 .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls),
1941 .clk_muxes = gxbb_clk_muxes,
1942 .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes),
1943 .clk_dividers = gxbb_clk_dividers,
1944 .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
1945 .clk_audio_dividers = gxbb_audio_dividers,
1946 .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
1947 .hw_onecell_data = &gxbb_hw_onecell_data, 2114 .hw_onecell_data = &gxbb_hw_onecell_data,
1948}; 2115};
1949 2116
1950static const struct clkc_data gxl_clkc_data = { 2117static const struct clkc_data gxl_clkc_data = {
1951 .clk_gates = gxbb_clk_gates, 2118 .regmap_clks = gxl_clk_regmaps,
1952 .clk_gates_count = ARRAY_SIZE(gxbb_clk_gates), 2119 .regmap_clks_count = ARRAY_SIZE(gxl_clk_regmaps),
1953 .clk_mplls = gxbb_clk_mplls,
1954 .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls),
1955 .clk_plls = gxl_clk_plls,
1956 .clk_plls_count = ARRAY_SIZE(gxl_clk_plls),
1957 .clk_muxes = gxbb_clk_muxes,
1958 .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes),
1959 .clk_dividers = gxbb_clk_dividers,
1960 .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
1961 .clk_audio_dividers = gxbb_audio_dividers,
1962 .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
1963 .hw_onecell_data = &gxl_hw_onecell_data, 2120 .hw_onecell_data = &gxl_hw_onecell_data,
1964}; 2121};
1965 2122
@@ -1969,71 +2126,79 @@ static const struct of_device_id clkc_match_table[] = {
1969 {}, 2126 {},
1970}; 2127};
1971 2128
2129static const struct regmap_config clkc_regmap_config = {
2130 .reg_bits = 32,
2131 .val_bits = 32,
2132 .reg_stride = 4,
2133};
2134
1972static int gxbb_clkc_probe(struct platform_device *pdev) 2135static int gxbb_clkc_probe(struct platform_device *pdev)
1973{ 2136{
1974 const struct clkc_data *clkc_data; 2137 const struct clkc_data *clkc_data;
2138 struct resource *res;
1975 void __iomem *clk_base; 2139 void __iomem *clk_base;
1976 int ret, clkid, i; 2140 struct regmap *map;
2141 int ret, i;
1977 struct device *dev = &pdev->dev; 2142 struct device *dev = &pdev->dev;
1978 2143
1979 clkc_data = of_device_get_match_data(&pdev->dev); 2144 clkc_data = of_device_get_match_data(dev);
1980 if (!clkc_data) 2145 if (!clkc_data)
1981 return -EINVAL; 2146 return -EINVAL;
1982 2147
1983 /* Generic clocks and PLLs */ 2148 /* Get the hhi system controller node if available */
1984 clk_base = of_iomap(dev->of_node, 0); 2149 map = syscon_node_to_regmap(of_get_parent(dev->of_node));
1985 if (!clk_base) { 2150 if (IS_ERR(map)) {
1986 pr_err("%s: Unable to map clk base\n", __func__); 2151 dev_err(dev,
1987 return -ENXIO; 2152 "failed to get HHI regmap - Trying obsolete regs\n");
1988 }
1989
1990 /* Populate base address for PLLs */
1991 for (i = 0; i < clkc_data->clk_plls_count; i++)
1992 clkc_data->clk_plls[i]->base = clk_base;
1993
1994 /* Populate base address for MPLLs */
1995 for (i = 0; i < clkc_data->clk_mplls_count; i++)
1996 clkc_data->clk_mplls[i]->base = clk_base;
1997 2153
1998 /* Populate base address for gates */ 2154 /*
1999 for (i = 0; i < clkc_data->clk_gates_count; i++) 2155 * FIXME: HHI registers should be accessed through
2000 clkc_data->clk_gates[i]->reg = clk_base + 2156 * the appropriate system controller. This is required because
2001 (u64)clkc_data->clk_gates[i]->reg; 2157 * there is more than just clocks in this register space
2002 2158 *
2003 /* Populate base address for muxes */ 2159 * This fallback method is only provided temporarily until
2004 for (i = 0; i < clkc_data->clk_muxes_count; i++) 2160 * all the platform DTs are properly using the syscon node
2005 clkc_data->clk_muxes[i]->reg = clk_base + 2161 */
2006 (u64)clkc_data->clk_muxes[i]->reg; 2162 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2163 if (!res)
2164 return -EINVAL;
2165
2166 clk_base = devm_ioremap(dev, res->start, resource_size(res));
2167 if (!clk_base) {
2168 dev_err(dev, "Unable to map clk base\n");
2169 return -ENXIO;
2170 }
2171
2172 map = devm_regmap_init_mmio(dev, clk_base,
2173 &clkc_regmap_config);
2174 if (IS_ERR(map))
2175 return PTR_ERR(map);
2176 }
2007 2177
2008 /* Populate base address for dividers */ 2178 /* Populate regmap for the common regmap backed clocks */
2009 for (i = 0; i < clkc_data->clk_dividers_count; i++) 2179 for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++)
2010 clkc_data->clk_dividers[i]->reg = clk_base + 2180 gx_clk_regmaps[i]->map = map;
2011 (u64)clkc_data->clk_dividers[i]->reg;
2012 2181
2013 /* Populate base address for the audio dividers */ 2182 /* Populate regmap for soc specific clocks */
2014 for (i = 0; i < clkc_data->clk_audio_dividers_count; i++) 2183 for (i = 0; i < clkc_data->regmap_clks_count; i++)
2015 clkc_data->clk_audio_dividers[i]->base = clk_base; 2184 clkc_data->regmap_clks[i]->map = map;
2016 2185
2017 /* 2186 /* Register all clks */
2018 * register all clks 2187 for (i = 0; i < clkc_data->hw_onecell_data->num; i++) {
2019 */
2020 for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) {
2021 /* array might be sparse */ 2188 /* array might be sparse */
2022 if (!clkc_data->hw_onecell_data->hws[clkid]) 2189 if (!clkc_data->hw_onecell_data->hws[i])
2023 continue; 2190 continue;
2024 2191
2025 ret = devm_clk_hw_register(dev, 2192 ret = devm_clk_hw_register(dev,
2026 clkc_data->hw_onecell_data->hws[clkid]); 2193 clkc_data->hw_onecell_data->hws[i]);
2027 if (ret) 2194 if (ret) {
2028 goto iounmap; 2195 dev_err(dev, "Clock registration failed\n");
2196 return ret;
2197 }
2029 } 2198 }
2030 2199
2031 return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, 2200 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
2032 clkc_data->hw_onecell_data); 2201 clkc_data->hw_onecell_data);
2033
2034iounmap:
2035 iounmap(clk_base);
2036 return ret;
2037} 2202}
2038 2203
2039static struct platform_driver gxbb_driver = { 2204static struct platform_driver gxbb_driver = {
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index aee6fbba2004..9febf3f03739 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -194,8 +194,18 @@
194#define CLKID_VPU_1_DIV 130 194#define CLKID_VPU_1_DIV 130
195#define CLKID_VAPB_0_DIV 134 195#define CLKID_VAPB_0_DIV 134
196#define CLKID_VAPB_1_DIV 137 196#define CLKID_VAPB_1_DIV 137
197 197#define CLKID_HDMI_PLL_PRE_MULT 141
198#define NR_CLKS 141 198#define CLKID_MPLL0_DIV 142
199#define CLKID_MPLL1_DIV 143
200#define CLKID_MPLL2_DIV 144
201#define CLKID_MPLL_PREDIV 145
202#define CLKID_FCLK_DIV2_DIV 146
203#define CLKID_FCLK_DIV3_DIV 147
204#define CLKID_FCLK_DIV4_DIV 148
205#define CLKID_FCLK_DIV5_DIV 149
206#define CLKID_FCLK_DIV7_DIV 150
207
208#define NR_CLKS 151
199 209
200/* include the CLKIDs that have been made part of the DT binding */ 210/* include the CLKIDs that have been made part of the DT binding */
201#include <dt-bindings/clock/gxbb-clkc.h> 211#include <dt-bindings/clock/gxbb-clkc.h>
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 3ffea80c1308..cc2992493e0b 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -23,14 +23,16 @@
23 23
24#include <linux/clk.h> 24#include <linux/clk.h>
25#include <linux/clk-provider.h> 25#include <linux/clk-provider.h>
26#include <linux/init.h>
26#include <linux/of_address.h> 27#include <linux/of_address.h>
27#include <linux/platform_device.h> 28#include <linux/platform_device.h>
28#include <linux/reset-controller.h> 29#include <linux/reset-controller.h>
29#include <linux/slab.h> 30#include <linux/slab.h>
30#include <linux/init.h> 31#include <linux/regmap.h>
31 32
32#include "clkc.h" 33#include "clkc.h"
33#include "meson8b.h" 34#include "meson8b.h"
35#include "clk-regmap.h"
34 36
35static DEFINE_SPINLOCK(meson_clk_lock); 37static DEFINE_SPINLOCK(meson_clk_lock);
36 38
@@ -97,20 +99,6 @@ static const struct pll_rate_table sys_pll_rate_table[] = {
97 { /* sentinel */ }, 99 { /* sentinel */ },
98}; 100};
99 101
100static const struct clk_div_table cpu_div_table[] = {
101 { .val = 1, .div = 1 },
102 { .val = 2, .div = 2 },
103 { .val = 3, .div = 3 },
104 { .val = 2, .div = 4 },
105 { .val = 3, .div = 6 },
106 { .val = 4, .div = 8 },
107 { .val = 5, .div = 10 },
108 { .val = 6, .div = 12 },
109 { .val = 7, .div = 14 },
110 { .val = 8, .div = 16 },
111 { /* sentinel */ },
112};
113
114static struct clk_fixed_rate meson8b_xtal = { 102static struct clk_fixed_rate meson8b_xtal = {
115 .fixed_rate = 24000000, 103 .fixed_rate = 24000000,
116 .hw.init = &(struct clk_init_data){ 104 .hw.init = &(struct clk_init_data){
@@ -120,23 +108,39 @@ static struct clk_fixed_rate meson8b_xtal = {
120 }, 108 },
121}; 109};
122 110
123static struct meson_clk_pll meson8b_fixed_pll = { 111static struct clk_regmap meson8b_fixed_pll = {
124 .m = { 112 .data = &(struct meson_clk_pll_data){
125 .reg_off = HHI_MPLL_CNTL, 113 .m = {
126 .shift = 0, 114 .reg_off = HHI_MPLL_CNTL,
127 .width = 9, 115 .shift = 0,
128 }, 116 .width = 9,
129 .n = { 117 },
130 .reg_off = HHI_MPLL_CNTL, 118 .n = {
131 .shift = 9, 119 .reg_off = HHI_MPLL_CNTL,
132 .width = 5, 120 .shift = 9,
133 }, 121 .width = 5,
134 .od = { 122 },
135 .reg_off = HHI_MPLL_CNTL, 123 .od = {
136 .shift = 16, 124 .reg_off = HHI_MPLL_CNTL,
137 .width = 2, 125 .shift = 16,
126 .width = 2,
127 },
128 .frac = {
129 .reg_off = HHI_MPLL_CNTL2,
130 .shift = 0,
131 .width = 12,
132 },
133 .l = {
134 .reg_off = HHI_MPLL_CNTL,
135 .shift = 31,
136 .width = 1,
137 },
138 .rst = {
139 .reg_off = HHI_MPLL_CNTL,
140 .shift = 29,
141 .width = 1,
142 },
138 }, 143 },
139 .lock = &meson_clk_lock,
140 .hw.init = &(struct clk_init_data){ 144 .hw.init = &(struct clk_init_data){
141 .name = "fixed_pll", 145 .name = "fixed_pll",
142 .ops = &meson_clk_pll_ro_ops, 146 .ops = &meson_clk_pll_ro_ops,
@@ -146,23 +150,34 @@ static struct meson_clk_pll meson8b_fixed_pll = {
146 }, 150 },
147}; 151};
148 152
149static struct meson_clk_pll meson8b_vid_pll = { 153static struct clk_regmap meson8b_vid_pll = {
150 .m = { 154 .data = &(struct meson_clk_pll_data){
151 .reg_off = HHI_VID_PLL_CNTL, 155 .m = {
152 .shift = 0, 156 .reg_off = HHI_VID_PLL_CNTL,
153 .width = 9, 157 .shift = 0,
158 .width = 9,
159 },
160 .n = {
161 .reg_off = HHI_VID_PLL_CNTL,
162 .shift = 9,
163 .width = 5,
164 },
165 .od = {
166 .reg_off = HHI_VID_PLL_CNTL,
167 .shift = 16,
168 .width = 2,
169 },
170 .l = {
171 .reg_off = HHI_VID_PLL_CNTL,
172 .shift = 31,
173 .width = 1,
174 },
175 .rst = {
176 .reg_off = HHI_VID_PLL_CNTL,
177 .shift = 29,
178 .width = 1,
179 },
154 }, 180 },
155 .n = {
156 .reg_off = HHI_VID_PLL_CNTL,
157 .shift = 9,
158 .width = 5,
159 },
160 .od = {
161 .reg_off = HHI_VID_PLL_CNTL,
162 .shift = 16,
163 .width = 2,
164 },
165 .lock = &meson_clk_lock,
166 .hw.init = &(struct clk_init_data){ 181 .hw.init = &(struct clk_init_data){
167 .name = "vid_pll", 182 .name = "vid_pll",
168 .ops = &meson_clk_pll_ro_ops, 183 .ops = &meson_clk_pll_ro_ops,
@@ -172,213 +187,317 @@ static struct meson_clk_pll meson8b_vid_pll = {
172 }, 187 },
173}; 188};
174 189
175static struct meson_clk_pll meson8b_sys_pll = { 190static struct clk_regmap meson8b_sys_pll = {
176 .m = { 191 .data = &(struct meson_clk_pll_data){
177 .reg_off = HHI_SYS_PLL_CNTL, 192 .m = {
178 .shift = 0, 193 .reg_off = HHI_SYS_PLL_CNTL,
179 .width = 9, 194 .shift = 0,
180 }, 195 .width = 9,
181 .n = { 196 },
182 .reg_off = HHI_SYS_PLL_CNTL, 197 .n = {
183 .shift = 9, 198 .reg_off = HHI_SYS_PLL_CNTL,
184 .width = 5, 199 .shift = 9,
200 .width = 5,
201 },
202 .od = {
203 .reg_off = HHI_SYS_PLL_CNTL,
204 .shift = 16,
205 .width = 2,
206 },
207 .l = {
208 .reg_off = HHI_SYS_PLL_CNTL,
209 .shift = 31,
210 .width = 1,
211 },
212 .rst = {
213 .reg_off = HHI_SYS_PLL_CNTL,
214 .shift = 29,
215 .width = 1,
216 },
217 .table = sys_pll_rate_table,
185 }, 218 },
186 .od = {
187 .reg_off = HHI_SYS_PLL_CNTL,
188 .shift = 16,
189 .width = 2,
190 },
191 .rate_table = sys_pll_rate_table,
192 .rate_count = ARRAY_SIZE(sys_pll_rate_table),
193 .lock = &meson_clk_lock,
194 .hw.init = &(struct clk_init_data){ 219 .hw.init = &(struct clk_init_data){
195 .name = "sys_pll", 220 .name = "sys_pll",
196 .ops = &meson_clk_pll_ops, 221 .ops = &meson_clk_pll_ro_ops,
197 .parent_names = (const char *[]){ "xtal" }, 222 .parent_names = (const char *[]){ "xtal" },
198 .num_parents = 1, 223 .num_parents = 1,
199 .flags = CLK_GET_RATE_NOCACHE, 224 .flags = CLK_GET_RATE_NOCACHE,
200 }, 225 },
201}; 226};
202 227
203static struct clk_fixed_factor meson8b_fclk_div2 = { 228static struct clk_fixed_factor meson8b_fclk_div2_div = {
204 .mult = 1, 229 .mult = 1,
205 .div = 2, 230 .div = 2,
206 .hw.init = &(struct clk_init_data){ 231 .hw.init = &(struct clk_init_data){
207 .name = "fclk_div2", 232 .name = "fclk_div2_div",
208 .ops = &clk_fixed_factor_ops, 233 .ops = &clk_fixed_factor_ops,
209 .parent_names = (const char *[]){ "fixed_pll" }, 234 .parent_names = (const char *[]){ "fixed_pll" },
210 .num_parents = 1, 235 .num_parents = 1,
211 }, 236 },
212}; 237};
213 238
214static struct clk_fixed_factor meson8b_fclk_div3 = { 239static struct clk_regmap meson8b_fclk_div2 = {
240 .data = &(struct clk_regmap_gate_data){
241 .offset = HHI_MPLL_CNTL6,
242 .bit_idx = 27,
243 },
244 .hw.init = &(struct clk_init_data){
245 .name = "fclk_div2",
246 .ops = &clk_regmap_gate_ops,
247 .parent_names = (const char *[]){ "fclk_div2_div" },
248 .num_parents = 1,
249 },
250};
251
252static struct clk_fixed_factor meson8b_fclk_div3_div = {
215 .mult = 1, 253 .mult = 1,
216 .div = 3, 254 .div = 3,
217 .hw.init = &(struct clk_init_data){ 255 .hw.init = &(struct clk_init_data){
218 .name = "fclk_div3", 256 .name = "fclk_div_div3",
219 .ops = &clk_fixed_factor_ops, 257 .ops = &clk_fixed_factor_ops,
220 .parent_names = (const char *[]){ "fixed_pll" }, 258 .parent_names = (const char *[]){ "fixed_pll" },
221 .num_parents = 1, 259 .num_parents = 1,
222 }, 260 },
223}; 261};
224 262
225static struct clk_fixed_factor meson8b_fclk_div4 = { 263static struct clk_regmap meson8b_fclk_div3 = {
264 .data = &(struct clk_regmap_gate_data){
265 .offset = HHI_MPLL_CNTL6,
266 .bit_idx = 28,
267 },
268 .hw.init = &(struct clk_init_data){
269 .name = "fclk_div3",
270 .ops = &clk_regmap_gate_ops,
271 .parent_names = (const char *[]){ "fclk_div3_div" },
272 .num_parents = 1,
273 },
274};
275
276static struct clk_fixed_factor meson8b_fclk_div4_div = {
226 .mult = 1, 277 .mult = 1,
227 .div = 4, 278 .div = 4,
228 .hw.init = &(struct clk_init_data){ 279 .hw.init = &(struct clk_init_data){
229 .name = "fclk_div4", 280 .name = "fclk_div4_div",
230 .ops = &clk_fixed_factor_ops, 281 .ops = &clk_fixed_factor_ops,
231 .parent_names = (const char *[]){ "fixed_pll" }, 282 .parent_names = (const char *[]){ "fixed_pll" },
232 .num_parents = 1, 283 .num_parents = 1,
233 }, 284 },
234}; 285};
235 286
236static struct clk_fixed_factor meson8b_fclk_div5 = { 287static struct clk_regmap meson8b_fclk_div4 = {
288 .data = &(struct clk_regmap_gate_data){
289 .offset = HHI_MPLL_CNTL6,
290 .bit_idx = 29,
291 },
292 .hw.init = &(struct clk_init_data){
293 .name = "fclk_div4",
294 .ops = &clk_regmap_gate_ops,
295 .parent_names = (const char *[]){ "fclk_div4_div" },
296 .num_parents = 1,
297 },
298};
299
300static struct clk_fixed_factor meson8b_fclk_div5_div = {
237 .mult = 1, 301 .mult = 1,
238 .div = 5, 302 .div = 5,
239 .hw.init = &(struct clk_init_data){ 303 .hw.init = &(struct clk_init_data){
240 .name = "fclk_div5", 304 .name = "fclk_div5_div",
241 .ops = &clk_fixed_factor_ops, 305 .ops = &clk_fixed_factor_ops,
242 .parent_names = (const char *[]){ "fixed_pll" }, 306 .parent_names = (const char *[]){ "fixed_pll" },
243 .num_parents = 1, 307 .num_parents = 1,
244 }, 308 },
245}; 309};
246 310
247static struct clk_fixed_factor meson8b_fclk_div7 = { 311static struct clk_regmap meson8b_fclk_div5 = {
312 .data = &(struct clk_regmap_gate_data){
313 .offset = HHI_MPLL_CNTL6,
314 .bit_idx = 30,
315 },
316 .hw.init = &(struct clk_init_data){
317 .name = "fclk_div5",
318 .ops = &clk_regmap_gate_ops,
319 .parent_names = (const char *[]){ "fclk_div5_div" },
320 .num_parents = 1,
321 },
322};
323
324static struct clk_fixed_factor meson8b_fclk_div7_div = {
248 .mult = 1, 325 .mult = 1,
249 .div = 7, 326 .div = 7,
250 .hw.init = &(struct clk_init_data){ 327 .hw.init = &(struct clk_init_data){
251 .name = "fclk_div7", 328 .name = "fclk_div7_div",
252 .ops = &clk_fixed_factor_ops, 329 .ops = &clk_fixed_factor_ops,
253 .parent_names = (const char *[]){ "fixed_pll" }, 330 .parent_names = (const char *[]){ "fixed_pll" },
254 .num_parents = 1, 331 .num_parents = 1,
255 }, 332 },
256}; 333};
257 334
258static struct meson_clk_mpll meson8b_mpll0 = { 335static struct clk_regmap meson8b_fclk_div7 = {
259 .sdm = { 336 .data = &(struct clk_regmap_gate_data){
260 .reg_off = HHI_MPLL_CNTL7, 337 .offset = HHI_MPLL_CNTL6,
261 .shift = 0, 338 .bit_idx = 31,
262 .width = 14,
263 }, 339 },
264 .sdm_en = { 340 .hw.init = &(struct clk_init_data){
265 .reg_off = HHI_MPLL_CNTL7, 341 .name = "fclk_div7",
266 .shift = 15, 342 .ops = &clk_regmap_gate_ops,
267 .width = 1, 343 .parent_names = (const char *[]){ "fclk_div7_div" },
344 .num_parents = 1,
268 }, 345 },
269 .n2 = { 346};
270 .reg_off = HHI_MPLL_CNTL7, 347
271 .shift = 16, 348static struct clk_regmap meson8b_mpll_prediv = {
272 .width = 9, 349 .data = &(struct clk_regmap_div_data){
350 .offset = HHI_MPLL_CNTL5,
351 .shift = 12,
352 .width = 1,
273 }, 353 },
274 .en = { 354 .hw.init = &(struct clk_init_data){
275 .reg_off = HHI_MPLL_CNTL7, 355 .name = "mpll_prediv",
276 .shift = 14, 356 .ops = &clk_regmap_divider_ro_ops,
277 .width = 1, 357 .parent_names = (const char *[]){ "fixed_pll" },
358 .num_parents = 1,
278 }, 359 },
279 .ssen = { 360};
280 .reg_off = HHI_MPLL_CNTL, 361
281 .shift = 25, 362static struct clk_regmap meson8b_mpll0_div = {
282 .width = 1, 363 .data = &(struct meson_clk_mpll_data){
364 .sdm = {
365 .reg_off = HHI_MPLL_CNTL7,
366 .shift = 0,
367 .width = 14,
368 },
369 .sdm_en = {
370 .reg_off = HHI_MPLL_CNTL7,
371 .shift = 15,
372 .width = 1,
373 },
374 .n2 = {
375 .reg_off = HHI_MPLL_CNTL7,
376 .shift = 16,
377 .width = 9,
378 },
379 .ssen = {
380 .reg_off = HHI_MPLL_CNTL,
381 .shift = 25,
382 .width = 1,
383 },
384 .lock = &meson_clk_lock,
283 }, 385 },
284 .lock = &meson_clk_lock,
285 .hw.init = &(struct clk_init_data){ 386 .hw.init = &(struct clk_init_data){
286 .name = "mpll0", 387 .name = "mpll0_div",
287 .ops = &meson_clk_mpll_ops, 388 .ops = &meson_clk_mpll_ops,
288 .parent_names = (const char *[]){ "fixed_pll" }, 389 .parent_names = (const char *[]){ "mpll_prediv" },
289 .num_parents = 1, 390 .num_parents = 1,
290 }, 391 },
291}; 392};
292 393
293static struct meson_clk_mpll meson8b_mpll1 = { 394static struct clk_regmap meson8b_mpll0 = {
294 .sdm = { 395 .data = &(struct clk_regmap_gate_data){
295 .reg_off = HHI_MPLL_CNTL8, 396 .offset = HHI_MPLL_CNTL7,
296 .shift = 0, 397 .bit_idx = 14,
297 .width = 14,
298 }, 398 },
299 .sdm_en = { 399 .hw.init = &(struct clk_init_data){
300 .reg_off = HHI_MPLL_CNTL8, 400 .name = "mpll0",
301 .shift = 15, 401 .ops = &clk_regmap_gate_ops,
302 .width = 1, 402 .parent_names = (const char *[]){ "mpll0_div" },
303 }, 403 .num_parents = 1,
304 .n2 = { 404 .flags = CLK_SET_RATE_PARENT,
305 .reg_off = HHI_MPLL_CNTL8,
306 .shift = 16,
307 .width = 9,
308 }, 405 },
309 .en = { 406};
310 .reg_off = HHI_MPLL_CNTL8, 407
311 .shift = 14, 408static struct clk_regmap meson8b_mpll1_div = {
312 .width = 1, 409 .data = &(struct meson_clk_mpll_data){
410 .sdm = {
411 .reg_off = HHI_MPLL_CNTL8,
412 .shift = 0,
413 .width = 14,
414 },
415 .sdm_en = {
416 .reg_off = HHI_MPLL_CNTL8,
417 .shift = 15,
418 .width = 1,
419 },
420 .n2 = {
421 .reg_off = HHI_MPLL_CNTL8,
422 .shift = 16,
423 .width = 9,
424 },
425 .lock = &meson_clk_lock,
313 }, 426 },
314 .lock = &meson_clk_lock,
315 .hw.init = &(struct clk_init_data){ 427 .hw.init = &(struct clk_init_data){
316 .name = "mpll1", 428 .name = "mpll1_div",
317 .ops = &meson_clk_mpll_ops, 429 .ops = &meson_clk_mpll_ops,
318 .parent_names = (const char *[]){ "fixed_pll" }, 430 .parent_names = (const char *[]){ "mpll_prediv" },
319 .num_parents = 1, 431 .num_parents = 1,
320 }, 432 },
321}; 433};
322 434
323static struct meson_clk_mpll meson8b_mpll2 = { 435static struct clk_regmap meson8b_mpll1 = {
324 .sdm = { 436 .data = &(struct clk_regmap_gate_data){
325 .reg_off = HHI_MPLL_CNTL9, 437 .offset = HHI_MPLL_CNTL8,
326 .shift = 0, 438 .bit_idx = 14,
327 .width = 14,
328 },
329 .sdm_en = {
330 .reg_off = HHI_MPLL_CNTL9,
331 .shift = 15,
332 .width = 1,
333 }, 439 },
334 .n2 = { 440 .hw.init = &(struct clk_init_data){
335 .reg_off = HHI_MPLL_CNTL9, 441 .name = "mpll1",
336 .shift = 16, 442 .ops = &clk_regmap_gate_ops,
337 .width = 9, 443 .parent_names = (const char *[]){ "mpll1_div" },
444 .num_parents = 1,
445 .flags = CLK_SET_RATE_PARENT,
338 }, 446 },
339 .en = { 447};
340 .reg_off = HHI_MPLL_CNTL9, 448
341 .shift = 14, 449static struct clk_regmap meson8b_mpll2_div = {
342 .width = 1, 450 .data = &(struct meson_clk_mpll_data){
451 .sdm = {
452 .reg_off = HHI_MPLL_CNTL9,
453 .shift = 0,
454 .width = 14,
455 },
456 .sdm_en = {
457 .reg_off = HHI_MPLL_CNTL9,
458 .shift = 15,
459 .width = 1,
460 },
461 .n2 = {
462 .reg_off = HHI_MPLL_CNTL9,
463 .shift = 16,
464 .width = 9,
465 },
466 .lock = &meson_clk_lock,
343 }, 467 },
344 .lock = &meson_clk_lock,
345 .hw.init = &(struct clk_init_data){ 468 .hw.init = &(struct clk_init_data){
346 .name = "mpll2", 469 .name = "mpll2_div",
347 .ops = &meson_clk_mpll_ops, 470 .ops = &meson_clk_mpll_ops,
348 .parent_names = (const char *[]){ "fixed_pll" }, 471 .parent_names = (const char *[]){ "mpll_prediv" },
349 .num_parents = 1, 472 .num_parents = 1,
350 }, 473 },
351}; 474};
352 475
353/* 476static struct clk_regmap meson8b_mpll2 = {
354 * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL 477 .data = &(struct clk_regmap_gate_data){
355 * post-dividers and should be modeled with their respective PLLs via the 478 .offset = HHI_MPLL_CNTL9,
356 * forthcoming coordinated clock rates feature 479 .bit_idx = 14,
357 */ 480 },
358static struct meson_clk_cpu meson8b_cpu_clk = {
359 .reg_off = HHI_SYS_CPU_CLK_CNTL1,
360 .div_table = cpu_div_table,
361 .clk_nb.notifier_call = meson_clk_cpu_notifier_cb,
362 .hw.init = &(struct clk_init_data){ 481 .hw.init = &(struct clk_init_data){
363 .name = "cpu_clk", 482 .name = "mpll2",
364 .ops = &meson_clk_cpu_ops, 483 .ops = &clk_regmap_gate_ops,
365 .parent_names = (const char *[]){ "sys_pll" }, 484 .parent_names = (const char *[]){ "mpll2_div" },
366 .num_parents = 1, 485 .num_parents = 1,
486 .flags = CLK_SET_RATE_PARENT,
367 }, 487 },
368}; 488};
369 489
370static u32 mux_table_clk81[] = { 6, 5, 7 }; 490static u32 mux_table_clk81[] = { 6, 5, 7 };
371 491static struct clk_regmap meson8b_mpeg_clk_sel = {
372struct clk_mux meson8b_mpeg_clk_sel = { 492 .data = &(struct clk_regmap_mux_data){
373 .reg = (void *)HHI_MPEG_CLK_CNTL, 493 .offset = HHI_MPEG_CLK_CNTL,
374 .mask = 0x7, 494 .mask = 0x7,
375 .shift = 12, 495 .shift = 12,
376 .flags = CLK_MUX_READ_ONLY, 496 .table = mux_table_clk81,
377 .table = mux_table_clk81, 497 },
378 .lock = &meson_clk_lock,
379 .hw.init = &(struct clk_init_data){ 498 .hw.init = &(struct clk_init_data){
380 .name = "mpeg_clk_sel", 499 .name = "mpeg_clk_sel",
381 .ops = &clk_mux_ro_ops, 500 .ops = &clk_regmap_mux_ro_ops,
382 /* 501 /*
383 * FIXME bits 14:12 selects from 8 possible parents: 502 * FIXME bits 14:12 selects from 8 possible parents:
384 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2, 503 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
@@ -387,34 +506,136 @@ struct clk_mux meson8b_mpeg_clk_sel = {
387 .parent_names = (const char *[]){ "fclk_div3", "fclk_div4", 506 .parent_names = (const char *[]){ "fclk_div3", "fclk_div4",
388 "fclk_div5" }, 507 "fclk_div5" },
389 .num_parents = 3, 508 .num_parents = 3,
390 .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
391 }, 509 },
392}; 510};
393 511
394struct clk_divider meson8b_mpeg_clk_div = { 512static struct clk_regmap meson8b_mpeg_clk_div = {
395 .reg = (void *)HHI_MPEG_CLK_CNTL, 513 .data = &(struct clk_regmap_div_data){
396 .shift = 0, 514 .offset = HHI_MPEG_CLK_CNTL,
397 .width = 7, 515 .shift = 0,
398 .lock = &meson_clk_lock, 516 .width = 7,
517 },
399 .hw.init = &(struct clk_init_data){ 518 .hw.init = &(struct clk_init_data){
400 .name = "mpeg_clk_div", 519 .name = "mpeg_clk_div",
401 .ops = &clk_divider_ops, 520 .ops = &clk_regmap_divider_ro_ops,
402 .parent_names = (const char *[]){ "mpeg_clk_sel" }, 521 .parent_names = (const char *[]){ "mpeg_clk_sel" },
403 .num_parents = 1, 522 .num_parents = 1,
404 .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
405 }, 523 },
406}; 524};
407 525
408struct clk_gate meson8b_clk81 = { 526static struct clk_regmap meson8b_clk81 = {
409 .reg = (void *)HHI_MPEG_CLK_CNTL, 527 .data = &(struct clk_regmap_gate_data){
410 .bit_idx = 7, 528 .offset = HHI_MPEG_CLK_CNTL,
411 .lock = &meson_clk_lock, 529 .bit_idx = 7,
530 },
412 .hw.init = &(struct clk_init_data){ 531 .hw.init = &(struct clk_init_data){
413 .name = "clk81", 532 .name = "clk81",
414 .ops = &clk_gate_ops, 533 .ops = &clk_regmap_gate_ops,
415 .parent_names = (const char *[]){ "mpeg_clk_div" }, 534 .parent_names = (const char *[]){ "mpeg_clk_div" },
416 .num_parents = 1, 535 .num_parents = 1,
417 .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), 536 .flags = CLK_IS_CRITICAL,
537 },
538};
539
540static struct clk_regmap meson8b_cpu_in_sel = {
541 .data = &(struct clk_regmap_mux_data){
542 .offset = HHI_SYS_CPU_CLK_CNTL0,
543 .mask = 0x1,
544 .shift = 0,
545 },
546 .hw.init = &(struct clk_init_data){
547 .name = "cpu_in_sel",
548 .ops = &clk_regmap_mux_ro_ops,
549 .parent_names = (const char *[]){ "xtal", "sys_pll" },
550 .num_parents = 2,
551 .flags = (CLK_SET_RATE_PARENT |
552 CLK_SET_RATE_NO_REPARENT),
553 },
554};
555
556static struct clk_fixed_factor meson8b_cpu_div2 = {
557 .mult = 1,
558 .div = 2,
559 .hw.init = &(struct clk_init_data){
560 .name = "cpu_div2",
561 .ops = &clk_fixed_factor_ops,
562 .parent_names = (const char *[]){ "cpu_in_sel" },
563 .num_parents = 1,
564 .flags = CLK_SET_RATE_PARENT,
565 },
566};
567
568static struct clk_fixed_factor meson8b_cpu_div3 = {
569 .mult = 1,
570 .div = 3,
571 .hw.init = &(struct clk_init_data){
572 .name = "cpu_div3",
573 .ops = &clk_fixed_factor_ops,
574 .parent_names = (const char *[]){ "cpu_in_sel" },
575 .num_parents = 1,
576 .flags = CLK_SET_RATE_PARENT,
577 },
578};
579
580static const struct clk_div_table cpu_scale_table[] = {
581 { .val = 2, .div = 4 },
582 { .val = 3, .div = 6 },
583 { .val = 4, .div = 8 },
584 { .val = 5, .div = 10 },
585 { .val = 6, .div = 12 },
586 { .val = 7, .div = 14 },
587 { .val = 8, .div = 16 },
588 { /* sentinel */ },
589};
590
591static struct clk_regmap meson8b_cpu_scale_div = {
592 .data = &(struct clk_regmap_div_data){
593 .offset = HHI_SYS_CPU_CLK_CNTL1,
594 .shift = 20,
595 .width = 9,
596 .table = cpu_scale_table,
597 .flags = CLK_DIVIDER_ALLOW_ZERO,
598 },
599 .hw.init = &(struct clk_init_data){
600 .name = "cpu_scale_div",
601 .ops = &clk_regmap_divider_ro_ops,
602 .parent_names = (const char *[]){ "cpu_in_sel" },
603 .num_parents = 1,
604 .flags = CLK_SET_RATE_PARENT,
605 },
606};
607
608static struct clk_regmap meson8b_cpu_scale_out_sel = {
609 .data = &(struct clk_regmap_mux_data){
610 .offset = HHI_SYS_CPU_CLK_CNTL0,
611 .mask = 0x3,
612 .shift = 2,
613 },
614 .hw.init = &(struct clk_init_data){
615 .name = "cpu_scale_out_sel",
616 .ops = &clk_regmap_mux_ro_ops,
617 .parent_names = (const char *[]) { "cpu_in_sel",
618 "cpu_div2",
619 "cpu_div3",
620 "cpu_scale_div" },
621 .num_parents = 4,
622 .flags = CLK_SET_RATE_PARENT,
623 },
624};
625
626static struct clk_regmap meson8b_cpu_clk = {
627 .data = &(struct clk_regmap_mux_data){
628 .offset = HHI_SYS_CPU_CLK_CNTL0,
629 .mask = 0x1,
630 .shift = 7,
631 },
632 .hw.init = &(struct clk_init_data){
633 .name = "cpu_clk",
634 .ops = &clk_regmap_mux_ro_ops,
635 .parent_names = (const char *[]){ "xtal", "cpu_out_sel" },
636 .num_parents = 2,
637 .flags = (CLK_SET_RATE_PARENT |
638 CLK_SET_RATE_NO_REPARENT),
418 }, 639 },
419}; 640};
420 641
@@ -599,24 +820,26 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
599 [CLKID_MPLL0] = &meson8b_mpll0.hw, 820 [CLKID_MPLL0] = &meson8b_mpll0.hw,
600 [CLKID_MPLL1] = &meson8b_mpll1.hw, 821 [CLKID_MPLL1] = &meson8b_mpll1.hw,
601 [CLKID_MPLL2] = &meson8b_mpll2.hw, 822 [CLKID_MPLL2] = &meson8b_mpll2.hw,
823 [CLKID_MPLL0_DIV] = &meson8b_mpll0_div.hw,
824 [CLKID_MPLL1_DIV] = &meson8b_mpll1_div.hw,
825 [CLKID_MPLL2_DIV] = &meson8b_mpll2_div.hw,
826 [CLKID_CPU_IN_SEL] = &meson8b_cpu_in_sel.hw,
827 [CLKID_CPU_DIV2] = &meson8b_cpu_div2.hw,
828 [CLKID_CPU_DIV3] = &meson8b_cpu_div3.hw,
829 [CLKID_CPU_SCALE_DIV] = &meson8b_cpu_scale_div.hw,
830 [CLKID_CPU_SCALE_OUT_SEL] = &meson8b_cpu_scale_out_sel.hw,
831 [CLKID_MPLL_PREDIV] = &meson8b_mpll_prediv.hw,
832 [CLKID_FCLK_DIV2_DIV] = &meson8b_fclk_div2_div.hw,
833 [CLKID_FCLK_DIV3_DIV] = &meson8b_fclk_div3_div.hw,
834 [CLKID_FCLK_DIV4_DIV] = &meson8b_fclk_div4_div.hw,
835 [CLKID_FCLK_DIV5_DIV] = &meson8b_fclk_div5_div.hw,
836 [CLKID_FCLK_DIV7_DIV] = &meson8b_fclk_div7_div.hw,
602 [CLK_NR_CLKS] = NULL, 837 [CLK_NR_CLKS] = NULL,
603 }, 838 },
604 .num = CLK_NR_CLKS, 839 .num = CLK_NR_CLKS,
605}; 840};
606 841
607static struct meson_clk_pll *const meson8b_clk_plls[] = { 842static struct clk_regmap *const meson8b_clk_regmaps[] = {
608 &meson8b_fixed_pll,
609 &meson8b_vid_pll,
610 &meson8b_sys_pll,
611};
612
613static struct meson_clk_mpll *const meson8b_clk_mplls[] = {
614 &meson8b_mpll0,
615 &meson8b_mpll1,
616 &meson8b_mpll2,
617};
618
619static struct clk_gate *const meson8b_clk_gates[] = {
620 &meson8b_clk81, 843 &meson8b_clk81,
621 &meson8b_ddr, 844 &meson8b_ddr,
622 &meson8b_dos, 845 &meson8b_dos,
@@ -695,14 +918,27 @@ static struct clk_gate *const meson8b_clk_gates[] = {
695 &meson8b_ao_ahb_sram, 918 &meson8b_ao_ahb_sram,
696 &meson8b_ao_ahb_bus, 919 &meson8b_ao_ahb_bus,
697 &meson8b_ao_iface, 920 &meson8b_ao_iface,
698};
699
700static struct clk_mux *const meson8b_clk_muxes[] = {
701 &meson8b_mpeg_clk_sel,
702};
703
704static struct clk_divider *const meson8b_clk_dividers[] = {
705 &meson8b_mpeg_clk_div, 921 &meson8b_mpeg_clk_div,
922 &meson8b_mpeg_clk_sel,
923 &meson8b_mpll0,
924 &meson8b_mpll1,
925 &meson8b_mpll2,
926 &meson8b_mpll0_div,
927 &meson8b_mpll1_div,
928 &meson8b_mpll2_div,
929 &meson8b_fixed_pll,
930 &meson8b_vid_pll,
931 &meson8b_sys_pll,
932 &meson8b_cpu_in_sel,
933 &meson8b_cpu_scale_div,
934 &meson8b_cpu_scale_out_sel,
935 &meson8b_cpu_clk,
936 &meson8b_mpll_prediv,
937 &meson8b_fclk_div2,
938 &meson8b_fclk_div3,
939 &meson8b_fclk_div4,
940 &meson8b_fclk_div5,
941 &meson8b_fclk_div7,
706}; 942};
707 943
708static const struct meson8b_clk_reset_line { 944static const struct meson8b_clk_reset_line {
@@ -804,82 +1040,45 @@ static const struct reset_control_ops meson8b_clk_reset_ops = {
804 .deassert = meson8b_clk_reset_deassert, 1040 .deassert = meson8b_clk_reset_deassert,
805}; 1041};
806 1042
1043static const struct regmap_config clkc_regmap_config = {
1044 .reg_bits = 32,
1045 .val_bits = 32,
1046 .reg_stride = 4,
1047};
1048
807static int meson8b_clkc_probe(struct platform_device *pdev) 1049static int meson8b_clkc_probe(struct platform_device *pdev)
808{ 1050{
809 int ret, clkid, i; 1051 int ret, i;
810 struct clk_hw *parent_hw;
811 struct clk *parent_clk;
812 struct device *dev = &pdev->dev; 1052 struct device *dev = &pdev->dev;
1053 struct regmap *map;
813 1054
814 if (!clk_base) 1055 if (!clk_base)
815 return -ENXIO; 1056 return -ENXIO;
816 1057
817 /* Populate base address for PLLs */ 1058 map = devm_regmap_init_mmio(dev, clk_base, &clkc_regmap_config);
818 for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) 1059 if (IS_ERR(map))
819 meson8b_clk_plls[i]->base = clk_base; 1060 return PTR_ERR(map);
820
821 /* Populate base address for MPLLs */
822 for (i = 0; i < ARRAY_SIZE(meson8b_clk_mplls); i++)
823 meson8b_clk_mplls[i]->base = clk_base;
824
825 /* Populate the base address for CPU clk */
826 meson8b_cpu_clk.base = clk_base;
827
828 /* Populate base address for gates */
829 for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++)
830 meson8b_clk_gates[i]->reg = clk_base +
831 (u32)meson8b_clk_gates[i]->reg;
832
833 /* Populate base address for muxes */
834 for (i = 0; i < ARRAY_SIZE(meson8b_clk_muxes); i++)
835 meson8b_clk_muxes[i]->reg = clk_base +
836 (u32)meson8b_clk_muxes[i]->reg;
837 1061
838 /* Populate base address for dividers */ 1062 /* Populate regmap for the regmap backed clocks */
839 for (i = 0; i < ARRAY_SIZE(meson8b_clk_dividers); i++) 1063 for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++)
840 meson8b_clk_dividers[i]->reg = clk_base + 1064 meson8b_clk_regmaps[i]->map = map;
841 (u32)meson8b_clk_dividers[i]->reg;
842 1065
843 /* 1066 /*
844 * register all clks 1067 * register all clks
845 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1 1068 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
846 */ 1069 */
847 for (clkid = CLKID_XTAL; clkid < CLK_NR_CLKS; clkid++) { 1070 for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
848 /* array might be sparse */ 1071 /* array might be sparse */
849 if (!meson8b_hw_onecell_data.hws[clkid]) 1072 if (!meson8b_hw_onecell_data.hws[i])
850 continue; 1073 continue;
851 1074
852 /* FIXME convert to devm_clk_register */ 1075 ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[i]);
853 ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[clkid]);
854 if (ret) 1076 if (ret)
855 return ret; 1077 return ret;
856 } 1078 }
857 1079
858 /* 1080 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
859 * Register CPU clk notifier 1081 &meson8b_hw_onecell_data);
860 *
861 * FIXME this is wrong for a lot of reasons. First, the muxes should be
862 * struct clk_hw objects. Second, we shouldn't program the muxes in
863 * notifier handlers. The tricky programming sequence will be handled
864 * by the forthcoming coordinated clock rates mechanism once that
865 * feature is released.
866 *
867 * Furthermore, looking up the parent this way is terrible. At some
868 * point we will stop allocating a default struct clk when registering
869 * a new clk_hw, and this hack will no longer work. Releasing the ccr
870 * feature before that time solves the problem :-)
871 */
872 parent_hw = clk_hw_get_parent(&meson8b_cpu_clk.hw);
873 parent_clk = parent_hw->clk;
874 ret = clk_notifier_register(parent_clk, &meson8b_cpu_clk.clk_nb);
875 if (ret) {
876 pr_err("%s: failed to register clock notifier for cpu_clk\n",
877 __func__);
878 return ret;
879 }
880
881 return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
882 &meson8b_hw_onecell_data);
883} 1082}
884 1083
885static const struct of_device_id meson8b_clkc_match_table[] = { 1084static const struct of_device_id meson8b_clkc_match_table[] = {
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
index 2eaf8a52e7dd..6e414bd36981 100644
--- a/drivers/clk/meson/meson8b.h
+++ b/drivers/clk/meson/meson8b.h
@@ -69,7 +69,22 @@
69 * will remain defined here. 69 * will remain defined here.
70 */ 70 */
71 71
72#define CLK_NR_CLKS 96 72#define CLKID_MPLL0_DIV 96
73#define CLKID_MPLL1_DIV 97
74#define CLKID_MPLL2_DIV 98
75#define CLKID_CPU_IN_SEL 99
76#define CLKID_CPU_DIV2 100
77#define CLKID_CPU_DIV3 101
78#define CLKID_CPU_SCALE_DIV 102
79#define CLKID_CPU_SCALE_OUT_SEL 103
80#define CLKID_MPLL_PREDIV 104
81#define CLKID_FCLK_DIV2_DIV 105
82#define CLKID_FCLK_DIV3_DIV 106
83#define CLKID_FCLK_DIV4_DIV 107
84#define CLKID_FCLK_DIV5_DIV 108
85#define CLKID_FCLK_DIV7_DIV 109
86
87#define CLK_NR_CLKS 110
73 88
74/* 89/*
75 * include the CLKID and RESETID that have 90 * include the CLKID and RESETID that have