diff options
Diffstat (limited to 'drivers/clk/meson/clk-mpll.c')
-rw-r--r-- | drivers/clk/meson/clk-mpll.c | 125 |
1 files changed, 30 insertions, 95 deletions
diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c index 5144360e2c80..0df1227b65b3 100644 --- a/drivers/clk/meson/clk-mpll.c +++ b/drivers/clk/meson/clk-mpll.c | |||
@@ -68,11 +68,15 @@ | |||
68 | #define N2_MIN 4 | 68 | #define N2_MIN 4 |
69 | #define N2_MAX 511 | 69 | #define N2_MAX 511 |
70 | 70 | ||
71 | #define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw) | 71 | static inline struct meson_clk_mpll_data * |
72 | meson_clk_mpll_data(struct clk_regmap *clk) | ||
73 | { | ||
74 | return (struct meson_clk_mpll_data *)clk->data; | ||
75 | } | ||
72 | 76 | ||
73 | static long rate_from_params(unsigned long parent_rate, | 77 | static long rate_from_params(unsigned long parent_rate, |
74 | unsigned long sdm, | 78 | unsigned int sdm, |
75 | unsigned long n2) | 79 | unsigned int n2) |
76 | { | 80 | { |
77 | unsigned long divisor = (SDM_DEN * n2) + sdm; | 81 | unsigned long divisor = (SDM_DEN * n2) + sdm; |
78 | 82 | ||
@@ -84,8 +88,8 @@ static long rate_from_params(unsigned long parent_rate, | |||
84 | 88 | ||
85 | static void params_from_rate(unsigned long requested_rate, | 89 | static void params_from_rate(unsigned long requested_rate, |
86 | unsigned long parent_rate, | 90 | unsigned long parent_rate, |
87 | unsigned long *sdm, | 91 | unsigned int *sdm, |
88 | unsigned long *n2) | 92 | unsigned int *n2) |
89 | { | 93 | { |
90 | uint64_t div = parent_rate; | 94 | uint64_t div = parent_rate; |
91 | unsigned long rem = do_div(div, requested_rate); | 95 | unsigned long rem = do_div(div, requested_rate); |
@@ -105,31 +109,23 @@ static void params_from_rate(unsigned long requested_rate, | |||
105 | static unsigned long mpll_recalc_rate(struct clk_hw *hw, | 109 | static unsigned long mpll_recalc_rate(struct clk_hw *hw, |
106 | unsigned long parent_rate) | 110 | unsigned long parent_rate) |
107 | { | 111 | { |
108 | struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); | 112 | struct clk_regmap *clk = to_clk_regmap(hw); |
109 | struct parm *p; | 113 | struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); |
110 | unsigned long reg, sdm, n2; | 114 | unsigned int sdm, n2; |
111 | long rate; | 115 | long rate; |
112 | 116 | ||
113 | p = &mpll->sdm; | 117 | sdm = meson_parm_read(clk->map, &mpll->sdm); |
114 | reg = readl(mpll->base + p->reg_off); | 118 | n2 = meson_parm_read(clk->map, &mpll->n2); |
115 | sdm = PARM_GET(p->width, p->shift, reg); | ||
116 | |||
117 | p = &mpll->n2; | ||
118 | reg = readl(mpll->base + p->reg_off); | ||
119 | n2 = PARM_GET(p->width, p->shift, reg); | ||
120 | 119 | ||
121 | rate = rate_from_params(parent_rate, sdm, n2); | 120 | rate = rate_from_params(parent_rate, sdm, n2); |
122 | if (rate < 0) | 121 | return rate < 0 ? 0 : rate; |
123 | return 0; | ||
124 | |||
125 | return rate; | ||
126 | } | 122 | } |
127 | 123 | ||
128 | static long mpll_round_rate(struct clk_hw *hw, | 124 | static long mpll_round_rate(struct clk_hw *hw, |
129 | unsigned long rate, | 125 | unsigned long rate, |
130 | unsigned long *parent_rate) | 126 | unsigned long *parent_rate) |
131 | { | 127 | { |
132 | unsigned long sdm, n2; | 128 | unsigned int sdm, n2; |
133 | 129 | ||
134 | params_from_rate(rate, *parent_rate, &sdm, &n2); | 130 | params_from_rate(rate, *parent_rate, &sdm, &n2); |
135 | return rate_from_params(*parent_rate, sdm, n2); | 131 | return rate_from_params(*parent_rate, sdm, n2); |
@@ -139,9 +135,9 @@ static int mpll_set_rate(struct clk_hw *hw, | |||
139 | unsigned long rate, | 135 | unsigned long rate, |
140 | unsigned long parent_rate) | 136 | unsigned long parent_rate) |
141 | { | 137 | { |
142 | struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); | 138 | struct clk_regmap *clk = to_clk_regmap(hw); |
143 | struct parm *p; | 139 | struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); |
144 | unsigned long reg, sdm, n2; | 140 | unsigned int sdm, n2; |
145 | unsigned long flags = 0; | 141 | unsigned long flags = 0; |
146 | 142 | ||
147 | params_from_rate(rate, parent_rate, &sdm, &n2); | 143 | params_from_rate(rate, parent_rate, &sdm, &n2); |
@@ -151,97 +147,36 @@ static int mpll_set_rate(struct clk_hw *hw, | |||
151 | else | 147 | else |
152 | __acquire(mpll->lock); | 148 | __acquire(mpll->lock); |
153 | 149 | ||
154 | p = &mpll->sdm; | 150 | /* Enable and set the fractional part */ |
155 | reg = readl(mpll->base + p->reg_off); | 151 | meson_parm_write(clk->map, &mpll->sdm, sdm); |
156 | reg = PARM_SET(p->width, p->shift, reg, sdm); | 152 | meson_parm_write(clk->map, &mpll->sdm_en, 1); |
157 | writel(reg, mpll->base + p->reg_off); | ||
158 | |||
159 | p = &mpll->sdm_en; | ||
160 | reg = readl(mpll->base + p->reg_off); | ||
161 | reg = PARM_SET(p->width, p->shift, reg, 1); | ||
162 | writel(reg, mpll->base + p->reg_off); | ||
163 | |||
164 | p = &mpll->ssen; | ||
165 | if (p->width != 0) { | ||
166 | reg = readl(mpll->base + p->reg_off); | ||
167 | reg = PARM_SET(p->width, p->shift, reg, 1); | ||
168 | writel(reg, mpll->base + p->reg_off); | ||
169 | } | ||
170 | |||
171 | p = &mpll->n2; | ||
172 | reg = readl(mpll->base + p->reg_off); | ||
173 | reg = PARM_SET(p->width, p->shift, reg, n2); | ||
174 | writel(reg, mpll->base + p->reg_off); | ||
175 | |||
176 | if (mpll->lock) | ||
177 | spin_unlock_irqrestore(mpll->lock, flags); | ||
178 | else | ||
179 | __release(mpll->lock); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | 153 | ||
184 | static void mpll_enable_core(struct clk_hw *hw, int enable) | 154 | /* Set additional fractional part enable if required */ |
185 | { | 155 | if (MESON_PARM_APPLICABLE(&mpll->ssen)) |
186 | struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); | 156 | meson_parm_write(clk->map, &mpll->ssen, 1); |
187 | struct parm *p; | ||
188 | unsigned long reg; | ||
189 | unsigned long flags = 0; | ||
190 | 157 | ||
191 | if (mpll->lock) | 158 | /* Set the integer divider part */ |
192 | spin_lock_irqsave(mpll->lock, flags); | 159 | meson_parm_write(clk->map, &mpll->n2, n2); |
193 | else | ||
194 | __acquire(mpll->lock); | ||
195 | 160 | ||
196 | p = &mpll->en; | 161 | /* Set the magic misc bit if required */ |
197 | reg = readl(mpll->base + p->reg_off); | 162 | if (MESON_PARM_APPLICABLE(&mpll->misc)) |
198 | reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0); | 163 | meson_parm_write(clk->map, &mpll->misc, 1); |
199 | writel(reg, mpll->base + p->reg_off); | ||
200 | 164 | ||
201 | if (mpll->lock) | 165 | if (mpll->lock) |
202 | spin_unlock_irqrestore(mpll->lock, flags); | 166 | spin_unlock_irqrestore(mpll->lock, flags); |
203 | else | 167 | else |
204 | __release(mpll->lock); | 168 | __release(mpll->lock); |
205 | } | ||
206 | |||
207 | |||
208 | static int mpll_enable(struct clk_hw *hw) | ||
209 | { | ||
210 | mpll_enable_core(hw, 1); | ||
211 | 169 | ||
212 | return 0; | 170 | return 0; |
213 | } | 171 | } |
214 | 172 | ||
215 | static void mpll_disable(struct clk_hw *hw) | ||
216 | { | ||
217 | mpll_enable_core(hw, 0); | ||
218 | } | ||
219 | |||
220 | static int mpll_is_enabled(struct clk_hw *hw) | ||
221 | { | ||
222 | struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); | ||
223 | struct parm *p; | ||
224 | unsigned long reg; | ||
225 | int en; | ||
226 | |||
227 | p = &mpll->en; | ||
228 | reg = readl(mpll->base + p->reg_off); | ||
229 | en = PARM_GET(p->width, p->shift, reg); | ||
230 | |||
231 | return en; | ||
232 | } | ||
233 | |||
234 | const struct clk_ops meson_clk_mpll_ro_ops = { | 173 | const struct clk_ops meson_clk_mpll_ro_ops = { |
235 | .recalc_rate = mpll_recalc_rate, | 174 | .recalc_rate = mpll_recalc_rate, |
236 | .round_rate = mpll_round_rate, | 175 | .round_rate = mpll_round_rate, |
237 | .is_enabled = mpll_is_enabled, | ||
238 | }; | 176 | }; |
239 | 177 | ||
240 | const struct clk_ops meson_clk_mpll_ops = { | 178 | const struct clk_ops meson_clk_mpll_ops = { |
241 | .recalc_rate = mpll_recalc_rate, | 179 | .recalc_rate = mpll_recalc_rate, |
242 | .round_rate = mpll_round_rate, | 180 | .round_rate = mpll_round_rate, |
243 | .set_rate = mpll_set_rate, | 181 | .set_rate = mpll_set_rate, |
244 | .enable = mpll_enable, | ||
245 | .disable = mpll_disable, | ||
246 | .is_enabled = mpll_is_enabled, | ||
247 | }; | 182 | }; |