| 1 | |
| 2 | |
| 3 | * Copyright (C) 2014 Intel Corporation
|
| 4 | *
|
| 5 | * Adjustable fractional divider clock implementation.
|
| 6 | * Uses rational best approximation algorithm.
|
| 7 | *
|
| 8 | * Output is calculated as
|
| 9 | *
|
| 10 | * rate = (m / n) * parent_rate (1)
|
| 11 | *
|
| 12 | * This is useful when we have a prescaler block which asks for
|
| 13 | * m (numerator) and n (denominator) values to be provided to satisfy
|
| 14 | * the (1) as much as possible.
|
| 15 | *
|
| 16 | * Since m and n have the limitation by a range, e.g.
|
| 17 | *
|
| 18 | * n >= 1, n < N_width, where N_width = 2^nwidth (2)
|
| 19 | *
|
| 20 | * for some cases the output may be saturated. Hence, from (1) and (2),
|
| 21 | * assuming the worst case when m = 1, the inequality
|
| 22 | *
|
| 23 | * floor(log2(parent_rate / rate)) <= nwidth (3)
|
| 24 | *
|
| 25 | * may be derived. Thus, in cases when
|
| 26 | *
|
| 27 | * (parent_rate / rate) >> N_width (4)
|
| 28 | *
|
| 29 | * we might scale up the rate by 2^scale (see the description of
|
| 30 | * CLK_FRAC_DIVIDER_POWER_OF_TWO_PS for additional information), where
|
| 31 | *
|
| 32 | * scale = floor(log2(parent_rate / rate)) - nwidth (5)
|
| 33 | *
|
| 34 | * and assume that the IP, that needs m and n, has also its own
|
| 35 | * prescaler, which is capable to divide by 2^scale. In this way
|
| 36 | * we get the denominator to satisfy the desired range (2) and
|
| 37 | * at the same time a much better result of m and n than simple
|
| 38 | * saturated values.
|
| 39 |
|
| 40 |
|
| 41 | #include <linux/debugfs.h>
|
| 42 | #include <linux/device.h>
|
| 43 | #include <linux/io.h>
|
| 44 | #include <linux/math.h>
|
| 45 | #include <linux/module.h>
|
| 46 | #include <linux/rational.h>
|
| 47 | #include <linux/slab.h>
|
| 48 |
|
| 49 | #include <linux/clk-provider.h>
|
| 50 |
|
| 51 | #include "clk-fractional-divider.h"
|
| 52 |
|
| 53 | static inline u32 clk_fd_readl(struct clk_fractional_divider *fd)
|
| 54 | {
|
| 55 | if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
|
| 56 | return ioread32be(fd->reg);
|
| 57 |
|
| 58 | return readl(fd->reg);
|
| 59 | }
|
| 60 |
|
| 61 | static inline void clk_fd_writel(struct clk_fractional_divider *fd, u32 val)
|
| 62 | {
|
| 63 | if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
|
| 64 | iowrite32be(val, fd->reg);
|
| 65 | else
|
| 66 | writel(val, fd->reg);
|
| 67 | }
|
| 68 |
|
| 69 | static void clk_fd_get_div(struct clk_hw *hw, struct u32_fract *fract)
|
| 70 | {
|
| 71 | struct clk_fractional_divider *fd = to_clk_fd(hw);
|
| 72 | unsigned long flags = 0;
|
| 73 | unsigned long m, n;
|
| 74 | u32 mmask, nmask;
|
| 75 | u32 val;
|
| 76 |
|
| 77 | if (fd->lock)
|
| 78 | spin_lock_irqsave(fd->lock, flags);
|
| 79 | else
|
| 80 | __acquire(fd->lock);
|
| 81 |
|
| 82 | val = clk_fd_readl(fd);
|
| 83 |
|
| 84 | if (fd->lock)
|
| 85 | spin_unlock_irqrestore(fd->lock, flags);
|
| 86 | else
|
| 87 | __release(fd->lock);
|
| 88 |
|
| 89 | mmask = GENMASK(fd->mwidth - 1, 0) << fd->mshift;
|
| 90 | nmask = GENMASK(fd->nwidth - 1, 0) << fd->nshift;
|
| 91 |
|
| 92 | m = (val & mmask) >> fd->mshift;
|
| 93 | n = (val & nmask) >> fd->nshift;
|
| 94 |
|
| 95 | if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
|
| 96 | m++;
|
| 97 | n++;
|
| 98 | }
|
| 99 |
|
| 100 | fract->numerator = m;
|
| 101 | fract->denominator = n;
|
| 102 | }
|
| 103 |
|
| 104 | static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
| 105 | {
|
| 106 | struct u32_fract fract;
|
| 107 | u64 ret;
|
| 108 |
|
| 109 | clk_fd_get_div(hw, &fract);
|
| 110 |
|
| 111 | if (!fract.numerator || !fract.denominator)
|
| 112 | return parent_rate;
|
| 113 |
|
| 114 | ret = (u64)parent_rate * fract.numerator;
|
| 115 | do_div(ret, fract.denominator);
|
| 116 |
|
| 117 | return ret;
|
| 118 | }
|
| 119 |
|
| 120 | void clk_fractional_divider_general_approximation(struct clk_hw *hw,
|
| 121 | unsigned long rate,
|
| 122 | unsigned long *parent_rate,
|
| 123 | unsigned long *m, unsigned long *n)
|
| 124 | {
|
| 125 | struct clk_fractional_divider *fd = to_clk_fd(hw);
|
| 126 | unsigned long max_m, max_n;
|
| 127 |
|
| 128 | |
| 129 | * Get rate closer to *parent_rate to guarantee there is no overflow
|
| 130 | * for m and n. In the result it will be the nearest rate left shifted
|
| 131 | * by (scale - fd->nwidth) bits.
|
| 132 | *
|
| 133 | * For the detailed explanation see the top comment in this file.
|
| 134 |
|
| 135 | if (fd->flags & CLK_FRAC_DIVIDER_POWER_OF_TWO_PS) {
|
| 136 | unsigned long scale = fls_long(*parent_rate / rate - 1);
|
| 137 |
|
| 138 | if (scale > fd->nwidth)
|
| 139 | rate <<= scale - fd->nwidth;
|
| 140 | }
|
| 141 |
|
| 142 | if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
|
| 143 | max_m = BIT(fd->mwidth);
|
| 144 | max_n = BIT(fd->nwidth);
|
| 145 | } else {
|
| 146 | max_m = GENMASK(fd->mwidth - 1, 0);
|
| 147 | max_n = GENMASK(fd->nwidth - 1, 0);
|
| 148 | }
|
| 149 |
|
| 150 | rational_best_approximation(rate, *parent_rate, max_m, max_n, m, n);
|
| 151 | }
|
| 152 | EXPORT_SYMBOL_GPL(clk_fractional_divider_general_approximation);
|
| 153 |
|
| 154 | static int clk_fd_determine_rate(struct clk_hw *hw,
|
| 155 | struct clk_rate_request *req)
|
| 156 | {
|
| 157 | struct clk_fractional_divider *fd = to_clk_fd(hw);
|
| 158 | unsigned long m, n;
|
| 159 | u64 ret;
|
| 160 |
|
| 161 | if (!req->rate || (!clk_hw_can_set_rate_parent(hw) && req->rate >= req->best_parent_rate)) {
|
| 162 | req->rate = req->best_parent_rate;
|
| 163 |
|
| 164 | return 0;
|
| 165 | }
|
| 166 |
|
| 167 | if (fd->approximation)
|
| 168 | fd->approximation(hw, req->rate, &req->best_parent_rate, &m, &n);
|
| 169 | else
|
| 170 | clk_fractional_divider_general_approximation(hw, req->rate,
|
| 171 | &req->best_parent_rate,
|
| 172 | &m, &n);
|
| 173 |
|
| 174 | ret = (u64)req->best_parent_rate * m;
|
| 175 | do_div(ret, n);
|
| 176 |
|
| 177 | req->rate = ret;
|
| 178 |
|
| 179 | return 0;
|
| 180 | }
|
| 181 |
|
| 182 | static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
|
| 183 | unsigned long parent_rate)
|
| 184 | {
|
| 185 | struct clk_fractional_divider *fd = to_clk_fd(hw);
|
| 186 | unsigned long flags = 0;
|
| 187 | unsigned long m, n, max_m, max_n;
|
| 188 | u32 mmask, nmask;
|
| 189 | u32 val;
|
| 190 |
|
| 191 | if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
|
| 192 | max_m = BIT(fd->mwidth);
|
| 193 | max_n = BIT(fd->nwidth);
|
| 194 | } else {
|
| 195 | max_m = GENMASK(fd->mwidth - 1, 0);
|
| 196 | max_n = GENMASK(fd->nwidth - 1, 0);
|
| 197 | }
|
| 198 | rational_best_approximation(rate, parent_rate, max_m, max_n, &m, &n);
|
| 199 |
|
| 200 | if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
|
| 201 | m--;
|
| 202 | n--;
|
| 203 | }
|
| 204 |
|
| 205 | mmask = GENMASK(fd->mwidth - 1, 0) << fd->mshift;
|
| 206 | nmask = GENMASK(fd->nwidth - 1, 0) << fd->nshift;
|
| 207 |
|
| 208 | if (fd->lock)
|
| 209 | spin_lock_irqsave(fd->lock, flags);
|
| 210 | else
|
| 211 | __acquire(fd->lock);
|
| 212 |
|
| 213 | val = clk_fd_readl(fd);
|
| 214 | val &= ~(mmask | nmask);
|
| 215 | val |= (m << fd->mshift) | (n << fd->nshift);
|
| 216 | clk_fd_writel(fd, val);
|
| 217 |
|
| 218 | if (fd->lock)
|
| 219 | spin_unlock_irqrestore(fd->lock, flags);
|
| 220 | else
|
| 221 | __release(fd->lock);
|
| 222 |
|
| 223 | return 0;
|
| 224 | }
|
| 225 |
|
| 226 | #ifdef CONFIG_DEBUG_FS
|
| 227 | static int clk_fd_numerator_get(void *hw, u64 *val)
|
| 228 | {
|
| 229 | struct u32_fract fract;
|
| 230 |
|
| 231 | clk_fd_get_div(hw, &fract);
|
| 232 |
|
| 233 | *val = fract.numerator;
|
| 234 |
|
| 235 | return 0;
|
| 236 | }
|
| 237 | DEFINE_DEBUGFS_ATTRIBUTE(clk_fd_numerator_fops, clk_fd_numerator_get, NULL, "%llu\n");
|
| 238 |
|
| 239 | static int clk_fd_denominator_get(void *hw, u64 *val)
|
| 240 | {
|
| 241 | struct u32_fract fract;
|
| 242 |
|
| 243 | clk_fd_get_div(hw, &fract);
|
| 244 |
|
| 245 | *val = fract.denominator;
|
| 246 |
|
| 247 | return 0;
|
| 248 | }
|
| 249 | DEFINE_DEBUGFS_ATTRIBUTE(clk_fd_denominator_fops, clk_fd_denominator_get, NULL, "%llu\n");
|
| 250 |
|
| 251 | static void clk_fd_debug_init(struct clk_hw *hw, struct dentry *dentry)
|
| 252 | {
|
| 253 | debugfs_create_file("numerator", 0444, dentry, hw, &clk_fd_numerator_fops);
|
| 254 | debugfs_create_file("denominator", 0444, dentry, hw, &clk_fd_denominator_fops);
|
| 255 | }
|
| 256 | #endif
|
| 257 |
|
| 258 | const struct clk_ops clk_fractional_divider_ops = {
|
| 259 | .recalc_rate = clk_fd_recalc_rate,
|
| 260 | .determine_rate = clk_fd_determine_rate,
|
| 261 | .set_rate = clk_fd_set_rate,
|
| 262 | #ifdef CONFIG_DEBUG_FS
|
| 263 | .debug_init = clk_fd_debug_init,
|
| 264 | #endif
|
| 265 | };
|
| 266 | EXPORT_SYMBOL_GPL(clk_fractional_divider_ops);
|
| 267 |
|
| 268 | struct clk_hw *clk_hw_register_fractional_divider(struct device *dev,
|
| 269 | const char *name, const char *parent_name, unsigned long flags,
|
| 270 | void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
|
| 271 | u8 clk_divider_flags, spinlock_t *lock)
|
| 272 | {
|
| 273 | struct clk_fractional_divider *fd;
|
| 274 | struct clk_init_data init;
|
| 275 | struct clk_hw *hw;
|
| 276 | int ret;
|
| 277 |
|
| 278 | fd = kzalloc_obj(*fd);
|
| 279 | if (!fd)
|
| 280 | return ERR_PTR(-ENOMEM);
|
| 281 |
|
| 282 | init.name = name;
|
| 283 | init.ops = &clk_fractional_divider_ops;
|
| 284 | init.flags = flags;
|
| 285 | init.parent_names = parent_name ? &parent_name : NULL;
|
| 286 | init.num_parents = parent_name ? 1 : 0;
|
| 287 |
|
| 288 | fd->reg = reg;
|
| 289 | fd->mshift = mshift;
|
| 290 | fd->mwidth = mwidth;
|
| 291 | fd->nshift = nshift;
|
| 292 | fd->nwidth = nwidth;
|
| 293 | fd->flags = clk_divider_flags;
|
| 294 | fd->lock = lock;
|
| 295 | fd->hw.init = &init;
|
| 296 |
|
| 297 | hw = &fd->hw;
|
| 298 | ret = clk_hw_register(dev, hw);
|
| 299 | if (ret) {
|
| 300 | kfree(fd);
|
| 301 | hw = ERR_PTR(ret);
|
| 302 | }
|
| 303 |
|
| 304 | return hw;
|
| 305 | }
|
| 306 | EXPORT_SYMBOL_GPL(clk_hw_register_fractional_divider);
|
| 307 |
|
| 308 | struct clk *clk_register_fractional_divider(struct device *dev,
|
| 309 | const char *name, const char *parent_name, unsigned long flags,
|
| 310 | void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
|
| 311 | u8 clk_divider_flags, spinlock_t *lock)
|
| 312 | {
|
| 313 | struct clk_hw *hw;
|
| 314 |
|
| 315 | hw = clk_hw_register_fractional_divider(dev, name, parent_name, flags,
|
| 316 | reg, mshift, mwidth, nshift, nwidth, clk_divider_flags,
|
| 317 | lock);
|
| 318 | if (IS_ERR(hw))
|
| 319 | return ERR_CAST(hw);
|
| 320 | return hw->clk;
|
| 321 | }
|
| 322 | EXPORT_SYMBOL_GPL(clk_register_fractional_divider);
|
| 323 |
|
| 324 | void clk_hw_unregister_fractional_divider(struct clk_hw *hw)
|
| 325 | {
|
| 326 | struct clk_fractional_divider *fd;
|
| 327 |
|
| 328 | fd = to_clk_fd(hw);
|
| 329 |
|
| 330 | clk_hw_unregister(hw);
|
| 331 | kfree(fd);
|
| 332 | }
|