[linux-yocto] [PATCH 20/29] pwm: lpss: Fix base_unit calculation
rebecca.swee.fun.chang at intel.com
rebecca.swee.fun.chang at intel.com
Mon Apr 7 08:18:11 PDT 2014
From: "Chew, Chiau Ee" <chiau.ee.chew at 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.chew at intel.com>
Signed-off-by: Chew, Chiau Ee <chiau.ee.chew at intel.com>
Signed-off-by: Maurice Petallo <mauricex.r.petallo at 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
More information about the linux-yocto
mailing list