On Fri, Nov 13, 2015 at 06:34:10PM +0800, Qipeng Zha wrote:
> For Broxton PWM controller, base unit is defined as 8bit integer
> and 14bit fraction, so need to update base unit setting to output
> wave with right frequency.
> 
> Signed-off-by: Qipeng Zha <[email protected]>

Looking good. Few minor comments, see below.

> ---
>  drivers/pwm/pwm-lpss.c | 29 +++++++++++++++--------------
>  drivers/pwm/pwm-lpss.h |  1 +
>  2 files changed, 16 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
> index 2504410..f4f8ee5 100644
> --- a/drivers/pwm/pwm-lpss.c
> +++ b/drivers/pwm/pwm-lpss.c
> @@ -14,6 +14,7 @@
>   */
>  
>  #include <linux/io.h>
> +#include <linux/time.h>
>  #include <linux/kernel.h>
>  #include <linux/module.h>
>  #include <linux/pm_runtime.h>
> @@ -24,11 +25,8 @@
>  #define PWM_ENABLE                   BIT(31)
>  #define PWM_SW_UPDATE                        BIT(30)
>  #define PWM_BASE_UNIT_SHIFT          8
> -#define PWM_BASE_UNIT_MASK           0x00ffff00
>  #define PWM_ON_TIME_DIV_MASK         0x000000ff
>  #define PWM_DIVISION_CORRECTION              0x2
> -#define PWM_LIMIT                    (0x8000 + PWM_DIVISION_CORRECTION)
> -#define NSECS_PER_SEC                        1000000000UL
>  
>  /* Size of each PWM register space if multiple */
>  #define PWM_SIZE                     0x400
> @@ -36,13 +34,14 @@
>  struct pwm_lpss_chip {
>       struct pwm_chip chip;
>       void __iomem *regs;
> -     unsigned long clk_rate;
> +     const struct pwm_lpss_boardinfo *info;
>  };
>  
>  /* BayTrail */
>  const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
>       .clk_rate = 25000000,
>       .npwm = 1,
> +     .base_unit_bits = 16,
>  };
>  EXPORT_SYMBOL_GPL(pwm_lpss_byt_info);
>  
> @@ -50,6 +49,7 @@ EXPORT_SYMBOL_GPL(pwm_lpss_byt_info);
>  const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
>       .clk_rate = 19200000,
>       .npwm = 1,
> +     .base_unit_bits = 16,
>  };
>  EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info);
>  
> @@ -57,6 +57,7 @@ EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info);
>  const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
>       .clk_rate = 19200000,
>       .npwm = 4,
> +     .base_unit_bits = 22,
>  };
>  EXPORT_SYMBOL_GPL(pwm_lpss_bxt_info);
>  
> @@ -84,23 +85,22 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct 
> pwm_device *pwm,
>  {
>       struct pwm_lpss_chip *lpwm = to_lpwm(chip);
>       u8 on_time_div;
> -     unsigned long c;
> -     unsigned long long base_unit, freq = NSECS_PER_SEC;
> +     unsigned long c, base_unit_range;
> +     unsigned long long base_unit, freq = NSEC_PER_SEC;
>       u32 ctrl;
>  
>       do_div(freq, period_ns);
>  
> -     /* The equation is: base_unit = ((freq / c) * 65536) + correction */
> -     base_unit = freq * 65536;
> +     /* The equation is: base_unit = ((freq / c) * base_unit_range) + 
> correction */
> +     base_unit_range = 1 << lpwm->info->base_unit_bits;

BIT()?

> +     base_unit = freq * base_unit_range;
>  
> -     c = lpwm->clk_rate;
> +     c = lpwm->info->clk_rate;
>       if (!c)
>               return -EINVAL;
>  
>       do_div(base_unit, c);
>       base_unit += PWM_DIVISION_CORRECTION;
> -     if (base_unit > PWM_LIMIT)
> -             return -EINVAL;
>  
>       if (duty_ns <= 0)
>               duty_ns = 1;
> @@ -109,8 +109,9 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct 
> pwm_device *pwm,
>       pm_runtime_get_sync(chip->dev);
>  
>       ctrl = pwm_lpss_read(pwm);
> -     ctrl &= ~(PWM_BASE_UNIT_MASK | PWM_ON_TIME_DIV_MASK);
> -     ctrl |= (u16) base_unit << PWM_BASE_UNIT_SHIFT;
> +     ctrl &= ~PWM_ON_TIME_DIV_MASK;
> +     ctrl &= ~((base_unit_range - 1) << PWM_BASE_UNIT_SHIFT);
> +     ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT;

I think you should first mask base_unit (with base_unit_range - 1) so that it
will not accidentally overwrite the upper bits.

>       ctrl |= on_time_div;
>       /* request PWM to update on next cycle */
>       ctrl |= PWM_SW_UPDATE;
> @@ -156,7 +157,7 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, 
> struct resource *r,
>       if (IS_ERR(lpwm->regs))
>               return ERR_CAST(lpwm->regs);
>  
> -     lpwm->clk_rate = info->clk_rate;
> +     lpwm->info = info;
>       lpwm->chip.dev = dev;
>       lpwm->chip.ops = &pwm_lpss_ops;
>       lpwm->chip.base = -1;
> diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
> index e8cf337..04766e0 100644
> --- a/drivers/pwm/pwm-lpss.h
> +++ b/drivers/pwm/pwm-lpss.h
> @@ -21,6 +21,7 @@ struct pwm_lpss_chip;
>  struct pwm_lpss_boardinfo {
>       unsigned long clk_rate;
>       unsigned int npwm;
> +     unsigned long base_unit_bits;
>  };
>  
>  extern const struct pwm_lpss_boardinfo pwm_lpss_byt_info;
> -- 
> 1.8.3.2
--
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

Reply via email to