Skip to content

Commit 1faa7cb

Browse files
committed
Merge branch 'clk-frac-divider' into clk-next
- Add power of two flag to fractional divider clk type * clk-frac-divider: clk: fractional-divider: Document the arithmetics used behind the code clk: fractional-divider: Introduce POWER_OF_TWO_PS flag clk: fractional-divider: Hide clk_fractional_divider_ops from wide audience clk: fractional-divider: Export approximation algorithm to the CCF users
2 parents 7110569 + e81b917 commit 1faa7cb

File tree

7 files changed

+79
-29
lines changed

7 files changed

+79
-29
lines changed

drivers/acpi/acpi_lpss.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,8 @@ static int register_device_clock(struct acpi_device *adev,
436436
if (!clk_name)
437437
return -ENOMEM;
438438
clk = clk_register_fractional_divider(NULL, clk_name, parent,
439-
0, prv_base,
440-
1, 15, 16, 15, 0, NULL);
439+
CLK_FRAC_DIVIDER_POWER_OF_TWO_PS,
440+
prv_base, 1, 15, 16, 15, 0, NULL);
441441
parent = clk_name;
442442

443443
clk_name = kasprintf(GFP_KERNEL, "%s-update", devname);

drivers/clk/clk-fractional-divider.c

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,39 @@
33
* Copyright (C) 2014 Intel Corporation
44
*
55
* Adjustable fractional divider clock implementation.
6-
* Output rate = (m / n) * parent_rate.
76
* 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.
839
*/
940

1041
#include <linux/clk-provider.h>
@@ -14,6 +45,8 @@
1445
#include <linux/slab.h>
1546
#include <linux/rational.h>
1647

48+
#include "clk-fractional-divider.h"
49+
1750
static inline u32 clk_fd_readl(struct clk_fractional_divider *fd)
1851
{
1952
if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
@@ -68,21 +101,26 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
68101
return ret;
69102
}
70103

71-
static void clk_fd_general_approximation(struct clk_hw *hw, unsigned long rate,
72-
unsigned long *parent_rate,
73-
unsigned long *m, unsigned long *n)
104+
void clk_fractional_divider_general_approximation(struct clk_hw *hw,
105+
unsigned long rate,
106+
unsigned long *parent_rate,
107+
unsigned long *m, unsigned long *n)
74108
{
75109
struct clk_fractional_divider *fd = to_clk_fd(hw);
76-
unsigned long scale;
77110

78111
/*
79112
* Get rate closer to *parent_rate to guarantee there is no overflow
80113
* for m and n. In the result it will be the nearest rate left shifted
81114
* by (scale - fd->nwidth) bits.
115+
*
116+
* For the detailed explanation see the top comment in this file.
82117
*/
83-
scale = fls_long(*parent_rate / rate - 1);
84-
if (scale > fd->nwidth)
85-
rate <<= scale - fd->nwidth;
118+
if (fd->flags & CLK_FRAC_DIVIDER_POWER_OF_TWO_PS) {
119+
unsigned long scale = fls_long(*parent_rate / rate - 1);
120+
121+
if (scale > fd->nwidth)
122+
rate <<= scale - fd->nwidth;
123+
}
86124

87125
rational_best_approximation(rate, *parent_rate,
88126
GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
@@ -102,7 +140,7 @@ static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
102140
if (fd->approximation)
103141
fd->approximation(hw, rate, parent_rate, &m, &n);
104142
else
105-
clk_fd_general_approximation(hw, rate, parent_rate, &m, &n);
143+
clk_fractional_divider_general_approximation(hw, rate, parent_rate, &m, &n);
106144

107145
ret = (u64)*parent_rate * m;
108146
do_div(ret, n);

drivers/clk/clk-fractional-divider.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef _CLK_FRACTIONAL_DIV_H
3+
#define _CLK_FRACTIONAL_DIV_H
4+
5+
struct clk_hw;
6+
7+
extern const struct clk_ops clk_fractional_divider_ops;
8+
9+
void clk_fractional_divider_general_approximation(struct clk_hw *hw,
10+
unsigned long rate,
11+
unsigned long *parent_rate,
12+
unsigned long *m,
13+
unsigned long *n);
14+
15+
#endif

drivers/clk/imx/clk-composite-7ulp.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/err.h>
1111
#include <linux/slab.h>
1212

13+
#include "../clk-fractional-divider.h"
1314
#include "clk.h"
1415

1516
#define PCG_PCS_SHIFT 24

drivers/clk/rockchip/clk.c

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <linux/regmap.h>
2323
#include <linux/reboot.h>
2424
#include <linux/rational.h>
25+
26+
#include "../clk-fractional-divider.h"
2527
#include "clk.h"
2628

2729
/*
@@ -178,10 +180,8 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
178180
unsigned long rate, unsigned long *parent_rate,
179181
unsigned long *m, unsigned long *n)
180182
{
181-
struct clk_fractional_divider *fd = to_clk_fd(hw);
182183
unsigned long p_rate, p_parent_rate;
183184
struct clk_hw *p_parent;
184-
unsigned long scale;
185185

186186
p_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
187187
if ((rate * 20 > p_rate) && (p_rate % rate != 0)) {
@@ -190,18 +190,7 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
190190
*parent_rate = p_parent_rate;
191191
}
192192

193-
/*
194-
* Get rate closer to *parent_rate to guarantee there is no overflow
195-
* for m and n. In the result it will be the nearest rate left shifted
196-
* by (scale - fd->nwidth) bits.
197-
*/
198-
scale = fls_long(*parent_rate / rate - 1);
199-
if (scale > fd->nwidth)
200-
rate <<= scale - fd->nwidth;
201-
202-
rational_best_approximation(rate, *parent_rate,
203-
GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
204-
m, n);
193+
clk_fractional_divider_general_approximation(hw, rate, parent_rate, m, n);
205194
}
206195

207196
static struct clk *rockchip_clk_register_frac_branch(

drivers/mfd/intel-lpss.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,8 @@ static int intel_lpss_register_clock_divider(struct intel_lpss *lpss,
301301

302302
snprintf(name, sizeof(name), "%s-div", devname);
303303
tmp = clk_register_fractional_divider(NULL, name, __clk_get_name(tmp),
304-
0, lpss->priv, 1, 15, 16, 15, 0,
304+
CLK_FRAC_DIVIDER_POWER_OF_TWO_PS,
305+
lpss->priv, 1, 15, 16, 15, 0,
305306
NULL);
306307
if (IS_ERR(tmp))
307308
return PTR_ERR(tmp);

include/linux/clk-provider.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,12 @@ struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev,
10011001
* CLK_FRAC_DIVIDER_BIG_ENDIAN - By default little endian register accesses are
10021002
* used for the divider register. Setting this flag makes the register
10031003
* accesses big endian.
1004+
* CLK_FRAC_DIVIDER_POWER_OF_TWO_PS - By default the resulting fraction might
1005+
* be saturated and the caller will get quite far from the good enough
1006+
* approximation. Instead the caller may require, by setting this flag,
1007+
* to shift left by a few bits in case, when the asked one is quite small
1008+
* to satisfy the desired range of denominator. It assumes that on the
1009+
* caller's side the power-of-two capable prescaler exists.
10041010
*/
10051011
struct clk_fractional_divider {
10061012
struct clk_hw hw;
@@ -1020,10 +1026,10 @@ struct clk_fractional_divider {
10201026

10211027
#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, hw)
10221028

1023-
#define CLK_FRAC_DIVIDER_ZERO_BASED BIT(0)
1024-
#define CLK_FRAC_DIVIDER_BIG_ENDIAN BIT(1)
1029+
#define CLK_FRAC_DIVIDER_ZERO_BASED BIT(0)
1030+
#define CLK_FRAC_DIVIDER_BIG_ENDIAN BIT(1)
1031+
#define CLK_FRAC_DIVIDER_POWER_OF_TWO_PS BIT(2)
10251032

1026-
extern const struct clk_ops clk_fractional_divider_ops;
10271033
struct clk *clk_register_fractional_divider(struct device *dev,
10281034
const char *name, const char *parent_name, unsigned long flags,
10291035
void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,

0 commit comments

Comments
 (0)