clk.c (0337966d121ebebf73a1c346123e8112796e684e) clk.c (5d890c2df900db0197d46ec75383d7633ef41c82)
1/*
2 * Copyright (c) 2014 MundoReader S.L.
3 * Author: Heiko Stuebner <heiko@sntech.de>
4 *
5 * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
6 * Author: Xing Zheng <zhengxing@rock-chips.com>
7 *
8 * based on

--- 15 unchanged lines hidden (view full) ---

24 */
25
26#include <linux/slab.h>
27#include <linux/clk.h>
28#include <linux/clk-provider.h>
29#include <linux/mfd/syscon.h>
30#include <linux/regmap.h>
31#include <linux/reboot.h>
1/*
2 * Copyright (c) 2014 MundoReader S.L.
3 * Author: Heiko Stuebner <heiko@sntech.de>
4 *
5 * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
6 * Author: Xing Zheng <zhengxing@rock-chips.com>
7 *
8 * based on

--- 15 unchanged lines hidden (view full) ---

24 */
25
26#include <linux/slab.h>
27#include <linux/clk.h>
28#include <linux/clk-provider.h>
29#include <linux/mfd/syscon.h>
30#include <linux/regmap.h>
31#include <linux/reboot.h>
32#include <linux/rational.h>
32#include "clk.h"
33
34/**
35 * Register a clock branch.
36 * Most clock branches have a form like
37 *
38 * src1 --|--\
39 * |M |--[GATE]-[DIV]-

--- 119 unchanged lines hidden (view full) ---

159 frac->rate_change_idx);
160 frac->rate_change_remuxed = 0;
161 }
162 }
163
164 return notifier_from_errno(ret);
165}
166
33#include "clk.h"
34
35/**
36 * Register a clock branch.
37 * Most clock branches have a form like
38 *
39 * src1 --|--\
40 * |M |--[GATE]-[DIV]-

--- 119 unchanged lines hidden (view full) ---

160 frac->rate_change_idx);
161 frac->rate_change_remuxed = 0;
162 }
163 }
164
165 return notifier_from_errno(ret);
166}
167
168/**
169 * fractional divider must set that denominator is 20 times larger than
170 * numerator to generate precise clock frequency.
171 */
172void rockchip_fractional_approximation(struct clk_hw *hw,
173 unsigned long rate, unsigned long *parent_rate,
174 unsigned long *m, unsigned long *n)
175{
176 struct clk_fractional_divider *fd = to_clk_fd(hw);
177 unsigned long p_rate, p_parent_rate;
178 struct clk_hw *p_parent;
179 unsigned long scale;
180
181 p_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
182 if ((rate * 20 > p_rate) && (p_rate % rate != 0)) {
183 p_parent = clk_hw_get_parent(clk_hw_get_parent(hw));
184 p_parent_rate = clk_hw_get_rate(p_parent);
185 *parent_rate = p_parent_rate;
186 }
187
188 /*
189 * Get rate closer to *parent_rate to guarantee there is no overflow
190 * for m and n. In the result it will be the nearest rate left shifted
191 * by (scale - fd->nwidth) bits.
192 */
193 scale = fls_long(*parent_rate / rate - 1);
194 if (scale > fd->nwidth)
195 rate <<= scale - fd->nwidth;
196
197 rational_best_approximation(rate, *parent_rate,
198 GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
199 m, n);
200}
201
167static struct clk *rockchip_clk_register_frac_branch(
168 struct rockchip_clk_provider *ctx, const char *name,
169 const char *const *parent_names, u8 num_parents,
170 void __iomem *base, int muxdiv_offset, u8 div_flags,
171 int gate_offset, u8 gate_shift, u8 gate_flags,
172 unsigned long flags, struct rockchip_clk_branch *child,
173 spinlock_t *lock)
174{

--- 30 unchanged lines hidden (view full) ---

205 div->reg = base + muxdiv_offset;
206 div->mshift = 16;
207 div->mwidth = 16;
208 div->mmask = GENMASK(div->mwidth - 1, 0) << div->mshift;
209 div->nshift = 0;
210 div->nwidth = 16;
211 div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift;
212 div->lock = lock;
202static struct clk *rockchip_clk_register_frac_branch(
203 struct rockchip_clk_provider *ctx, const char *name,
204 const char *const *parent_names, u8 num_parents,
205 void __iomem *base, int muxdiv_offset, u8 div_flags,
206 int gate_offset, u8 gate_shift, u8 gate_flags,
207 unsigned long flags, struct rockchip_clk_branch *child,
208 spinlock_t *lock)
209{

--- 30 unchanged lines hidden (view full) ---

240 div->reg = base + muxdiv_offset;
241 div->mshift = 16;
242 div->mwidth = 16;
243 div->mmask = GENMASK(div->mwidth - 1, 0) << div->mshift;
244 div->nshift = 0;
245 div->nwidth = 16;
246 div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift;
247 div->lock = lock;
248 div->approximation = rockchip_fractional_approximation;
213 div_ops = &clk_fractional_divider_ops;
214
215 clk = clk_register_composite(NULL, name, parent_names, num_parents,
216 NULL, NULL,
217 &div->hw, div_ops,
218 gate ? &gate->hw : NULL, gate_ops,
219 flags | CLK_SET_RATE_UNGATE);
220 if (IS_ERR(clk)) {

--- 369 unchanged lines hidden ---
249 div_ops = &clk_fractional_divider_ops;
250
251 clk = clk_register_composite(NULL, name, parent_names, num_parents,
252 NULL, NULL,
253 &div->hw, div_ops,
254 gate ? &gate->hw : NULL, gate_ops,
255 flags | CLK_SET_RATE_UNGATE);
256 if (IS_ERR(clk)) {

--- 369 unchanged lines hidden ---