diff options
Diffstat (limited to 'drivers/clk/meson')
-rw-r--r-- | drivers/clk/meson/Kconfig | 9 | ||||
-rw-r--r-- | drivers/clk/meson/Makefile | 5 | ||||
-rw-r--r-- | drivers/clk/meson/axg.c | 955 | ||||
-rw-r--r-- | drivers/clk/meson/axg.h | 12 | ||||
-rw-r--r-- | drivers/clk/meson/clk-audio-divider.c | 63 | ||||
-rw-r--r-- | drivers/clk/meson/clk-cpu.c | 178 | ||||
-rw-r--r-- | drivers/clk/meson/clk-mpll.c | 125 | ||||
-rw-r--r-- | drivers/clk/meson/clk-pll.c | 306 | ||||
-rw-r--r-- | drivers/clk/meson/clk-regmap.c | 166 | ||||
-rw-r--r-- | drivers/clk/meson/clk-regmap.h | 111 | ||||
-rw-r--r-- | drivers/clk/meson/clkc.h | 107 | ||||
-rw-r--r-- | drivers/clk/meson/gxbb-aoclk-regmap.c | 46 | ||||
-rw-r--r-- | drivers/clk/meson/gxbb-aoclk.c | 20 | ||||
-rw-r--r-- | drivers/clk/meson/gxbb-aoclk.h | 11 | ||||
-rw-r--r-- | drivers/clk/meson/gxbb.c | 1591 | ||||
-rw-r--r-- | drivers/clk/meson/gxbb.h | 14 | ||||
-rw-r--r-- | drivers/clk/meson/meson8b.c | 705 | ||||
-rw-r--r-- | drivers/clk/meson/meson8b.h | 17 |
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 | ||
6 | config COMMON_CLK_REGMAP_MESON | ||
7 | bool | ||
8 | select REGMAP | ||
9 | |||
6 | config COMMON_CLK_MESON8B | 10 | config 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 | ||
5 | obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o | 5 | obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-audio-divider.o |
6 | obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o | 6 | obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o |
7 | obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-regmap.o gxbb-aoclk-32k.o | 7 | obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-32k.o |
8 | obj-$(CONFIG_COMMON_CLK_AXG) += axg.o | 8 | obj-$(CONFIG_COMMON_CLK_AXG) += axg.o |
9 | obj-$(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 | ||
22 | static DEFINE_SPINLOCK(meson_clk_lock); | 24 | static DEFINE_SPINLOCK(meson_clk_lock); |
23 | 25 | ||
24 | static const struct pll_rate_table sys_pll_rate_table[] = { | 26 | static 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 | |||
116 | static 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 | ||
141 | static struct meson_clk_pll axg_sys_pll = { | 67 | static 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 | ||
260 | static struct pll_params_table axg_gp0_params_table[] = { | 195 | static 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 | ||
269 | static struct meson_clk_pll axg_gp0_pll = { | 204 | static 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 | ||
248 | static 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 | |||
257 | static 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 | ||
303 | static struct clk_fixed_factor axg_fclk_div2 = { | 302 | static 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 | ||
314 | static struct clk_fixed_factor axg_fclk_div3 = { | 313 | static 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 | |||
326 | static 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 | ||
325 | static struct clk_fixed_factor axg_fclk_div4 = { | 337 | static 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 | |||
350 | static 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 | ||
336 | static struct clk_fixed_factor axg_fclk_div5 = { | 361 | static 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 | |||
374 | static 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 | ||
347 | static struct clk_fixed_factor axg_fclk_div7 = { | 385 | static 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 | |||
398 | static 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 | ||
358 | static struct meson_clk_mpll axg_mpll0 = { | 409 | static 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, | 422 | static 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, | 436 | static 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 | ||
393 | static struct meson_clk_mpll axg_mpll1 = { | 473 | static 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, | 487 | static 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 | ||
423 | static struct meson_clk_mpll axg_mpll2 = { | 519 | static 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, | 533 | static 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 | ||
453 | static struct meson_clk_mpll axg_mpll3 = { | 565 | static 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 | |||
579 | static 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, | 611 | static 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 | */ | ||
488 | static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; | 625 | static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; |
489 | static const char * const clk81_parent_names[] = { | 626 | static 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 | ||
494 | static struct clk_mux axg_mpeg_clk_sel = { | 631 | static 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 | ||
509 | static struct clk_divider axg_mpeg_clk_div = { | 646 | static 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 | ||
523 | static struct clk_gate axg_clk81 = { | 661 | static 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 */ |
548 | static struct clk_mux axg_sd_emmc_b_clk0_sel = { | 687 | static 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 | ||
562 | static struct clk_divider axg_sd_emmc_b_clk0_div = { | 702 | static 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 | ||
577 | static struct clk_gate axg_sd_emmc_b_clk0 = { | 718 | static 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 */ |
591 | static struct clk_mux axg_sd_emmc_c_clk0_sel = { | 733 | static 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 | ||
605 | static struct clk_divider axg_sd_emmc_c_clk0_div = { | 748 | static 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 | ||
620 | static struct clk_gate axg_sd_emmc_c_clk0 = { | 764 | static 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 | 915 | static struct clk_regmap *const axg_clk_regmaps[] = { | |
760 | static struct meson_clk_pll *const axg_clk_plls[] = { | ||
761 | &axg_fixed_pll, | ||
762 | &axg_sys_pll, | ||
763 | &axg_gp0_pll, | ||
764 | }; | ||
765 | |||
766 | static struct meson_clk_mpll *const axg_clk_mplls[] = { | ||
767 | &axg_mpll0, | ||
768 | &axg_mpll1, | ||
769 | &axg_mpll2, | ||
770 | &axg_mpll3, | ||
771 | }; | ||
772 | |||
773 | static 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 | |||
823 | static 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 | |||
829 | static 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, | |
835 | struct 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, | |
849 | static 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 | ||
863 | static const struct of_device_id clkc_match_table[] = { | 989 | static 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 | ||
994 | static const struct regmap_config clkc_regmap_config = { | ||
995 | .reg_bits = 32, | ||
996 | .val_bits = 32, | ||
997 | .reg_stride = 4, | ||
998 | }; | ||
999 | |||
868 | static int axg_clkc_probe(struct platform_device *pdev) | 1000 | static 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 | ||
930 | static struct platform_driver axg_driver = { | 1059 | static 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, \ | 31 | static inline struct meson_clk_audio_div_data * |
32 | struct meson_clk_audio_divider, hw) | 32 | meson_clk_audio_div_data(struct clk_regmap *clk) |
33 | { | ||
34 | return (struct meson_clk_audio_div_data *)clk->data; | ||
35 | } | ||
33 | 36 | ||
34 | static int _div_round(unsigned long parent_rate, unsigned long rate, | 37 | static 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 | ||
48 | static int _valid_divider(struct clk_hw *hw, int divider) | 51 | static 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) | |||
61 | static unsigned long audio_divider_recalc_rate(struct clk_hw *hw, | 58 | static 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 | |||
57 | static 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 | |||
66 | static 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 | |||
93 | static 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 */ | ||
116 | static 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 */ | ||
138 | static 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 | */ | ||
159 | int 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 | |||
174 | const 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) | 71 | static inline struct meson_clk_mpll_data * |
72 | meson_clk_mpll_data(struct clk_regmap *clk) | ||
73 | { | ||
74 | return (struct meson_clk_mpll_data *)clk->data; | ||
75 | } | ||
72 | 76 | ||
73 | static long rate_from_params(unsigned long parent_rate, | 77 | static 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 | ||
85 | static void params_from_rate(unsigned long requested_rate, | 89 | static 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, | |||
105 | static unsigned long mpll_recalc_rate(struct clk_hw *hw, | 109 | static 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 | ||
128 | static long mpll_round_rate(struct clk_hw *hw, | 124 | static 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 | ||
184 | static 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 | |||
208 | static 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 | ||
215 | static void mpll_disable(struct clk_hw *hw) | ||
216 | { | ||
217 | mpll_enable_core(hw, 0); | ||
218 | } | ||
219 | |||
220 | static 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 | |||
234 | const struct clk_ops meson_clk_mpll_ro_ops = { | 173 | const 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 | ||
240 | const struct clk_ops meson_clk_mpll_ops = { | 178 | const 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) | 48 | static inline struct meson_clk_pll_data * |
45 | #define MESON_PLL_LOCK BIT(31) | 49 | meson_clk_pll_data(struct clk_regmap *clk) |
46 | |||
47 | #define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) | ||
48 | |||
49 | static 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 | ||
90 | static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, | 54 | static 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 | ||
106 | static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_pll *pll, | 72 | static 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 */ | 99 | static u16 __pll_params_with_frac(unsigned long rate, |
120 | static 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 | |||
119 | static const struct pll_rate_table * | ||
120 | meson_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 | ||
143 | static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll, | 144 | static 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) { | 169 | static 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 | ||
159 | static void meson_clk_pll_init_params(struct meson_clk_pll *pll) | 186 | static 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 | ||
168 | static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, | 199 | static 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 | ||
246 | const struct clk_ops meson_clk_pll_ops = { | 253 | const 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 | |||
7 | static 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 | |||
19 | static int clk_regmap_gate_enable(struct clk_hw *hw) | ||
20 | { | ||
21 | return clk_regmap_gate_endisable(hw, 1); | ||
22 | } | ||
23 | |||
24 | static void clk_regmap_gate_disable(struct clk_hw *hw) | ||
25 | { | ||
26 | clk_regmap_gate_endisable(hw, 0); | ||
27 | } | ||
28 | |||
29 | static 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 | |||
44 | const 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 | }; | ||
49 | EXPORT_SYMBOL_GPL(clk_regmap_gate_ops); | ||
50 | |||
51 | static 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 | |||
70 | static 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 | |||
96 | static 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 | |||
116 | const 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 | }; | ||
121 | EXPORT_SYMBOL_GPL(clk_regmap_divider_ops); | ||
122 | |||
123 | const 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 | }; | ||
127 | EXPORT_SYMBOL_GPL(clk_regmap_divider_ro_ops); | ||
128 | |||
129 | static 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 | |||
145 | static 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 | |||
156 | const 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 | }; | ||
161 | EXPORT_SYMBOL_GPL(clk_regmap_mux_ops); | ||
162 | |||
163 | const struct clk_ops clk_regmap_mux_ro_ops = { | ||
164 | .get_parent = clk_regmap_mux_get_parent, | ||
165 | }; | ||
166 | EXPORT_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 | */ | ||
21 | struct 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 | */ | ||
39 | struct clk_regmap_gate_data { | ||
40 | unsigned int offset; | ||
41 | u8 bit_idx; | ||
42 | u8 flags; | ||
43 | }; | ||
44 | |||
45 | static inline struct clk_regmap_gate_data * | ||
46 | clk_get_regmap_gate_data(struct clk_regmap *clk) | ||
47 | { | ||
48 | return (struct clk_regmap_gate_data *)clk->data; | ||
49 | } | ||
50 | |||
51 | extern 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 | */ | ||
64 | struct 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 | |||
72 | static inline struct clk_regmap_div_data * | ||
73 | clk_get_regmap_div_data(struct clk_regmap *clk) | ||
74 | { | ||
75 | return (struct clk_regmap_div_data *)clk->data; | ||
76 | } | ||
77 | |||
78 | extern const struct clk_ops clk_regmap_divider_ops; | ||
79 | extern 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 | */ | ||
94 | struct clk_regmap_mux_data { | ||
95 | unsigned int offset; | ||
96 | u32 *table; | ||
97 | u32 mask; | ||
98 | u8 shift; | ||
99 | u8 flags; | ||
100 | }; | ||
101 | |||
102 | static inline struct clk_regmap_mux_data * | ||
103 | clk_get_regmap_mux_data(struct clk_regmap *clk) | ||
104 | { | ||
105 | return (struct clk_regmap_mux_data *)clk->data; | ||
106 | } | ||
107 | |||
108 | extern const struct clk_ops clk_regmap_mux_ops; | ||
109 | extern 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 | ||
41 | static 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 | |||
49 | static 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 | |||
38 | struct pll_rate_table { | 57 | struct 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 | |||
65 | struct 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 | ||
76 | struct 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 | ||
87 | struct meson_clk_pll { | 76 | struct 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 | ||
103 | struct meson_clk_cpu { | 93 | struct 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 | |||
111 | int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event, | ||
112 | void *data); | ||
113 | |||
114 | struct 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 | ||
125 | struct meson_clk_audio_divider { | 102 | struct 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) \ |
134 | struct clk_gate _name = { \ | 108 | struct 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 | |||
13 | static 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 | |||
21 | static 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 | |||
29 | static 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 | |||
42 | const 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 | ||
67 | static DEFINE_SPINLOCK(gxbb_aoclk_lock); | ||
68 | |||
69 | struct gxbb_aoclk_reset_controller { | 68 | struct 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) \ |
90 | static struct aoclk_gate_regmap _name##_ao = { \ | 89 | static 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); | |||
107 | GXBB_AO_GATE(ir_blaster, 6); | 108 | GXBB_AO_GATE(ir_blaster, 6); |
108 | 109 | ||
109 | static struct aoclk_cec_32k cec_32k_ao = { | 110 | static 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 | ||
129 | static struct aoclk_gate_regmap *gxbb_aoclk_gate[] = { | 129 | static 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 | ||
20 | struct 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 | |||
30 | extern const struct clk_ops meson_aoclk_gate_regmap_ops; | 20 | extern const struct clk_ops meson_aoclk_gate_regmap_ops; |
31 | 21 | ||
32 | struct aoclk_cec_32k { | 22 | struct 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 | ||
30 | static DEFINE_SPINLOCK(meson_clk_lock); | 33 | static DEFINE_SPINLOCK(meson_clk_lock); |
31 | 34 | ||
32 | static 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 | |||
124 | static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = { | 35 | static 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 | ||
281 | static struct meson_clk_pll gxbb_fixed_pll = { | 192 | static 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 | ||
307 | static struct meson_clk_pll gxbb_hdmi_pll = { | 234 | static 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, | 245 | static 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, | 297 | static 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 | ||
343 | static struct meson_clk_pll gxbb_sys_pll = { | 355 | static 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 | ||
371 | struct pll_params_table gxbb_gp0_params_table[] = { | 392 | static 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 | ||
378 | static struct meson_clk_pll gxbb_gp0_pll = { | 399 | static 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 | ||
412 | struct pll_params_table gxl_gp0_params_table[] = { | 439 | static 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 | ||
421 | static struct meson_clk_pll gxl_gp0_pll = { | 448 | static 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 | ||
455 | static struct clk_fixed_factor gxbb_fclk_div2 = { | 493 | static 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 | ||
466 | static struct clk_fixed_factor gxbb_fclk_div3 = { | 504 | static 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 | |||
517 | static 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 | ||
477 | static struct clk_fixed_factor gxbb_fclk_div4 = { | 528 | static 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 | |||
541 | static 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 | ||
488 | static struct clk_fixed_factor gxbb_fclk_div5 = { | 552 | static 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 | |||
565 | static 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 | ||
499 | static struct clk_fixed_factor gxbb_fclk_div7 = { | 576 | static 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 | |||
589 | static 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 | ||
510 | static struct meson_clk_mpll gxbb_mpll0 = { | 600 | static 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, | 613 | static 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, | 627 | static 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 | ||
545 | static struct meson_clk_mpll gxbb_mpll1 = { | 659 | static 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, | 673 | static 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 | ||
575 | static struct meson_clk_mpll gxbb_mpll2 = { | 700 | static 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, | 714 | static 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 | /* | 741 | static 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 | ||
611 | static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; | 755 | static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; |
612 | static const char * const clk81_parent_names[] = { | 756 | static 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 | ||
617 | static struct clk_mux gxbb_mpeg_clk_sel = { | 761 | static 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 | ||
638 | static struct clk_divider gxbb_mpeg_clk_div = { | 781 | static 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 */ |
653 | static struct clk_gate gxbb_clk81 = { | 796 | static 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 | ||
666 | static struct clk_mux gxbb_sar_adc_clk_sel = { | 810 | static 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 | ||
680 | static struct clk_divider gxbb_sar_adc_clk_div = { | 825 | static 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 | ||
693 | static struct clk_gate gxbb_sar_adc_clk = { | 839 | static 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 | ||
711 | static u32 mux_table_mali_0_1[] = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
712 | static const char * const gxbb_mali_0_1_parent_names[] = { | 858 | static 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 | ||
717 | static struct clk_mux gxbb_mali_0_sel = { | 863 | static 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 | ||
737 | static struct clk_divider gxbb_mali_0_div = { | 883 | static 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 | ||
751 | static struct clk_gate gxbb_mali_0 = { | 898 | static 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 | ||
764 | static struct clk_mux gxbb_mali_1_sel = { | 912 | static 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 | ||
784 | static struct clk_divider gxbb_mali_1_div = { | 932 | static 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 | ||
798 | static struct clk_gate gxbb_mali_1 = { | 947 | static 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 | ||
811 | static u32 mux_table_mali[] = {0, 1}; | ||
812 | static const char * const gxbb_mali_parent_names[] = { | 961 | static const char * const gxbb_mali_parent_names[] = { |
813 | "mali_0", "mali_1" | 962 | "mali_0", "mali_1" |
814 | }; | 963 | }; |
815 | 964 | ||
816 | static struct clk_mux gxbb_mali = { | 965 | static 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 | ||
831 | static struct clk_mux gxbb_cts_amclk_sel = { | 980 | static 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 | ||
847 | static struct meson_clk_audio_divider gxbb_cts_amclk_div = { | 996 | static 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 | ||
864 | static struct clk_gate gxbb_cts_amclk = { | 1014 | static 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 | ||
877 | static struct clk_mux gxbb_cts_mclk_i958_sel = { | 1028 | static 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 | ||
893 | static struct clk_divider gxbb_cts_mclk_i958_div = { | 1044 | static 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 | ||
908 | static struct clk_gate gxbb_cts_mclk_i958 = { | 1060 | static 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 | ||
921 | static struct clk_mux gxbb_cts_i958 = { | 1074 | static 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 | ||
939 | static struct clk_divider gxbb_32k_clk_div = { | 1093 | static 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 | ||
953 | static struct clk_gate gxbb_32k_clk = { | 1108 | static 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 | ||
970 | static struct clk_mux gxbb_32k_clk_sel = { | 1126 | static 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 */ |
996 | static struct clk_mux gxbb_sd_emmc_a_clk0_sel = { | 1153 | static 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 | ||
1010 | static struct clk_divider gxbb_sd_emmc_a_clk0_div = { | 1168 | static 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 | ||
1025 | static struct clk_gate gxbb_sd_emmc_a_clk0 = { | 1184 | static 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 */ |
1039 | static struct clk_mux gxbb_sd_emmc_b_clk0_sel = { | 1199 | static 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 | ||
1053 | static struct clk_divider gxbb_sd_emmc_b_clk0_div = { | 1214 | static 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 | ||
1068 | static struct clk_gate gxbb_sd_emmc_b_clk0 = { | 1230 | static 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 */ |
1082 | static struct clk_mux gxbb_sd_emmc_c_clk0_sel = { | 1245 | static 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 | ||
1096 | static struct clk_divider gxbb_sd_emmc_c_clk0_div = { | 1260 | static 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 | ||
1111 | static struct clk_gate gxbb_sd_emmc_c_clk0 = { | 1276 | static 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 | ||
1126 | static u32 mux_table_vpu[] = {0, 1, 2, 3}; | ||
1127 | static const char * const gxbb_vpu_parent_names[] = { | 1292 | static 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 | ||
1131 | static struct clk_mux gxbb_vpu_0_sel = { | 1296 | static 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 | ||
1150 | static struct clk_divider gxbb_vpu_0_div = { | 1315 | static 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 | ||
1164 | static struct clk_gate gxbb_vpu_0 = { | 1330 | static 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 | ||
1177 | static struct clk_mux gxbb_vpu_1_sel = { | 1344 | static 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 | ||
1196 | static struct clk_divider gxbb_vpu_1_div = { | 1363 | static 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 | ||
1210 | static struct clk_gate gxbb_vpu_1 = { | 1378 | static 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 | ||
1223 | static struct clk_mux gxbb_vpu = { | 1392 | static 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 | ||
1243 | static u32 mux_table_vapb[] = {0, 1, 2, 3}; | ||
1244 | static const char * const gxbb_vapb_parent_names[] = { | 1413 | static 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 | ||
1248 | static struct clk_mux gxbb_vapb_0_sel = { | 1417 | static 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 | ||
1267 | static struct clk_divider gxbb_vapb_0_div = { | 1436 | static 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 | ||
1281 | static struct clk_gate gxbb_vapb_0 = { | 1451 | static 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 | ||
1294 | static struct clk_mux gxbb_vapb_1_sel = { | 1465 | static 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 | ||
1313 | static struct clk_divider gxbb_vapb_1_div = { | 1484 | static 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 | ||
1327 | static struct clk_gate gxbb_vapb_1 = { | 1499 | static 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 | ||
1340 | static struct clk_mux gxbb_vapb_sel = { | 1513 | static 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 | ||
1358 | static struct clk_gate gxbb_vapb = { | 1532 | static 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 = { | |||
1609 | static struct clk_hw_onecell_data gxl_hw_onecell_data = { | 1794 | static 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 */ | 1950 | static struct clk_regmap *const gxbb_clk_regmaps[] = { |
1757 | |||
1758 | static 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 | |||
1765 | static 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 | ||
1772 | static struct meson_clk_mpll *const gxbb_clk_mplls[] = { | 1955 | static 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 | ||
1778 | static struct clk_gate *const gxbb_clk_gates[] = { | 1960 | static 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, | |
1877 | static 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, | |
1898 | static 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 | |||
1914 | static 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 | ||
1918 | struct clkc_data { | 2105 | struct 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 | ||
1934 | static const struct clkc_data gxbb_clkc_data = { | 2111 | static 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 | ||
1950 | static const struct clkc_data gxl_clkc_data = { | 2117 | static 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 | ||
2129 | static const struct regmap_config clkc_regmap_config = { | ||
2130 | .reg_bits = 32, | ||
2131 | .val_bits = 32, | ||
2132 | .reg_stride = 4, | ||
2133 | }; | ||
2134 | |||
1972 | static int gxbb_clkc_probe(struct platform_device *pdev) | 2135 | static 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 | |||
2034 | iounmap: | ||
2035 | iounmap(clk_base); | ||
2036 | return ret; | ||
2037 | } | 2202 | } |
2038 | 2203 | ||
2039 | static struct platform_driver gxbb_driver = { | 2204 | static 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 | ||
35 | static DEFINE_SPINLOCK(meson_clk_lock); | 37 | static 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 | ||
100 | static 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 | |||
114 | static struct clk_fixed_rate meson8b_xtal = { | 102 | static 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 | ||
123 | static struct meson_clk_pll meson8b_fixed_pll = { | 111 | static 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 | ||
149 | static struct meson_clk_pll meson8b_vid_pll = { | 153 | static 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 | ||
175 | static struct meson_clk_pll meson8b_sys_pll = { | 190 | static 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 | ||
203 | static struct clk_fixed_factor meson8b_fclk_div2 = { | 228 | static 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 | ||
214 | static struct clk_fixed_factor meson8b_fclk_div3 = { | 239 | static 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 | |||
252 | static 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 | ||
225 | static struct clk_fixed_factor meson8b_fclk_div4 = { | 263 | static 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 | |||
276 | static 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 | ||
236 | static struct clk_fixed_factor meson8b_fclk_div5 = { | 287 | static 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 | |||
300 | static 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 | ||
247 | static struct clk_fixed_factor meson8b_fclk_div7 = { | 311 | static 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 | |||
324 | static 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 | ||
258 | static struct meson_clk_mpll meson8b_mpll0 = { | 335 | static 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, | 348 | static 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, | 362 | static 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 | ||
293 | static struct meson_clk_mpll meson8b_mpll1 = { | 394 | static 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, | 408 | static 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 | ||
323 | static struct meson_clk_mpll meson8b_mpll2 = { | 435 | static 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, | 449 | static 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 | /* | 476 | static 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 | }, |
358 | static 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 | ||
370 | static u32 mux_table_clk81[] = { 6, 5, 7 }; | 490 | static u32 mux_table_clk81[] = { 6, 5, 7 }; |
371 | 491 | static struct clk_regmap meson8b_mpeg_clk_sel = { | |
372 | struct 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 | ||
394 | struct clk_divider meson8b_mpeg_clk_div = { | 512 | static 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 | ||
408 | struct clk_gate meson8b_clk81 = { | 526 | static 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 | |||
540 | static 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 | |||
556 | static 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 | |||
568 | static 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 | |||
580 | static 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 | |||
591 | static 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 | |||
608 | static 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 | |||
626 | static 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 | ||
607 | static struct meson_clk_pll *const meson8b_clk_plls[] = { | 842 | static struct clk_regmap *const meson8b_clk_regmaps[] = { |
608 | &meson8b_fixed_pll, | ||
609 | &meson8b_vid_pll, | ||
610 | &meson8b_sys_pll, | ||
611 | }; | ||
612 | |||
613 | static struct meson_clk_mpll *const meson8b_clk_mplls[] = { | ||
614 | &meson8b_mpll0, | ||
615 | &meson8b_mpll1, | ||
616 | &meson8b_mpll2, | ||
617 | }; | ||
618 | |||
619 | static 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 | |||
700 | static struct clk_mux *const meson8b_clk_muxes[] = { | ||
701 | &meson8b_mpeg_clk_sel, | ||
702 | }; | ||
703 | |||
704 | static 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 | ||
708 | static const struct meson8b_clk_reset_line { | 944 | static 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 | ||
1043 | static const struct regmap_config clkc_regmap_config = { | ||
1044 | .reg_bits = 32, | ||
1045 | .val_bits = 32, | ||
1046 | .reg_stride = 4, | ||
1047 | }; | ||
1048 | |||
807 | static int meson8b_clkc_probe(struct platform_device *pdev) | 1049 | static 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 | ||
885 | static const struct of_device_id meson8b_clkc_match_table[] = { | 1084 | static 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 |