pwm: lpss: Update PWM setting for Broxton
authorqipeng.zha <qipeng.zha@intel.com>
Tue, 17 Nov 2015 09:20:15 +0000 (17:20 +0800)
committerThierry Reding <thierry.reding@gmail.com>
Wed, 16 Dec 2015 15:45:38 +0000 (16:45 +0100)
For Broxton PWM controller, base unit is defined as 8-bit integer
and 14-bit fraction, so need to update base unit setting to output
wave with right frequency.

Signed-off-by: Qipeng Zha <qipeng.zha@intel.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
drivers/pwm/pwm-lpss.c
drivers/pwm/pwm-lpss.h

index 3f61c50..ebf8450 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
+#include <linux/time.h>
 
 #include "pwm-lpss.h"
 
 #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
 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,25 @@ 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 = BIT(lpwm->info->base_unit_bits);
+       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 +112,10 @@ 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);
+       base_unit &= (base_unit_range - 1);
+       ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT;
        ctrl |= on_time_div;
        /* request PWM to update on next cycle */
        ctrl |= PWM_SW_UPDATE;
@@ -155,7 +160,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;
index e8cf337..04766e0 100644 (file)
@@ -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;