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 --- |