From: "Chew, Chiau Ee" <chiau.ee.c...@intel.com>

This to improve the accuracy of base_unit calculation
so that the resulting PWM frquency will be more
optimal.

Signed-off-by: Chew, Kean Ho <kean.ho.c...@intel.com>
Signed-off-by: Chew, Chiau Ee <chiau.ee.c...@intel.com>
Signed-off-by: Maurice Petallo <mauricex.r.peta...@intel.com>
---
 drivers/pwm/pwm-lpss.c |   25 ++++++++++---------------
 drivers/pwm/pwm-lpss.h |   14 ++++++++------
 2 files changed, 18 insertions(+), 21 deletions(-)

diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
index eeed096..7fae747 100644
--- a/drivers/pwm/pwm-lpss.c
+++ b/drivers/pwm/pwm-lpss.c
@@ -35,32 +35,27 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct 
pwm_device *pwm,
        int duty_ns, int period_ns)
 {
        struct pwm_lpss_chip *lpwm = to_lpwm(chip);
-       u8 base_unit_hi, base_unit_lo, on_time_div;
+       u8 on_time_div;
        unsigned long c = clk_get_rate(lpwm->clk);
-       unsigned long hz, cycle_cnt;
+       unsigned long long base_unit, hz = 1000000000UL;
        u32 ctrl;
 
-       hz = 1000000000UL / period_ns;
+       do_div(hz, period_ns);
 
-       /*
-        * There is no duty cycle resolution if base_unit value is higher
-        * than 128.
-        */
-       base_unit_hi = (hz * 256) / c;
-       if (base_unit_hi > 128)
+       /* The equation is: base_unit = ((hz / c) * 65536) + correction */
+       base_unit = hz * 65536;
+       do_div(base_unit, c);
+       base_unit += PWM_DIVISION_CORRECTION;
+       if (base_unit > PWM_LIMIT)
                return -EINVAL;
 
-       base_unit_lo = (hz * 65536) / c;
-       cycle_cnt = base_unit_hi ? 256 / base_unit_hi : 256;
-
        if (duty_ns <= 0)
                duty_ns = 1;
-
-       on_time_div = cycle_cnt / (period_ns / duty_ns);
+       on_time_div = 255 - (255 * duty_ns / period_ns);
 
        ctrl = readl(lpwm->regs + PWM);
        ctrl &= ~(PWM_BASE_UNIT_MASK | PWM_ON_TIME_DIV_MASK);
-       ctrl |= (base_unit_hi | base_unit_lo) << PWM_BASE_UNIT_SHIFT;
+       ctrl |= (u16) base_unit << PWM_BASE_UNIT_SHIFT;
        ctrl |= on_time_div;
        /* request PWM to update on next cycle */
        ctrl |= PWM_SW_UPDATE;
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
index d1705e5..a9f2307 100644
--- a/drivers/pwm/pwm-lpss.h
+++ b/drivers/pwm/pwm-lpss.h
@@ -1,9 +1,11 @@
-#define PWM                    0x00000000
-#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                            0x00000000
+#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)
 
 struct pwm_lpss_chip {
        struct pwm_chip chip;
-- 
1.7.10.4

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to