]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
pwm: sifive: make set_config() and set_enable() work properly
authorVincent Chen <vincent.chen@sifive.com>
Mon, 3 May 2021 07:26:49 +0000 (15:26 +0800)
committerLeo Yu-Chi Liang <ycliang@andestech.com>
Fri, 14 May 2021 08:25:42 +0000 (16:25 +0800)
The pwm_sifive_set_config() and pwm_sifive_set_enable() cannot work
properly due to the wrong implementations. It will cause the u-boot
PWM command to not work as expected. The bugs will be resolved in this
patch.

Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
Reviewed-by: Rick Chen <rick@andestech.com>
drivers/pwm/pwm-sifive.c

index 01212d630a922983eec80cda0d4f6fdf49c8f9d6..b9813a3b6bbeadda0990223af5d391375654a382 100644 (file)
@@ -38,6 +38,9 @@
 #define PWM_SIFIVE_SIZE_PWMCMP          4
 #define PWM_SIFIVE_CMPWIDTH             16
 
+#define PWM_SIFIVE_CHANNEL_ENABLE_VAL   0
+#define PWM_SIFIVE_CHANNEL_DISABLE_VAL  0xffff
+
 DECLARE_GLOBAL_DATA_PTR;
 
 struct pwm_sifive_regs {
@@ -77,7 +80,7 @@ static int pwm_sifive_set_config(struct udevice *dev, uint channel,
         */
        scale_pow = lldiv((uint64_t)priv->freq * period_ns, 1000000000);
        scale = clamp(ilog2(scale_pow) - PWM_SIFIVE_CMPWIDTH, 0, 0xf);
-       val |= FIELD_PREP(PWM_SIFIVE_PWMCFG_SCALE, scale);
+       val |= (FIELD_PREP(PWM_SIFIVE_PWMCFG_SCALE, scale) | PWM_SIFIVE_PWMCFG_EN_ALWAYS);
 
        /*
         * The problem of output producing mixed setting as mentioned at top,
@@ -88,6 +91,7 @@ static int pwm_sifive_set_config(struct udevice *dev, uint channel,
        num = (u64)duty_ns * (1U << PWM_SIFIVE_CMPWIDTH);
        frac = DIV_ROUND_CLOSEST_ULL(num, period_ns);
        frac = min(frac, (1U << PWM_SIFIVE_CMPWIDTH) - 1);
+       frac = (1U << PWM_SIFIVE_CMPWIDTH) - 1 - frac;
 
        writel(val, priv->base + regs->cfg);
        writel(frac, priv->base + regs->cmp0 + channel *
@@ -100,18 +104,15 @@ static int pwm_sifive_set_enable(struct udevice *dev, uint channel, bool enable)
 {
        struct pwm_sifive_priv *priv = dev_get_priv(dev);
        const struct pwm_sifive_regs *regs = &priv->data->regs;
-       u32 val;
 
        debug("%s: Enable '%s'\n", __func__, dev->name);
 
-       if (enable) {
-               val = readl(priv->base + regs->cfg);
-               val |= PWM_SIFIVE_PWMCFG_EN_ALWAYS;
-               writel(val, priv->base + regs->cfg);
-       } else {
-               writel(0, priv->base + regs->cmp0 + channel *
-                      PWM_SIFIVE_SIZE_PWMCMP);
-       }
+       if (enable)
+               writel(PWM_SIFIVE_CHANNEL_ENABLE_VAL, priv->base +
+                      regs->cmp0 + channel * PWM_SIFIVE_SIZE_PWMCMP);
+       else
+               writel(PWM_SIFIVE_CHANNEL_DISABLE_VAL, priv->base +
+                      regs->cmp0 + channel * PWM_SIFIVE_SIZE_PWMCMP);
 
        return 0;
 }