aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJerome Brunet <jbrunet@baylibre.com>2018-02-12 09:58:42 -0500
committerNeil Armstrong <narmstrong@baylibre.com>2018-03-13 05:04:03 -0400
commit722825dcd54b2e427c1aee54a7992eb4ab04a49d (patch)
tree5abe9c46643a0681d86e24f214816a8ffb911fa3
parent88a4e1283681e0f07048b2bd867cc81fbbae57cc (diff)
clk: meson: migrate plls clocks to clk_regmap
Rework meson pll driver to use clk_regmap and move meson8b, gxbb and axg's clock using meson_clk_pll to clk_regmap. This rework is not just about clk_regmap, there a serious clean-up of the driver code: * Add lock and reset field: Previously inferred from the n field. * Simplify the reset logic: Code seemed to apply reset differently but in fact it was always the same -> assert reset, apply params, de-assert reset. The 2 lock checking loops have been kept for now, as they seem to be necessary. * Do the sequence of init register pokes only at .init() instead of in .set_rate(). Redoing the init on every set_rate() is not necessary Signed-off-by: Jerome Brunet <jbrunet@baylibre.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
-rw-r--r--drivers/clk/meson/axg.c213
-rw-r--r--drivers/clk/meson/clk-pll.c243
-rw-r--r--drivers/clk/meson/clkc.h36
-rw-r--r--drivers/clk/meson/gxbb.c424
-rw-r--r--drivers/clk/meson/meson8b.c149
5 files changed, 535 insertions, 530 deletions
diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 85f9466ce006..8c27ceffda4a 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -22,28 +22,39 @@
22 22
23static DEFINE_SPINLOCK(meson_clk_lock); 23static DEFINE_SPINLOCK(meson_clk_lock);
24 24
25static struct meson_clk_pll axg_fixed_pll = { 25static struct clk_regmap axg_fixed_pll = {
26 .m = { 26 .data = &(struct meson_clk_pll_data){
27 .reg_off = HHI_MPLL_CNTL, 27 .m = {
28 .shift = 0, 28 .reg_off = HHI_MPLL_CNTL,
29 .width = 9, 29 .shift = 0,
30 }, 30 .width = 9,
31 .n = { 31 },
32 .reg_off = HHI_MPLL_CNTL, 32 .n = {
33 .shift = 9, 33 .reg_off = HHI_MPLL_CNTL,
34 .width = 5, 34 .shift = 9,
35 }, 35 .width = 5,
36 .od = { 36 },
37 .reg_off = HHI_MPLL_CNTL, 37 .od = {
38 .shift = 16, 38 .reg_off = HHI_MPLL_CNTL,
39 .width = 2, 39 .shift = 16,
40 }, 40 .width = 2,
41 .frac = { 41 },
42 .reg_off = HHI_MPLL_CNTL2, 42 .frac = {
43 .shift = 0, 43 .reg_off = HHI_MPLL_CNTL2,
44 .width = 12, 44 .shift = 0,
45 }, 45 .width = 12,
46 .lock = &meson_clk_lock, 46 },
47 .l = {
48 .reg_off = HHI_MPLL_CNTL,
49 .shift = 31,
50 .width = 1,
51 },
52 .rst = {
53 .reg_off = HHI_MPLL_CNTL,
54 .shift = 29,
55 .width = 1,
56 },
57 },
47 .hw.init = &(struct clk_init_data){ 58 .hw.init = &(struct clk_init_data){
48 .name = "fixed_pll", 59 .name = "fixed_pll",
49 .ops = &meson_clk_pll_ro_ops, 60 .ops = &meson_clk_pll_ro_ops,
@@ -52,23 +63,34 @@ static struct meson_clk_pll axg_fixed_pll = {
52 }, 63 },
53}; 64};
54 65
55static struct meson_clk_pll axg_sys_pll = { 66static struct clk_regmap axg_sys_pll = {
56 .m = { 67 .data = &(struct meson_clk_pll_data){
57 .reg_off = HHI_SYS_PLL_CNTL, 68 .m = {
58 .shift = 0, 69 .reg_off = HHI_SYS_PLL_CNTL,
59 .width = 9, 70 .shift = 0,
60 }, 71 .width = 9,
61 .n = { 72 },
62 .reg_off = HHI_SYS_PLL_CNTL, 73 .n = {
63 .shift = 9, 74 .reg_off = HHI_SYS_PLL_CNTL,
64 .width = 5, 75 .shift = 9,
65 }, 76 .width = 5,
66 .od = { 77 },
67 .reg_off = HHI_SYS_PLL_CNTL, 78 .od = {
68 .shift = 16, 79 .reg_off = HHI_SYS_PLL_CNTL,
69 .width = 2, 80 .shift = 16,
81 .width = 2,
82 },
83 .l = {
84 .reg_off = HHI_SYS_PLL_CNTL,
85 .shift = 31,
86 .width = 1,
87 },
88 .rst = {
89 .reg_off = HHI_SYS_PLL_CNTL,
90 .shift = 29,
91 .width = 1,
92 },
70 }, 93 },
71 .lock = &meson_clk_lock,
72 .hw.init = &(struct clk_init_data){ 94 .hw.init = &(struct clk_init_data){
73 .name = "sys_pll", 95 .name = "sys_pll",
74 .ops = &meson_clk_pll_ro_ops, 96 .ops = &meson_clk_pll_ro_ops,
@@ -169,40 +191,47 @@ static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
169 { /* sentinel */ }, 191 { /* sentinel */ },
170}; 192};
171 193
172static struct pll_params_table axg_gp0_params_table[] = { 194const struct reg_sequence axg_gp0_init_regs[] = {
173 PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250), 195 { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
174 PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000), 196 { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084a000 },
175 PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be), 197 { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be },
176 PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288), 198 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
177 PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d), 199 { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
178 PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000), 200 { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
179}; 201};
180 202
181static struct meson_clk_pll axg_gp0_pll = { 203static struct clk_regmap axg_gp0_pll = {
182 .m = { 204 .data = &(struct meson_clk_pll_data){
183 .reg_off = HHI_GP0_PLL_CNTL, 205 .m = {
184 .shift = 0, 206 .reg_off = HHI_GP0_PLL_CNTL,
185 .width = 9, 207 .shift = 0,
186 }, 208 .width = 9,
187 .n = { 209 },
188 .reg_off = HHI_GP0_PLL_CNTL, 210 .n = {
189 .shift = 9, 211 .reg_off = HHI_GP0_PLL_CNTL,
190 .width = 5, 212 .shift = 9,
191 }, 213 .width = 5,
192 .od = { 214 },
193 .reg_off = HHI_GP0_PLL_CNTL, 215 .od = {
194 .shift = 16, 216 .reg_off = HHI_GP0_PLL_CNTL,
195 .width = 2, 217 .shift = 16,
196 }, 218 .width = 2,
197 .params = { 219 },
198 .params_table = axg_gp0_params_table, 220 .l = {
199 .params_count = ARRAY_SIZE(axg_gp0_params_table), 221 .reg_off = HHI_GP0_PLL_CNTL,
200 .no_init_reset = true, 222 .shift = 31,
201 .reset_lock_loop = true, 223 .width = 1,
202 }, 224 },
203 .rate_table = axg_gp0_pll_rate_table, 225 .rst = {
204 .rate_count = ARRAY_SIZE(axg_gp0_pll_rate_table), 226 .reg_off = HHI_GP0_PLL_CNTL,
205 .lock = &meson_clk_lock, 227 .shift = 29,
228 .width = 1,
229 },
230 .table = axg_gp0_pll_rate_table,
231 .init_regs = axg_gp0_init_regs,
232 .init_count = ARRAY_SIZE(axg_gp0_init_regs),
233 .flags = CLK_MESON_PLL_LOCK_LOOP_RST,
234 },
206 .hw.init = &(struct clk_init_data){ 235 .hw.init = &(struct clk_init_data){
207 .name = "gp0_pll", 236 .name = "gp0_pll",
208 .ops = &meson_clk_pll_ops, 237 .ops = &meson_clk_pll_ops,
@@ -698,14 +727,7 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
698 .num = NR_CLKS, 727 .num = NR_CLKS,
699}; 728};
700 729
701/* Convenience tables to populate base addresses in .probe */ 730/* Convenience table to populate regmap in .probe */
702
703static struct meson_clk_pll *const axg_clk_plls[] = {
704 &axg_fixed_pll,
705 &axg_sys_pll,
706 &axg_gp0_pll,
707};
708
709static struct clk_regmap *const axg_clk_regmaps[] = { 731static struct clk_regmap *const axg_clk_regmaps[] = {
710 &axg_clk81, 732 &axg_clk81,
711 &axg_ddr, 733 &axg_ddr,
@@ -764,22 +786,13 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
764 &axg_mpll1, 786 &axg_mpll1,
765 &axg_mpll2, 787 &axg_mpll2,
766 &axg_mpll3, 788 &axg_mpll3,
767}; 789 &axg_fixed_pll,
768 790 &axg_sys_pll,
769struct clkc_data { 791 &axg_gp0_pll,
770 struct meson_clk_pll *const *clk_plls;
771 unsigned int clk_plls_count;
772 struct clk_hw_onecell_data *hw_onecell_data;
773};
774
775static const struct clkc_data axg_clkc_data = {
776 .clk_plls = axg_clk_plls,
777 .clk_plls_count = ARRAY_SIZE(axg_clk_plls),
778 .hw_onecell_data = &axg_hw_onecell_data,
779}; 792};
780 793
781static const struct of_device_id clkc_match_table[] = { 794static const struct of_device_id clkc_match_table[] = {
782 { .compatible = "amlogic,axg-clkc", .data = &axg_clkc_data }, 795 { .compatible = "amlogic,axg-clkc" },
783 {} 796 {}
784}; 797};
785 798
@@ -792,16 +805,11 @@ static const struct regmap_config clkc_regmap_config = {
792static int axg_clkc_probe(struct platform_device *pdev) 805static int axg_clkc_probe(struct platform_device *pdev)
793{ 806{
794 struct device *dev = &pdev->dev; 807 struct device *dev = &pdev->dev;
795 const struct clkc_data *clkc_data;
796 struct resource *res; 808 struct resource *res;
797 void __iomem *clk_base; 809 void __iomem *clk_base;
798 struct regmap *map; 810 struct regmap *map;
799 int ret, i; 811 int ret, i;
800 812
801 clkc_data = of_device_get_match_data(dev);
802 if (!clkc_data)
803 return -EINVAL;
804
805 /* Generic clocks and PLLs */ 813 /* Generic clocks and PLLs */
806 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 814 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
807 if (!res) 815 if (!res)
@@ -817,21 +825,16 @@ static int axg_clkc_probe(struct platform_device *pdev)
817 if (IS_ERR(map)) 825 if (IS_ERR(map))
818 return PTR_ERR(map); 826 return PTR_ERR(map);
819 827
820 /* Populate base address for PLLs */
821 for (i = 0; i < clkc_data->clk_plls_count; i++)
822 clkc_data->clk_plls[i]->base = clk_base;
823
824 /* Populate regmap for the regmap backed clocks */ 828 /* Populate regmap for the regmap backed clocks */
825 for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++) 829 for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++)
826 axg_clk_regmaps[i]->map = map; 830 axg_clk_regmaps[i]->map = map;
827 831
828 for (i = 0; i < clkc_data->hw_onecell_data->num; i++) { 832 for (i = 0; i < axg_hw_onecell_data.num; i++) {
829 /* array might be sparse */ 833 /* array might be sparse */
830 if (!clkc_data->hw_onecell_data->hws[i]) 834 if (!axg_hw_onecell_data.hws[i])
831 continue; 835 continue;
832 836
833 ret = devm_clk_hw_register(dev, 837 ret = devm_clk_hw_register(dev, axg_hw_onecell_data.hws[i]);
834 clkc_data->hw_onecell_data->hws[i]);
835 if (ret) { 838 if (ret) {
836 dev_err(dev, "Clock registration failed\n"); 839 dev_err(dev, "Clock registration failed\n");
837 return ret; 840 return ret;
@@ -839,7 +842,7 @@ static int axg_clkc_probe(struct platform_device *pdev)
839 } 842 }
840 843
841 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, 844 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
842 clkc_data->hw_onecell_data); 845 &axg_hw_onecell_data);
843} 846}
844 847
845static struct platform_driver axg_driver = { 848static struct platform_driver axg_driver = {
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 218c769c6d50..f3d909719111 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -42,52 +42,36 @@
42 42
43#include "clkc.h" 43#include "clkc.h"
44 44
45#define MESON_PLL_RESET BIT(29) 45static inline struct meson_clk_pll_data *
46#define MESON_PLL_LOCK BIT(31) 46meson_clk_pll_data(struct clk_regmap *clk)
47 47{
48#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) 48 return (struct meson_clk_pll_data *)clk->data;
49}
49 50
50static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, 51static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
51 unsigned long parent_rate) 52 unsigned long parent_rate)
52{ 53{
53 struct meson_clk_pll *pll = to_meson_clk_pll(hw); 54 struct clk_regmap *clk = to_clk_regmap(hw);
54 struct parm *p; 55 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
55 u64 rate; 56 u64 rate;
56 u16 n, m, frac = 0, od, od2 = 0, od3 = 0; 57 u16 n, m, frac = 0, od, od2 = 0, od3 = 0;
57 u32 reg;
58
59 p = &pll->n;
60 reg = readl(pll->base + p->reg_off);
61 n = PARM_GET(p->width, p->shift, reg);
62 58
63 p = &pll->m; 59 n = meson_parm_read(clk->map, &pll->n);
64 reg = readl(pll->base + p->reg_off); 60 m = meson_parm_read(clk->map, &pll->m);
65 m = PARM_GET(p->width, p->shift, reg); 61 od = meson_parm_read(clk->map, &pll->od);
66 62
67 p = &pll->od; 63 if (MESON_PARM_APPLICABLE(&pll->od2))
68 reg = readl(pll->base + p->reg_off); 64 od2 = meson_parm_read(clk->map, &pll->od2);
69 od = PARM_GET(p->width, p->shift, reg);
70 65
71 p = &pll->od2; 66 if (MESON_PARM_APPLICABLE(&pll->od3))
72 if (p->width) { 67 od3 = meson_parm_read(clk->map, &pll->od3);
73 reg = readl(pll->base + p->reg_off);
74 od2 = PARM_GET(p->width, p->shift, reg);
75 }
76
77 p = &pll->od3;
78 if (p->width) {
79 reg = readl(pll->base + p->reg_off);
80 od3 = PARM_GET(p->width, p->shift, reg);
81 }
82 68
83 rate = (u64)m * parent_rate; 69 rate = (u64)m * parent_rate;
84 70
85 p = &pll->frac; 71 if (MESON_PARM_APPLICABLE(&pll->frac)) {
86 if (p->width) { 72 frac = meson_parm_read(clk->map, &pll->frac);
87 reg = readl(pll->base + p->reg_off);
88 frac = PARM_GET(p->width, p->shift, reg);
89 73
90 rate += mul_u64_u32_shr(parent_rate, frac, p->width); 74 rate += mul_u64_u32_shr(parent_rate, frac, pll->frac.width);
91 } 75 }
92 76
93 return div_u64(rate, n) >> od >> od2 >> od3; 77 return div_u64(rate, n) >> od >> od2 >> od3;
@@ -96,177 +80,136 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
96static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, 80static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
97 unsigned long *parent_rate) 81 unsigned long *parent_rate)
98{ 82{
99 struct meson_clk_pll *pll = to_meson_clk_pll(hw); 83 struct clk_regmap *clk = to_clk_regmap(hw);
100 const struct pll_rate_table *rate_table = pll->rate_table; 84 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
101 int i; 85 const struct pll_rate_table *pllt;
102 86
103 /* 87 /*
104 * if the table is missing, just return the current rate 88 * if the table is missing, just return the current rate
105 * since we don't have the other available frequencies 89 * since we don't have the other available frequencies
106 */ 90 */
107 if (!rate_table) 91 if (!pll->table)
108 return meson_clk_pll_recalc_rate(hw, *parent_rate); 92 return meson_clk_pll_recalc_rate(hw, *parent_rate);
109 93
110 for (i = 0; i < pll->rate_count; i++) { 94 for (pllt = pll->table; pllt->rate; pllt++) {
111 if (rate <= rate_table[i].rate) 95 if (rate <= pllt->rate)
112 return rate_table[i].rate; 96 return pllt->rate;
113 } 97 }
114 98
115 /* else return the smallest value */ 99 /* else return the smallest value */
116 return rate_table[0].rate; 100 return pll->table[0].rate;
117} 101}
118 102
119static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_pll *pll, 103static const struct pll_rate_table *
120 unsigned long rate) 104meson_clk_get_pll_settings(const struct pll_rate_table *table,
105 unsigned long rate)
121{ 106{
122 const struct pll_rate_table *rate_table = pll->rate_table; 107 const struct pll_rate_table *pllt;
123 int i;
124 108
125 if (!rate_table) 109 if (!table)
126 return NULL; 110 return NULL;
127 111
128 for (i = 0; i < pll->rate_count; i++) { 112 for (pllt = table; pllt->rate; pllt++) {
129 if (rate == rate_table[i].rate) 113 if (rate == pllt->rate)
130 return &rate_table[i]; 114 return pllt;
131 } 115 }
116
132 return NULL; 117 return NULL;
133} 118}
134 119
135/* Specific wait loop for GXL/GXM GP0 PLL */ 120static int meson_clk_pll_wait_lock(struct clk_hw *hw)
136static int meson_clk_pll_wait_lock_reset(struct meson_clk_pll *pll,
137 struct parm *p_n)
138{ 121{
139 int delay = 100; 122 struct clk_regmap *clk = to_clk_regmap(hw);
140 u32 reg; 123 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
141 124 int delay = pll->flags & CLK_MESON_PLL_LOCK_LOOP_RST ?
142 while (delay > 0) { 125 100 : 24000000;
143 reg = readl(pll->base + p_n->reg_off); 126
144 writel(reg | MESON_PLL_RESET, pll->base + p_n->reg_off); 127 do {
145 udelay(10); 128 /* Specific wait loop for GXL/GXM GP0 PLL */
146 writel(reg & ~MESON_PLL_RESET, pll->base + p_n->reg_off); 129 if (pll->flags & CLK_MESON_PLL_LOCK_LOOP_RST) {
147 130 /* Procedure taken from the vendor kernel */
148 /* This delay comes from AMLogic tree clk-gp0-gxl driver */ 131 meson_parm_write(clk->map, &pll->rst, 1);
149 mdelay(1); 132 udelay(10);
150 133 meson_parm_write(clk->map, &pll->rst, 0);
151 reg = readl(pll->base + p_n->reg_off); 134 mdelay(1);
152 if (reg & MESON_PLL_LOCK) 135 }
136
137 /* Is the clock locked now ? */
138 if (meson_parm_read(clk->map, &pll->l))
153 return 0; 139 return 0;
154 delay--;
155 }
156 return -ETIMEDOUT;
157}
158 140
159static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
160 struct parm *p_n)
161{
162 int delay = 24000000;
163 u32 reg;
164
165 while (delay > 0) {
166 reg = readl(pll->base + p_n->reg_off);
167
168 if (reg & MESON_PLL_LOCK)
169 return 0;
170 delay--; 141 delay--;
171 } 142 } while (delay > 0);
143
172 return -ETIMEDOUT; 144 return -ETIMEDOUT;
173} 145}
174 146
175static void meson_clk_pll_init_params(struct meson_clk_pll *pll) 147static void meson_clk_pll_init(struct clk_hw *hw)
176{ 148{
177 int i; 149 struct clk_regmap *clk = to_clk_regmap(hw);
178 150 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
179 for (i = 0 ; i < pll->params.params_count ; ++i) 151
180 writel(pll->params.params_table[i].value, 152 if (pll->init_count) {
181 pll->base + pll->params.params_table[i].reg_off); 153 meson_parm_write(clk->map, &pll->rst, 1);
154 regmap_multi_reg_write(clk->map, pll->init_regs,
155 pll->init_count);
156 meson_parm_write(clk->map, &pll->rst, 0);
157 }
182} 158}
183 159
184static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, 160static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
185 unsigned long parent_rate) 161 unsigned long parent_rate)
186{ 162{
187 struct meson_clk_pll *pll = to_meson_clk_pll(hw); 163 struct clk_regmap *clk = to_clk_regmap(hw);
188 struct parm *p; 164 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
189 const struct pll_rate_table *rate_set; 165 const struct pll_rate_table *pllt;
190 unsigned long old_rate; 166 unsigned long old_rate;
191 int ret = 0;
192 u32 reg;
193 167
194 if (parent_rate == 0 || rate == 0) 168 if (parent_rate == 0 || rate == 0)
195 return -EINVAL; 169 return -EINVAL;
196 170
197 old_rate = rate; 171 old_rate = rate;
198 172
199 rate_set = meson_clk_get_pll_settings(pll, rate); 173 pllt = meson_clk_get_pll_settings(pll->table, rate);
200 if (!rate_set) 174 if (!pllt)
201 return -EINVAL; 175 return -EINVAL;
202 176
203 /* Initialize the PLL in a clean state if specified */ 177 /* Put the pll in reset to write the params */
204 if (pll->params.params_count) 178 meson_parm_write(clk->map, &pll->rst, 1);
205 meson_clk_pll_init_params(pll);
206
207 /* PLL reset */
208 p = &pll->n;
209 reg = readl(pll->base + p->reg_off);
210 /* If no_init_reset is provided, avoid resetting at this point */
211 if (!pll->params.no_init_reset)
212 writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
213
214 reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
215 writel(reg, pll->base + p->reg_off);
216
217 p = &pll->m;
218 reg = readl(pll->base + p->reg_off);
219 reg = PARM_SET(p->width, p->shift, reg, rate_set->m);
220 writel(reg, pll->base + p->reg_off);
221
222 p = &pll->od;
223 reg = readl(pll->base + p->reg_off);
224 reg = PARM_SET(p->width, p->shift, reg, rate_set->od);
225 writel(reg, pll->base + p->reg_off);
226
227 p = &pll->od2;
228 if (p->width) {
229 reg = readl(pll->base + p->reg_off);
230 reg = PARM_SET(p->width, p->shift, reg, rate_set->od2);
231 writel(reg, pll->base + p->reg_off);
232 }
233 179
234 p = &pll->od3; 180 meson_parm_write(clk->map, &pll->n, pllt->n);
235 if (p->width) { 181 meson_parm_write(clk->map, &pll->m, pllt->m);
236 reg = readl(pll->base + p->reg_off); 182 meson_parm_write(clk->map, &pll->od, pllt->od);
237 reg = PARM_SET(p->width, p->shift, reg, rate_set->od3);
238 writel(reg, pll->base + p->reg_off);
239 }
240 183
241 p = &pll->frac; 184 if (MESON_PARM_APPLICABLE(&pll->od2))
242 if (p->width) { 185 meson_parm_write(clk->map, &pll->od2, pllt->od2);
243 reg = readl(pll->base + p->reg_off);
244 reg = PARM_SET(p->width, p->shift, reg, rate_set->frac);
245 writel(reg, pll->base + p->reg_off);
246 }
247 186
248 p = &pll->n; 187 if (MESON_PARM_APPLICABLE(&pll->od3))
249 /* If clear_reset_for_lock is provided, remove the reset bit here */ 188 meson_parm_write(clk->map, &pll->od3, pllt->od3);
250 if (pll->params.clear_reset_for_lock) { 189
251 reg = readl(pll->base + p->reg_off); 190 if (MESON_PARM_APPLICABLE(&pll->frac))
252 writel(reg & ~MESON_PLL_RESET, pll->base + p->reg_off); 191 meson_parm_write(clk->map, &pll->frac, pllt->frac);
253 } 192
193 /* make sure the reset is cleared at this point */
194 meson_parm_write(clk->map, &pll->rst, 0);
254 195
255 /* If reset_lock_loop, use a special loop including resetting */ 196 if (meson_clk_pll_wait_lock(hw)) {
256 if (pll->params.reset_lock_loop)
257 ret = meson_clk_pll_wait_lock_reset(pll, p);
258 else
259 ret = meson_clk_pll_wait_lock(pll, p);
260 if (ret) {
261 pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", 197 pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
262 __func__, old_rate); 198 __func__, old_rate);
199 /*
200 * FIXME: Do we really need/want this HACK ?
201 * It looks unsafe. what happens if the clock gets into a
202 * broken state and we can't lock back on the old_rate ? Looks
203 * like an infinite recursion is possible
204 */
263 meson_clk_pll_set_rate(hw, old_rate, parent_rate); 205 meson_clk_pll_set_rate(hw, old_rate, parent_rate);
264 } 206 }
265 207
266 return ret; 208 return 0;
267} 209}
268 210
269const struct clk_ops meson_clk_pll_ops = { 211const struct clk_ops meson_clk_pll_ops = {
212 .init = meson_clk_pll_init,
270 .recalc_rate = meson_clk_pll_recalc_rate, 213 .recalc_rate = meson_clk_pll_recalc_rate,
271 .round_rate = meson_clk_pll_round_rate, 214 .round_rate = meson_clk_pll_round_rate,
272 .set_rate = meson_clk_pll_set_rate, 215 .set_rate = meson_clk_pll_set_rate,
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index a4a526cbca4c..f0d70eaffcf3 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -82,41 +82,21 @@ struct pll_rate_table {
82 .frac = (_frac), \ 82 .frac = (_frac), \
83 } \ 83 } \
84 84
85struct pll_params_table { 85#define CLK_MESON_PLL_LOCK_LOOP_RST BIT(0)
86 unsigned int reg_off;
87 unsigned int value;
88};
89
90#define PLL_PARAM(_reg, _val) \
91 { \
92 .reg_off = (_reg), \
93 .value = (_val), \
94 }
95
96struct pll_setup_params {
97 struct pll_params_table *params_table;
98 unsigned int params_count;
99 /* Workaround for GP0, do not reset before configuring */
100 bool no_init_reset;
101 /* Workaround for GP0, unreset right before checking for lock */
102 bool clear_reset_for_lock;
103 /* Workaround for GXL GP0, reset in the lock checking loop */
104 bool reset_lock_loop;
105};
106 86
107struct meson_clk_pll { 87struct meson_clk_pll_data {
108 struct clk_hw hw;
109 void __iomem *base;
110 struct parm m; 88 struct parm m;
111 struct parm n; 89 struct parm n;
112 struct parm frac; 90 struct parm frac;
113 struct parm od; 91 struct parm od;
114 struct parm od2; 92 struct parm od2;
115 struct parm od3; 93 struct parm od3;
116 const struct pll_setup_params params; 94 struct parm l;
117 const struct pll_rate_table *rate_table; 95 struct parm rst;
118 unsigned int rate_count; 96 const struct reg_sequence *init_regs;
119 spinlock_t *lock; 97 unsigned int init_count;
98 const struct pll_rate_table *table;
99 u8 flags;
120}; 100};
121 101
122#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) 102#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 196557f11608..49f5716ce8b6 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -188,28 +188,39 @@ static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
188 { /* sentinel */ }, 188 { /* sentinel */ },
189}; 189};
190 190
191static struct meson_clk_pll gxbb_fixed_pll = { 191static struct clk_regmap gxbb_fixed_pll = {
192 .m = { 192 .data = &(struct meson_clk_pll_data){
193 .reg_off = HHI_MPLL_CNTL, 193 .m = {
194 .shift = 0, 194 .reg_off = HHI_MPLL_CNTL,
195 .width = 9, 195 .shift = 0,
196 }, 196 .width = 9,
197 .n = { 197 },
198 .reg_off = HHI_MPLL_CNTL, 198 .n = {
199 .shift = 9, 199 .reg_off = HHI_MPLL_CNTL,
200 .width = 5, 200 .shift = 9,
201 }, 201 .width = 5,
202 .od = { 202 },
203 .reg_off = HHI_MPLL_CNTL, 203 .od = {
204 .shift = 16, 204 .reg_off = HHI_MPLL_CNTL,
205 .width = 2, 205 .shift = 16,
206 }, 206 .width = 2,
207 .frac = { 207 },
208 .reg_off = HHI_MPLL_CNTL2, 208 .frac = {
209 .shift = 0, 209 .reg_off = HHI_MPLL_CNTL2,
210 .width = 12, 210 .shift = 0,
211 }, 211 .width = 12,
212 .lock = &meson_clk_lock, 212 },
213 .l = {
214 .reg_off = HHI_MPLL_CNTL,
215 .shift = 31,
216 .width = 1,
217 },
218 .rst = {
219 .reg_off = HHI_MPLL_CNTL,
220 .shift = 29,
221 .width = 1,
222 },
223 },
213 .hw.init = &(struct clk_init_data){ 224 .hw.init = &(struct clk_init_data){
214 .name = "fixed_pll", 225 .name = "fixed_pll",
215 .ops = &meson_clk_pll_ro_ops, 226 .ops = &meson_clk_pll_ro_ops,
@@ -230,38 +241,49 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
230 }, 241 },
231}; 242};
232 243
233static struct meson_clk_pll gxbb_hdmi_pll = { 244static struct clk_regmap gxbb_hdmi_pll = {
234 .m = { 245 .data = &(struct meson_clk_pll_data){
235 .reg_off = HHI_HDMI_PLL_CNTL, 246 .m = {
236 .shift = 0, 247 .reg_off = HHI_HDMI_PLL_CNTL,
237 .width = 9, 248 .shift = 0,
238 }, 249 .width = 9,
239 .n = { 250 },
240 .reg_off = HHI_HDMI_PLL_CNTL, 251 .n = {
241 .shift = 9, 252 .reg_off = HHI_HDMI_PLL_CNTL,
242 .width = 5, 253 .shift = 9,
243 }, 254 .width = 5,
244 .frac = { 255 },
245 .reg_off = HHI_HDMI_PLL_CNTL2, 256 .frac = {
246 .shift = 0, 257 .reg_off = HHI_HDMI_PLL_CNTL2,
247 .width = 12, 258 .shift = 0,
248 }, 259 .width = 12,
249 .od = { 260 },
250 .reg_off = HHI_HDMI_PLL_CNTL2, 261 .od = {
251 .shift = 16, 262 .reg_off = HHI_HDMI_PLL_CNTL2,
252 .width = 2, 263 .shift = 16,
253 }, 264 .width = 2,
254 .od2 = { 265 },
255 .reg_off = HHI_HDMI_PLL_CNTL2, 266 .od2 = {
256 .shift = 22, 267 .reg_off = HHI_HDMI_PLL_CNTL2,
257 .width = 2, 268 .shift = 22,
258 }, 269 .width = 2,
259 .od3 = { 270 },
260 .reg_off = HHI_HDMI_PLL_CNTL2, 271 .od3 = {
261 .shift = 18, 272 .reg_off = HHI_HDMI_PLL_CNTL2,
262 .width = 2, 273 .shift = 18,
274 .width = 2,
275 },
276 .l = {
277 .reg_off = HHI_HDMI_PLL_CNTL,
278 .shift = 31,
279 .width = 1,
280 },
281 .rst = {
282 .reg_off = HHI_HDMI_PLL_CNTL,
283 .shift = 28,
284 .width = 1,
285 },
263 }, 286 },
264 .lock = &meson_clk_lock,
265 .hw.init = &(struct clk_init_data){ 287 .hw.init = &(struct clk_init_data){
266 .name = "hdmi_pll", 288 .name = "hdmi_pll",
267 .ops = &meson_clk_pll_ro_ops, 289 .ops = &meson_clk_pll_ro_ops,
@@ -271,43 +293,55 @@ static struct meson_clk_pll gxbb_hdmi_pll = {
271 }, 293 },
272}; 294};
273 295
274static struct meson_clk_pll gxl_hdmi_pll = { 296static struct clk_regmap gxl_hdmi_pll = {
275 .m = { 297 .data = &(struct meson_clk_pll_data){
276 .reg_off = HHI_HDMI_PLL_CNTL, 298 .m = {
277 .shift = 0, 299 .reg_off = HHI_HDMI_PLL_CNTL,
278 .width = 9, 300 .shift = 0,
279 }, 301 .width = 9,
280 .n = { 302 },
281 .reg_off = HHI_HDMI_PLL_CNTL, 303 .n = {
282 .shift = 9, 304 .reg_off = HHI_HDMI_PLL_CNTL,
283 .width = 5, 305 .shift = 9,
306 .width = 5,
307 },
308 .frac = {
309 /*
310 * On gxl, there is a register shift due to
311 * HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
312 * so we compute the register offset based on the PLL
313 * base to get it right
314 */
315 .reg_off = HHI_HDMI_PLL_CNTL + 4,
316 .shift = 0,
317 .width = 12,
318 },
319 .od = {
320 .reg_off = HHI_HDMI_PLL_CNTL + 8,
321 .shift = 21,
322 .width = 2,
323 },
324 .od2 = {
325 .reg_off = HHI_HDMI_PLL_CNTL + 8,
326 .shift = 23,
327 .width = 2,
328 },
329 .od3 = {
330 .reg_off = HHI_HDMI_PLL_CNTL + 8,
331 .shift = 19,
332 .width = 2,
333 },
334 .l = {
335 .reg_off = HHI_HDMI_PLL_CNTL,
336 .shift = 31,
337 .width = 1,
338 },
339 .rst = {
340 .reg_off = HHI_HDMI_PLL_CNTL,
341 .shift = 29,
342 .width = 1,
343 },
284 }, 344 },
285 .frac = {
286 /*
287 * On gxl, there is a register shift due to HHI_HDMI_PLL_CNTL1
288 * which does not exist on gxbb, so we compute the register
289 * offset based on the PLL base to get it right
290 */
291 .reg_off = HHI_HDMI_PLL_CNTL + 4,
292 .shift = 0,
293 .width = 12,
294 },
295 .od = {
296 .reg_off = HHI_HDMI_PLL_CNTL + 8,
297 .shift = 21,
298 .width = 2,
299 },
300 .od2 = {
301 .reg_off = HHI_HDMI_PLL_CNTL + 8,
302 .shift = 23,
303 .width = 2,
304 },
305 .od3 = {
306 .reg_off = HHI_HDMI_PLL_CNTL + 8,
307 .shift = 19,
308 .width = 2,
309 },
310 .lock = &meson_clk_lock,
311 .hw.init = &(struct clk_init_data){ 345 .hw.init = &(struct clk_init_data){
312 .name = "hdmi_pll", 346 .name = "hdmi_pll",
313 .ops = &meson_clk_pll_ro_ops, 347 .ops = &meson_clk_pll_ro_ops,
@@ -317,23 +351,34 @@ static struct meson_clk_pll gxl_hdmi_pll = {
317 }, 351 },
318}; 352};
319 353
320static struct meson_clk_pll gxbb_sys_pll = { 354static struct clk_regmap gxbb_sys_pll = {
321 .m = { 355 .data = &(struct meson_clk_pll_data){
322 .reg_off = HHI_SYS_PLL_CNTL, 356 .m = {
323 .shift = 0, 357 .reg_off = HHI_SYS_PLL_CNTL,
324 .width = 9, 358 .shift = 0,
325 }, 359 .width = 9,
326 .n = { 360 },
327 .reg_off = HHI_SYS_PLL_CNTL, 361 .n = {
328 .shift = 9, 362 .reg_off = HHI_SYS_PLL_CNTL,
329 .width = 5, 363 .shift = 9,
330 }, 364 .width = 5,
331 .od = { 365 },
332 .reg_off = HHI_SYS_PLL_CNTL, 366 .od = {
333 .shift = 10, 367 .reg_off = HHI_SYS_PLL_CNTL,
334 .width = 2, 368 .shift = 10,
369 .width = 2,
370 },
371 .l = {
372 .reg_off = HHI_SYS_PLL_CNTL,
373 .shift = 31,
374 .width = 1,
375 },
376 .rst = {
377 .reg_off = HHI_SYS_PLL_CNTL,
378 .shift = 29,
379 .width = 1,
380 },
335 }, 381 },
336 .lock = &meson_clk_lock,
337 .hw.init = &(struct clk_init_data){ 382 .hw.init = &(struct clk_init_data){
338 .name = "sys_pll", 383 .name = "sys_pll",
339 .ops = &meson_clk_pll_ro_ops, 384 .ops = &meson_clk_pll_ro_ops,
@@ -343,38 +388,44 @@ static struct meson_clk_pll gxbb_sys_pll = {
343 }, 388 },
344}; 389};
345 390
346struct pll_params_table gxbb_gp0_params_table[] = { 391const struct reg_sequence gxbb_gp0_init_regs[] = {
347 PLL_PARAM(HHI_GP0_PLL_CNTL, 0x6a000228), 392 { .reg = HHI_GP0_PLL_CNTL, .def = 0x6a000228 },
348 PLL_PARAM(HHI_GP0_PLL_CNTL2, 0x69c80000), 393 { .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 },
349 PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a5590c4), 394 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 },
350 PLL_PARAM(HHI_GP0_PLL_CNTL4, 0x0000500d), 395 { .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d },
351}; 396};
352 397
353static struct meson_clk_pll gxbb_gp0_pll = { 398static struct clk_regmap gxbb_gp0_pll = {
354 .m = { 399 .data = &(struct meson_clk_pll_data){
355 .reg_off = HHI_GP0_PLL_CNTL, 400 .m = {
356 .shift = 0, 401 .reg_off = HHI_GP0_PLL_CNTL,
357 .width = 9, 402 .shift = 0,
358 }, 403 .width = 9,
359 .n = { 404 },
360 .reg_off = HHI_GP0_PLL_CNTL, 405 .n = {
361 .shift = 9, 406 .reg_off = HHI_GP0_PLL_CNTL,
362 .width = 5, 407 .shift = 9,
363 }, 408 .width = 5,
364 .od = { 409 },
365 .reg_off = HHI_GP0_PLL_CNTL, 410 .od = {
366 .shift = 16, 411 .reg_off = HHI_GP0_PLL_CNTL,
367 .width = 2, 412 .shift = 16,
368 }, 413 .width = 2,
369 .params = { 414 },
370 .params_table = gxbb_gp0_params_table, 415 .l = {
371 .params_count = ARRAY_SIZE(gxbb_gp0_params_table), 416 .reg_off = HHI_GP0_PLL_CNTL,
372 .no_init_reset = true, 417 .shift = 31,
373 .clear_reset_for_lock = true, 418 .width = 1,
419 },
420 .rst = {
421 .reg_off = HHI_GP0_PLL_CNTL,
422 .shift = 29,
423 .width = 1,
424 },
425 .table = gxbb_gp0_pll_rate_table,
426 .init_regs = gxbb_gp0_init_regs,
427 .init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
374 }, 428 },
375 .rate_table = gxbb_gp0_pll_rate_table,
376 .rate_count = ARRAY_SIZE(gxbb_gp0_pll_rate_table),
377 .lock = &meson_clk_lock,
378 .hw.init = &(struct clk_init_data){ 429 .hw.init = &(struct clk_init_data){
379 .name = "gp0_pll", 430 .name = "gp0_pll",
380 .ops = &meson_clk_pll_ops, 431 .ops = &meson_clk_pll_ops,
@@ -384,40 +435,47 @@ static struct meson_clk_pll gxbb_gp0_pll = {
384 }, 435 },
385}; 436};
386 437
387struct pll_params_table gxl_gp0_params_table[] = { 438const struct reg_sequence gxl_gp0_init_regs[] = {
388 PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250), 439 { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
389 PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000), 440 { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084a000 },
390 PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be), 441 { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be },
391 PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288), 442 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
392 PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d), 443 { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
393 PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000), 444 { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
394}; 445};
395 446
396static struct meson_clk_pll gxl_gp0_pll = { 447static struct clk_regmap gxl_gp0_pll = {
397 .m = { 448 .data = &(struct meson_clk_pll_data){
398 .reg_off = HHI_GP0_PLL_CNTL, 449 .m = {
399 .shift = 0, 450 .reg_off = HHI_GP0_PLL_CNTL,
400 .width = 9, 451 .shift = 0,
401 }, 452 .width = 9,
402 .n = { 453 },
403 .reg_off = HHI_GP0_PLL_CNTL, 454 .n = {
404 .shift = 9, 455 .reg_off = HHI_GP0_PLL_CNTL,
405 .width = 5, 456 .shift = 9,
406 }, 457 .width = 5,
407 .od = { 458 },
408 .reg_off = HHI_GP0_PLL_CNTL, 459 .od = {
409 .shift = 16, 460 .reg_off = HHI_GP0_PLL_CNTL,
410 .width = 2, 461 .shift = 16,
411 }, 462 .width = 2,
412 .params = { 463 },
413 .params_table = gxl_gp0_params_table, 464 .l = {
414 .params_count = ARRAY_SIZE(gxl_gp0_params_table), 465 .reg_off = HHI_GP0_PLL_CNTL,
415 .no_init_reset = true, 466 .shift = 31,
416 .reset_lock_loop = true, 467 .width = 1,
468 },
469 .rst = {
470 .reg_off = HHI_GP0_PLL_CNTL,
471 .shift = 29,
472 .width = 1,
473 },
474 .table = gxl_gp0_pll_rate_table,
475 .init_regs = gxl_gp0_init_regs,
476 .init_count = ARRAY_SIZE(gxl_gp0_init_regs),
477 .flags = CLK_MESON_PLL_LOCK_LOOP_RST,
417 }, 478 },
418 .rate_table = gxl_gp0_pll_rate_table,
419 .rate_count = ARRAY_SIZE(gxl_gp0_pll_rate_table),
420 .lock = &meson_clk_lock,
421 .hw.init = &(struct clk_init_data){ 479 .hw.init = &(struct clk_init_data){
422 .name = "gp0_pll", 480 .name = "gp0_pll",
423 .ops = &meson_clk_pll_ops, 481 .ops = &meson_clk_pll_ops,
@@ -1762,20 +1820,14 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
1762 .num = NR_CLKS, 1820 .num = NR_CLKS,
1763}; 1821};
1764 1822
1765/* Convenience tables to populate base addresses in .probe */ 1823static struct clk_regmap *const gxbb_clk_regmaps[] = {
1766
1767static struct meson_clk_pll *const gxbb_clk_plls[] = {
1768 &gxbb_fixed_pll,
1769 &gxbb_hdmi_pll,
1770 &gxbb_sys_pll,
1771 &gxbb_gp0_pll, 1824 &gxbb_gp0_pll,
1825 &gxbb_hdmi_pll,
1772}; 1826};
1773 1827
1774static struct meson_clk_pll *const gxl_clk_plls[] = { 1828static struct clk_regmap *const gxl_clk_regmaps[] = {
1775 &gxbb_fixed_pll,
1776 &gxl_hdmi_pll,
1777 &gxbb_sys_pll,
1778 &gxl_gp0_pll, 1829 &gxl_gp0_pll,
1830 &gxl_hdmi_pll,
1779}; 1831};
1780 1832
1781static struct clk_regmap *const gx_clk_regmaps[] = { 1833static struct clk_regmap *const gx_clk_regmaps[] = {
@@ -1910,23 +1962,25 @@ static struct clk_regmap *const gx_clk_regmaps[] = {
1910 &gxbb_mpll1, 1962 &gxbb_mpll1,
1911 &gxbb_mpll2, 1963 &gxbb_mpll2,
1912 &gxbb_cts_amclk_div, 1964 &gxbb_cts_amclk_div,
1965 &gxbb_fixed_pll,
1966 &gxbb_sys_pll,
1913}; 1967};
1914 1968
1915struct clkc_data { 1969struct clkc_data {
1916 struct meson_clk_pll *const *clk_plls; 1970 struct clk_regmap *const *regmap_clks;
1917 unsigned int clk_plls_count; 1971 unsigned int regmap_clks_count;
1918 struct clk_hw_onecell_data *hw_onecell_data; 1972 struct clk_hw_onecell_data *hw_onecell_data;
1919}; 1973};
1920 1974
1921static const struct clkc_data gxbb_clkc_data = { 1975static const struct clkc_data gxbb_clkc_data = {
1922 .clk_plls = gxbb_clk_plls, 1976 .regmap_clks = gxbb_clk_regmaps,
1923 .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls), 1977 .regmap_clks_count = ARRAY_SIZE(gxbb_clk_regmaps),
1924 .hw_onecell_data = &gxbb_hw_onecell_data, 1978 .hw_onecell_data = &gxbb_hw_onecell_data,
1925}; 1979};
1926 1980
1927static const struct clkc_data gxl_clkc_data = { 1981static const struct clkc_data gxl_clkc_data = {
1928 .clk_plls = gxl_clk_plls, 1982 .regmap_clks = gxl_clk_regmaps,
1929 .clk_plls_count = ARRAY_SIZE(gxl_clk_plls), 1983 .regmap_clks_count = ARRAY_SIZE(gxl_clk_regmaps),
1930 .hw_onecell_data = &gxl_hw_onecell_data, 1984 .hw_onecell_data = &gxl_hw_onecell_data,
1931}; 1985};
1932 1986
@@ -1969,14 +2023,14 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
1969 if (IS_ERR(map)) 2023 if (IS_ERR(map))
1970 return PTR_ERR(map); 2024 return PTR_ERR(map);
1971 2025
1972 /* Populate base address for PLLs */
1973 for (i = 0; i < clkc_data->clk_plls_count; i++)
1974 clkc_data->clk_plls[i]->base = clk_base;
1975
1976 /* Populate regmap for the common regmap backed clocks */ 2026 /* Populate regmap for the common regmap backed clocks */
1977 for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++) 2027 for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++)
1978 gx_clk_regmaps[i]->map = map; 2028 gx_clk_regmaps[i]->map = map;
1979 2029
2030 /* Populate regmap for soc specific clocks */
2031 for (i = 0; i < clkc_data->regmap_clks_count; i++)
2032 clkc_data->regmap_clks[i]->map = map;
2033
1980 /* Register all clks */ 2034 /* Register all clks */
1981 for (i = 0; i < clkc_data->hw_onecell_data->num; i++) { 2035 for (i = 0; i < clkc_data->hw_onecell_data->num; i++) {
1982 /* array might be sparse */ 2036 /* array might be sparse */
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 4bb51c8f3102..4fd8253c54bb 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -122,23 +122,34 @@ static struct clk_fixed_rate meson8b_xtal = {
122 }, 122 },
123}; 123};
124 124
125static struct meson_clk_pll meson8b_fixed_pll = { 125static struct clk_regmap meson8b_fixed_pll = {
126 .m = { 126 .data = &(struct meson_clk_pll_data){
127 .reg_off = HHI_MPLL_CNTL, 127 .m = {
128 .shift = 0, 128 .reg_off = HHI_MPLL_CNTL,
129 .width = 9, 129 .shift = 0,
130 }, 130 .width = 9,
131 .n = { 131 },
132 .reg_off = HHI_MPLL_CNTL, 132 .n = {
133 .shift = 9, 133 .reg_off = HHI_MPLL_CNTL,
134 .width = 5, 134 .shift = 9,
135 }, 135 .width = 5,
136 .od = { 136 },
137 .reg_off = HHI_MPLL_CNTL, 137 .od = {
138 .shift = 16, 138 .reg_off = HHI_MPLL_CNTL,
139 .width = 2, 139 .shift = 16,
140 }, 140 .width = 2,
141 .lock = &meson_clk_lock, 141 },
142 .l = {
143 .reg_off = HHI_MPLL_CNTL,
144 .shift = 31,
145 .width = 1,
146 },
147 .rst = {
148 .reg_off = HHI_MPLL_CNTL,
149 .shift = 29,
150 .width = 1,
151 },
152 },
142 .hw.init = &(struct clk_init_data){ 153 .hw.init = &(struct clk_init_data){
143 .name = "fixed_pll", 154 .name = "fixed_pll",
144 .ops = &meson_clk_pll_ro_ops, 155 .ops = &meson_clk_pll_ro_ops,
@@ -148,23 +159,34 @@ static struct meson_clk_pll meson8b_fixed_pll = {
148 }, 159 },
149}; 160};
150 161
151static struct meson_clk_pll meson8b_vid_pll = { 162static struct clk_regmap meson8b_vid_pll = {
152 .m = { 163 .data = &(struct meson_clk_pll_data){
153 .reg_off = HHI_VID_PLL_CNTL, 164 .m = {
154 .shift = 0, 165 .reg_off = HHI_VID_PLL_CNTL,
155 .width = 9, 166 .shift = 0,
156 }, 167 .width = 9,
157 .n = { 168 },
158 .reg_off = HHI_VID_PLL_CNTL, 169 .n = {
159 .shift = 9, 170 .reg_off = HHI_VID_PLL_CNTL,
160 .width = 5, 171 .shift = 9,
161 }, 172 .width = 5,
162 .od = { 173 },
163 .reg_off = HHI_VID_PLL_CNTL, 174 .od = {
164 .shift = 16, 175 .reg_off = HHI_VID_PLL_CNTL,
165 .width = 2, 176 .shift = 16,
177 .width = 2,
178 },
179 .l = {
180 .reg_off = HHI_VID_PLL_CNTL,
181 .shift = 31,
182 .width = 1,
183 },
184 .rst = {
185 .reg_off = HHI_VID_PLL_CNTL,
186 .shift = 29,
187 .width = 1,
188 },
166 }, 189 },
167 .lock = &meson_clk_lock,
168 .hw.init = &(struct clk_init_data){ 190 .hw.init = &(struct clk_init_data){
169 .name = "vid_pll", 191 .name = "vid_pll",
170 .ops = &meson_clk_pll_ro_ops, 192 .ops = &meson_clk_pll_ro_ops,
@@ -174,25 +196,35 @@ static struct meson_clk_pll meson8b_vid_pll = {
174 }, 196 },
175}; 197};
176 198
177static struct meson_clk_pll meson8b_sys_pll = { 199static struct clk_regmap meson8b_sys_pll = {
178 .m = { 200 .data = &(struct meson_clk_pll_data){
179 .reg_off = HHI_SYS_PLL_CNTL, 201 .m = {
180 .shift = 0, 202 .reg_off = HHI_SYS_PLL_CNTL,
181 .width = 9, 203 .shift = 0,
182 }, 204 .width = 9,
183 .n = { 205 },
184 .reg_off = HHI_SYS_PLL_CNTL, 206 .n = {
185 .shift = 9, 207 .reg_off = HHI_SYS_PLL_CNTL,
186 .width = 5, 208 .shift = 9,
187 }, 209 .width = 5,
188 .od = { 210 },
189 .reg_off = HHI_SYS_PLL_CNTL, 211 .od = {
190 .shift = 16, 212 .reg_off = HHI_SYS_PLL_CNTL,
191 .width = 2, 213 .shift = 16,
192 }, 214 .width = 2,
193 .rate_table = sys_pll_rate_table, 215 },
194 .rate_count = ARRAY_SIZE(sys_pll_rate_table), 216 .l = {
195 .lock = &meson_clk_lock, 217 .reg_off = HHI_SYS_PLL_CNTL,
218 .shift = 31,
219 .width = 1,
220 },
221 .rst = {
222 .reg_off = HHI_SYS_PLL_CNTL,
223 .shift = 29,
224 .width = 1,
225 },
226 .table = sys_pll_rate_table,
227 },
196 .hw.init = &(struct clk_init_data){ 228 .hw.init = &(struct clk_init_data){
197 .name = "sys_pll", 229 .name = "sys_pll",
198 .ops = &meson_clk_pll_ops, 230 .ops = &meson_clk_pll_ops,
@@ -613,12 +645,6 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
613 .num = CLK_NR_CLKS, 645 .num = CLK_NR_CLKS,
614}; 646};
615 647
616static struct meson_clk_pll *const meson8b_clk_plls[] = {
617 &meson8b_fixed_pll,
618 &meson8b_vid_pll,
619 &meson8b_sys_pll,
620};
621
622static struct clk_regmap *const meson8b_clk_regmaps[] = { 648static struct clk_regmap *const meson8b_clk_regmaps[] = {
623 &meson8b_clk81, 649 &meson8b_clk81,
624 &meson8b_ddr, 650 &meson8b_ddr,
@@ -703,6 +729,9 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
703 &meson8b_mpll0, 729 &meson8b_mpll0,
704 &meson8b_mpll1, 730 &meson8b_mpll1,
705 &meson8b_mpll2, 731 &meson8b_mpll2,
732 &meson8b_fixed_pll,
733 &meson8b_vid_pll,
734 &meson8b_sys_pll,
706}; 735};
707 736
708static const struct meson8b_clk_reset_line { 737static const struct meson8b_clk_reset_line {
@@ -825,10 +854,6 @@ static int meson8b_clkc_probe(struct platform_device *pdev)
825 if (IS_ERR(map)) 854 if (IS_ERR(map))
826 return PTR_ERR(map); 855 return PTR_ERR(map);
827 856
828 /* Populate base address for PLLs */
829 for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++)
830 meson8b_clk_plls[i]->base = clk_base;
831
832 /* Populate the base address for CPU clk */ 857 /* Populate the base address for CPU clk */
833 meson8b_cpu_clk.base = clk_base; 858 meson8b_cpu_clk.base = clk_base;
834 859