Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: lpc32xx: add a quirk for PWM and MS clock dividers

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>

authored by

Vladimir Zapolskiy and committed by
Stephen Boyd
f84d42a9 4154f619

+28 -4
+28 -4
drivers/clk/nxp/clk-lpc32xx.c
··· 1282 1282 1283 1283 LPC32XX_DEFINE_MUX(PWM1_MUX, PWMCLK_CTRL, 1, 0x1, NULL, 0), 1284 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 1286 LPC32XX_DEFINE_GATE(PWM1_GATE, PWMCLK_CTRL, 0, 0), 1287 1287 LPC32XX_DEFINE_COMPOSITE(PWM1, PWM1_MUX, PWM1_DIV, PWM1_GATE), 1288 1288 1289 1289 LPC32XX_DEFINE_MUX(PWM2_MUX, PWMCLK_CTRL, 3, 0x1, NULL, 0), 1290 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 1292 LPC32XX_DEFINE_GATE(PWM2_GATE, PWMCLK_CTRL, 2, 0), 1293 1293 LPC32XX_DEFINE_COMPOSITE(PWM2, PWM2_MUX, PWM2_DIV, PWM2_GATE), 1294 1294 ··· 1335 1335 LPC32XX_DEFINE_GATE(USB_DIV_GATE, USB_CTRL, 17, 0), 1336 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, 1339 - CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO), 1338 + LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL, CLK_DIVIDER_ONE_BASED), 1340 1339 LPC32XX_DEFINE_CLK(SD_GATE, MS_CTRL, BIT(5) | BIT(9), BIT(5) | BIT(9), 1341 1340 0x0, BIT(5) | BIT(9), 0x0, 0x0, clk_mask_ops), 1342 1341 LPC32XX_DEFINE_COMPOSITE(SD, _NULL, SD_DIV, SD_GATE), ··· 1477 1478 return clk; 1478 1479 } 1479 1480 1481 + static void __init lpc32xx_clk_div_quirk(u32 reg, u32 div_mask, u32 gate) 1482 + { 1483 + u32 val; 1484 + 1485 + regmap_read(clk_regmap, reg, &val); 1486 + 1487 + if (!(val & div_mask)) { 1488 + val &= ~gate; 1489 + val |= BIT(__ffs(div_mask)); 1490 + } 1491 + 1492 + regmap_update_bits(clk_regmap, reg, gate | div_mask, val); 1493 + } 1494 + 1480 1495 static void __init lpc32xx_clk_init(struct device_node *np) 1481 1496 { 1482 1497 unsigned int i; ··· 1529 1516 iounmap(base); 1530 1517 return; 1531 1518 } 1519 + 1520 + /* 1521 + * Divider part of PWM and MS clocks requires a quirk to avoid 1522 + * a misinterpretation of formally valid zero value in register 1523 + * bitfield, which indicates another clock gate. Instead of 1524 + * adding complexity to a gate clock ensure that zero value in 1525 + * divider clock is never met in runtime. 1526 + */ 1527 + lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf0, BIT(0)); 1528 + lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf00, BIT(2)); 1529 + lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_MS_CTRL, 0xf, BIT(5) | BIT(9)); 1532 1530 1533 1531 for (i = 1; i < LPC32XX_CLK_MAX; i++) { 1534 1532 clk[i] = lpc32xx_clk_register(i);