Skip to content

Commit 959ca92

Browse files
msperlanholt
authored andcommitted
clk: bcm2835: correctly enable fractional clock support
The current driver calculates the clock divider with fractional support enabled. But it does not enable fractional support in the control register itself resulting in an integer only divider, but in clk_set_rate responds back the fractionally divided clock frequency. This patch enables fractional support in the control register whenever there is a fractional bit set in the requested clock divider. Mash clock limits are are also handled for the PWM clock applying the correct divider limits (2 and max_int) applicable to basic fractional divider support (mash order of 1). It also adds locking to protect the read/modify/write cycle of the register modification. Fixes: 41691b8 ("clk: bcm2835: Add support for programming the audio domain clocks") Signed-off-by: Martin Sperl <[email protected]> Signed-off-by: Eric Anholt <[email protected]> Reviewed-by: Eric Anholt <[email protected]>
1 parent 997f16b commit 959ca92

File tree

1 file changed

+39
-6
lines changed

1 file changed

+39
-6
lines changed

drivers/clk/bcm/clk-bcm2835.c

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#define CM_GNRICCTL 0x000
5252
#define CM_GNRICDIV 0x004
5353
# define CM_DIV_FRAC_BITS 12
54+
# define CM_DIV_FRAC_MASK GENMASK(CM_DIV_FRAC_BITS - 1, 0)
5455

5556
#define CM_VPUCTL 0x008
5657
#define CM_VPUDIV 0x00c
@@ -128,6 +129,7 @@
128129
# define CM_GATE BIT(CM_GATE_BIT)
129130
# define CM_BUSY BIT(7)
130131
# define CM_BUSYD BIT(8)
132+
# define CM_FRAC BIT(9)
131133
# define CM_SRC_SHIFT 0
132134
# define CM_SRC_BITS 4
133135
# define CM_SRC_MASK 0xf
@@ -644,6 +646,7 @@ struct bcm2835_clock_data {
644646
u32 frac_bits;
645647

646648
bool is_vpu_clock;
649+
bool is_mash_clock;
647650
};
648651

649652
static const char *const bcm2835_clock_per_parents[] = {
@@ -825,6 +828,7 @@ static const struct bcm2835_clock_data bcm2835_clock_pwm_data = {
825828
.div_reg = CM_PWMDIV,
826829
.int_bits = 12,
827830
.frac_bits = 12,
831+
.is_mash_clock = true,
828832
};
829833

830834
struct bcm2835_pll {
@@ -1180,7 +1184,7 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
11801184
GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1;
11811185
u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS;
11821186
u64 rem;
1183-
u32 div;
1187+
u32 div, mindiv, maxdiv;
11841188

11851189
rem = do_div(temp, rate);
11861190
div = temp;
@@ -1190,11 +1194,23 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
11901194
div += unused_frac_mask + 1;
11911195
div &= ~unused_frac_mask;
11921196

1193-
/* clamp to min divider of 1 */
1194-
div = max_t(u32, div, 1 << CM_DIV_FRAC_BITS);
1195-
/* clamp to the highest possible fractional divider */
1196-
div = min_t(u32, div, GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
1197-
CM_DIV_FRAC_BITS - data->frac_bits));
1197+
/* different clamping limits apply for a mash clock */
1198+
if (data->is_mash_clock) {
1199+
/* clamp to min divider of 2 */
1200+
mindiv = 2 << CM_DIV_FRAC_BITS;
1201+
/* clamp to the highest possible integer divider */
1202+
maxdiv = (BIT(data->int_bits) - 1) << CM_DIV_FRAC_BITS;
1203+
} else {
1204+
/* clamp to min divider of 1 */
1205+
mindiv = 1 << CM_DIV_FRAC_BITS;
1206+
/* clamp to the highest possible fractional divider */
1207+
maxdiv = GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
1208+
CM_DIV_FRAC_BITS - data->frac_bits);
1209+
}
1210+
1211+
/* apply the clamping limits */
1212+
div = max_t(u32, div, mindiv);
1213+
div = min_t(u32, div, maxdiv);
11981214

11991215
return div;
12001216
}
@@ -1288,9 +1304,26 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw,
12881304
struct bcm2835_cprman *cprman = clock->cprman;
12891305
const struct bcm2835_clock_data *data = clock->data;
12901306
u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false);
1307+
u32 ctl;
1308+
1309+
spin_lock(&cprman->regs_lock);
1310+
1311+
/*
1312+
* Setting up frac support
1313+
*
1314+
* In principle it is recommended to stop/start the clock first,
1315+
* but as we set CLK_SET_RATE_GATE during registration of the
1316+
* clock this requirement should be take care of by the
1317+
* clk-framework.
1318+
*/
1319+
ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC;
1320+
ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
1321+
cprman_write(cprman, data->ctl_reg, ctl);
12911322

12921323
cprman_write(cprman, data->div_reg, div);
12931324

1325+
spin_unlock(&cprman->regs_lock);
1326+
12941327
return 0;
12951328
}
12961329

0 commit comments

Comments
 (0)