pwm: sifive: make set_config() and set_enable() work properly
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>
This commit is contained in:

committed by
Leo Yu-Chi Liang

parent
81dadfa4bc
commit
cc25f346c9
@@ -38,6 +38,9 @@
|
|||||||
#define PWM_SIFIVE_SIZE_PWMCMP 4
|
#define PWM_SIFIVE_SIZE_PWMCMP 4
|
||||||
#define PWM_SIFIVE_CMPWIDTH 16
|
#define PWM_SIFIVE_CMPWIDTH 16
|
||||||
|
|
||||||
|
#define PWM_SIFIVE_CHANNEL_ENABLE_VAL 0
|
||||||
|
#define PWM_SIFIVE_CHANNEL_DISABLE_VAL 0xffff
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
struct pwm_sifive_regs {
|
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_pow = lldiv((uint64_t)priv->freq * period_ns, 1000000000);
|
||||||
scale = clamp(ilog2(scale_pow) - PWM_SIFIVE_CMPWIDTH, 0, 0xf);
|
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,
|
* 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);
|
num = (u64)duty_ns * (1U << PWM_SIFIVE_CMPWIDTH);
|
||||||
frac = DIV_ROUND_CLOSEST_ULL(num, period_ns);
|
frac = DIV_ROUND_CLOSEST_ULL(num, period_ns);
|
||||||
frac = min(frac, (1U << PWM_SIFIVE_CMPWIDTH) - 1);
|
frac = min(frac, (1U << PWM_SIFIVE_CMPWIDTH) - 1);
|
||||||
|
frac = (1U << PWM_SIFIVE_CMPWIDTH) - 1 - frac;
|
||||||
|
|
||||||
writel(val, priv->base + regs->cfg);
|
writel(val, priv->base + regs->cfg);
|
||||||
writel(frac, priv->base + regs->cmp0 + channel *
|
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);
|
struct pwm_sifive_priv *priv = dev_get_priv(dev);
|
||||||
const struct pwm_sifive_regs *regs = &priv->data->regs;
|
const struct pwm_sifive_regs *regs = &priv->data->regs;
|
||||||
u32 val;
|
|
||||||
|
|
||||||
debug("%s: Enable '%s'\n", __func__, dev->name);
|
debug("%s: Enable '%s'\n", __func__, dev->name);
|
||||||
|
|
||||||
if (enable) {
|
if (enable)
|
||||||
val = readl(priv->base + regs->cfg);
|
writel(PWM_SIFIVE_CHANNEL_ENABLE_VAL, priv->base +
|
||||||
val |= PWM_SIFIVE_PWMCFG_EN_ALWAYS;
|
regs->cmp0 + channel * PWM_SIFIVE_SIZE_PWMCMP);
|
||||||
writel(val, priv->base + regs->cfg);
|
else
|
||||||
} else {
|
writel(PWM_SIFIVE_CHANNEL_DISABLE_VAL, priv->base +
|
||||||
writel(0, priv->base + regs->cmp0 + channel *
|
regs->cmp0 + channel * PWM_SIFIVE_SIZE_PWMCMP);
|
||||||
PWM_SIFIVE_SIZE_PWMCMP);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user