diff options
author | Vladimir Zapolskiy <vz@mleia.com> | 2017-04-04 15:32:03 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-04-12 06:41:15 -0400 |
commit | e02a5d1d5a053374dffe9ed6300113a125121f29 (patch) | |
tree | c98efa84dcd3dddfc4b5aaf8de7f94f27f383a07 | |
parent | 666d5f34d8972d1d159b9f79f56620b6e817cc8a (diff) |
clk: lpc32xx: add a quirk for PWM and MS clock dividers
[ Upstream commit f84d42a9cffc4ecd96f1ce3a038f841782142eb2 ]
In common clock framework CLK_DIVIDER_ONE_BASED or'ed with
CLK_DIVIDER_ALLOW_ZERO flags indicates that
1) a divider clock may be set to zero value,
2) divider's zero value is interpreted as a non-divided clock.
On the LPC32xx platform clock dividers of PWM and memory card clocks
comply with the first condition, but zero value means a gated clock,
thus it may happen that the divider value is not updated when
the clock is enabled and the clock remains gated.
The change adds one-shot quirks, which check for zero value of divider
on initialization and set it to a non-zero value, therefore in runtime
a gate clock will work as expected.
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Reviewed-by: Sylvain Lemieux <slemieux.tyco@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/clk/nxp/clk-lpc32xx.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c index 34c97353cdeb..5b98ff9076f3 100644 --- a/drivers/clk/nxp/clk-lpc32xx.c +++ b/drivers/clk/nxp/clk-lpc32xx.c | |||
@@ -1282,13 +1282,13 @@ static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = { | |||
1282 | 1282 | ||
1283 | LPC32XX_DEFINE_MUX(PWM1_MUX, PWMCLK_CTRL, 1, 0x1, NULL, 0), | 1283 | LPC32XX_DEFINE_MUX(PWM1_MUX, PWMCLK_CTRL, 1, 0x1, NULL, 0), |
1284 | LPC32XX_DEFINE_DIV(PWM1_DIV, PWMCLK_CTRL, 4, 4, NULL, | 1284 | LPC32XX_DEFINE_DIV(PWM1_DIV, PWMCLK_CTRL, 4, 4, NULL, |
1285 | CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO), | 1285 | CLK_DIVIDER_ONE_BASED), |
1286 | LPC32XX_DEFINE_GATE(PWM1_GATE, PWMCLK_CTRL, 0, 0), | 1286 | LPC32XX_DEFINE_GATE(PWM1_GATE, PWMCLK_CTRL, 0, 0), |
1287 | LPC32XX_DEFINE_COMPOSITE(PWM1, PWM1_MUX, PWM1_DIV, PWM1_GATE), | 1287 | LPC32XX_DEFINE_COMPOSITE(PWM1, PWM1_MUX, PWM1_DIV, PWM1_GATE), |
1288 | 1288 | ||
1289 | LPC32XX_DEFINE_MUX(PWM2_MUX, PWMCLK_CTRL, 3, 0x1, NULL, 0), | 1289 | LPC32XX_DEFINE_MUX(PWM2_MUX, PWMCLK_CTRL, 3, 0x1, NULL, 0), |
1290 | LPC32XX_DEFINE_DIV(PWM2_DIV, PWMCLK_CTRL, 8, 4, NULL, | 1290 | LPC32XX_DEFINE_DIV(PWM2_DIV, PWMCLK_CTRL, 8, 4, NULL, |
1291 | CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO), | 1291 | CLK_DIVIDER_ONE_BASED), |
1292 | LPC32XX_DEFINE_GATE(PWM2_GATE, PWMCLK_CTRL, 2, 0), | 1292 | LPC32XX_DEFINE_GATE(PWM2_GATE, PWMCLK_CTRL, 2, 0), |
1293 | LPC32XX_DEFINE_COMPOSITE(PWM2, PWM2_MUX, PWM2_DIV, PWM2_GATE), | 1293 | LPC32XX_DEFINE_COMPOSITE(PWM2, PWM2_MUX, PWM2_DIV, PWM2_GATE), |
1294 | 1294 | ||
@@ -1335,8 +1335,7 @@ static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = { | |||
1335 | LPC32XX_DEFINE_GATE(USB_DIV_GATE, USB_CTRL, 17, 0), | 1335 | LPC32XX_DEFINE_GATE(USB_DIV_GATE, USB_CTRL, 17, 0), |
1336 | LPC32XX_DEFINE_COMPOSITE(USB_DIV, _NULL, USB_DIV_DIV, USB_DIV_GATE), | 1336 | LPC32XX_DEFINE_COMPOSITE(USB_DIV, _NULL, USB_DIV_DIV, USB_DIV_GATE), |
1337 | 1337 | ||
1338 | LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL, | 1338 | LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL, CLK_DIVIDER_ONE_BASED), |
1339 | CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO), | ||
1340 | LPC32XX_DEFINE_CLK(SD_GATE, MS_CTRL, BIT(5) | BIT(9), BIT(5) | BIT(9), | 1339 | LPC32XX_DEFINE_CLK(SD_GATE, MS_CTRL, BIT(5) | BIT(9), BIT(5) | BIT(9), |
1341 | 0x0, BIT(5) | BIT(9), 0x0, 0x0, clk_mask_ops), | 1340 | 0x0, BIT(5) | BIT(9), 0x0, 0x0, clk_mask_ops), |
1342 | LPC32XX_DEFINE_COMPOSITE(SD, _NULL, SD_DIV, SD_GATE), | 1341 | LPC32XX_DEFINE_COMPOSITE(SD, _NULL, SD_DIV, SD_GATE), |
@@ -1478,6 +1477,20 @@ static struct clk * __init lpc32xx_clk_register(u32 id) | |||
1478 | return clk; | 1477 | return clk; |
1479 | } | 1478 | } |
1480 | 1479 | ||
1480 | static void __init lpc32xx_clk_div_quirk(u32 reg, u32 div_mask, u32 gate) | ||
1481 | { | ||
1482 | u32 val; | ||
1483 | |||
1484 | regmap_read(clk_regmap, reg, &val); | ||
1485 | |||
1486 | if (!(val & div_mask)) { | ||
1487 | val &= ~gate; | ||
1488 | val |= BIT(__ffs(div_mask)); | ||
1489 | } | ||
1490 | |||
1491 | regmap_update_bits(clk_regmap, reg, gate | div_mask, val); | ||
1492 | } | ||
1493 | |||
1481 | static void __init lpc32xx_clk_init(struct device_node *np) | 1494 | static void __init lpc32xx_clk_init(struct device_node *np) |
1482 | { | 1495 | { |
1483 | unsigned int i; | 1496 | unsigned int i; |
@@ -1517,6 +1530,17 @@ static void __init lpc32xx_clk_init(struct device_node *np) | |||
1517 | return; | 1530 | return; |
1518 | } | 1531 | } |
1519 | 1532 | ||
1533 | /* | ||
1534 | * Divider part of PWM and MS clocks requires a quirk to avoid | ||
1535 | * a misinterpretation of formally valid zero value in register | ||
1536 | * bitfield, which indicates another clock gate. Instead of | ||
1537 | * adding complexity to a gate clock ensure that zero value in | ||
1538 | * divider clock is never met in runtime. | ||
1539 | */ | ||
1540 | lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf0, BIT(0)); | ||
1541 | lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf00, BIT(2)); | ||
1542 | lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_MS_CTRL, 0xf, BIT(5) | BIT(9)); | ||
1543 | |||
1520 | for (i = 1; i < LPC32XX_CLK_MAX; i++) { | 1544 | for (i = 1; i < LPC32XX_CLK_MAX; i++) { |
1521 | clk[i] = lpc32xx_clk_register(i); | 1545 | clk[i] = lpc32xx_clk_register(i); |
1522 | if (IS_ERR(clk[i])) { | 1546 | if (IS_ERR(clk[i])) { |