aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-davinci/include/mach/clock.h21
-rw-r--r--drivers/clk/davinci/psc.c18
-rw-r--r--drivers/clk/meson/axg-audio.c34
-rw-r--r--drivers/clk/meson/axg.c332
-rw-r--r--drivers/clk/meson/axg.h8
-rw-r--r--drivers/clk/meson/clk-pll.c156
-rw-r--r--drivers/clk/meson/clkc.h16
-rw-r--r--drivers/clk/meson/gxbb.c518
-rw-r--r--drivers/clk/meson/gxbb.h10
-rw-r--r--drivers/clk/meson/meson8b.c280
-rw-r--r--drivers/clk/meson/meson8b.h5
-rw-r--r--drivers/clk/mvebu/ap806-system-controller.c1
-rw-r--r--drivers/clk/mvebu/armada-37xx-periph.c58
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-a64.c48
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-a64.h4
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-h6.c53
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-a83t.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-h3.c25
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-r40.c52
-rw-r--r--drivers/clk/sunxi-ng/ccu_nkmp.c7
-rw-r--r--drivers/clk/sunxi-ng/ccu_nkmp.h1
-rw-r--r--drivers/clk/sunxi-ng/ccu_nm.c7
-rw-r--r--drivers/clk/sunxi-ng/ccu_nm.h30
-rw-r--r--include/dt-bindings/clock/sun50i-a64-ccu.h1
24 files changed, 926 insertions, 761 deletions
diff --git a/arch/arm/mach-davinci/include/mach/clock.h b/arch/arm/mach-davinci/include/mach/clock.h
deleted file mode 100644
index 42ed4f2f5ce4..000000000000
--- a/arch/arm/mach-davinci/include/mach/clock.h
+++ /dev/null
@@ -1,21 +0,0 @@
1/*
2 * arch/arm/mach-davinci/include/mach/clock.h
3 *
4 * Clock control driver for DaVinci - header file
5 *
6 * Authors: Vladimir Barinov <source@mvista.com>
7 *
8 * 2007 (c) MontaVista Software, Inc. This file is licensed under
9 * the terms of the GNU General Public License version 2. This program
10 * is licensed "as is" without any warranty of any kind, whether express
11 * or implied.
12 */
13#ifndef __ASM_ARCH_DAVINCI_CLOCK_H
14#define __ASM_ARCH_DAVINCI_CLOCK_H
15
16struct clk;
17
18int davinci_clk_reset_assert(struct clk *c);
19int davinci_clk_reset_deassert(struct clk *c);
20
21#endif
diff --git a/drivers/clk/davinci/psc.c b/drivers/clk/davinci/psc.c
index fffbed5e263b..5b69e24a224f 100644
--- a/drivers/clk/davinci/psc.c
+++ b/drivers/clk/davinci/psc.c
@@ -303,24 +303,6 @@ static int davinci_lpsc_clk_reset(struct clk *clk, bool reset)
303 return 0; 303 return 0;
304} 304}
305 305
306/*
307 * REVISIT: These exported functions can be removed after a non-DT lookup is
308 * added to the reset controller framework and the davinci-rproc driver is
309 * updated to use the generic reset controller framework.
310 */
311
312int davinci_clk_reset_assert(struct clk *clk)
313{
314 return davinci_lpsc_clk_reset(clk, true);
315}
316EXPORT_SYMBOL(davinci_clk_reset_assert);
317
318int davinci_clk_reset_deassert(struct clk *clk)
319{
320 return davinci_lpsc_clk_reset(clk, false);
321}
322EXPORT_SYMBOL(davinci_clk_reset_deassert);
323
324static int davinci_psc_reset_assert(struct reset_controller_dev *rcdev, 306static int davinci_psc_reset_assert(struct reset_controller_dev *rcdev,
325 unsigned long id) 307 unsigned long id)
326{ 308{
diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
index a0ed41e73bde..5f6c860aa122 100644
--- a/drivers/clk/meson/axg-audio.c
+++ b/drivers/clk/meson/axg-audio.c
@@ -101,10 +101,16 @@ static const char * const mst_mux_parent_names[] = {
101 "axg_mst_in4", "axg_mst_in5", "axg_mst_in6", "axg_mst_in7", 101 "axg_mst_in4", "axg_mst_in5", "axg_mst_in6", "axg_mst_in7",
102}; 102};
103 103
104#define AXG_MST_MCLK_MUX(_name, _reg) \ 104#define AXG_MST_MUX(_name, _reg, _flag) \
105 AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, CLK_MUX_ROUND_CLOSEST, \ 105 AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag, \
106 mst_mux_parent_names, CLK_SET_RATE_PARENT) 106 mst_mux_parent_names, CLK_SET_RATE_PARENT)
107 107
108#define AXG_MST_MCLK_MUX(_name, _reg) \
109 AXG_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST)
110
111#define AXG_MST_SYS_MUX(_name, _reg) \
112 AXG_MST_MUX(_name, _reg, 0)
113
108static AXG_MST_MCLK_MUX(mst_a_mclk, AUDIO_MCLK_A_CTRL); 114static AXG_MST_MCLK_MUX(mst_a_mclk, AUDIO_MCLK_A_CTRL);
109static AXG_MST_MCLK_MUX(mst_b_mclk, AUDIO_MCLK_B_CTRL); 115static AXG_MST_MCLK_MUX(mst_b_mclk, AUDIO_MCLK_B_CTRL);
110static AXG_MST_MCLK_MUX(mst_c_mclk, AUDIO_MCLK_C_CTRL); 116static AXG_MST_MCLK_MUX(mst_c_mclk, AUDIO_MCLK_C_CTRL);
@@ -112,13 +118,19 @@ static AXG_MST_MCLK_MUX(mst_d_mclk, AUDIO_MCLK_D_CTRL);
112static AXG_MST_MCLK_MUX(mst_e_mclk, AUDIO_MCLK_E_CTRL); 118static AXG_MST_MCLK_MUX(mst_e_mclk, AUDIO_MCLK_E_CTRL);
113static AXG_MST_MCLK_MUX(mst_f_mclk, AUDIO_MCLK_F_CTRL); 119static AXG_MST_MCLK_MUX(mst_f_mclk, AUDIO_MCLK_F_CTRL);
114static AXG_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL); 120static AXG_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
115static AXG_MST_MCLK_MUX(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
116static AXG_MST_MCLK_MUX(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0); 121static AXG_MST_MCLK_MUX(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0);
117static AXG_MST_MCLK_MUX(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1); 122static AXG_MST_SYS_MUX(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
123static AXG_MST_SYS_MUX(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
124
125#define AXG_MST_DIV(_name, _reg, _flag) \
126 AXG_AUD_DIV(_name##_div, _reg, 0, 16, _flag, \
127 "axg_"#_name"_sel", CLK_SET_RATE_PARENT) \
128
129#define AXG_MST_MCLK_DIV(_name, _reg) \
130 AXG_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST)
118 131
119#define AXG_MST_MCLK_DIV(_name, _reg) \ 132#define AXG_MST_SYS_DIV(_name, _reg) \
120 AXG_AUD_DIV(_name##_div, _reg, 0, 16, CLK_DIVIDER_ROUND_CLOSEST, \ 133 AXG_MST_DIV(_name, _reg, 0)
121 "axg_"#_name"_sel", CLK_SET_RATE_PARENT) \
122 134
123static AXG_MST_MCLK_DIV(mst_a_mclk, AUDIO_MCLK_A_CTRL); 135static AXG_MST_MCLK_DIV(mst_a_mclk, AUDIO_MCLK_A_CTRL);
124static AXG_MST_MCLK_DIV(mst_b_mclk, AUDIO_MCLK_B_CTRL); 136static AXG_MST_MCLK_DIV(mst_b_mclk, AUDIO_MCLK_B_CTRL);
@@ -127,12 +139,12 @@ static AXG_MST_MCLK_DIV(mst_d_mclk, AUDIO_MCLK_D_CTRL);
127static AXG_MST_MCLK_DIV(mst_e_mclk, AUDIO_MCLK_E_CTRL); 139static AXG_MST_MCLK_DIV(mst_e_mclk, AUDIO_MCLK_E_CTRL);
128static AXG_MST_MCLK_DIV(mst_f_mclk, AUDIO_MCLK_F_CTRL); 140static AXG_MST_MCLK_DIV(mst_f_mclk, AUDIO_MCLK_F_CTRL);
129static AXG_MST_MCLK_DIV(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL); 141static AXG_MST_MCLK_DIV(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
130static AXG_MST_MCLK_DIV(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
131static AXG_MST_MCLK_DIV(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0); 142static AXG_MST_MCLK_DIV(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0);
132static AXG_MST_MCLK_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1); 143static AXG_MST_SYS_DIV(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
144static AXG_MST_SYS_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
133 145
134#define AXG_MST_MCLK_GATE(_name, _reg) \ 146#define AXG_MST_MCLK_GATE(_name, _reg) \
135 AXG_AUD_GATE(_name, _reg, 31, "axg_"#_name"_div", \ 147 AXG_AUD_GATE(_name, _reg, 31, "axg_"#_name"_div", \
136 CLK_SET_RATE_PARENT) 148 CLK_SET_RATE_PARENT)
137 149
138static AXG_MST_MCLK_GATE(mst_a_mclk, AUDIO_MCLK_A_CTRL); 150static AXG_MST_MCLK_GATE(mst_a_mclk, AUDIO_MCLK_A_CTRL);
diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 00ce62ad6416..c981159b02c0 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -22,8 +22,13 @@
22 22
23static DEFINE_SPINLOCK(meson_clk_lock); 23static DEFINE_SPINLOCK(meson_clk_lock);
24 24
25static struct clk_regmap axg_fixed_pll = { 25static struct clk_regmap axg_fixed_pll_dco = {
26 .data = &(struct meson_clk_pll_data){ 26 .data = &(struct meson_clk_pll_data){
27 .en = {
28 .reg_off = HHI_MPLL_CNTL,
29 .shift = 30,
30 .width = 1,
31 },
27 .m = { 32 .m = {
28 .reg_off = HHI_MPLL_CNTL, 33 .reg_off = HHI_MPLL_CNTL,
29 .shift = 0, 34 .shift = 0,
@@ -34,11 +39,6 @@ static struct clk_regmap axg_fixed_pll = {
34 .shift = 9, 39 .shift = 9,
35 .width = 5, 40 .width = 5,
36 }, 41 },
37 .od = {
38 .reg_off = HHI_MPLL_CNTL,
39 .shift = 16,
40 .width = 2,
41 },
42 .frac = { 42 .frac = {
43 .reg_off = HHI_MPLL_CNTL2, 43 .reg_off = HHI_MPLL_CNTL2,
44 .shift = 0, 44 .shift = 0,
@@ -56,15 +56,39 @@ static struct clk_regmap axg_fixed_pll = {
56 }, 56 },
57 }, 57 },
58 .hw.init = &(struct clk_init_data){ 58 .hw.init = &(struct clk_init_data){
59 .name = "fixed_pll", 59 .name = "fixed_pll_dco",
60 .ops = &meson_clk_pll_ro_ops, 60 .ops = &meson_clk_pll_ro_ops,
61 .parent_names = (const char *[]){ "xtal" }, 61 .parent_names = (const char *[]){ "xtal" },
62 .num_parents = 1, 62 .num_parents = 1,
63 }, 63 },
64}; 64};
65 65
66static struct clk_regmap axg_sys_pll = { 66static struct clk_regmap axg_fixed_pll = {
67 .data = &(struct clk_regmap_div_data){
68 .offset = HHI_MPLL_CNTL,
69 .shift = 16,
70 .width = 2,
71 .flags = CLK_DIVIDER_POWER_OF_TWO,
72 },
73 .hw.init = &(struct clk_init_data){
74 .name = "fixed_pll",
75 .ops = &clk_regmap_divider_ro_ops,
76 .parent_names = (const char *[]){ "fixed_pll_dco" },
77 .num_parents = 1,
78 /*
79 * This clock won't ever change at runtime so
80 * CLK_SET_RATE_PARENT is not required
81 */
82 },
83};
84
85static struct clk_regmap axg_sys_pll_dco = {
67 .data = &(struct meson_clk_pll_data){ 86 .data = &(struct meson_clk_pll_data){
87 .en = {
88 .reg_off = HHI_SYS_PLL_CNTL,
89 .shift = 30,
90 .width = 1,
91 },
68 .m = { 92 .m = {
69 .reg_off = HHI_SYS_PLL_CNTL, 93 .reg_off = HHI_SYS_PLL_CNTL,
70 .shift = 0, 94 .shift = 0,
@@ -75,11 +99,6 @@ static struct clk_regmap axg_sys_pll = {
75 .shift = 9, 99 .shift = 9,
76 .width = 5, 100 .width = 5,
77 }, 101 },
78 .od = {
79 .reg_off = HHI_SYS_PLL_CNTL,
80 .shift = 16,
81 .width = 2,
82 },
83 .l = { 102 .l = {
84 .reg_off = HHI_SYS_PLL_CNTL, 103 .reg_off = HHI_SYS_PLL_CNTL,
85 .shift = 31, 104 .shift = 31,
@@ -92,102 +111,59 @@ static struct clk_regmap axg_sys_pll = {
92 }, 111 },
93 }, 112 },
94 .hw.init = &(struct clk_init_data){ 113 .hw.init = &(struct clk_init_data){
95 .name = "sys_pll", 114 .name = "sys_pll_dco",
96 .ops = &meson_clk_pll_ro_ops, 115 .ops = &meson_clk_pll_ro_ops,
97 .parent_names = (const char *[]){ "xtal" }, 116 .parent_names = (const char *[]){ "xtal" },
98 .num_parents = 1, 117 .num_parents = 1,
99 .flags = CLK_GET_RATE_NOCACHE,
100 }, 118 },
101}; 119};
102 120
103static const struct pll_rate_table axg_gp0_pll_rate_table[] = { 121static struct clk_regmap axg_sys_pll = {
104 PLL_RATE(240000000, 40, 1, 2), 122 .data = &(struct clk_regmap_div_data){
105 PLL_RATE(246000000, 41, 1, 2), 123 .offset = HHI_SYS_PLL_CNTL,
106 PLL_RATE(252000000, 42, 1, 2), 124 .shift = 16,
107 PLL_RATE(258000000, 43, 1, 2), 125 .width = 2,
108 PLL_RATE(264000000, 44, 1, 2), 126 .flags = CLK_DIVIDER_POWER_OF_TWO,
109 PLL_RATE(270000000, 45, 1, 2), 127 },
110 PLL_RATE(276000000, 46, 1, 2), 128 .hw.init = &(struct clk_init_data){
111 PLL_RATE(282000000, 47, 1, 2), 129 .name = "sys_pll",
112 PLL_RATE(288000000, 48, 1, 2), 130 .ops = &clk_regmap_divider_ro_ops,
113 PLL_RATE(294000000, 49, 1, 2), 131 .parent_names = (const char *[]){ "sys_pll_dco" },
114 PLL_RATE(300000000, 50, 1, 2), 132 .num_parents = 1,
115 PLL_RATE(306000000, 51, 1, 2), 133 .flags = CLK_SET_RATE_PARENT,
116 PLL_RATE(312000000, 52, 1, 2), 134 },
117 PLL_RATE(318000000, 53, 1, 2), 135};
118 PLL_RATE(324000000, 54, 1, 2), 136
119 PLL_RATE(330000000, 55, 1, 2), 137static const struct pll_params_table axg_gp0_pll_params_table[] = {
120 PLL_RATE(336000000, 56, 1, 2), 138 PLL_PARAMS(40, 1),
121 PLL_RATE(342000000, 57, 1, 2), 139 PLL_PARAMS(41, 1),
122 PLL_RATE(348000000, 58, 1, 2), 140 PLL_PARAMS(42, 1),
123 PLL_RATE(354000000, 59, 1, 2), 141 PLL_PARAMS(43, 1),
124 PLL_RATE(360000000, 60, 1, 2), 142 PLL_PARAMS(44, 1),
125 PLL_RATE(366000000, 61, 1, 2), 143 PLL_PARAMS(45, 1),
126 PLL_RATE(372000000, 62, 1, 2), 144 PLL_PARAMS(46, 1),
127 PLL_RATE(378000000, 63, 1, 2), 145 PLL_PARAMS(47, 1),
128 PLL_RATE(384000000, 64, 1, 2), 146 PLL_PARAMS(48, 1),
129 PLL_RATE(390000000, 65, 1, 3), 147 PLL_PARAMS(49, 1),
130 PLL_RATE(396000000, 66, 1, 3), 148 PLL_PARAMS(50, 1),
131 PLL_RATE(402000000, 67, 1, 3), 149 PLL_PARAMS(51, 1),
132 PLL_RATE(408000000, 68, 1, 3), 150 PLL_PARAMS(52, 1),
133 PLL_RATE(480000000, 40, 1, 1), 151 PLL_PARAMS(53, 1),
134 PLL_RATE(492000000, 41, 1, 1), 152 PLL_PARAMS(54, 1),
135 PLL_RATE(504000000, 42, 1, 1), 153 PLL_PARAMS(55, 1),
136 PLL_RATE(516000000, 43, 1, 1), 154 PLL_PARAMS(56, 1),
137 PLL_RATE(528000000, 44, 1, 1), 155 PLL_PARAMS(57, 1),
138 PLL_RATE(540000000, 45, 1, 1), 156 PLL_PARAMS(58, 1),
139 PLL_RATE(552000000, 46, 1, 1), 157 PLL_PARAMS(59, 1),
140 PLL_RATE(564000000, 47, 1, 1), 158 PLL_PARAMS(60, 1),
141 PLL_RATE(576000000, 48, 1, 1), 159 PLL_PARAMS(61, 1),
142 PLL_RATE(588000000, 49, 1, 1), 160 PLL_PARAMS(62, 1),
143 PLL_RATE(600000000, 50, 1, 1), 161 PLL_PARAMS(63, 1),
144 PLL_RATE(612000000, 51, 1, 1), 162 PLL_PARAMS(64, 1),
145 PLL_RATE(624000000, 52, 1, 1), 163 PLL_PARAMS(65, 1),
146 PLL_RATE(636000000, 53, 1, 1), 164 PLL_PARAMS(66, 1),
147 PLL_RATE(648000000, 54, 1, 1), 165 PLL_PARAMS(67, 1),
148 PLL_RATE(660000000, 55, 1, 1), 166 PLL_PARAMS(68, 1),
149 PLL_RATE(672000000, 56, 1, 1),
150 PLL_RATE(684000000, 57, 1, 1),
151 PLL_RATE(696000000, 58, 1, 1),
152 PLL_RATE(708000000, 59, 1, 1),
153 PLL_RATE(720000000, 60, 1, 1),
154 PLL_RATE(732000000, 61, 1, 1),
155 PLL_RATE(744000000, 62, 1, 1),
156 PLL_RATE(756000000, 63, 1, 1),
157 PLL_RATE(768000000, 64, 1, 1),
158 PLL_RATE(780000000, 65, 1, 1),
159 PLL_RATE(792000000, 66, 1, 1),
160 PLL_RATE(804000000, 67, 1, 1),
161 PLL_RATE(816000000, 68, 1, 1),
162 PLL_RATE(960000000, 40, 1, 0),
163 PLL_RATE(984000000, 41, 1, 0),
164 PLL_RATE(1008000000, 42, 1, 0),
165 PLL_RATE(1032000000, 43, 1, 0),
166 PLL_RATE(1056000000, 44, 1, 0),
167 PLL_RATE(1080000000, 45, 1, 0),
168 PLL_RATE(1104000000, 46, 1, 0),
169 PLL_RATE(1128000000, 47, 1, 0),
170 PLL_RATE(1152000000, 48, 1, 0),
171 PLL_RATE(1176000000, 49, 1, 0),
172 PLL_RATE(1200000000, 50, 1, 0),
173 PLL_RATE(1224000000, 51, 1, 0),
174 PLL_RATE(1248000000, 52, 1, 0),
175 PLL_RATE(1272000000, 53, 1, 0),
176 PLL_RATE(1296000000, 54, 1, 0),
177 PLL_RATE(1320000000, 55, 1, 0),
178 PLL_RATE(1344000000, 56, 1, 0),
179 PLL_RATE(1368000000, 57, 1, 0),
180 PLL_RATE(1392000000, 58, 1, 0),
181 PLL_RATE(1416000000, 59, 1, 0),
182 PLL_RATE(1440000000, 60, 1, 0),
183 PLL_RATE(1464000000, 61, 1, 0),
184 PLL_RATE(1488000000, 62, 1, 0),
185 PLL_RATE(1512000000, 63, 1, 0),
186 PLL_RATE(1536000000, 64, 1, 0),
187 PLL_RATE(1560000000, 65, 1, 0),
188 PLL_RATE(1584000000, 66, 1, 0),
189 PLL_RATE(1608000000, 67, 1, 0),
190 PLL_RATE(1632000000, 68, 1, 0),
191 { /* sentinel */ }, 167 { /* sentinel */ },
192}; 168};
193 169
@@ -197,11 +173,15 @@ static const struct reg_sequence axg_gp0_init_regs[] = {
197 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, 173 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
198 { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d }, 174 { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
199 { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 }, 175 { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
200 { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
201}; 176};
202 177
203static struct clk_regmap axg_gp0_pll = { 178static struct clk_regmap axg_gp0_pll_dco = {
204 .data = &(struct meson_clk_pll_data){ 179 .data = &(struct meson_clk_pll_data){
180 .en = {
181 .reg_off = HHI_GP0_PLL_CNTL,
182 .shift = 30,
183 .width = 1,
184 },
205 .m = { 185 .m = {
206 .reg_off = HHI_GP0_PLL_CNTL, 186 .reg_off = HHI_GP0_PLL_CNTL,
207 .shift = 0, 187 .shift = 0,
@@ -212,11 +192,6 @@ static struct clk_regmap axg_gp0_pll = {
212 .shift = 9, 192 .shift = 9,
213 .width = 5, 193 .width = 5,
214 }, 194 },
215 .od = {
216 .reg_off = HHI_GP0_PLL_CNTL,
217 .shift = 16,
218 .width = 2,
219 },
220 .frac = { 195 .frac = {
221 .reg_off = HHI_GP0_PLL_CNTL1, 196 .reg_off = HHI_GP0_PLL_CNTL1,
222 .shift = 0, 197 .shift = 0,
@@ -232,29 +207,49 @@ static struct clk_regmap axg_gp0_pll = {
232 .shift = 29, 207 .shift = 29,
233 .width = 1, 208 .width = 1,
234 }, 209 },
235 .table = axg_gp0_pll_rate_table, 210 .table = axg_gp0_pll_params_table,
236 .init_regs = axg_gp0_init_regs, 211 .init_regs = axg_gp0_init_regs,
237 .init_count = ARRAY_SIZE(axg_gp0_init_regs), 212 .init_count = ARRAY_SIZE(axg_gp0_init_regs),
238 }, 213 },
239 .hw.init = &(struct clk_init_data){ 214 .hw.init = &(struct clk_init_data){
240 .name = "gp0_pll", 215 .name = "gp0_pll_dco",
241 .ops = &meson_clk_pll_ops, 216 .ops = &meson_clk_pll_ops,
242 .parent_names = (const char *[]){ "xtal" }, 217 .parent_names = (const char *[]){ "xtal" },
243 .num_parents = 1, 218 .num_parents = 1,
244 }, 219 },
245}; 220};
246 221
222static struct clk_regmap axg_gp0_pll = {
223 .data = &(struct clk_regmap_div_data){
224 .offset = HHI_GP0_PLL_CNTL,
225 .shift = 16,
226 .width = 2,
227 .flags = CLK_DIVIDER_POWER_OF_TWO,
228 },
229 .hw.init = &(struct clk_init_data){
230 .name = "gp0_pll",
231 .ops = &clk_regmap_divider_ops,
232 .parent_names = (const char *[]){ "gp0_pll_dco" },
233 .num_parents = 1,
234 .flags = CLK_SET_RATE_PARENT,
235 },
236};
237
247static const struct reg_sequence axg_hifi_init_regs[] = { 238static const struct reg_sequence axg_hifi_init_regs[] = {
248 { .reg = HHI_HIFI_PLL_CNTL1, .def = 0xc084b000 }, 239 { .reg = HHI_HIFI_PLL_CNTL1, .def = 0xc084b000 },
249 { .reg = HHI_HIFI_PLL_CNTL2, .def = 0xb75020be }, 240 { .reg = HHI_HIFI_PLL_CNTL2, .def = 0xb75020be },
250 { .reg = HHI_HIFI_PLL_CNTL3, .def = 0x0a6a3a88 }, 241 { .reg = HHI_HIFI_PLL_CNTL3, .def = 0x0a6a3a88 },
251 { .reg = HHI_HIFI_PLL_CNTL4, .def = 0xc000004d }, 242 { .reg = HHI_HIFI_PLL_CNTL4, .def = 0xc000004d },
252 { .reg = HHI_HIFI_PLL_CNTL5, .def = 0x00058000 }, 243 { .reg = HHI_HIFI_PLL_CNTL5, .def = 0x00058000 },
253 { .reg = HHI_HIFI_PLL_CNTL, .def = 0x40010250 },
254}; 244};
255 245
256static struct clk_regmap axg_hifi_pll = { 246static struct clk_regmap axg_hifi_pll_dco = {
257 .data = &(struct meson_clk_pll_data){ 247 .data = &(struct meson_clk_pll_data){
248 .en = {
249 .reg_off = HHI_HIFI_PLL_CNTL,
250 .shift = 30,
251 .width = 1,
252 },
258 .m = { 253 .m = {
259 .reg_off = HHI_HIFI_PLL_CNTL, 254 .reg_off = HHI_HIFI_PLL_CNTL,
260 .shift = 0, 255 .shift = 0,
@@ -265,11 +260,6 @@ static struct clk_regmap axg_hifi_pll = {
265 .shift = 9, 260 .shift = 9,
266 .width = 5, 261 .width = 5,
267 }, 262 },
268 .od = {
269 .reg_off = HHI_HIFI_PLL_CNTL,
270 .shift = 16,
271 .width = 2,
272 },
273 .frac = { 263 .frac = {
274 .reg_off = HHI_HIFI_PLL_CNTL5, 264 .reg_off = HHI_HIFI_PLL_CNTL5,
275 .shift = 0, 265 .shift = 0,
@@ -285,19 +275,35 @@ static struct clk_regmap axg_hifi_pll = {
285 .shift = 29, 275 .shift = 29,
286 .width = 1, 276 .width = 1,
287 }, 277 },
288 .table = axg_gp0_pll_rate_table, 278 .table = axg_gp0_pll_params_table,
289 .init_regs = axg_hifi_init_regs, 279 .init_regs = axg_hifi_init_regs,
290 .init_count = ARRAY_SIZE(axg_hifi_init_regs), 280 .init_count = ARRAY_SIZE(axg_hifi_init_regs),
291 .flags = CLK_MESON_PLL_ROUND_CLOSEST, 281 .flags = CLK_MESON_PLL_ROUND_CLOSEST,
292 }, 282 },
293 .hw.init = &(struct clk_init_data){ 283 .hw.init = &(struct clk_init_data){
294 .name = "hifi_pll", 284 .name = "hifi_pll_dco",
295 .ops = &meson_clk_pll_ops, 285 .ops = &meson_clk_pll_ops,
296 .parent_names = (const char *[]){ "xtal" }, 286 .parent_names = (const char *[]){ "xtal" },
297 .num_parents = 1, 287 .num_parents = 1,
298 }, 288 },
299}; 289};
300 290
291static struct clk_regmap axg_hifi_pll = {
292 .data = &(struct clk_regmap_div_data){
293 .offset = HHI_HIFI_PLL_CNTL,
294 .shift = 16,
295 .width = 2,
296 .flags = CLK_DIVIDER_POWER_OF_TWO,
297 },
298 .hw.init = &(struct clk_init_data){
299 .name = "hifi_pll",
300 .ops = &clk_regmap_divider_ops,
301 .parent_names = (const char *[]){ "hifi_pll_dco" },
302 .num_parents = 1,
303 .flags = CLK_SET_RATE_PARENT,
304 },
305};
306
301static struct clk_fixed_factor axg_fclk_div2_div = { 307static struct clk_fixed_factor axg_fclk_div2_div = {
302 .mult = 1, 308 .mult = 1,
303 .div = 2, 309 .div = 2,
@@ -625,29 +631,31 @@ static struct clk_regmap axg_mpll3 = {
625 }, 631 },
626}; 632};
627 633
628static const struct pll_rate_table axg_pcie_pll_rate_table[] = { 634static const struct pll_params_table axg_pcie_pll_params_table[] = {
629 { 635 {
630 .rate = 100000000, 636 .m = 200,
631 .m = 200, 637 .n = 3,
632 .n = 3,
633 .od = 1,
634 .od2 = 3,
635 }, 638 },
636 { /* sentinel */ }, 639 { /* sentinel */ },
637}; 640};
638 641
639static const struct reg_sequence axg_pcie_init_regs[] = { 642static const struct reg_sequence axg_pcie_init_regs[] = {
640 { .reg = HHI_PCIE_PLL_CNTL, .def = 0x400106c8 },
641 { .reg = HHI_PCIE_PLL_CNTL1, .def = 0x0084a2aa }, 643 { .reg = HHI_PCIE_PLL_CNTL1, .def = 0x0084a2aa },
642 { .reg = HHI_PCIE_PLL_CNTL2, .def = 0xb75020be }, 644 { .reg = HHI_PCIE_PLL_CNTL2, .def = 0xb75020be },
643 { .reg = HHI_PCIE_PLL_CNTL3, .def = 0x0a47488e }, 645 { .reg = HHI_PCIE_PLL_CNTL3, .def = 0x0a47488e },
644 { .reg = HHI_PCIE_PLL_CNTL4, .def = 0xc000004d }, 646 { .reg = HHI_PCIE_PLL_CNTL4, .def = 0xc000004d },
645 { .reg = HHI_PCIE_PLL_CNTL5, .def = 0x00078000 }, 647 { .reg = HHI_PCIE_PLL_CNTL5, .def = 0x00078000 },
646 { .reg = HHI_PCIE_PLL_CNTL6, .def = 0x002323c6 }, 648 { .reg = HHI_PCIE_PLL_CNTL6, .def = 0x002323c6 },
649 { .reg = HHI_PCIE_PLL_CNTL, .def = 0x400106c8 },
647}; 650};
648 651
649static struct clk_regmap axg_pcie_pll = { 652static struct clk_regmap axg_pcie_pll_dco = {
650 .data = &(struct meson_clk_pll_data){ 653 .data = &(struct meson_clk_pll_data){
654 .en = {
655 .reg_off = HHI_PCIE_PLL_CNTL,
656 .shift = 30,
657 .width = 1,
658 },
651 .m = { 659 .m = {
652 .reg_off = HHI_PCIE_PLL_CNTL, 660 .reg_off = HHI_PCIE_PLL_CNTL,
653 .shift = 0, 661 .shift = 0,
@@ -658,16 +666,6 @@ static struct clk_regmap axg_pcie_pll = {
658 .shift = 9, 666 .shift = 9,
659 .width = 5, 667 .width = 5,
660 }, 668 },
661 .od = {
662 .reg_off = HHI_PCIE_PLL_CNTL,
663 .shift = 16,
664 .width = 2,
665 },
666 .od2 = {
667 .reg_off = HHI_PCIE_PLL_CNTL6,
668 .shift = 6,
669 .width = 2,
670 },
671 .frac = { 669 .frac = {
672 .reg_off = HHI_PCIE_PLL_CNTL1, 670 .reg_off = HHI_PCIE_PLL_CNTL1,
673 .shift = 0, 671 .shift = 0,
@@ -683,29 +681,63 @@ static struct clk_regmap axg_pcie_pll = {
683 .shift = 29, 681 .shift = 29,
684 .width = 1, 682 .width = 1,
685 }, 683 },
686 .table = axg_pcie_pll_rate_table, 684 .table = axg_pcie_pll_params_table,
687 .init_regs = axg_pcie_init_regs, 685 .init_regs = axg_pcie_init_regs,
688 .init_count = ARRAY_SIZE(axg_pcie_init_regs), 686 .init_count = ARRAY_SIZE(axg_pcie_init_regs),
689 }, 687 },
690 .hw.init = &(struct clk_init_data){ 688 .hw.init = &(struct clk_init_data){
691 .name = "pcie_pll", 689 .name = "pcie_pll_dco",
692 .ops = &meson_clk_pll_ops, 690 .ops = &meson_clk_pll_ops,
693 .parent_names = (const char *[]){ "xtal" }, 691 .parent_names = (const char *[]){ "xtal" },
694 .num_parents = 1, 692 .num_parents = 1,
695 }, 693 },
696}; 694};
697 695
696static struct clk_regmap axg_pcie_pll_od = {
697 .data = &(struct clk_regmap_div_data){
698 .offset = HHI_PCIE_PLL_CNTL,
699 .shift = 16,
700 .width = 2,
701 .flags = CLK_DIVIDER_POWER_OF_TWO,
702 },
703 .hw.init = &(struct clk_init_data){
704 .name = "pcie_pll_od",
705 .ops = &clk_regmap_divider_ops,
706 .parent_names = (const char *[]){ "pcie_pll_dco" },
707 .num_parents = 1,
708 .flags = CLK_SET_RATE_PARENT,
709 },
710};
711
712static struct clk_regmap axg_pcie_pll = {
713 .data = &(struct clk_regmap_div_data){
714 .offset = HHI_PCIE_PLL_CNTL6,
715 .shift = 6,
716 .width = 2,
717 .flags = CLK_DIVIDER_POWER_OF_TWO,
718 },
719 .hw.init = &(struct clk_init_data){
720 .name = "pcie_pll",
721 .ops = &clk_regmap_divider_ops,
722 .parent_names = (const char *[]){ "pcie_pll_od" },
723 .num_parents = 1,
724 .flags = CLK_SET_RATE_PARENT,
725 },
726};
727
698static struct clk_regmap axg_pcie_mux = { 728static struct clk_regmap axg_pcie_mux = {
699 .data = &(struct clk_regmap_mux_data){ 729 .data = &(struct clk_regmap_mux_data){
700 .offset = HHI_PCIE_PLL_CNTL6, 730 .offset = HHI_PCIE_PLL_CNTL6,
701 .mask = 0x1, 731 .mask = 0x1,
702 .shift = 2, 732 .shift = 2,
733 /* skip the parent mpll3, reserved for debug */
734 .table = (u32[]){ 1 },
703 }, 735 },
704 .hw.init = &(struct clk_init_data){ 736 .hw.init = &(struct clk_init_data){
705 .name = "pcie_mux", 737 .name = "pcie_mux",
706 .ops = &clk_regmap_mux_ops, 738 .ops = &clk_regmap_mux_ops,
707 .parent_names = (const char *[]){ "mpll3", "pcie_pll" }, 739 .parent_names = (const char *[]){ "pcie_pll" },
708 .num_parents = 2, 740 .num_parents = 1,
709 .flags = CLK_SET_RATE_PARENT, 741 .flags = CLK_SET_RATE_PARENT,
710 }, 742 },
711}; 743};
@@ -1107,6 +1139,12 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
1107 [CLKID_GEN_CLK_SEL] = &axg_gen_clk_sel.hw, 1139 [CLKID_GEN_CLK_SEL] = &axg_gen_clk_sel.hw,
1108 [CLKID_GEN_CLK_DIV] = &axg_gen_clk_div.hw, 1140 [CLKID_GEN_CLK_DIV] = &axg_gen_clk_div.hw,
1109 [CLKID_GEN_CLK] = &axg_gen_clk.hw, 1141 [CLKID_GEN_CLK] = &axg_gen_clk.hw,
1142 [CLKID_SYS_PLL_DCO] = &axg_sys_pll_dco.hw,
1143 [CLKID_FIXED_PLL_DCO] = &axg_fixed_pll_dco.hw,
1144 [CLKID_GP0_PLL_DCO] = &axg_gp0_pll_dco.hw,
1145 [CLKID_HIFI_PLL_DCO] = &axg_hifi_pll_dco.hw,
1146 [CLKID_PCIE_PLL_DCO] = &axg_pcie_pll_dco.hw,
1147 [CLKID_PCIE_PLL_OD] = &axg_pcie_pll_od.hw,
1110 [NR_CLKS] = NULL, 1148 [NR_CLKS] = NULL,
1111 }, 1149 },
1112 .num = NR_CLKS, 1150 .num = NR_CLKS,
@@ -1185,6 +1223,8 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
1185 &axg_fclk_div4, 1223 &axg_fclk_div4,
1186 &axg_fclk_div5, 1224 &axg_fclk_div5,
1187 &axg_fclk_div7, 1225 &axg_fclk_div7,
1226 &axg_pcie_pll_dco,
1227 &axg_pcie_pll_od,
1188 &axg_pcie_pll, 1228 &axg_pcie_pll,
1189 &axg_pcie_mux, 1229 &axg_pcie_mux,
1190 &axg_pcie_ref, 1230 &axg_pcie_ref,
@@ -1194,6 +1234,12 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
1194 &axg_gen_clk_sel, 1234 &axg_gen_clk_sel,
1195 &axg_gen_clk_div, 1235 &axg_gen_clk_div,
1196 &axg_gen_clk, 1236 &axg_gen_clk,
1237 &axg_fixed_pll_dco,
1238 &axg_sys_pll_dco,
1239 &axg_gp0_pll_dco,
1240 &axg_hifi_pll_dco,
1241 &axg_pcie_pll_dco,
1242 &axg_pcie_pll_od,
1197}; 1243};
1198 1244
1199static const struct of_device_id clkc_match_table[] = { 1245static const struct of_device_id clkc_match_table[] = {
diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h
index 1d04144a1b2c..0431dabac629 100644
--- a/drivers/clk/meson/axg.h
+++ b/drivers/clk/meson/axg.h
@@ -133,8 +133,14 @@
133#define CLKID_PCIE_REF 78 133#define CLKID_PCIE_REF 78
134#define CLKID_GEN_CLK_SEL 82 134#define CLKID_GEN_CLK_SEL 82
135#define CLKID_GEN_CLK_DIV 83 135#define CLKID_GEN_CLK_DIV 83
136#define CLKID_SYS_PLL_DCO 85
137#define CLKID_FIXED_PLL_DCO 86
138#define CLKID_GP0_PLL_DCO 87
139#define CLKID_HIFI_PLL_DCO 88
140#define CLKID_PCIE_PLL_DCO 89
141#define CLKID_PCIE_PLL_OD 90
136 142
137#define NR_CLKS 85 143#define NR_CLKS 91
138 144
139/* include the CLKIDs that have been made part of the DT binding */ 145/* include the CLKIDs that have been made part of the DT binding */
140#include <dt-bindings/clock/axg-clkc.h> 146#include <dt-bindings/clock/axg-clkc.h>
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 3e04617ac47f..f5b5b3fabe3c 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -11,15 +11,19 @@
11 * In the most basic form, a Meson PLL is composed as follows: 11 * In the most basic form, a Meson PLL is composed as follows:
12 * 12 *
13 * PLL 13 * PLL
14 * +------------------------------+ 14 * +--------------------------------+
15 * | | 15 * | |
16 * in -----[ /N ]---[ *M ]---[ >>OD ]----->> out 16 * | +--+ |
17 * | ^ ^ | 17 * in >>-----[ /N ]--->| | +-----+ |
18 * +------------------------------+ 18 * | | |------| DCO |---->> out
19 * | | 19 * | +--------->| | +--v--+ |
20 * FREF VCO 20 * | | +--+ | |
21 * | | | |
22 * | +--[ *(M + (F/Fmax) ]<--+ |
23 * | |
24 * +--------------------------------+
21 * 25 *
22 * out = in * (m + frac / frac_max) / (n << sum(ods)) 26 * out = in * (m + frac / frac_max) / n
23 */ 27 */
24 28
25#include <linux/clk-provider.h> 29#include <linux/clk-provider.h>
@@ -41,12 +45,11 @@ meson_clk_pll_data(struct clk_regmap *clk)
41} 45}
42 46
43static unsigned long __pll_params_to_rate(unsigned long parent_rate, 47static unsigned long __pll_params_to_rate(unsigned long parent_rate,
44 const struct pll_rate_table *pllt, 48 const struct pll_params_table *pllt,
45 u16 frac, 49 u16 frac,
46 struct meson_clk_pll_data *pll) 50 struct meson_clk_pll_data *pll)
47{ 51{
48 u64 rate = (u64)parent_rate * pllt->m; 52 u64 rate = (u64)parent_rate * pllt->m;
49 unsigned int od = pllt->od + pllt->od2 + pllt->od3;
50 53
51 if (frac && MESON_PARM_APPLICABLE(&pll->frac)) { 54 if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
52 u64 frac_rate = (u64)parent_rate * frac; 55 u64 frac_rate = (u64)parent_rate * frac;
@@ -55,7 +58,7 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
55 (1 << pll->frac.width)); 58 (1 << pll->frac.width));
56 } 59 }
57 60
58 return DIV_ROUND_UP_ULL(rate, pllt->n << od); 61 return DIV_ROUND_UP_ULL(rate, pllt->n);
59} 62}
60 63
61static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, 64static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
@@ -63,20 +66,11 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
63{ 66{
64 struct clk_regmap *clk = to_clk_regmap(hw); 67 struct clk_regmap *clk = to_clk_regmap(hw);
65 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); 68 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
66 struct pll_rate_table pllt; 69 struct pll_params_table pllt;
67 u16 frac; 70 u16 frac;
68 71
69 pllt.n = meson_parm_read(clk->map, &pll->n); 72 pllt.n = meson_parm_read(clk->map, &pll->n);
70 pllt.m = meson_parm_read(clk->map, &pll->m); 73 pllt.m = meson_parm_read(clk->map, &pll->m);
71 pllt.od = meson_parm_read(clk->map, &pll->od);
72
73 pllt.od2 = MESON_PARM_APPLICABLE(&pll->od2) ?
74 meson_parm_read(clk->map, &pll->od2) :
75 0;
76
77 pllt.od3 = MESON_PARM_APPLICABLE(&pll->od3) ?
78 meson_parm_read(clk->map, &pll->od3) :
79 0;
80 74
81 frac = MESON_PARM_APPLICABLE(&pll->frac) ? 75 frac = MESON_PARM_APPLICABLE(&pll->frac) ?
82 meson_parm_read(clk->map, &pll->frac) : 76 meson_parm_read(clk->map, &pll->frac) :
@@ -87,14 +81,12 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
87 81
88static u16 __pll_params_with_frac(unsigned long rate, 82static u16 __pll_params_with_frac(unsigned long rate,
89 unsigned long parent_rate, 83 unsigned long parent_rate,
90 const struct pll_rate_table *pllt, 84 const struct pll_params_table *pllt,
91 struct meson_clk_pll_data *pll) 85 struct meson_clk_pll_data *pll)
92{ 86{
93 u16 frac_max = (1 << pll->frac.width); 87 u16 frac_max = (1 << pll->frac.width);
94 u64 val = (u64)rate * pllt->n; 88 u64 val = (u64)rate * pllt->n;
95 89
96 val <<= pllt->od + pllt->od2 + pllt->od3;
97
98 if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) 90 if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
99 val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate); 91 val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
100 else 92 else
@@ -105,29 +97,50 @@ static u16 __pll_params_with_frac(unsigned long rate,
105 return min((u16)val, (u16)(frac_max - 1)); 97 return min((u16)val, (u16)(frac_max - 1));
106} 98}
107 99
108static const struct pll_rate_table * 100static bool meson_clk_pll_is_better(unsigned long rate,
101 unsigned long best,
102 unsigned long now,
103 struct meson_clk_pll_data *pll)
104{
105 if (!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
106 MESON_PARM_APPLICABLE(&pll->frac)) {
107 /* Round down */
108 if (now < rate && best < now)
109 return true;
110 } else {
111 /* Round Closest */
112 if (abs(now - rate) < abs(best - rate))
113 return true;
114 }
115
116 return false;
117}
118
119static const struct pll_params_table *
109meson_clk_get_pll_settings(unsigned long rate, 120meson_clk_get_pll_settings(unsigned long rate,
121 unsigned long parent_rate,
110 struct meson_clk_pll_data *pll) 122 struct meson_clk_pll_data *pll)
111{ 123{
112 const struct pll_rate_table *table = pll->table; 124 const struct pll_params_table *table = pll->table;
113 unsigned int i = 0; 125 unsigned long best = 0, now = 0;
126 unsigned int i, best_i = 0;
114 127
115 if (!table) 128 if (!table)
116 return NULL; 129 return NULL;
117 130
118 /* Find the first table element exceeding rate */ 131 for (i = 0; table[i].n; i++) {
119 while (table[i].rate && table[i].rate <= rate) 132 now = __pll_params_to_rate(parent_rate, &table[i], 0, pll);
120 i++;
121 133
122 if (i != 0) { 134 /* If we get an exact match, don't bother any further */
123 if (MESON_PARM_APPLICABLE(&pll->frac) || 135 if (now == rate) {
124 !(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) || 136 return &table[i];
125 (abs(rate - table[i - 1].rate) < 137 } else if (meson_clk_pll_is_better(rate, best, now, pll)) {
126 abs(rate - table[i].rate))) 138 best = now;
127 i--; 139 best_i = i;
140 }
128 } 141 }
129 142
130 return (struct pll_rate_table *)&table[i]; 143 return (struct pll_params_table *)&table[best_i];
131} 144}
132 145
133static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, 146static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -135,16 +148,18 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
135{ 148{
136 struct clk_regmap *clk = to_clk_regmap(hw); 149 struct clk_regmap *clk = to_clk_regmap(hw);
137 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); 150 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
138 const struct pll_rate_table *pllt = 151 const struct pll_params_table *pllt =
139 meson_clk_get_pll_settings(rate, pll); 152 meson_clk_get_pll_settings(rate, *parent_rate, pll);
153 unsigned long round;
140 u16 frac; 154 u16 frac;
141 155
142 if (!pllt) 156 if (!pllt)
143 return meson_clk_pll_recalc_rate(hw, *parent_rate); 157 return meson_clk_pll_recalc_rate(hw, *parent_rate);
144 158
145 if (!MESON_PARM_APPLICABLE(&pll->frac) 159 round = __pll_params_to_rate(*parent_rate, pllt, 0, pll);
146 || rate == pllt->rate) 160
147 return pllt->rate; 161 if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round)
162 return round;
148 163
149 /* 164 /*
150 * The rate provided by the setting is not an exact match, let's 165 * The rate provided by the setting is not an exact match, let's
@@ -185,12 +200,45 @@ static void meson_clk_pll_init(struct clk_hw *hw)
185 } 200 }
186} 201}
187 202
203static int meson_clk_pll_enable(struct clk_hw *hw)
204{
205 struct clk_regmap *clk = to_clk_regmap(hw);
206 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
207
208 /* Make sure the pll is in reset */
209 meson_parm_write(clk->map, &pll->rst, 1);
210
211 /* Enable the pll */
212 meson_parm_write(clk->map, &pll->en, 1);
213
214 /* Take the pll out reset */
215 meson_parm_write(clk->map, &pll->rst, 0);
216
217 if (meson_clk_pll_wait_lock(hw))
218 return -EIO;
219
220 return 0;
221}
222
223static void meson_clk_pll_disable(struct clk_hw *hw)
224{
225 struct clk_regmap *clk = to_clk_regmap(hw);
226 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
227
228 /* Put the pll is in reset */
229 meson_parm_write(clk->map, &pll->rst, 1);
230
231 /* Disable the pll */
232 meson_parm_write(clk->map, &pll->en, 0);
233}
234
188static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, 235static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
189 unsigned long parent_rate) 236 unsigned long parent_rate)
190{ 237{
191 struct clk_regmap *clk = to_clk_regmap(hw); 238 struct clk_regmap *clk = to_clk_regmap(hw);
192 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); 239 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
193 const struct pll_rate_table *pllt; 240 const struct pll_params_table *pllt;
241 unsigned int enabled;
194 unsigned long old_rate; 242 unsigned long old_rate;
195 u16 frac = 0; 243 u16 frac = 0;
196 244
@@ -199,32 +247,28 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
199 247
200 old_rate = rate; 248 old_rate = rate;
201 249
202 pllt = meson_clk_get_pll_settings(rate, pll); 250 pllt = meson_clk_get_pll_settings(rate, parent_rate, pll);
203 if (!pllt) 251 if (!pllt)
204 return -EINVAL; 252 return -EINVAL;
205 253
206 /* Put the pll in reset to write the params */ 254 enabled = meson_parm_read(clk->map, &pll->en);
207 meson_parm_write(clk->map, &pll->rst, 1); 255 if (enabled)
256 meson_clk_pll_disable(hw);
208 257
209 meson_parm_write(clk->map, &pll->n, pllt->n); 258 meson_parm_write(clk->map, &pll->n, pllt->n);
210 meson_parm_write(clk->map, &pll->m, pllt->m); 259 meson_parm_write(clk->map, &pll->m, pllt->m);
211 meson_parm_write(clk->map, &pll->od, pllt->od);
212 260
213 if (MESON_PARM_APPLICABLE(&pll->od2))
214 meson_parm_write(clk->map, &pll->od2, pllt->od2);
215
216 if (MESON_PARM_APPLICABLE(&pll->od3))
217 meson_parm_write(clk->map, &pll->od3, pllt->od3);
218 261
219 if (MESON_PARM_APPLICABLE(&pll->frac)) { 262 if (MESON_PARM_APPLICABLE(&pll->frac)) {
220 frac = __pll_params_with_frac(rate, parent_rate, pllt, pll); 263 frac = __pll_params_with_frac(rate, parent_rate, pllt, pll);
221 meson_parm_write(clk->map, &pll->frac, frac); 264 meson_parm_write(clk->map, &pll->frac, frac);
222 } 265 }
223 266
224 /* make sure the reset is cleared at this point */ 267 /* If the pll is stopped, bail out now */
225 meson_parm_write(clk->map, &pll->rst, 0); 268 if (!enabled)
269 return 0;
226 270
227 if (meson_clk_pll_wait_lock(hw)) { 271 if (meson_clk_pll_enable(hw)) {
228 pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", 272 pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
229 __func__, old_rate); 273 __func__, old_rate);
230 /* 274 /*
@@ -244,6 +288,8 @@ const struct clk_ops meson_clk_pll_ops = {
244 .recalc_rate = meson_clk_pll_recalc_rate, 288 .recalc_rate = meson_clk_pll_recalc_rate,
245 .round_rate = meson_clk_pll_round_rate, 289 .round_rate = meson_clk_pll_round_rate,
246 .set_rate = meson_clk_pll_set_rate, 290 .set_rate = meson_clk_pll_set_rate,
291 .enable = meson_clk_pll_enable,
292 .disable = meson_clk_pll_disable
247}; 293};
248 294
249const struct clk_ops meson_clk_pll_ro_ops = { 295const struct clk_ops meson_clk_pll_ro_ops = {
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index 24cec16b6038..6b96d55c047d 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -43,37 +43,29 @@ static inline void meson_parm_write(struct regmap *map, struct parm *p,
43} 43}
44 44
45 45
46struct pll_rate_table { 46struct pll_params_table {
47 unsigned long rate;
48 u16 m; 47 u16 m;
49 u16 n; 48 u16 n;
50 u16 od;
51 u16 od2;
52 u16 od3;
53}; 49};
54 50
55#define PLL_RATE(_r, _m, _n, _od) \ 51#define PLL_PARAMS(_m, _n) \
56 { \ 52 { \
57 .rate = (_r), \
58 .m = (_m), \ 53 .m = (_m), \
59 .n = (_n), \ 54 .n = (_n), \
60 .od = (_od), \
61 } 55 }
62 56
63#define CLK_MESON_PLL_ROUND_CLOSEST BIT(0) 57#define CLK_MESON_PLL_ROUND_CLOSEST BIT(0)
64 58
65struct meson_clk_pll_data { 59struct meson_clk_pll_data {
60 struct parm en;
66 struct parm m; 61 struct parm m;
67 struct parm n; 62 struct parm n;
68 struct parm frac; 63 struct parm frac;
69 struct parm od;
70 struct parm od2;
71 struct parm od3;
72 struct parm l; 64 struct parm l;
73 struct parm rst; 65 struct parm rst;
74 const struct reg_sequence *init_regs; 66 const struct reg_sequence *init_regs;
75 unsigned int init_count; 67 unsigned int init_count;
76 const struct pll_rate_table *table; 68 const struct pll_params_table *table;
77 u8 flags; 69 u8 flags;
78}; 70};
79 71
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 86d3ae58e84c..9309cfaaa464 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -18,165 +18,77 @@
18 18
19static DEFINE_SPINLOCK(meson_clk_lock); 19static DEFINE_SPINLOCK(meson_clk_lock);
20 20
21static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = { 21static const struct pll_params_table gxbb_gp0_pll_params_table[] = {
22 PLL_RATE(96000000, 32, 1, 3), 22 PLL_PARAMS(32, 1),
23 PLL_RATE(99000000, 33, 1, 3), 23 PLL_PARAMS(33, 1),
24 PLL_RATE(102000000, 34, 1, 3), 24 PLL_PARAMS(34, 1),
25 PLL_RATE(105000000, 35, 1, 3), 25 PLL_PARAMS(35, 1),
26 PLL_RATE(108000000, 36, 1, 3), 26 PLL_PARAMS(36, 1),
27 PLL_RATE(111000000, 37, 1, 3), 27 PLL_PARAMS(37, 1),
28 PLL_RATE(114000000, 38, 1, 3), 28 PLL_PARAMS(38, 1),
29 PLL_RATE(117000000, 39, 1, 3), 29 PLL_PARAMS(39, 1),
30 PLL_RATE(120000000, 40, 1, 3), 30 PLL_PARAMS(40, 1),
31 PLL_RATE(123000000, 41, 1, 3), 31 PLL_PARAMS(41, 1),
32 PLL_RATE(126000000, 42, 1, 3), 32 PLL_PARAMS(42, 1),
33 PLL_RATE(129000000, 43, 1, 3), 33 PLL_PARAMS(43, 1),
34 PLL_RATE(132000000, 44, 1, 3), 34 PLL_PARAMS(44, 1),
35 PLL_RATE(135000000, 45, 1, 3), 35 PLL_PARAMS(45, 1),
36 PLL_RATE(138000000, 46, 1, 3), 36 PLL_PARAMS(46, 1),
37 PLL_RATE(141000000, 47, 1, 3), 37 PLL_PARAMS(47, 1),
38 PLL_RATE(144000000, 48, 1, 3), 38 PLL_PARAMS(48, 1),
39 PLL_RATE(147000000, 49, 1, 3), 39 PLL_PARAMS(49, 1),
40 PLL_RATE(150000000, 50, 1, 3), 40 PLL_PARAMS(50, 1),
41 PLL_RATE(153000000, 51, 1, 3), 41 PLL_PARAMS(51, 1),
42 PLL_RATE(156000000, 52, 1, 3), 42 PLL_PARAMS(52, 1),
43 PLL_RATE(159000000, 53, 1, 3), 43 PLL_PARAMS(53, 1),
44 PLL_RATE(162000000, 54, 1, 3), 44 PLL_PARAMS(54, 1),
45 PLL_RATE(165000000, 55, 1, 3), 45 PLL_PARAMS(55, 1),
46 PLL_RATE(168000000, 56, 1, 3), 46 PLL_PARAMS(56, 1),
47 PLL_RATE(171000000, 57, 1, 3), 47 PLL_PARAMS(57, 1),
48 PLL_RATE(174000000, 58, 1, 3), 48 PLL_PARAMS(58, 1),
49 PLL_RATE(177000000, 59, 1, 3), 49 PLL_PARAMS(59, 1),
50 PLL_RATE(180000000, 60, 1, 3), 50 PLL_PARAMS(60, 1),
51 PLL_RATE(183000000, 61, 1, 3), 51 PLL_PARAMS(61, 1),
52 PLL_RATE(186000000, 62, 1, 3), 52 PLL_PARAMS(62, 1),
53 PLL_RATE(192000000, 32, 1, 2),
54 PLL_RATE(198000000, 33, 1, 2),
55 PLL_RATE(204000000, 34, 1, 2),
56 PLL_RATE(210000000, 35, 1, 2),
57 PLL_RATE(216000000, 36, 1, 2),
58 PLL_RATE(222000000, 37, 1, 2),
59 PLL_RATE(228000000, 38, 1, 2),
60 PLL_RATE(234000000, 39, 1, 2),
61 PLL_RATE(240000000, 40, 1, 2),
62 PLL_RATE(246000000, 41, 1, 2),
63 PLL_RATE(252000000, 42, 1, 2),
64 PLL_RATE(258000000, 43, 1, 2),
65 PLL_RATE(264000000, 44, 1, 2),
66 PLL_RATE(270000000, 45, 1, 2),
67 PLL_RATE(276000000, 46, 1, 2),
68 PLL_RATE(282000000, 47, 1, 2),
69 PLL_RATE(288000000, 48, 1, 2),
70 PLL_RATE(294000000, 49, 1, 2),
71 PLL_RATE(300000000, 50, 1, 2),
72 PLL_RATE(306000000, 51, 1, 2),
73 PLL_RATE(312000000, 52, 1, 2),
74 PLL_RATE(318000000, 53, 1, 2),
75 PLL_RATE(324000000, 54, 1, 2),
76 PLL_RATE(330000000, 55, 1, 2),
77 PLL_RATE(336000000, 56, 1, 2),
78 PLL_RATE(342000000, 57, 1, 2),
79 PLL_RATE(348000000, 58, 1, 2),
80 PLL_RATE(354000000, 59, 1, 2),
81 PLL_RATE(360000000, 60, 1, 2),
82 PLL_RATE(366000000, 61, 1, 2),
83 PLL_RATE(372000000, 62, 1, 2),
84 PLL_RATE(384000000, 32, 1, 1),
85 PLL_RATE(396000000, 33, 1, 1),
86 PLL_RATE(408000000, 34, 1, 1),
87 PLL_RATE(420000000, 35, 1, 1),
88 PLL_RATE(432000000, 36, 1, 1),
89 PLL_RATE(444000000, 37, 1, 1),
90 PLL_RATE(456000000, 38, 1, 1),
91 PLL_RATE(468000000, 39, 1, 1),
92 PLL_RATE(480000000, 40, 1, 1),
93 PLL_RATE(492000000, 41, 1, 1),
94 PLL_RATE(504000000, 42, 1, 1),
95 PLL_RATE(516000000, 43, 1, 1),
96 PLL_RATE(528000000, 44, 1, 1),
97 PLL_RATE(540000000, 45, 1, 1),
98 PLL_RATE(552000000, 46, 1, 1),
99 PLL_RATE(564000000, 47, 1, 1),
100 PLL_RATE(576000000, 48, 1, 1),
101 PLL_RATE(588000000, 49, 1, 1),
102 PLL_RATE(600000000, 50, 1, 1),
103 PLL_RATE(612000000, 51, 1, 1),
104 PLL_RATE(624000000, 52, 1, 1),
105 PLL_RATE(636000000, 53, 1, 1),
106 PLL_RATE(648000000, 54, 1, 1),
107 PLL_RATE(660000000, 55, 1, 1),
108 PLL_RATE(672000000, 56, 1, 1),
109 PLL_RATE(684000000, 57, 1, 1),
110 PLL_RATE(696000000, 58, 1, 1),
111 PLL_RATE(708000000, 59, 1, 1),
112 PLL_RATE(720000000, 60, 1, 1),
113 PLL_RATE(732000000, 61, 1, 1),
114 PLL_RATE(744000000, 62, 1, 1),
115 PLL_RATE(768000000, 32, 1, 0),
116 PLL_RATE(792000000, 33, 1, 0),
117 PLL_RATE(816000000, 34, 1, 0),
118 PLL_RATE(840000000, 35, 1, 0),
119 PLL_RATE(864000000, 36, 1, 0),
120 PLL_RATE(888000000, 37, 1, 0),
121 PLL_RATE(912000000, 38, 1, 0),
122 PLL_RATE(936000000, 39, 1, 0),
123 PLL_RATE(960000000, 40, 1, 0),
124 PLL_RATE(984000000, 41, 1, 0),
125 PLL_RATE(1008000000, 42, 1, 0),
126 PLL_RATE(1032000000, 43, 1, 0),
127 PLL_RATE(1056000000, 44, 1, 0),
128 PLL_RATE(1080000000, 45, 1, 0),
129 PLL_RATE(1104000000, 46, 1, 0),
130 PLL_RATE(1128000000, 47, 1, 0),
131 PLL_RATE(1152000000, 48, 1, 0),
132 PLL_RATE(1176000000, 49, 1, 0),
133 PLL_RATE(1200000000, 50, 1, 0),
134 PLL_RATE(1224000000, 51, 1, 0),
135 PLL_RATE(1248000000, 52, 1, 0),
136 PLL_RATE(1272000000, 53, 1, 0),
137 PLL_RATE(1296000000, 54, 1, 0),
138 PLL_RATE(1320000000, 55, 1, 0),
139 PLL_RATE(1344000000, 56, 1, 0),
140 PLL_RATE(1368000000, 57, 1, 0),
141 PLL_RATE(1392000000, 58, 1, 0),
142 PLL_RATE(1416000000, 59, 1, 0),
143 PLL_RATE(1440000000, 60, 1, 0),
144 PLL_RATE(1464000000, 61, 1, 0),
145 PLL_RATE(1488000000, 62, 1, 0),
146 { /* sentinel */ }, 53 { /* sentinel */ },
147}; 54};
148 55
149static const struct pll_rate_table gxl_gp0_pll_rate_table[] = { 56static const struct pll_params_table gxl_gp0_pll_params_table[] = {
150 PLL_RATE(504000000, 42, 1, 1), 57 PLL_PARAMS(42, 1),
151 PLL_RATE(516000000, 43, 1, 1), 58 PLL_PARAMS(43, 1),
152 PLL_RATE(528000000, 44, 1, 1), 59 PLL_PARAMS(44, 1),
153 PLL_RATE(540000000, 45, 1, 1), 60 PLL_PARAMS(45, 1),
154 PLL_RATE(552000000, 46, 1, 1), 61 PLL_PARAMS(46, 1),
155 PLL_RATE(564000000, 47, 1, 1), 62 PLL_PARAMS(47, 1),
156 PLL_RATE(576000000, 48, 1, 1), 63 PLL_PARAMS(48, 1),
157 PLL_RATE(588000000, 49, 1, 1), 64 PLL_PARAMS(49, 1),
158 PLL_RATE(600000000, 50, 1, 1), 65 PLL_PARAMS(50, 1),
159 PLL_RATE(612000000, 51, 1, 1), 66 PLL_PARAMS(51, 1),
160 PLL_RATE(624000000, 52, 1, 1), 67 PLL_PARAMS(52, 1),
161 PLL_RATE(636000000, 53, 1, 1), 68 PLL_PARAMS(53, 1),
162 PLL_RATE(648000000, 54, 1, 1), 69 PLL_PARAMS(54, 1),
163 PLL_RATE(660000000, 55, 1, 1), 70 PLL_PARAMS(55, 1),
164 PLL_RATE(672000000, 56, 1, 1), 71 PLL_PARAMS(56, 1),
165 PLL_RATE(684000000, 57, 1, 1), 72 PLL_PARAMS(57, 1),
166 PLL_RATE(696000000, 58, 1, 1), 73 PLL_PARAMS(58, 1),
167 PLL_RATE(708000000, 59, 1, 1), 74 PLL_PARAMS(59, 1),
168 PLL_RATE(720000000, 60, 1, 1), 75 PLL_PARAMS(60, 1),
169 PLL_RATE(732000000, 61, 1, 1), 76 PLL_PARAMS(61, 1),
170 PLL_RATE(744000000, 62, 1, 1), 77 PLL_PARAMS(62, 1),
171 PLL_RATE(756000000, 63, 1, 1), 78 PLL_PARAMS(63, 1),
172 PLL_RATE(768000000, 64, 1, 1), 79 PLL_PARAMS(64, 1),
173 PLL_RATE(780000000, 65, 1, 1), 80 PLL_PARAMS(65, 1),
174 PLL_RATE(792000000, 66, 1, 1), 81 PLL_PARAMS(66, 1),
175 { /* sentinel */ }, 82 { /* sentinel */ },
176}; 83};
177 84
178static struct clk_regmap gxbb_fixed_pll = { 85static struct clk_regmap gxbb_fixed_pll_dco = {
179 .data = &(struct meson_clk_pll_data){ 86 .data = &(struct meson_clk_pll_data){
87 .en = {
88 .reg_off = HHI_MPLL_CNTL,
89 .shift = 30,
90 .width = 1,
91 },
180 .m = { 92 .m = {
181 .reg_off = HHI_MPLL_CNTL, 93 .reg_off = HHI_MPLL_CNTL,
182 .shift = 0, 94 .shift = 0,
@@ -187,11 +99,6 @@ static struct clk_regmap gxbb_fixed_pll = {
187 .shift = 9, 99 .shift = 9,
188 .width = 5, 100 .width = 5,
189 }, 101 },
190 .od = {
191 .reg_off = HHI_MPLL_CNTL,
192 .shift = 16,
193 .width = 2,
194 },
195 .frac = { 102 .frac = {
196 .reg_off = HHI_MPLL_CNTL2, 103 .reg_off = HHI_MPLL_CNTL2,
197 .shift = 0, 104 .shift = 0,
@@ -209,11 +116,29 @@ static struct clk_regmap gxbb_fixed_pll = {
209 }, 116 },
210 }, 117 },
211 .hw.init = &(struct clk_init_data){ 118 .hw.init = &(struct clk_init_data){
212 .name = "fixed_pll", 119 .name = "fixed_pll_dco",
213 .ops = &meson_clk_pll_ro_ops, 120 .ops = &meson_clk_pll_ro_ops,
214 .parent_names = (const char *[]){ "xtal" }, 121 .parent_names = (const char *[]){ "xtal" },
215 .num_parents = 1, 122 .num_parents = 1,
216 .flags = CLK_GET_RATE_NOCACHE, 123 },
124};
125
126static struct clk_regmap gxbb_fixed_pll = {
127 .data = &(struct clk_regmap_div_data){
128 .offset = HHI_MPLL_CNTL,
129 .shift = 16,
130 .width = 2,
131 .flags = CLK_DIVIDER_POWER_OF_TWO,
132 },
133 .hw.init = &(struct clk_init_data){
134 .name = "fixed_pll",
135 .ops = &clk_regmap_divider_ro_ops,
136 .parent_names = (const char *[]){ "fixed_pll_dco" },
137 .num_parents = 1,
138 /*
139 * This clock won't ever change at runtime so
140 * CLK_SET_RATE_PARENT is not required
141 */
217 }, 142 },
218}; 143};
219 144
@@ -228,8 +153,13 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
228 }, 153 },
229}; 154};
230 155
231static struct clk_regmap gxbb_hdmi_pll = { 156static struct clk_regmap gxbb_hdmi_pll_dco = {
232 .data = &(struct meson_clk_pll_data){ 157 .data = &(struct meson_clk_pll_data){
158 .en = {
159 .reg_off = HHI_HDMI_PLL_CNTL,
160 .shift = 30,
161 .width = 1,
162 },
233 .m = { 163 .m = {
234 .reg_off = HHI_HDMI_PLL_CNTL, 164 .reg_off = HHI_HDMI_PLL_CNTL,
235 .shift = 0, 165 .shift = 0,
@@ -245,21 +175,6 @@ static struct clk_regmap gxbb_hdmi_pll = {
245 .shift = 0, 175 .shift = 0,
246 .width = 12, 176 .width = 12,
247 }, 177 },
248 .od = {
249 .reg_off = HHI_HDMI_PLL_CNTL2,
250 .shift = 16,
251 .width = 2,
252 },
253 .od2 = {
254 .reg_off = HHI_HDMI_PLL_CNTL2,
255 .shift = 22,
256 .width = 2,
257 },
258 .od3 = {
259 .reg_off = HHI_HDMI_PLL_CNTL2,
260 .shift = 18,
261 .width = 2,
262 },
263 .l = { 178 .l = {
264 .reg_off = HHI_HDMI_PLL_CNTL, 179 .reg_off = HHI_HDMI_PLL_CNTL,
265 .shift = 31, 180 .shift = 31,
@@ -272,74 +187,121 @@ static struct clk_regmap gxbb_hdmi_pll = {
272 }, 187 },
273 }, 188 },
274 .hw.init = &(struct clk_init_data){ 189 .hw.init = &(struct clk_init_data){
275 .name = "hdmi_pll", 190 .name = "hdmi_pll_dco",
276 .ops = &meson_clk_pll_ro_ops, 191 .ops = &meson_clk_pll_ro_ops,
277 .parent_names = (const char *[]){ "hdmi_pll_pre_mult" }, 192 .parent_names = (const char *[]){ "hdmi_pll_pre_mult" },
278 .num_parents = 1, 193 .num_parents = 1,
194 /*
195 * Display directly handle hdmi pll registers ATM, we need
196 * NOCACHE to keep our view of the clock as accurate as possible
197 */
279 .flags = CLK_GET_RATE_NOCACHE, 198 .flags = CLK_GET_RATE_NOCACHE,
280 }, 199 },
281}; 200};
282 201
202static struct clk_regmap gxbb_hdmi_pll_od = {
203 .data = &(struct clk_regmap_div_data){
204 .offset = HHI_HDMI_PLL_CNTL2,
205 .shift = 16,
206 .width = 2,
207 .flags = CLK_DIVIDER_POWER_OF_TWO,
208 },
209 .hw.init = &(struct clk_init_data){
210 .name = "hdmi_pll_od",
211 .ops = &clk_regmap_divider_ro_ops,
212 .parent_names = (const char *[]){ "hdmi_pll_dco" },
213 .num_parents = 1,
214 .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
215 },
216};
217
218static struct clk_regmap gxbb_hdmi_pll_od2 = {
219 .data = &(struct clk_regmap_div_data){
220 .offset = HHI_HDMI_PLL_CNTL2,
221 .shift = 22,
222 .width = 2,
223 .flags = CLK_DIVIDER_POWER_OF_TWO,
224 },
225 .hw.init = &(struct clk_init_data){
226 .name = "hdmi_pll_od2",
227 .ops = &clk_regmap_divider_ro_ops,
228 .parent_names = (const char *[]){ "hdmi_pll_od" },
229 .num_parents = 1,
230 .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
231 },
232};
233
234static struct clk_regmap gxbb_hdmi_pll = {
235 .data = &(struct clk_regmap_div_data){
236 .offset = HHI_HDMI_PLL_CNTL2,
237 .shift = 18,
238 .width = 2,
239 .flags = CLK_DIVIDER_POWER_OF_TWO,
240 },
241 .hw.init = &(struct clk_init_data){
242 .name = "hdmi_pll",
243 .ops = &clk_regmap_divider_ro_ops,
244 .parent_names = (const char *[]){ "hdmi_pll_od2" },
245 .num_parents = 1,
246 .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
247 },
248};
249
250static struct clk_regmap gxl_hdmi_pll_od = {
251 .data = &(struct clk_regmap_div_data){
252 .offset = HHI_HDMI_PLL_CNTL + 8,
253 .shift = 21,
254 .width = 2,
255 .flags = CLK_DIVIDER_POWER_OF_TWO,
256 },
257 .hw.init = &(struct clk_init_data){
258 .name = "hdmi_pll_od",
259 .ops = &clk_regmap_divider_ro_ops,
260 .parent_names = (const char *[]){ "hdmi_pll_dco" },
261 .num_parents = 1,
262 .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
263 },
264};
265
266static struct clk_regmap gxl_hdmi_pll_od2 = {
267 .data = &(struct clk_regmap_div_data){
268 .offset = HHI_HDMI_PLL_CNTL + 8,
269 .shift = 23,
270 .width = 2,
271 .flags = CLK_DIVIDER_POWER_OF_TWO,
272 },
273 .hw.init = &(struct clk_init_data){
274 .name = "hdmi_pll_od2",
275 .ops = &clk_regmap_divider_ro_ops,
276 .parent_names = (const char *[]){ "hdmi_pll_od" },
277 .num_parents = 1,
278 .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
279 },
280};
281
283static struct clk_regmap gxl_hdmi_pll = { 282static struct clk_regmap gxl_hdmi_pll = {
284 .data = &(struct meson_clk_pll_data){ 283 .data = &(struct clk_regmap_div_data){
285 .m = { 284 .offset = HHI_HDMI_PLL_CNTL + 8,
286 .reg_off = HHI_HDMI_PLL_CNTL, 285 .shift = 19,
287 .shift = 0, 286 .width = 2,
288 .width = 9, 287 .flags = CLK_DIVIDER_POWER_OF_TWO,
289 },
290 .n = {
291 .reg_off = HHI_HDMI_PLL_CNTL,
292 .shift = 9,
293 .width = 5,
294 },
295 .frac = {
296 /*
297 * On gxl, there is a register shift due to
298 * HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
299 * so we compute the register offset based on the PLL
300 * base to get it right
301 */
302 .reg_off = HHI_HDMI_PLL_CNTL + 4,
303 .shift = 0,
304 .width = 12,
305 },
306 .od = {
307 .reg_off = HHI_HDMI_PLL_CNTL + 8,
308 .shift = 21,
309 .width = 2,
310 },
311 .od2 = {
312 .reg_off = HHI_HDMI_PLL_CNTL + 8,
313 .shift = 23,
314 .width = 2,
315 },
316 .od3 = {
317 .reg_off = HHI_HDMI_PLL_CNTL + 8,
318 .shift = 19,
319 .width = 2,
320 },
321 .l = {
322 .reg_off = HHI_HDMI_PLL_CNTL,
323 .shift = 31,
324 .width = 1,
325 },
326 .rst = {
327 .reg_off = HHI_HDMI_PLL_CNTL,
328 .shift = 29,
329 .width = 1,
330 },
331 }, 288 },
332 .hw.init = &(struct clk_init_data){ 289 .hw.init = &(struct clk_init_data){
333 .name = "hdmi_pll", 290 .name = "hdmi_pll",
334 .ops = &meson_clk_pll_ro_ops, 291 .ops = &clk_regmap_divider_ro_ops,
335 .parent_names = (const char *[]){ "xtal" }, 292 .parent_names = (const char *[]){ "hdmi_pll_od2" },
336 .num_parents = 1, 293 .num_parents = 1,
337 .flags = CLK_GET_RATE_NOCACHE, 294 .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
338 }, 295 },
339}; 296};
340 297
341static struct clk_regmap gxbb_sys_pll = { 298static struct clk_regmap gxbb_sys_pll_dco = {
342 .data = &(struct meson_clk_pll_data){ 299 .data = &(struct meson_clk_pll_data){
300 .en = {
301 .reg_off = HHI_SYS_PLL_CNTL,
302 .shift = 30,
303 .width = 1,
304 },
343 .m = { 305 .m = {
344 .reg_off = HHI_SYS_PLL_CNTL, 306 .reg_off = HHI_SYS_PLL_CNTL,
345 .shift = 0, 307 .shift = 0,
@@ -350,11 +312,6 @@ static struct clk_regmap gxbb_sys_pll = {
350 .shift = 9, 312 .shift = 9,
351 .width = 5, 313 .width = 5,
352 }, 314 },
353 .od = {
354 .reg_off = HHI_SYS_PLL_CNTL,
355 .shift = 10,
356 .width = 2,
357 },
358 .l = { 315 .l = {
359 .reg_off = HHI_SYS_PLL_CNTL, 316 .reg_off = HHI_SYS_PLL_CNTL,
360 .shift = 31, 317 .shift = 31,
@@ -367,11 +324,26 @@ static struct clk_regmap gxbb_sys_pll = {
367 }, 324 },
368 }, 325 },
369 .hw.init = &(struct clk_init_data){ 326 .hw.init = &(struct clk_init_data){
370 .name = "sys_pll", 327 .name = "sys_pll_dco",
371 .ops = &meson_clk_pll_ro_ops, 328 .ops = &meson_clk_pll_ro_ops,
372 .parent_names = (const char *[]){ "xtal" }, 329 .parent_names = (const char *[]){ "xtal" },
373 .num_parents = 1, 330 .num_parents = 1,
374 .flags = CLK_GET_RATE_NOCACHE, 331 },
332};
333
334static struct clk_regmap gxbb_sys_pll = {
335 .data = &(struct clk_regmap_div_data){
336 .offset = HHI_SYS_PLL_CNTL,
337 .shift = 10,
338 .width = 2,
339 .flags = CLK_DIVIDER_POWER_OF_TWO,
340 },
341 .hw.init = &(struct clk_init_data){
342 .name = "sys_pll",
343 .ops = &clk_regmap_divider_ro_ops,
344 .parent_names = (const char *[]){ "sys_pll_dco" },
345 .num_parents = 1,
346 .flags = CLK_SET_RATE_PARENT,
375 }, 347 },
376}; 348};
377 349
@@ -379,11 +351,15 @@ static const struct reg_sequence gxbb_gp0_init_regs[] = {
379 { .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 }, 351 { .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 },
380 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 }, 352 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 },
381 { .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d }, 353 { .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d },
382 { .reg = HHI_GP0_PLL_CNTL, .def = 0x4a000228 },
383}; 354};
384 355
385static struct clk_regmap gxbb_gp0_pll = { 356static struct clk_regmap gxbb_gp0_pll_dco = {
386 .data = &(struct meson_clk_pll_data){ 357 .data = &(struct meson_clk_pll_data){
358 .en = {
359 .reg_off = HHI_GP0_PLL_CNTL,
360 .shift = 30,
361 .width = 1,
362 },
387 .m = { 363 .m = {
388 .reg_off = HHI_GP0_PLL_CNTL, 364 .reg_off = HHI_GP0_PLL_CNTL,
389 .shift = 0, 365 .shift = 0,
@@ -394,11 +370,6 @@ static struct clk_regmap gxbb_gp0_pll = {
394 .shift = 9, 370 .shift = 9,
395 .width = 5, 371 .width = 5,
396 }, 372 },
397 .od = {
398 .reg_off = HHI_GP0_PLL_CNTL,
399 .shift = 16,
400 .width = 2,
401 },
402 .l = { 373 .l = {
403 .reg_off = HHI_GP0_PLL_CNTL, 374 .reg_off = HHI_GP0_PLL_CNTL,
404 .shift = 31, 375 .shift = 31,
@@ -409,16 +380,15 @@ static struct clk_regmap gxbb_gp0_pll = {
409 .shift = 29, 380 .shift = 29,
410 .width = 1, 381 .width = 1,
411 }, 382 },
412 .table = gxbb_gp0_pll_rate_table, 383 .table = gxbb_gp0_pll_params_table,
413 .init_regs = gxbb_gp0_init_regs, 384 .init_regs = gxbb_gp0_init_regs,
414 .init_count = ARRAY_SIZE(gxbb_gp0_init_regs), 385 .init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
415 }, 386 },
416 .hw.init = &(struct clk_init_data){ 387 .hw.init = &(struct clk_init_data){
417 .name = "gp0_pll", 388 .name = "gp0_pll_dco",
418 .ops = &meson_clk_pll_ops, 389 .ops = &meson_clk_pll_ops,
419 .parent_names = (const char *[]){ "xtal" }, 390 .parent_names = (const char *[]){ "xtal" },
420 .num_parents = 1, 391 .num_parents = 1,
421 .flags = CLK_GET_RATE_NOCACHE,
422 }, 392 },
423}; 393};
424 394
@@ -428,11 +398,15 @@ static const struct reg_sequence gxl_gp0_init_regs[] = {
428 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, 398 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
429 { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d }, 399 { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
430 { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 }, 400 { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
431 { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
432}; 401};
433 402
434static struct clk_regmap gxl_gp0_pll = { 403static struct clk_regmap gxl_gp0_pll_dco = {
435 .data = &(struct meson_clk_pll_data){ 404 .data = &(struct meson_clk_pll_data){
405 .en = {
406 .reg_off = HHI_GP0_PLL_CNTL,
407 .shift = 30,
408 .width = 1,
409 },
436 .m = { 410 .m = {
437 .reg_off = HHI_GP0_PLL_CNTL, 411 .reg_off = HHI_GP0_PLL_CNTL,
438 .shift = 0, 412 .shift = 0,
@@ -443,11 +417,6 @@ static struct clk_regmap gxl_gp0_pll = {
443 .shift = 9, 417 .shift = 9,
444 .width = 5, 418 .width = 5,
445 }, 419 },
446 .od = {
447 .reg_off = HHI_GP0_PLL_CNTL,
448 .shift = 16,
449 .width = 2,
450 },
451 .frac = { 420 .frac = {
452 .reg_off = HHI_GP0_PLL_CNTL1, 421 .reg_off = HHI_GP0_PLL_CNTL1,
453 .shift = 0, 422 .shift = 0,
@@ -463,16 +432,31 @@ static struct clk_regmap gxl_gp0_pll = {
463 .shift = 29, 432 .shift = 29,
464 .width = 1, 433 .width = 1,
465 }, 434 },
466 .table = gxl_gp0_pll_rate_table, 435 .table = gxl_gp0_pll_params_table,
467 .init_regs = gxl_gp0_init_regs, 436 .init_regs = gxl_gp0_init_regs,
468 .init_count = ARRAY_SIZE(gxl_gp0_init_regs), 437 .init_count = ARRAY_SIZE(gxl_gp0_init_regs),
469 }, 438 },
470 .hw.init = &(struct clk_init_data){ 439 .hw.init = &(struct clk_init_data){
471 .name = "gp0_pll", 440 .name = "gp0_pll_dco",
472 .ops = &meson_clk_pll_ops, 441 .ops = &meson_clk_pll_ops,
473 .parent_names = (const char *[]){ "xtal" }, 442 .parent_names = (const char *[]){ "xtal" },
474 .num_parents = 1, 443 .num_parents = 1,
475 .flags = CLK_GET_RATE_NOCACHE, 444 },
445};
446
447static struct clk_regmap gxbb_gp0_pll = {
448 .data = &(struct clk_regmap_div_data){
449 .offset = HHI_GP0_PLL_CNTL,
450 .shift = 16,
451 .width = 2,
452 .flags = CLK_DIVIDER_POWER_OF_TWO,
453 },
454 .hw.init = &(struct clk_init_data){
455 .name = "gp0_pll",
456 .ops = &clk_regmap_divider_ops,
457 .parent_names = (const char *[]){ "gp0_pll_dco" },
458 .num_parents = 1,
459 .flags = CLK_SET_RATE_PARENT,
476 }, 460 },
477}; 461};
478 462
@@ -1933,6 +1917,12 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
1933 [CLKID_GEN_CLK_SEL] = &gxbb_gen_clk_sel.hw, 1917 [CLKID_GEN_CLK_SEL] = &gxbb_gen_clk_sel.hw,
1934 [CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw, 1918 [CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw,
1935 [CLKID_GEN_CLK] = &gxbb_gen_clk.hw, 1919 [CLKID_GEN_CLK] = &gxbb_gen_clk.hw,
1920 [CLKID_FIXED_PLL_DCO] = &gxbb_fixed_pll_dco.hw,
1921 [CLKID_HDMI_PLL_DCO] = &gxbb_hdmi_pll_dco.hw,
1922 [CLKID_HDMI_PLL_OD] = &gxbb_hdmi_pll_od.hw,
1923 [CLKID_HDMI_PLL_OD2] = &gxbb_hdmi_pll_od2.hw,
1924 [CLKID_SYS_PLL_DCO] = &gxbb_sys_pll_dco.hw,
1925 [CLKID_GP0_PLL_DCO] = &gxbb_gp0_pll_dco.hw,
1936 [NR_CLKS] = NULL, 1926 [NR_CLKS] = NULL,
1937 }, 1927 },
1938 .num = NR_CLKS, 1928 .num = NR_CLKS,
@@ -1948,7 +1938,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
1948 [CLKID_FCLK_DIV4] = &gxbb_fclk_div4.hw, 1938 [CLKID_FCLK_DIV4] = &gxbb_fclk_div4.hw,
1949 [CLKID_FCLK_DIV5] = &gxbb_fclk_div5.hw, 1939 [CLKID_FCLK_DIV5] = &gxbb_fclk_div5.hw,
1950 [CLKID_FCLK_DIV7] = &gxbb_fclk_div7.hw, 1940 [CLKID_FCLK_DIV7] = &gxbb_fclk_div7.hw,
1951 [CLKID_GP0_PLL] = &gxl_gp0_pll.hw, 1941 [CLKID_GP0_PLL] = &gxbb_gp0_pll.hw,
1952 [CLKID_MPEG_SEL] = &gxbb_mpeg_clk_sel.hw, 1942 [CLKID_MPEG_SEL] = &gxbb_mpeg_clk_sel.hw,
1953 [CLKID_MPEG_DIV] = &gxbb_mpeg_clk_div.hw, 1943 [CLKID_MPEG_DIV] = &gxbb_mpeg_clk_div.hw,
1954 [CLKID_CLK81] = &gxbb_clk81.hw, 1944 [CLKID_CLK81] = &gxbb_clk81.hw,
@@ -2098,19 +2088,29 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
2098 [CLKID_GEN_CLK_SEL] = &gxbb_gen_clk_sel.hw, 2088 [CLKID_GEN_CLK_SEL] = &gxbb_gen_clk_sel.hw,
2099 [CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw, 2089 [CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw,
2100 [CLKID_GEN_CLK] = &gxbb_gen_clk.hw, 2090 [CLKID_GEN_CLK] = &gxbb_gen_clk.hw,
2091 [CLKID_FIXED_PLL_DCO] = &gxbb_fixed_pll_dco.hw,
2092 [CLKID_HDMI_PLL_DCO] = &gxbb_hdmi_pll_dco.hw,
2093 [CLKID_HDMI_PLL_OD] = &gxl_hdmi_pll_od.hw,
2094 [CLKID_HDMI_PLL_OD2] = &gxl_hdmi_pll_od2.hw,
2095 [CLKID_SYS_PLL_DCO] = &gxbb_sys_pll_dco.hw,
2096 [CLKID_GP0_PLL_DCO] = &gxl_gp0_pll_dco.hw,
2101 [NR_CLKS] = NULL, 2097 [NR_CLKS] = NULL,
2102 }, 2098 },
2103 .num = NR_CLKS, 2099 .num = NR_CLKS,
2104}; 2100};
2105 2101
2106static struct clk_regmap *const gxbb_clk_regmaps[] = { 2102static struct clk_regmap *const gxbb_clk_regmaps[] = {
2107 &gxbb_gp0_pll, 2103 &gxbb_gp0_pll_dco,
2108 &gxbb_hdmi_pll, 2104 &gxbb_hdmi_pll,
2105 &gxbb_hdmi_pll_od,
2106 &gxbb_hdmi_pll_od2,
2109}; 2107};
2110 2108
2111static struct clk_regmap *const gxl_clk_regmaps[] = { 2109static struct clk_regmap *const gxl_clk_regmaps[] = {
2112 &gxl_gp0_pll, 2110 &gxl_gp0_pll_dco,
2113 &gxl_hdmi_pll, 2111 &gxl_hdmi_pll,
2112 &gxl_hdmi_pll_od,
2113 &gxl_hdmi_pll_od2,
2114}; 2114};
2115 2115
2116static struct clk_regmap *const gx_clk_regmaps[] = { 2116static struct clk_regmap *const gx_clk_regmaps[] = {
@@ -2265,6 +2265,10 @@ static struct clk_regmap *const gx_clk_regmaps[] = {
2265 &gxbb_gen_clk_sel, 2265 &gxbb_gen_clk_sel,
2266 &gxbb_gen_clk_div, 2266 &gxbb_gen_clk_div,
2267 &gxbb_gen_clk, 2267 &gxbb_gen_clk,
2268 &gxbb_fixed_pll_dco,
2269 &gxbb_hdmi_pll_dco,
2270 &gxbb_sys_pll_dco,
2271 &gxbb_gp0_pll,
2268}; 2272};
2269 2273
2270struct clkc_data { 2274struct clkc_data {
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index 20dfb1daf5b8..72bc077d9663 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -159,8 +159,14 @@
159#define CLKID_VDEC_HEVC_DIV 155 159#define CLKID_VDEC_HEVC_DIV 155
160#define CLKID_GEN_CLK_SEL 157 160#define CLKID_GEN_CLK_SEL 157
161#define CLKID_GEN_CLK_DIV 158 161#define CLKID_GEN_CLK_DIV 158
162 162#define CLKID_FIXED_PLL_DCO 160
163#define NR_CLKS 160 163#define CLKID_HDMI_PLL_DCO 161
164#define CLKID_HDMI_PLL_OD 162
165#define CLKID_HDMI_PLL_OD2 163
166#define CLKID_SYS_PLL_DCO 164
167#define CLKID_GP0_PLL_DCO 165
168
169#define NR_CLKS 166
164 170
165/* include the CLKIDs that have been made part of the DT binding */ 171/* include the CLKIDs that have been made part of the DT binding */
166#include <dt-bindings/clock/gxbb-clkc.h> 172#include <dt-bindings/clock/gxbb-clkc.h>
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 7447d96a265f..346b9e165b7a 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -11,7 +11,6 @@
11#include <linux/clk-provider.h> 11#include <linux/clk-provider.h>
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/of_address.h> 13#include <linux/of_address.h>
14#include <linux/platform_device.h>
15#include <linux/reset-controller.h> 14#include <linux/reset-controller.h>
16#include <linux/slab.h> 15#include <linux/slab.h>
17#include <linux/regmap.h> 16#include <linux/regmap.h>
@@ -22,66 +21,27 @@
22 21
23static DEFINE_SPINLOCK(meson_clk_lock); 22static DEFINE_SPINLOCK(meson_clk_lock);
24 23
25static void __iomem *clk_base;
26
27struct meson8b_clk_reset { 24struct meson8b_clk_reset {
28 struct reset_controller_dev reset; 25 struct reset_controller_dev reset;
29 void __iomem *base; 26 struct regmap *regmap;
30}; 27};
31 28
32static const struct pll_rate_table sys_pll_rate_table[] = { 29static const struct pll_params_table sys_pll_params_table[] = {
33 PLL_RATE(312000000, 52, 1, 2), 30 PLL_PARAMS(50, 1),
34 PLL_RATE(336000000, 56, 1, 2), 31 PLL_PARAMS(51, 1),
35 PLL_RATE(360000000, 60, 1, 2), 32 PLL_PARAMS(52, 1),
36 PLL_RATE(384000000, 64, 1, 2), 33 PLL_PARAMS(53, 1),
37 PLL_RATE(408000000, 68, 1, 2), 34 PLL_PARAMS(54, 1),
38 PLL_RATE(432000000, 72, 1, 2), 35 PLL_PARAMS(55, 1),
39 PLL_RATE(456000000, 76, 1, 2), 36 PLL_PARAMS(56, 1),
40 PLL_RATE(480000000, 80, 1, 2), 37 PLL_PARAMS(57, 1),
41 PLL_RATE(504000000, 84, 1, 2), 38 PLL_PARAMS(58, 1),
42 PLL_RATE(528000000, 88, 1, 2), 39 PLL_PARAMS(59, 1),
43 PLL_RATE(552000000, 92, 1, 2), 40 PLL_PARAMS(60, 1),
44 PLL_RATE(576000000, 96, 1, 2), 41 PLL_PARAMS(61, 1),
45 PLL_RATE(600000000, 50, 1, 1), 42 PLL_PARAMS(62, 1),
46 PLL_RATE(624000000, 52, 1, 1), 43 PLL_PARAMS(63, 1),
47 PLL_RATE(648000000, 54, 1, 1), 44 PLL_PARAMS(64, 1),
48 PLL_RATE(672000000, 56, 1, 1),
49 PLL_RATE(696000000, 58, 1, 1),
50 PLL_RATE(720000000, 60, 1, 1),
51 PLL_RATE(744000000, 62, 1, 1),
52 PLL_RATE(768000000, 64, 1, 1),
53 PLL_RATE(792000000, 66, 1, 1),
54 PLL_RATE(816000000, 68, 1, 1),
55 PLL_RATE(840000000, 70, 1, 1),
56 PLL_RATE(864000000, 72, 1, 1),
57 PLL_RATE(888000000, 74, 1, 1),
58 PLL_RATE(912000000, 76, 1, 1),
59 PLL_RATE(936000000, 78, 1, 1),
60 PLL_RATE(960000000, 80, 1, 1),
61 PLL_RATE(984000000, 82, 1, 1),
62 PLL_RATE(1008000000, 84, 1, 1),
63 PLL_RATE(1032000000, 86, 1, 1),
64 PLL_RATE(1056000000, 88, 1, 1),
65 PLL_RATE(1080000000, 90, 1, 1),
66 PLL_RATE(1104000000, 92, 1, 1),
67 PLL_RATE(1128000000, 94, 1, 1),
68 PLL_RATE(1152000000, 96, 1, 1),
69 PLL_RATE(1176000000, 98, 1, 1),
70 PLL_RATE(1200000000, 50, 1, 0),
71 PLL_RATE(1224000000, 51, 1, 0),
72 PLL_RATE(1248000000, 52, 1, 0),
73 PLL_RATE(1272000000, 53, 1, 0),
74 PLL_RATE(1296000000, 54, 1, 0),
75 PLL_RATE(1320000000, 55, 1, 0),
76 PLL_RATE(1344000000, 56, 1, 0),
77 PLL_RATE(1368000000, 57, 1, 0),
78 PLL_RATE(1392000000, 58, 1, 0),
79 PLL_RATE(1416000000, 59, 1, 0),
80 PLL_RATE(1440000000, 60, 1, 0),
81 PLL_RATE(1464000000, 61, 1, 0),
82 PLL_RATE(1488000000, 62, 1, 0),
83 PLL_RATE(1512000000, 63, 1, 0),
84 PLL_RATE(1536000000, 64, 1, 0),
85 { /* sentinel */ }, 45 { /* sentinel */ },
86}; 46};
87 47
@@ -94,8 +54,13 @@ static struct clk_fixed_rate meson8b_xtal = {
94 }, 54 },
95}; 55};
96 56
97static struct clk_regmap meson8b_fixed_pll = { 57static struct clk_regmap meson8b_fixed_pll_dco = {
98 .data = &(struct meson_clk_pll_data){ 58 .data = &(struct meson_clk_pll_data){
59 .en = {
60 .reg_off = HHI_MPLL_CNTL,
61 .shift = 30,
62 .width = 1,
63 },
99 .m = { 64 .m = {
100 .reg_off = HHI_MPLL_CNTL, 65 .reg_off = HHI_MPLL_CNTL,
101 .shift = 0, 66 .shift = 0,
@@ -106,11 +71,6 @@ static struct clk_regmap meson8b_fixed_pll = {
106 .shift = 9, 71 .shift = 9,
107 .width = 5, 72 .width = 5,
108 }, 73 },
109 .od = {
110 .reg_off = HHI_MPLL_CNTL,
111 .shift = 16,
112 .width = 2,
113 },
114 .frac = { 74 .frac = {
115 .reg_off = HHI_MPLL_CNTL2, 75 .reg_off = HHI_MPLL_CNTL2,
116 .shift = 0, 76 .shift = 0,
@@ -128,16 +88,39 @@ static struct clk_regmap meson8b_fixed_pll = {
128 }, 88 },
129 }, 89 },
130 .hw.init = &(struct clk_init_data){ 90 .hw.init = &(struct clk_init_data){
131 .name = "fixed_pll", 91 .name = "fixed_pll_dco",
132 .ops = &meson_clk_pll_ro_ops, 92 .ops = &meson_clk_pll_ro_ops,
133 .parent_names = (const char *[]){ "xtal" }, 93 .parent_names = (const char *[]){ "xtal" },
134 .num_parents = 1, 94 .num_parents = 1,
135 .flags = CLK_GET_RATE_NOCACHE,
136 }, 95 },
137}; 96};
138 97
139static struct clk_regmap meson8b_vid_pll = { 98static struct clk_regmap meson8b_fixed_pll = {
99 .data = &(struct clk_regmap_div_data){
100 .offset = HHI_MPLL_CNTL,
101 .shift = 16,
102 .width = 2,
103 .flags = CLK_DIVIDER_POWER_OF_TWO,
104 },
105 .hw.init = &(struct clk_init_data){
106 .name = "fixed_pll",
107 .ops = &clk_regmap_divider_ro_ops,
108 .parent_names = (const char *[]){ "fixed_pll_dco" },
109 .num_parents = 1,
110 /*
111 * This clock won't ever change at runtime so
112 * CLK_SET_RATE_PARENT is not required
113 */
114 },
115};
116
117static struct clk_regmap meson8b_vid_pll_dco = {
140 .data = &(struct meson_clk_pll_data){ 118 .data = &(struct meson_clk_pll_data){
119 .en = {
120 .reg_off = HHI_VID_PLL_CNTL,
121 .shift = 30,
122 .width = 1,
123 },
141 .m = { 124 .m = {
142 .reg_off = HHI_VID_PLL_CNTL, 125 .reg_off = HHI_VID_PLL_CNTL,
143 .shift = 0, 126 .shift = 0,
@@ -148,11 +131,6 @@ static struct clk_regmap meson8b_vid_pll = {
148 .shift = 9, 131 .shift = 9,
149 .width = 5, 132 .width = 5,
150 }, 133 },
151 .od = {
152 .reg_off = HHI_VID_PLL_CNTL,
153 .shift = 16,
154 .width = 2,
155 },
156 .l = { 134 .l = {
157 .reg_off = HHI_VID_PLL_CNTL, 135 .reg_off = HHI_VID_PLL_CNTL,
158 .shift = 31, 136 .shift = 31,
@@ -165,16 +143,36 @@ static struct clk_regmap meson8b_vid_pll = {
165 }, 143 },
166 }, 144 },
167 .hw.init = &(struct clk_init_data){ 145 .hw.init = &(struct clk_init_data){
168 .name = "vid_pll", 146 .name = "vid_pll_dco",
169 .ops = &meson_clk_pll_ro_ops, 147 .ops = &meson_clk_pll_ro_ops,
170 .parent_names = (const char *[]){ "xtal" }, 148 .parent_names = (const char *[]){ "xtal" },
171 .num_parents = 1, 149 .num_parents = 1,
172 .flags = CLK_GET_RATE_NOCACHE,
173 }, 150 },
174}; 151};
175 152
176static struct clk_regmap meson8b_sys_pll = { 153static struct clk_regmap meson8b_vid_pll = {
154 .data = &(struct clk_regmap_div_data){
155 .offset = HHI_VID_PLL_CNTL,
156 .shift = 16,
157 .width = 2,
158 .flags = CLK_DIVIDER_POWER_OF_TWO,
159 },
160 .hw.init = &(struct clk_init_data){
161 .name = "vid_pll",
162 .ops = &clk_regmap_divider_ro_ops,
163 .parent_names = (const char *[]){ "vid_pll_dco" },
164 .num_parents = 1,
165 .flags = CLK_SET_RATE_PARENT,
166 },
167};
168
169static struct clk_regmap meson8b_sys_pll_dco = {
177 .data = &(struct meson_clk_pll_data){ 170 .data = &(struct meson_clk_pll_data){
171 .en = {
172 .reg_off = HHI_SYS_PLL_CNTL,
173 .shift = 30,
174 .width = 1,
175 },
178 .m = { 176 .m = {
179 .reg_off = HHI_SYS_PLL_CNTL, 177 .reg_off = HHI_SYS_PLL_CNTL,
180 .shift = 0, 178 .shift = 0,
@@ -185,11 +183,6 @@ static struct clk_regmap meson8b_sys_pll = {
185 .shift = 9, 183 .shift = 9,
186 .width = 5, 184 .width = 5,
187 }, 185 },
188 .od = {
189 .reg_off = HHI_SYS_PLL_CNTL,
190 .shift = 16,
191 .width = 2,
192 },
193 .l = { 186 .l = {
194 .reg_off = HHI_SYS_PLL_CNTL, 187 .reg_off = HHI_SYS_PLL_CNTL,
195 .shift = 31, 188 .shift = 31,
@@ -200,14 +193,29 @@ static struct clk_regmap meson8b_sys_pll = {
200 .shift = 29, 193 .shift = 29,
201 .width = 1, 194 .width = 1,
202 }, 195 },
203 .table = sys_pll_rate_table, 196 .table = sys_pll_params_table,
204 }, 197 },
205 .hw.init = &(struct clk_init_data){ 198 .hw.init = &(struct clk_init_data){
206 .name = "sys_pll", 199 .name = "sys_pll_dco",
207 .ops = &meson_clk_pll_ro_ops, 200 .ops = &meson_clk_pll_ro_ops,
208 .parent_names = (const char *[]){ "xtal" }, 201 .parent_names = (const char *[]){ "xtal" },
209 .num_parents = 1, 202 .num_parents = 1,
210 .flags = CLK_GET_RATE_NOCACHE, 203 },
204};
205
206static struct clk_regmap meson8b_sys_pll = {
207 .data = &(struct clk_regmap_div_data){
208 .offset = HHI_SYS_PLL_CNTL,
209 .shift = 16,
210 .width = 2,
211 .flags = CLK_DIVIDER_POWER_OF_TWO,
212 },
213 .hw.init = &(struct clk_init_data){
214 .name = "sys_pll",
215 .ops = &clk_regmap_divider_ro_ops,
216 .parent_names = (const char *[]){ "sys_pll_dco" },
217 .num_parents = 1,
218 .flags = CLK_SET_RATE_PARENT,
211 }, 219 },
212}; 220};
213 221
@@ -879,6 +887,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
879 [CLKID_NAND_SEL] = &meson8b_nand_clk_sel.hw, 887 [CLKID_NAND_SEL] = &meson8b_nand_clk_sel.hw,
880 [CLKID_NAND_DIV] = &meson8b_nand_clk_div.hw, 888 [CLKID_NAND_DIV] = &meson8b_nand_clk_div.hw,
881 [CLKID_NAND_CLK] = &meson8b_nand_clk_gate.hw, 889 [CLKID_NAND_CLK] = &meson8b_nand_clk_gate.hw,
890 [CLKID_PLL_FIXED_DCO] = &meson8b_fixed_pll_dco.hw,
891 [CLKID_PLL_VID_DCO] = &meson8b_vid_pll_dco.hw,
892 [CLKID_PLL_SYS_DCO] = &meson8b_sys_pll_dco.hw,
882 [CLK_NR_CLKS] = NULL, 893 [CLK_NR_CLKS] = NULL,
883 }, 894 },
884 .num = CLK_NR_CLKS, 895 .num = CLK_NR_CLKS,
@@ -987,6 +998,9 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
987 &meson8b_nand_clk_sel, 998 &meson8b_nand_clk_sel,
988 &meson8b_nand_clk_div, 999 &meson8b_nand_clk_div,
989 &meson8b_nand_clk_gate, 1000 &meson8b_nand_clk_gate,
1001 &meson8b_fixed_pll_dco,
1002 &meson8b_vid_pll_dco,
1003 &meson8b_sys_pll_dco,
990}; 1004};
991 1005
992static const struct meson8b_clk_reset_line { 1006static const struct meson8b_clk_reset_line {
@@ -1050,7 +1064,6 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev,
1050 container_of(rcdev, struct meson8b_clk_reset, reset); 1064 container_of(rcdev, struct meson8b_clk_reset, reset);
1051 unsigned long flags; 1065 unsigned long flags;
1052 const struct meson8b_clk_reset_line *reset; 1066 const struct meson8b_clk_reset_line *reset;
1053 u32 val;
1054 1067
1055 if (id >= ARRAY_SIZE(meson8b_clk_reset_bits)) 1068 if (id >= ARRAY_SIZE(meson8b_clk_reset_bits))
1056 return -EINVAL; 1069 return -EINVAL;
@@ -1059,12 +1072,12 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev,
1059 1072
1060 spin_lock_irqsave(&meson_clk_lock, flags); 1073 spin_lock_irqsave(&meson_clk_lock, flags);
1061 1074
1062 val = readl(meson8b_clk_reset->base + reset->reg);
1063 if (assert) 1075 if (assert)
1064 val |= BIT(reset->bit_idx); 1076 regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
1077 BIT(reset->bit_idx), BIT(reset->bit_idx));
1065 else 1078 else
1066 val &= ~BIT(reset->bit_idx); 1079 regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
1067 writel(val, meson8b_clk_reset->base + reset->reg); 1080 BIT(reset->bit_idx), 0);
1068 1081
1069 spin_unlock_irqrestore(&meson_clk_lock, flags); 1082 spin_unlock_irqrestore(&meson_clk_lock, flags);
1070 1083
@@ -1094,62 +1107,12 @@ static const struct regmap_config clkc_regmap_config = {
1094 .reg_stride = 4, 1107 .reg_stride = 4,
1095}; 1108};
1096 1109
1097static int meson8b_clkc_probe(struct platform_device *pdev) 1110static void __init meson8b_clkc_init(struct device_node *np)
1098{
1099 int ret, i;
1100 struct device *dev = &pdev->dev;
1101 struct regmap *map;
1102
1103 if (!clk_base)
1104 return -ENXIO;
1105
1106 map = devm_regmap_init_mmio(dev, clk_base, &clkc_regmap_config);
1107 if (IS_ERR(map))
1108 return PTR_ERR(map);
1109
1110 /* Populate regmap for the regmap backed clocks */
1111 for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++)
1112 meson8b_clk_regmaps[i]->map = map;
1113
1114 /*
1115 * register all clks
1116 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
1117 */
1118 for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
1119 /* array might be sparse */
1120 if (!meson8b_hw_onecell_data.hws[i])
1121 continue;
1122
1123 ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[i]);
1124 if (ret)
1125 return ret;
1126 }
1127
1128 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
1129 &meson8b_hw_onecell_data);
1130}
1131
1132static const struct of_device_id meson8b_clkc_match_table[] = {
1133 { .compatible = "amlogic,meson8-clkc" },
1134 { .compatible = "amlogic,meson8b-clkc" },
1135 { .compatible = "amlogic,meson8m2-clkc" },
1136 { }
1137};
1138
1139static struct platform_driver meson8b_driver = {
1140 .probe = meson8b_clkc_probe,
1141 .driver = {
1142 .name = "meson8b-clkc",
1143 .of_match_table = meson8b_clkc_match_table,
1144 },
1145};
1146
1147builtin_platform_driver(meson8b_driver);
1148
1149static void __init meson8b_clkc_reset_init(struct device_node *np)
1150{ 1111{
1151 struct meson8b_clk_reset *rstc; 1112 struct meson8b_clk_reset *rstc;
1152 int ret; 1113 void __iomem *clk_base;
1114 struct regmap *map;
1115 int i, ret;
1153 1116
1154 /* Generic clocks, PLLs and some of the reset-bits */ 1117 /* Generic clocks, PLLs and some of the reset-bits */
1155 clk_base = of_iomap(np, 1); 1118 clk_base = of_iomap(np, 1);
@@ -1158,12 +1121,16 @@ static void __init meson8b_clkc_reset_init(struct device_node *np)
1158 return; 1121 return;
1159 } 1122 }
1160 1123
1124 map = regmap_init_mmio(NULL, clk_base, &clkc_regmap_config);
1125 if (IS_ERR(map))
1126 return;
1127
1161 rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); 1128 rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
1162 if (!rstc) 1129 if (!rstc)
1163 return; 1130 return;
1164 1131
1165 /* Reset Controller */ 1132 /* Reset Controller */
1166 rstc->base = clk_base; 1133 rstc->regmap = map;
1167 rstc->reset.ops = &meson8b_clk_reset_ops; 1134 rstc->reset.ops = &meson8b_clk_reset_ops;
1168 rstc->reset.nr_resets = ARRAY_SIZE(meson8b_clk_reset_bits); 1135 rstc->reset.nr_resets = ARRAY_SIZE(meson8b_clk_reset_bits);
1169 rstc->reset.of_node = np; 1136 rstc->reset.of_node = np;
@@ -1173,11 +1140,34 @@ static void __init meson8b_clkc_reset_init(struct device_node *np)
1173 __func__, ret); 1140 __func__, ret);
1174 return; 1141 return;
1175 } 1142 }
1143
1144 /* Populate regmap for the regmap backed clocks */
1145 for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++)
1146 meson8b_clk_regmaps[i]->map = map;
1147
1148 /*
1149 * register all clks
1150 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
1151 */
1152 for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
1153 /* array might be sparse */
1154 if (!meson8b_hw_onecell_data.hws[i])
1155 continue;
1156
1157 ret = clk_hw_register(NULL, meson8b_hw_onecell_data.hws[i]);
1158 if (ret)
1159 return;
1160 }
1161
1162 ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
1163 &meson8b_hw_onecell_data);
1164 if (ret)
1165 pr_err("%s: failed to register clock provider\n", __func__);
1176} 1166}
1177 1167
1178CLK_OF_DECLARE_DRIVER(meson8_clkc, "amlogic,meson8-clkc", 1168CLK_OF_DECLARE_DRIVER(meson8_clkc, "amlogic,meson8-clkc",
1179 meson8b_clkc_reset_init); 1169 meson8b_clkc_init);
1180CLK_OF_DECLARE_DRIVER(meson8b_clkc, "amlogic,meson8b-clkc", 1170CLK_OF_DECLARE_DRIVER(meson8b_clkc, "amlogic,meson8b-clkc",
1181 meson8b_clkc_reset_init); 1171 meson8b_clkc_init);
1182CLK_OF_DECLARE_DRIVER(meson8m2_clkc, "amlogic,meson8m2-clkc", 1172CLK_OF_DECLARE_DRIVER(meson8m2_clkc, "amlogic,meson8m2-clkc",
1183 meson8b_clkc_reset_init); 1173 meson8b_clkc_init);
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
index 5d09412b5084..1c6fb180e6a2 100644
--- a/drivers/clk/meson/meson8b.h
+++ b/drivers/clk/meson/meson8b.h
@@ -75,8 +75,11 @@
75#define CLKID_FCLK_DIV7_DIV 109 75#define CLKID_FCLK_DIV7_DIV 109
76#define CLKID_NAND_SEL 110 76#define CLKID_NAND_SEL 110
77#define CLKID_NAND_DIV 111 77#define CLKID_NAND_DIV 111
78#define CLKID_PLL_FIXED_DCO 113
79#define CLKID_PLL_VID_DCO 114
80#define CLKID_PLL_SYS_DCO 115
78 81
79#define CLK_NR_CLKS 113 82#define CLK_NR_CLKS 116
80 83
81/* 84/*
82 * include the CLKID and RESETID that have 85 * include the CLKID and RESETID that have
diff --git a/drivers/clk/mvebu/ap806-system-controller.c b/drivers/clk/mvebu/ap806-system-controller.c
index 9fbec3eb725f..ea54a874bbda 100644
--- a/drivers/clk/mvebu/ap806-system-controller.c
+++ b/drivers/clk/mvebu/ap806-system-controller.c
@@ -153,7 +153,6 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
153 goto fail4; 153 goto fail4;
154 } 154 }
155 155
156 of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data);
157 ret = of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data); 156 ret = of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data);
158 if (ret) 157 if (ret)
159 goto fail_clk_add; 158 goto fail_clk_add;
diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c
index 499f5962c8b0..1f1cff428d78 100644
--- a/drivers/clk/mvebu/armada-37xx-periph.c
+++ b/drivers/clk/mvebu/armada-37xx-periph.c
@@ -56,6 +56,15 @@
56struct clk_periph_driver_data { 56struct clk_periph_driver_data {
57 struct clk_hw_onecell_data *hw_data; 57 struct clk_hw_onecell_data *hw_data;
58 spinlock_t lock; 58 spinlock_t lock;
59 void __iomem *reg;
60
61 /* Storage registers for suspend/resume operations */
62 u32 tbg_sel;
63 u32 div_sel0;
64 u32 div_sel1;
65 u32 div_sel2;
66 u32 clk_sel;
67 u32 clk_dis;
59}; 68};
60 69
61struct clk_double_div { 70struct clk_double_div {
@@ -672,6 +681,40 @@ static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
672 return PTR_ERR_OR_ZERO(*hw); 681 return PTR_ERR_OR_ZERO(*hw);
673} 682}
674 683
684static int __maybe_unused armada_3700_periph_clock_suspend(struct device *dev)
685{
686 struct clk_periph_driver_data *data = dev_get_drvdata(dev);
687
688 data->tbg_sel = readl(data->reg + TBG_SEL);
689 data->div_sel0 = readl(data->reg + DIV_SEL0);
690 data->div_sel1 = readl(data->reg + DIV_SEL1);
691 data->div_sel2 = readl(data->reg + DIV_SEL2);
692 data->clk_sel = readl(data->reg + CLK_SEL);
693 data->clk_dis = readl(data->reg + CLK_DIS);
694
695 return 0;
696}
697
698static int __maybe_unused armada_3700_periph_clock_resume(struct device *dev)
699{
700 struct clk_periph_driver_data *data = dev_get_drvdata(dev);
701
702 /* Follow the same order than what the Cortex-M3 does (ATF code) */
703 writel(data->clk_dis, data->reg + CLK_DIS);
704 writel(data->div_sel0, data->reg + DIV_SEL0);
705 writel(data->div_sel1, data->reg + DIV_SEL1);
706 writel(data->div_sel2, data->reg + DIV_SEL2);
707 writel(data->tbg_sel, data->reg + TBG_SEL);
708 writel(data->clk_sel, data->reg + CLK_SEL);
709
710 return 0;
711}
712
713static const struct dev_pm_ops armada_3700_periph_clock_pm_ops = {
714 SET_SYSTEM_SLEEP_PM_OPS(armada_3700_periph_clock_suspend,
715 armada_3700_periph_clock_resume)
716};
717
675static int armada_3700_periph_clock_probe(struct platform_device *pdev) 718static int armada_3700_periph_clock_probe(struct platform_device *pdev)
676{ 719{
677 struct clk_periph_driver_data *driver_data; 720 struct clk_periph_driver_data *driver_data;
@@ -680,7 +723,6 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev)
680 struct device *dev = &pdev->dev; 723 struct device *dev = &pdev->dev;
681 int num_periph = 0, i, ret; 724 int num_periph = 0, i, ret;
682 struct resource *res; 725 struct resource *res;
683 void __iomem *reg;
684 726
685 data = of_device_get_match_data(dev); 727 data = of_device_get_match_data(dev);
686 if (!data) 728 if (!data)
@@ -689,11 +731,6 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev)
689 while (data[num_periph].name) 731 while (data[num_periph].name)
690 num_periph++; 732 num_periph++;
691 733
692 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
693 reg = devm_ioremap_resource(dev, res);
694 if (IS_ERR(reg))
695 return PTR_ERR(reg);
696
697 driver_data = devm_kzalloc(dev, sizeof(*driver_data), GFP_KERNEL); 734 driver_data = devm_kzalloc(dev, sizeof(*driver_data), GFP_KERNEL);
698 if (!driver_data) 735 if (!driver_data)
699 return -ENOMEM; 736 return -ENOMEM;
@@ -706,12 +743,16 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev)
706 return -ENOMEM; 743 return -ENOMEM;
707 driver_data->hw_data->num = num_periph; 744 driver_data->hw_data->num = num_periph;
708 745
746 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
747 driver_data->reg = devm_ioremap_resource(dev, res);
748 if (IS_ERR(driver_data->reg))
749 return PTR_ERR(driver_data->reg);
750
709 spin_lock_init(&driver_data->lock); 751 spin_lock_init(&driver_data->lock);
710 752
711 for (i = 0; i < num_periph; i++) { 753 for (i = 0; i < num_periph; i++) {
712 struct clk_hw **hw = &driver_data->hw_data->hws[i]; 754 struct clk_hw **hw = &driver_data->hw_data->hws[i];
713 755 if (armada_3700_add_composite_clk(&data[i], driver_data->reg,
714 if (armada_3700_add_composite_clk(&data[i], reg,
715 &driver_data->lock, dev, hw)) 756 &driver_data->lock, dev, hw))
716 dev_err(dev, "Can't register periph clock %s\n", 757 dev_err(dev, "Can't register periph clock %s\n",
717 data[i].name); 758 data[i].name);
@@ -749,6 +790,7 @@ static struct platform_driver armada_3700_periph_clock_driver = {
749 .driver = { 790 .driver = {
750 .name = "marvell-armada-3700-periph-clock", 791 .name = "marvell-armada-3700-periph-clock",
751 .of_match_table = armada_3700_periph_clock_of_match, 792 .of_match_table = armada_3700_periph_clock_of_match,
793 .pm = &armada_3700_periph_clock_pm_ops,
752 }, 794 },
753}; 795};
754 796
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index ee9c12cf3f08..5f80eb018014 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -64,17 +64,19 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
64 BIT(28), /* lock */ 64 BIT(28), /* lock */
65 CLK_SET_RATE_UNGATE); 65 CLK_SET_RATE_UNGATE);
66 66
67static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", 67static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video0_clk, "pll-video0",
68 "osc24M", 0x010, 68 "osc24M", 0x010,
69 8, 7, /* N */ 69 192000000, /* Minimum rate */
70 0, 4, /* M */ 70 1008000000, /* Maximum rate */
71 BIT(24), /* frac enable */ 71 8, 7, /* N */
72 BIT(25), /* frac select */ 72 0, 4, /* M */
73 270000000, /* frac rate 0 */ 73 BIT(24), /* frac enable */
74 297000000, /* frac rate 1 */ 74 BIT(25), /* frac select */
75 BIT(31), /* gate */ 75 270000000, /* frac rate 0 */
76 BIT(28), /* lock */ 76 297000000, /* frac rate 1 */
77 CLK_SET_RATE_UNGATE); 77 BIT(31), /* gate */
78 BIT(28), /* lock */
79 CLK_SET_RATE_UNGATE);
78 80
79static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", 81static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
80 "osc24M", 0x018, 82 "osc24M", 0x018,
@@ -125,17 +127,19 @@ static struct ccu_nk pll_periph1_clk = {
125 }, 127 },
126}; 128};
127 129
128static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1", 130static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video1_clk, "pll-video1",
129 "osc24M", 0x030, 131 "osc24M", 0x030,
130 8, 7, /* N */ 132 192000000, /* Minimum rate */
131 0, 4, /* M */ 133 1008000000, /* Maximum rate */
132 BIT(24), /* frac enable */ 134 8, 7, /* N */
133 BIT(25), /* frac select */ 135 0, 4, /* M */
134 270000000, /* frac rate 0 */ 136 BIT(24), /* frac enable */
135 297000000, /* frac rate 1 */ 137 BIT(25), /* frac select */
136 BIT(31), /* gate */ 138 270000000, /* frac rate 0 */
137 BIT(28), /* lock */ 139 297000000, /* frac rate 1 */
138 CLK_SET_RATE_UNGATE); 140 BIT(31), /* gate */
141 BIT(28), /* lock */
142 CLK_SET_RATE_UNGATE);
139 143
140static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", 144static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu",
141 "osc24M", 0x038, 145 "osc24M", 0x038,
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h
index 061b6fbb4f95..cd415b968e8c 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h
@@ -27,7 +27,9 @@
27#define CLK_PLL_AUDIO_2X 4 27#define CLK_PLL_AUDIO_2X 4
28#define CLK_PLL_AUDIO_4X 5 28#define CLK_PLL_AUDIO_4X 5
29#define CLK_PLL_AUDIO_8X 6 29#define CLK_PLL_AUDIO_8X 6
30#define CLK_PLL_VIDEO0 7 30
31/* PLL_VIDEO0 exported for HDMI PHY */
32
31#define CLK_PLL_VIDEO0_2X 8 33#define CLK_PLL_VIDEO0_2X 8
32#define CLK_PLL_VE 9 34#define CLK_PLL_VE 9
33#define CLK_PLL_DDR0 10 35#define CLK_PLL_DDR0 10
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
index bdbfe78fe133..2193e1495086 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
@@ -224,7 +224,7 @@ static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2",
224 psi_ahb1_ahb2_parents, 224 psi_ahb1_ahb2_parents,
225 0x510, 225 0x510,
226 0, 5, /* M */ 226 0, 5, /* M */
227 16, 2, /* P */ 227 8, 2, /* P */
228 24, 2, /* mux */ 228 24, 2, /* mux */
229 0); 229 0);
230 230
@@ -233,19 +233,19 @@ static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k",
233 "pll-periph0" }; 233 "pll-periph0" };
234static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c, 234static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c,
235 0, 5, /* M */ 235 0, 5, /* M */
236 16, 2, /* P */ 236 8, 2, /* P */
237 24, 2, /* mux */ 237 24, 2, /* mux */
238 0); 238 0);
239 239
240static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520, 240static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520,
241 0, 5, /* M */ 241 0, 5, /* M */
242 16, 2, /* P */ 242 8, 2, /* P */
243 24, 2, /* mux */ 243 24, 2, /* mux */
244 0); 244 0);
245 245
246static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524, 246static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524,
247 0, 5, /* M */ 247 0, 5, /* M */
248 16, 2, /* P */ 248 8, 2, /* P */
249 24, 2, /* mux */ 249 24, 2, /* mux */
250 0); 250 0);
251 251
@@ -352,7 +352,7 @@ static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2",
352static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2", 352static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2",
353 0x79c, BIT(0), 0); 353 0x79c, BIT(0), 0);
354 354
355static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x79c, BIT(0), 0); 355static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0);
356 356
357static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0); 357static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0);
358 358
@@ -408,26 +408,29 @@ static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0);
408 408
409static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x", 409static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x",
410 "pll-periph1-2x" }; 410 "pll-periph1-2x" };
411static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_parents, 0x830, 411static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
412 0, 4, /* M */ 412 0, 4, /* M */
413 8, 2, /* N */ 413 8, 2, /* N */
414 24, 3, /* mux */ 414 24, 3, /* mux */
415 BIT(31),/* gate */ 415 BIT(31), /* gate */
416 0); 416 2, /* post-div */
417 417 0);
418static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_parents, 0x834, 418
419 0, 4, /* M */ 419static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
420 8, 2, /* N */ 420 0, 4, /* M */
421 24, 3, /* mux */ 421 8, 2, /* N */
422 BIT(31),/* gate */ 422 24, 3, /* mux */
423 0); 423 BIT(31), /* gate */
424 424 2, /* post-div */
425static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_parents, 0x838, 425 0);
426 0, 4, /* M */ 426
427 8, 2, /* N */ 427static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838,
428 24, 3, /* mux */ 428 0, 4, /* M */
429 BIT(31),/* gate */ 429 8, 2, /* N */
430 0); 430 24, 3, /* mux */
431 BIT(31), /* gate */
432 2, /* post-div */
433 0);
431 434
432static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0); 435static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0);
433static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0); 436static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
index 7d08015b980d..2d6555d73170 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
@@ -108,6 +108,7 @@ static struct ccu_nkmp pll_video0_clk = {
108 .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), 108 .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
109 .m = _SUNXI_CCU_DIV(16, 1), /* input divider */ 109 .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
110 .p = _SUNXI_CCU_DIV(0, 2), /* output divider */ 110 .p = _SUNXI_CCU_DIV(0, 2), /* output divider */
111 .max_rate = 3000000000UL,
111 .common = { 112 .common = {
112 .reg = 0x010, 113 .reg = 0x010,
113 .lock_reg = CCU_SUN8I_A83T_LOCK_REG, 114 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,
@@ -220,6 +221,7 @@ static struct ccu_nkmp pll_video1_clk = {
220 .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), 221 .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
221 .m = _SUNXI_CCU_DIV(16, 1), /* input divider */ 222 .m = _SUNXI_CCU_DIV(16, 1), /* input divider */
222 .p = _SUNXI_CCU_DIV(0, 2), /* external divider p */ 223 .p = _SUNXI_CCU_DIV(0, 2), /* external divider p */
224 .max_rate = 3000000000UL,
223 .common = { 225 .common = {
224 .reg = 0x04c, 226 .reg = 0x04c,
225 .lock_reg = CCU_SUN8I_A83T_LOCK_REG, 227 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
index 77ed0b0ba681..eb5c608428fa 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
@@ -69,18 +69,19 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
69 BIT(28), /* lock */ 69 BIT(28), /* lock */
70 CLK_SET_RATE_UNGATE); 70 CLK_SET_RATE_UNGATE);
71 71
72static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video_clk, "pll-video", 72static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video_clk, "pll-video",
73 "osc24M", 0x0010, 73 "osc24M", 0x0010,
74 192000000, /* Minimum rate */ 74 192000000, /* Minimum rate */
75 8, 7, /* N */ 75 912000000, /* Maximum rate */
76 0, 4, /* M */ 76 8, 7, /* N */
77 BIT(24), /* frac enable */ 77 0, 4, /* M */
78 BIT(25), /* frac select */ 78 BIT(24), /* frac enable */
79 270000000, /* frac rate 0 */ 79 BIT(25), /* frac select */
80 297000000, /* frac rate 1 */ 80 270000000, /* frac rate 0 */
81 BIT(31), /* gate */ 81 297000000, /* frac rate 1 */
82 BIT(28), /* lock */ 82 BIT(31), /* gate */
83 CLK_SET_RATE_UNGATE); 83 BIT(28), /* lock */
84 CLK_SET_RATE_UNGATE);
84 85
85static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", 86static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
86 "osc24M", 0x0018, 87 "osc24M", 0x0018,
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
index 0f388f6944d5..582ebd41d20d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
@@ -65,19 +65,19 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
65 BIT(28), /* lock */ 65 BIT(28), /* lock */
66 CLK_SET_RATE_UNGATE); 66 CLK_SET_RATE_UNGATE);
67 67
68/* TODO: The result of N/M is required to be in [8, 25] range. */ 68static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video0_clk, "pll-video0",
69static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video0_clk, "pll-video0", 69 "osc24M", 0x0010,
70 "osc24M", 0x0010, 70 192000000, /* Minimum rate */
71 192000000, /* Minimum rate */ 71 1008000000, /* Maximum rate */
72 8, 7, /* N */ 72 8, 7, /* N */
73 0, 4, /* M */ 73 0, 4, /* M */
74 BIT(24), /* frac enable */ 74 BIT(24), /* frac enable */
75 BIT(25), /* frac select */ 75 BIT(25), /* frac select */
76 270000000, /* frac rate 0 */ 76 270000000, /* frac rate 0 */
77 297000000, /* frac rate 1 */ 77 297000000, /* frac rate 1 */
78 BIT(31), /* gate */ 78 BIT(31), /* gate */
79 BIT(28), /* lock */ 79 BIT(28), /* lock */
80 CLK_SET_RATE_UNGATE); 80 CLK_SET_RATE_UNGATE);
81 81
82/* TODO: The result of N/M is required to be in [8, 25] range. */ 82/* TODO: The result of N/M is required to be in [8, 25] range. */
83static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", 83static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
@@ -152,19 +152,19 @@ static struct ccu_nk pll_periph1_clk = {
152 }, 152 },
153}; 153};
154 154
155/* TODO: The result of N/M is required to be in [8, 25] range. */ 155static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video1_clk, "pll-video1",
156static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video1_clk, "pll-video1", 156 "osc24M", 0x030,
157 "osc24M", 0x030, 157 192000000, /* Minimum rate */
158 192000000, /* Minimum rate */ 158 1008000000, /* Maximum rate */
159 8, 7, /* N */ 159 8, 7, /* N */
160 0, 4, /* M */ 160 0, 4, /* M */
161 BIT(24), /* frac enable */ 161 BIT(24), /* frac enable */
162 BIT(25), /* frac select */ 162 BIT(25), /* frac select */
163 270000000, /* frac rate 0 */ 163 270000000, /* frac rate 0 */
164 297000000, /* frac rate 1 */ 164 297000000, /* frac rate 1 */
165 BIT(31), /* gate */ 165 BIT(31), /* gate */
166 BIT(28), /* lock */ 166 BIT(28), /* lock */
167 CLK_SET_RATE_UNGATE); 167 CLK_SET_RATE_UNGATE);
168 168
169static struct ccu_nkm pll_sata_clk = { 169static struct ccu_nkm pll_sata_clk = {
170 .enable = BIT(31), 170 .enable = BIT(31),
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c
index ebd9436d2c7c..9b49adb20d07 100644
--- a/drivers/clk/sunxi-ng/ccu_nkmp.c
+++ b/drivers/clk/sunxi-ng/ccu_nkmp.c
@@ -137,6 +137,13 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
137 if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV) 137 if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
138 rate *= nkmp->fixed_post_div; 138 rate *= nkmp->fixed_post_div;
139 139
140 if (nkmp->max_rate && rate > nkmp->max_rate) {
141 rate = nkmp->max_rate;
142 if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
143 rate /= nkmp->fixed_post_div;
144 return rate;
145 }
146
140 _nkmp.min_n = nkmp->n.min ?: 1; 147 _nkmp.min_n = nkmp->n.min ?: 1;
141 _nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width; 148 _nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width;
142 _nkmp.min_k = nkmp->k.min ?: 1; 149 _nkmp.min_k = nkmp->k.min ?: 1;
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.h b/drivers/clk/sunxi-ng/ccu_nkmp.h
index 6940503e7fc4..a9f8c116a745 100644
--- a/drivers/clk/sunxi-ng/ccu_nkmp.h
+++ b/drivers/clk/sunxi-ng/ccu_nkmp.h
@@ -35,6 +35,7 @@ struct ccu_nkmp {
35 struct ccu_div_internal p; 35 struct ccu_div_internal p;
36 36
37 unsigned int fixed_post_div; 37 unsigned int fixed_post_div;
38 unsigned int max_rate;
38 39
39 struct ccu_common common; 40 struct ccu_common common;
40}; 41};
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
index 4e2073307f34..6fe3c14f7b2d 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.c
+++ b/drivers/clk/sunxi-ng/ccu_nm.c
@@ -124,6 +124,13 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
124 return rate; 124 return rate;
125 } 125 }
126 126
127 if (nm->max_rate && rate > nm->max_rate) {
128 rate = nm->max_rate;
129 if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
130 rate /= nm->fixed_post_div;
131 return rate;
132 }
133
127 if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) { 134 if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) {
128 if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV) 135 if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
129 rate /= nm->fixed_post_div; 136 rate /= nm->fixed_post_div;
diff --git a/drivers/clk/sunxi-ng/ccu_nm.h b/drivers/clk/sunxi-ng/ccu_nm.h
index 1d8b459c50b7..de232f2199a6 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.h
+++ b/drivers/clk/sunxi-ng/ccu_nm.h
@@ -38,6 +38,7 @@ struct ccu_nm {
38 38
39 unsigned int fixed_post_div; 39 unsigned int fixed_post_div;
40 unsigned int min_rate; 40 unsigned int min_rate;
41 unsigned int max_rate;
41 42
42 struct ccu_common common; 43 struct ccu_common common;
43}; 44};
@@ -115,6 +116,35 @@ struct ccu_nm {
115 }, \ 116 }, \
116 } 117 }
117 118
119#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(_struct, _name, \
120 _parent, _reg, \
121 _min_rate, _max_rate, \
122 _nshift, _nwidth, \
123 _mshift, _mwidth, \
124 _frac_en, _frac_sel, \
125 _frac_rate_0, \
126 _frac_rate_1, \
127 _gate, _lock, _flags) \
128 struct ccu_nm _struct = { \
129 .enable = _gate, \
130 .lock = _lock, \
131 .n = _SUNXI_CCU_MULT(_nshift, _nwidth), \
132 .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
133 .frac = _SUNXI_CCU_FRAC(_frac_en, _frac_sel, \
134 _frac_rate_0, \
135 _frac_rate_1), \
136 .min_rate = _min_rate, \
137 .max_rate = _max_rate, \
138 .common = { \
139 .reg = _reg, \
140 .features = CCU_FEATURE_FRACTIONAL, \
141 .hw.init = CLK_HW_INIT(_name, \
142 _parent, \
143 &ccu_nm_ops, \
144 _flags), \
145 }, \
146 }
147
118#define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg, \ 148#define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg, \
119 _nshift, _nwidth, \ 149 _nshift, _nwidth, \
120 _mshift, _mwidth, \ 150 _mshift, _mwidth, \
diff --git a/include/dt-bindings/clock/sun50i-a64-ccu.h b/include/dt-bindings/clock/sun50i-a64-ccu.h
index d66432c6e675..a8ac4cfcdcbc 100644
--- a/include/dt-bindings/clock/sun50i-a64-ccu.h
+++ b/include/dt-bindings/clock/sun50i-a64-ccu.h
@@ -43,6 +43,7 @@
43#ifndef _DT_BINDINGS_CLK_SUN50I_A64_H_ 43#ifndef _DT_BINDINGS_CLK_SUN50I_A64_H_
44#define _DT_BINDINGS_CLK_SUN50I_A64_H_ 44#define _DT_BINDINGS_CLK_SUN50I_A64_H_
45 45
46#define CLK_PLL_VIDEO0 7
46#define CLK_PLL_PERIPH0 11 47#define CLK_PLL_PERIPH0 11
47 48
48#define CLK_BUS_MIPI_DSI 28 49#define CLK_BUS_MIPI_DSI 28