at91sam9x5 has an errata forbidding the use of slow clk as a clk source and sama5d3 SoCs has another errata forbidding the use of div1 prescaler.
Take both of these erratas into account. Signed-off-by: Boris Brezillon <[email protected]> --- drivers/pwm/pwm-atmel-hlcdc.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c index eaf8b12..405f8a5 100644 --- a/drivers/pwm/pwm-atmel-hlcdc.c +++ b/drivers/pwm/pwm-atmel-hlcdc.c @@ -36,6 +36,8 @@ struct atmel_hlcdc_pwm { struct pwm_chip chip; struct atmel_hlcdc *hlcdc; struct clk *cur_clk; + bool slow_clk_errata; + bool div1_clk_errata; }; static inline struct atmel_hlcdc_pwm *to_atmel_hlcdc_pwm(struct pwm_chip *chip) @@ -56,20 +58,28 @@ static int atmel_hlcdc_pwm_config(struct pwm_chip *c, u32 pwmcfg; int pres; - clk_freq = clk_get_rate(new_clk); - clk_period_ns = (u64)NSEC_PER_SEC * 256; - do_div(clk_period_ns, clk_freq); + if (!chip->slow_clk_errata) { + clk_freq = clk_get_rate(new_clk); + clk_period_ns = (u64)NSEC_PER_SEC * 256; + do_div(clk_period_ns, clk_freq); + } - if (clk_period_ns > period_ns) { + /* Errata: cannot use slow clk on some IP revisions */ + if (chip->slow_clk_errata || clk_period_ns > period_ns) { new_clk = hlcdc->sys_clk; clk_freq = clk_get_rate(new_clk); clk_period_ns = (u64)NSEC_PER_SEC * 256; do_div(clk_period_ns, clk_freq); } - for (pres = 0; pres <= ATMEL_HLCDC_PWMPS_MAX; pres++) + for (pres = 0; pres <= ATMEL_HLCDC_PWMPS_MAX; pres++) { + /* Errata: cannot divide by 1 on some IP revisions */ + if (!pres && chip->div1_clk_errata) + continue; + if ((clk_period_ns << pres) >= period_ns) break; + } if (pres > ATMEL_HLCDC_PWMPS_MAX) return -EINVAL; @@ -204,6 +214,14 @@ static int atmel_hlcdc_pwm_probe(struct platform_device *pdev) if (ret) return ret; + if (of_device_is_compatible(dev->parent->of_node, + "atmel,sama5d3-hlcdc")) + chip->div1_clk_errata = true; + + if (of_device_is_compatible(dev->parent->of_node, + "atmel,at91sam9x5-hlcdc")) + chip->slow_clk_errata = true; + chip->hlcdc = hlcdc; chip->chip.ops = &atmel_hlcdc_pwm_ops; chip->chip.dev = dev; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-pwm" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
