board.d: merge ucidef_add_switch() and ucidef_add_switch_ports()
[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