737a1a9b64e39f06e1899f7671e2a9426e847fc6
[openwrt/staging/yousong.git] / target / linux / brcm2708 / patches-4.4 / 0256-clk-bcm2835-correctly-enable-fractional-clock-suppor.patch
1 From d1b891afed88e5f675fa30f1dcc8e728472208ac Mon Sep 17 00:00:00 2001
2 From: Martin Sperl <kernel@martin.sperl.org>
3 Date: Mon, 29 Feb 2016 11:39:21 +0000
4 Subject: [PATCH] clk: bcm2835: correctly enable fractional clock support
5
6 The current driver calculates the clock divider with
7 fractional support enabled.
8
9 But it does not enable fractional support in the
10 control register itself resulting in an integer only divider,
11 but in clk_set_rate responds back the fractionally divided
12 clock frequency.
13
14 This patch enables fractional support in the control register
15 whenever there is a fractional bit set in the requested clock divider.
16
17 Mash clock limits are are also handled for the PWM clock
18 applying the correct divider limits (2 and max_int) applicable to
19 basic fractional divider support (mash order of 1).
20
21 It also adds locking to protect the read/modify/write cycle of
22 the register modification.
23
24 Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the
25 audio domain clocks")
26
27 Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
28 Signed-off-by: Eric Anholt <eric@anholt.net>
29 Reviewed-by: Eric Anholt <eric@anholt.net>
30 (cherry picked from commit 959ca92a3235fc4b17c1e18483fc390b3d612254)
31 ---
32 drivers/clk/bcm/clk-bcm2835.c | 45 +++++++++++++++++++++++++++++++++++++------
33 1 file changed, 39 insertions(+), 6 deletions(-)
34
35 --- a/drivers/clk/bcm/clk-bcm2835.c
36 +++ b/drivers/clk/bcm/clk-bcm2835.c
37 @@ -51,6 +51,7 @@
38 #define CM_GNRICCTL 0x000
39 #define CM_GNRICDIV 0x004
40 # define CM_DIV_FRAC_BITS 12
41 +# define CM_DIV_FRAC_MASK GENMASK(CM_DIV_FRAC_BITS - 1, 0)
42
43 #define CM_VPUCTL 0x008
44 #define CM_VPUDIV 0x00c
45 @@ -128,6 +129,7 @@
46 # define CM_GATE BIT(CM_GATE_BIT)
47 # define CM_BUSY BIT(7)
48 # define CM_BUSYD BIT(8)
49 +# define CM_FRAC BIT(9)
50 # define CM_SRC_SHIFT 0
51 # define CM_SRC_BITS 4
52 # define CM_SRC_MASK 0xf
53 @@ -647,6 +649,7 @@ struct bcm2835_clock_data {
54 u32 frac_bits;
55
56 bool is_vpu_clock;
57 + bool is_mash_clock;
58 };
59
60 static const char *const bcm2835_clock_per_parents[] = {
61 @@ -828,6 +831,7 @@ static const struct bcm2835_clock_data b
62 .div_reg = CM_PWMDIV,
63 .int_bits = 12,
64 .frac_bits = 12,
65 + .is_mash_clock = true,
66 };
67
68 struct bcm2835_pll {
69 @@ -1196,7 +1200,7 @@ static u32 bcm2835_clock_choose_div(stru
70 GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1;
71 u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS;
72 u64 rem;
73 - u32 div;
74 + u32 div, mindiv, maxdiv;
75
76 rem = do_div(temp, rate);
77 div = temp;
78 @@ -1206,11 +1210,23 @@ static u32 bcm2835_clock_choose_div(stru
79 div += unused_frac_mask + 1;
80 div &= ~unused_frac_mask;
81
82 - /* clamp to min divider of 1 */
83 - div = max_t(u32, div, 1 << CM_DIV_FRAC_BITS);
84 - /* clamp to the highest possible fractional divider */
85 - div = min_t(u32, div, GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
86 - CM_DIV_FRAC_BITS - data->frac_bits));
87 + /* different clamping limits apply for a mash clock */
88 + if (data->is_mash_clock) {
89 + /* clamp to min divider of 2 */
90 + mindiv = 2 << CM_DIV_FRAC_BITS;
91 + /* clamp to the highest possible integer divider */
92 + maxdiv = (BIT(data->int_bits) - 1) << CM_DIV_FRAC_BITS;
93 + } else {
94 + /* clamp to min divider of 1 */
95 + mindiv = 1 << CM_DIV_FRAC_BITS;
96 + /* clamp to the highest possible fractional divider */
97 + maxdiv = GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
98 + CM_DIV_FRAC_BITS - data->frac_bits);
99 + }
100 +
101 + /* apply the clamping limits */
102 + div = max_t(u32, div, mindiv);
103 + div = min_t(u32, div, maxdiv);
104
105 return div;
106 }
107 @@ -1304,9 +1320,26 @@ static int bcm2835_clock_set_rate(struct
108 struct bcm2835_cprman *cprman = clock->cprman;
109 const struct bcm2835_clock_data *data = clock->data;
110 u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false);
111 + u32 ctl;
112 +
113 + spin_lock(&cprman->regs_lock);
114 +
115 + /*
116 + * Setting up frac support
117 + *
118 + * In principle it is recommended to stop/start the clock first,
119 + * but as we set CLK_SET_RATE_GATE during registration of the
120 + * clock this requirement should be take care of by the
121 + * clk-framework.
122 + */
123 + ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC;
124 + ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
125 + cprman_write(cprman, data->ctl_reg, ctl);
126
127 cprman_write(cprman, data->div_reg, div);
128
129 + spin_unlock(&cprman->regs_lock);
130 +
131 return 0;
132 }
133