]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
pwm: tegra: fix PWM_SCALE_WIDTH calculation
authorR Raj Kumar <rrajk@nvidia.com>
Thu, 20 Oct 2016 10:09:22 +0000 (15:39 +0530)
committermobile promotions <svcmobile_promotions@nvidia.com>
Thu, 27 Oct 2016 09:51:18 +0000 (02:51 -0700)
Fixed PWM_SCALE_WIDTH calculation by considering
more precision level upto two digits.
-Cherry-picked from http://git-master/r/#/c/1239806/

Bug 200244492

Change-Id: I2632ba4af0f1dcc66a3bec2d06ee7b305c06d920
Signed-off-by: R Raj Kumar <rrajk@nvidia.com>
Reviewed-on: http://git-master/r/1243052
GVS: Gerrit_Virtual_Submit
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
drivers/pwm/pwm-tegra.c

index 004bcc2703e8143b389d3e9c27c6871276ccf7eb..3e93be5804ba9f0ff1ca221e512a622acf8550bf 100644 (file)
@@ -77,7 +77,7 @@ static inline void pwm_writel(struct tegra_pwm_chip *chip, unsigned int num,
        writel(val, chip->mmio_base + (num << 4));
 }
 
-static int tegra_get_optimal_rate(struct tegra_pwm_chip *pc,
+static long tegra_get_optimal_rate(struct tegra_pwm_chip *pc,
                                int duty_ns, int period_ns)
 {
        unsigned long due_dp, dn, due_dm;
@@ -123,7 +123,10 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 {
        struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
        unsigned long long c = duty_ns;
-       unsigned long rate, hz;
+       unsigned long hz;
+       unsigned long long ns100 = NSEC_PER_SEC;
+       unsigned int precision = 100;
+       long rate = 0;
        u32 val = 0;
        int err;
 
@@ -160,9 +163,12 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
         * cycles at the PWM clock rate will take period_ns nanoseconds.
         */
        rate = clk_get_rate(pc->clk) >> PWM_DUTY_WIDTH;
-       hz = NSEC_PER_SEC / period_ns;
 
-       rate = (rate + (hz / 2)) / hz;
+       /* Consider two digit precision in PWM_SCALE_WIDTH rate calculation */
+       hz = ns100 * precision;
+       do_div(hz, period_ns);
+
+       rate = DIV_ROUND_CLOSEST((rate * precision), hz);
 
        /*
         * Since the actual PWM divider is the register's frequency divider