From bf9cc80b6c3ec2754b570d377ed7f7e2ec96868a Mon Sep 17 00:00:00 2001 From: Ajit Pal Singh Date: Mon, 14 Jul 2014 15:33:29 +0100 Subject: [PATCH] pwm: sti: Fix PWM prescaler handling This patch fixes the pwm driver to write the complete 8 bits of the prescaler value to the PWM Control register. Signed-off-by: Ajit Pal Singh Signed-off-by: Lee Jones Signed-off-by: Thierry Reding --- drivers/pwm/pwm-sti.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c index 0b714e45e5c0..76346e32f403 100644 --- a/drivers/pwm/pwm-sti.c +++ b/drivers/pwm/pwm-sti.c @@ -25,10 +25,13 @@ #define STI_DS_REG(ch) (4 * (ch)) /* Channel's Duty Cycle register */ #define STI_PWMCR 0x50 /* Control/Config register */ #define STI_INTEN 0x54 /* Interrupt Enable/Disable register */ +#define PWM_PRESCALE_LOW_MASK 0x0f +#define PWM_PRESCALE_HIGH_MASK 0xf0 /* Regfield IDs */ enum { - PWMCLK_PRESCALE, + PWMCLK_PRESCALE_LOW, + PWMCLK_PRESCALE_HIGH, PWM_EN, PWM_INT_EN, @@ -49,7 +52,8 @@ struct sti_pwm_chip { unsigned long clk_rate; struct regmap *regmap; struct sti_pwm_compat_data *cdata; - struct regmap_field *prescale; + struct regmap_field *prescale_low; + struct regmap_field *prescale_high; struct regmap_field *pwm_en; struct regmap_field *pwm_int_en; unsigned long *pwm_periods; @@ -58,7 +62,8 @@ struct sti_pwm_chip { }; static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = { - [PWMCLK_PRESCALE] = REG_FIELD(STI_PWMCR, 0, 3), + [PWMCLK_PRESCALE_LOW] = REG_FIELD(STI_PWMCR, 0, 3), + [PWMCLK_PRESCALE_HIGH] = REG_FIELD(STI_PWMCR, 11, 14), [PWM_EN] = REG_FIELD(STI_PWMCR, 9, 9), [PWM_INT_EN] = REG_FIELD(STI_INTEN, 0, 0), }; @@ -109,10 +114,10 @@ static int sti_pwm_cmp_periods(const void *key, const void *elt) * For STiH4xx PWM IP, the PWM period is fixed to 256 local clock cycles. * The only way to change the period (apart from changing the PWM input clock) * is to change the PWM clock prescaler. - * The prescaler is of 4 bits, so only 16 prescaler values and hence only - * 16 possible period values are supported (for a particular clock rate). + * The prescaler is of 8 bits, so 256 prescaler values and hence + * 256 possible period values are supported (for a particular clock rate). * The requested period will be applied only if it matches one of these - * 16 values. + * 256 values. */ static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, int duty_ns, int period_ns) @@ -154,7 +159,13 @@ static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, if (ret) return ret; - ret = regmap_field_write(pc->prescale, prescale); + ret = regmap_field_write(pc->prescale_low, + prescale & PWM_PRESCALE_LOW_MASK); + if (ret) + goto clk_dis; + + ret = regmap_field_write(pc->prescale_high, + (prescale & PWM_PRESCALE_HIGH_MASK) >> 4); if (ret) goto clk_dis; @@ -222,10 +233,15 @@ static int sti_pwm_probe_dt(struct sti_pwm_chip *pc) reg_fields = cdata->reg_fields; - pc->prescale = devm_regmap_field_alloc(dev, pc->regmap, - reg_fields[PWMCLK_PRESCALE]); - if (IS_ERR(pc->prescale)) - return PTR_ERR(pc->prescale); + pc->prescale_low = devm_regmap_field_alloc(dev, pc->regmap, + reg_fields[PWMCLK_PRESCALE_LOW]); + if (IS_ERR(pc->prescale_low)) + return PTR_ERR(pc->prescale_low); + + pc->prescale_high = devm_regmap_field_alloc(dev, pc->regmap, + reg_fields[PWMCLK_PRESCALE_HIGH]); + if (IS_ERR(pc->prescale_high)) + return PTR_ERR(pc->prescale_high); pc->pwm_en = devm_regmap_field_alloc(dev, pc->regmap, reg_fields[PWM_EN]);