2f07cc66565535ba14d3379529c5c42b989f640c
[openwrt/openwrt.git] / target / linux / bcm53xx / patches-4.3 / 047-clk-iproc-Add-PLL-base-write-function.patch
1 From acbb7a3de7e4d83b23c0bbb3eaf77d15a041d865 Mon Sep 17 00:00:00 2001
2 From: Jon Mason <jonmason@broadcom.com>
3 Date: Thu, 15 Oct 2015 15:48:28 -0400
4 Subject: [PATCH 47/50] clk: iproc: Add PLL base write function
5
6 All writes to the PLL base address must be flushed if the
7 IPROC_CLK_NEEDS_READ_BACK flag is set. If we add a function to make the
8 necessary write and reads, we can make sure that any future code which
9 makes PLL base writes will do the correct thing.
10
11 Signed-off-by: Jon Mason <jonmason@broadcom.com>
12 ---
13 drivers/clk/bcm/clk-iproc-pll.c | 80 +++++++++++++++++------------------------
14 1 file changed, 33 insertions(+), 47 deletions(-)
15
16 --- a/drivers/clk/bcm/clk-iproc-pll.c
17 +++ b/drivers/clk/bcm/clk-iproc-pll.c
18 @@ -137,6 +137,18 @@ static int pll_wait_for_lock(struct ipro
19 return -EIO;
20 }
21
22 +static void iproc_pll_write(const struct iproc_pll *pll, void __iomem *base,
23 + const u32 offset, u32 val)
24 +{
25 + const struct iproc_pll_ctrl *ctrl = pll->ctrl;
26 +
27 + writel(val, base + offset);
28 +
29 + if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK &&
30 + base == pll->pll_base))
31 + val = readl(base + offset);
32 +}
33 +
34 static void __pll_disable(struct iproc_pll *pll)
35 {
36 const struct iproc_pll_ctrl *ctrl = pll->ctrl;
37 @@ -145,27 +157,24 @@ static void __pll_disable(struct iproc_p
38 if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
39 val = readl(pll->asiu_base + ctrl->asiu.offset);
40 val &= ~(1 << ctrl->asiu.en_shift);
41 - writel(val, pll->asiu_base + ctrl->asiu.offset);
42 + iproc_pll_write(pll, pll->asiu_base, ctrl->asiu.offset, val);
43 }
44
45 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
46 val = readl(pll->pll_base + ctrl->aon.offset);
47 val |= (bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
48 - writel(val, pll->pll_base + ctrl->aon.offset);
49 -
50 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
51 - readl(pll->pll_base + ctrl->aon.offset);
52 + iproc_pll_write(pll, pll->pll_base, ctrl->aon.offset, val);
53 }
54
55 if (pll->pwr_base) {
56 /* latch input value so core power can be shut down */
57 val = readl(pll->pwr_base + ctrl->aon.offset);
58 val |= (1 << ctrl->aon.iso_shift);
59 - writel(val, pll->pwr_base + ctrl->aon.offset);
60 + iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
61
62 /* power down the core */
63 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
64 - writel(val, pll->pwr_base + ctrl->aon.offset);
65 + iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
66 }
67 }
68
69 @@ -177,10 +186,7 @@ static int __pll_enable(struct iproc_pll
70 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
71 val = readl(pll->pll_base + ctrl->aon.offset);
72 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
73 - writel(val, pll->pll_base + ctrl->aon.offset);
74 -
75 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
76 - readl(pll->pll_base + ctrl->aon.offset);
77 + iproc_pll_write(pll, pll->pll_base, ctrl->aon.offset, val);
78 }
79
80 if (pll->pwr_base) {
81 @@ -188,14 +194,14 @@ static int __pll_enable(struct iproc_pll
82 val = readl(pll->pwr_base + ctrl->aon.offset);
83 val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
84 val &= ~(1 << ctrl->aon.iso_shift);
85 - writel(val, pll->pwr_base + ctrl->aon.offset);
86 + iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
87 }
88
89 /* certain PLLs also need to be ungated from the ASIU top level */
90 if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
91 val = readl(pll->asiu_base + ctrl->asiu.offset);
92 val |= (1 << ctrl->asiu.en_shift);
93 - writel(val, pll->asiu_base + ctrl->asiu.offset);
94 + iproc_pll_write(pll, pll->asiu_base, ctrl->asiu.offset, val);
95 }
96
97 return 0;
98 @@ -209,9 +215,7 @@ static void __pll_put_in_reset(struct ip
99
100 val = readl(pll->pll_base + reset->offset);
101 val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift);
102 - writel(val, pll->pll_base + reset->offset);
103 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
104 - readl(pll->pll_base + reset->offset);
105 + iproc_pll_write(pll, pll->pll_base, reset->offset, val);
106 }
107
108 static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
109 @@ -228,9 +232,7 @@ static void __pll_bring_out_reset(struct
110 val |= ki << reset->ki_shift | kp << reset->kp_shift |
111 ka << reset->ka_shift;
112 val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift;
113 - writel(val, pll->pll_base + reset->offset);
114 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
115 - readl(pll->pll_base + reset->offset);
116 + iproc_pll_write(pll, pll->pll_base, reset->offset, val);
117 }
118
119 static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
120 @@ -285,9 +287,8 @@ static int pll_set_rate(struct iproc_clk
121 /* put PLL in reset */
122 __pll_put_in_reset(pll);
123
124 - writel(0, pll->pll_base + ctrl->vco_ctrl.u_offset);
125 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
126 - readl(pll->pll_base + ctrl->vco_ctrl.u_offset);
127 + iproc_pll_write(pll, pll->pll_base, ctrl->vco_ctrl.u_offset, 0);
128 +
129 val = readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
130
131 if (rate >= VCO_LOW && rate < VCO_MID)
132 @@ -298,17 +299,13 @@ static int pll_set_rate(struct iproc_clk
133 else
134 val |= (1 << PLL_VCO_HIGH_SHIFT);
135
136 - writel(val, pll->pll_base + ctrl->vco_ctrl.l_offset);
137 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
138 - readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
139 + iproc_pll_write(pll, pll->pll_base, ctrl->vco_ctrl.l_offset, val);
140
141 /* program integer part of NDIV */
142 val = readl(pll->pll_base + ctrl->ndiv_int.offset);
143 val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift);
144 val |= vco->ndiv_int << ctrl->ndiv_int.shift;
145 - writel(val, pll->pll_base + ctrl->ndiv_int.offset);
146 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
147 - readl(pll->pll_base + ctrl->ndiv_int.offset);
148 + iproc_pll_write(pll, pll->pll_base, ctrl->ndiv_int.offset, val);
149
150 /* program fractional part of NDIV */
151 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
152 @@ -316,18 +313,15 @@ static int pll_set_rate(struct iproc_clk
153 val &= ~(bit_mask(ctrl->ndiv_frac.width) <<
154 ctrl->ndiv_frac.shift);
155 val |= vco->ndiv_frac << ctrl->ndiv_frac.shift;
156 - writel(val, pll->pll_base + ctrl->ndiv_frac.offset);
157 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
158 - readl(pll->pll_base + ctrl->ndiv_frac.offset);
159 + iproc_pll_write(pll, pll->pll_base, ctrl->ndiv_frac.offset,
160 + val);
161 }
162
163 /* program PDIV */
164 val = readl(pll->pll_base + ctrl->pdiv.offset);
165 val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift);
166 val |= vco->pdiv << ctrl->pdiv.shift;
167 - writel(val, pll->pll_base + ctrl->pdiv.offset);
168 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
169 - readl(pll->pll_base + ctrl->pdiv.offset);
170 + iproc_pll_write(pll, pll->pll_base, ctrl->pdiv.offset, val);
171
172 __pll_bring_out_reset(pll, kp, ka, ki);
173
174 @@ -464,14 +458,12 @@ static int iproc_clk_enable(struct clk_h
175 /* channel enable is active low */
176 val = readl(pll->pll_base + ctrl->enable.offset);
177 val &= ~(1 << ctrl->enable.enable_shift);
178 - writel(val, pll->pll_base + ctrl->enable.offset);
179 + iproc_pll_write(pll, pll->pll_base, ctrl->enable.offset, val);
180
181 /* also make sure channel is not held */
182 val = readl(pll->pll_base + ctrl->enable.offset);
183 val &= ~(1 << ctrl->enable.hold_shift);
184 - writel(val, pll->pll_base + ctrl->enable.offset);
185 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
186 - readl(pll->pll_base + ctrl->enable.offset);
187 + iproc_pll_write(pll, pll->pll_base, ctrl->enable.offset, val);
188
189 return 0;
190 }
191 @@ -488,9 +480,7 @@ static void iproc_clk_disable(struct clk
192
193 val = readl(pll->pll_base + ctrl->enable.offset);
194 val |= 1 << ctrl->enable.enable_shift;
195 - writel(val, pll->pll_base + ctrl->enable.offset);
196 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
197 - readl(pll->pll_base + ctrl->enable.offset);
198 + iproc_pll_write(pll, pll->pll_base, ctrl->enable.offset, val);
199 }
200
201 static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
202 @@ -559,9 +549,7 @@ static int iproc_clk_set_rate(struct clk
203 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
204 val |= div << ctrl->mdiv.shift;
205 }
206 - writel(val, pll->pll_base + ctrl->mdiv.offset);
207 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
208 - readl(pll->pll_base + ctrl->mdiv.offset);
209 + iproc_pll_write(pll, pll->pll_base, ctrl->mdiv.offset, val);
210 clk->rate = parent_rate / div;
211
212 return 0;
213 @@ -588,9 +576,7 @@ static void iproc_pll_sw_cfg(struct ipro
214
215 val = readl(pll->pll_base + ctrl->sw_ctrl.offset);
216 val |= BIT(ctrl->sw_ctrl.shift);
217 - writel(val, pll->pll_base + ctrl->sw_ctrl.offset);
218 - if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
219 - readl(pll->pll_base + ctrl->sw_ctrl.offset);
220 + iproc_pll_write(pll, pll->pll_base, ctrl->sw_ctrl.offset, val);
221 }
222 }
223