|
3 | 3 | * Copyright (C) 2014 Intel Corporation
|
4 | 4 | *
|
5 | 5 | * Adjustable fractional divider clock implementation.
|
6 |
| - * Output rate = (m / n) * parent_rate. |
7 | 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 much much better result of m and n than simple |
| 38 | + * saturated values. |
8 | 39 | */
|
9 | 40 |
|
10 | 41 | #include <linux/clk-provider.h>
|
@@ -81,6 +112,8 @@ void clk_fractional_divider_general_approximation(struct clk_hw *hw,
|
81 | 112 | * Get rate closer to *parent_rate to guarantee there is no overflow
|
82 | 113 | * for m and n. In the result it will be the nearest rate left shifted
|
83 | 114 | * by (scale - fd->nwidth) bits.
|
| 115 | + * |
| 116 | + * For the detailed explanation see the top comment in this file. |
84 | 117 | */
|
85 | 118 | if (fd->flags & CLK_FRAC_DIVIDER_POWER_OF_TWO_PS) {
|
86 | 119 | unsigned long scale = fls_long(*parent_rate / rate - 1);
|
|
0 commit comments