Re: [U-Boot] [PATCH] pwm: rk_pwm: Make PWM driver to support all Rockchip Socs
Hi David, On 2019/11/25 下午3:38, David Wu wrote: The new PWM driver supports PWM polarity, lock and more functions. Please add a little bit more info about the patch, eg. the difference for pwm v1 vs v2 vs v3. Thanks, - Kever Signed-off-by: David Wu --- arch/arm/include/asm/arch-rockchip/pwm.h | 17 ++- drivers/pwm/rk_pwm.c | 139 +++ 2 files changed, 131 insertions(+), 25 deletions(-) diff --git a/arch/arm/include/asm/arch-rockchip/pwm.h b/arch/arm/include/asm/arch-rockchip/pwm.h index b5178db394..e8594055cd 100644 --- a/arch/arm/include/asm/arch-rockchip/pwm.h +++ b/arch/arm/include/asm/arch-rockchip/pwm.h @@ -7,13 +7,15 @@ #ifndef _ASM_ARCH_PWM_H #define _ASM_ARCH_PWM_H -struct rk3288_pwm { - u32 cnt; - u32 period_hpr; - u32 duty_lpr; - u32 ctrl; +struct rockchip_pwm_regs { + unsigned long duty; + unsigned long period; + unsigned long cntr; + unsigned long ctrl; }; -check_member(rk3288_pwm, ctrl, 0xc); + +#define PWM_CTRL_TIMER_EN (1 << 0) +#define PWM_CTRL_OUTPUT_EN (1 << 3) #define RK_PWM_DISABLE (0 << 0) #define RK_PWM_ENABLE (1 << 0) @@ -33,6 +35,9 @@ check_member(rk3288_pwm, ctrl, 0xc); #define PWM_OUTPUT_LEFT (0 << 5) #define PWM_OUTPUT_CENTER (1 << 5) +#define PWM_LOCK (1 << 6) +#define PWM_UNLOCK (0 << 6) + #define PWM_LP_ENABLE (1 << 8) #define PWM_LP_DISABLE (0 << 8) diff --git a/drivers/pwm/rk_pwm.c b/drivers/pwm/rk_pwm.c index 88db294cf1..c9d9b7c11b 100644 --- a/drivers/pwm/rk_pwm.c +++ b/drivers/pwm/rk_pwm.c @@ -15,22 +15,38 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + +struct rockchip_pwm_data { + struct rockchip_pwm_regs regs; + unsigned int prescaler; + bool supports_polarity; + bool supports_lock; + u32 enable_conf; + u32 enable_conf_mask; +}; + struct rk_pwm_priv { - struct rk3288_pwm *regs; + fdt_addr_t base; ulong freq; - uint enable_conf; + u32 conf_polarity; + const struct rockchip_pwm_data *data; }; static int rk_pwm_set_invert(struct udevice *dev, uint channel, bool polarity) { struct rk_pwm_priv *priv = dev_get_priv(dev); + if (!priv->data->supports_polarity) { + debug("%s: Do not support polarity\n", __func__); + return 0; + } + debug("%s: polarity=%u\n", __func__, polarity); - priv->enable_conf &= ~(PWM_DUTY_MASK | PWM_INACTIVE_MASK); if (polarity) - priv->enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSTIVE; + priv->conf_polarity = PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSTIVE; else - priv->enable_conf |= PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE; + priv->conf_polarity = PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE; return 0; } @@ -39,20 +55,44 @@ static int rk_pwm_set_config(struct udevice *dev, uint channel, uint period_ns, uint duty_ns) { struct rk_pwm_priv *priv = dev_get_priv(dev); - struct rk3288_pwm *regs = priv->regs; + const struct rockchip_pwm_regs *regs = >data->regs; unsigned long period, duty; + u32 ctrl; debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns); - writel(PWM_SEL_SRC_CLK | PWM_OUTPUT_LEFT | PWM_LP_DISABLE | - PWM_CONTINUOUS | priv->enable_conf | - RK_PWM_DISABLE, - >ctrl); - period = lldiv((uint64_t)(priv->freq / 1000) * period_ns, 100); - duty = lldiv((uint64_t)(priv->freq / 1000) * duty_ns, 100); + ctrl = readl(priv->base + regs->ctrl); + /* +* Lock the period and duty of previous configuration, then +* change the duty and period, that would not be effective. +*/ + if (priv->data->supports_lock) { + ctrl |= PWM_LOCK; + writel(ctrl, priv->base + regs->ctrl); + } + + period = lldiv((uint64_t)priv->freq * period_ns, + priv->data->prescaler * 10); + duty = lldiv((uint64_t)priv->freq * duty_ns, +priv->data->prescaler * 10); + + writel(period, priv->base + regs->period); + writel(duty, priv->base + regs->duty); + + if (priv->data->supports_polarity) { + ctrl &= ~(PWM_DUTY_MASK | PWM_INACTIVE_MASK); + ctrl |= priv->conf_polarity; + } + + /* +* Unlock and set polarity at the same time, +* the configuration of duty, period and polarity +* would be effective together at next period. +*/ + if (priv->data->supports_lock) + ctrl &= ~PWM_LOCK; + writel(ctrl, priv->base + regs->ctrl); - writel(period, >period_hpr); - writel(duty,
[U-Boot] [PATCH] pwm: rk_pwm: Make PWM driver to support all Rockchip Socs
The new PWM driver supports PWM polarity, lock and more functions. Signed-off-by: David Wu --- arch/arm/include/asm/arch-rockchip/pwm.h | 17 ++- drivers/pwm/rk_pwm.c | 139 +++ 2 files changed, 131 insertions(+), 25 deletions(-) diff --git a/arch/arm/include/asm/arch-rockchip/pwm.h b/arch/arm/include/asm/arch-rockchip/pwm.h index b5178db394..e8594055cd 100644 --- a/arch/arm/include/asm/arch-rockchip/pwm.h +++ b/arch/arm/include/asm/arch-rockchip/pwm.h @@ -7,13 +7,15 @@ #ifndef _ASM_ARCH_PWM_H #define _ASM_ARCH_PWM_H -struct rk3288_pwm { - u32 cnt; - u32 period_hpr; - u32 duty_lpr; - u32 ctrl; +struct rockchip_pwm_regs { + unsigned long duty; + unsigned long period; + unsigned long cntr; + unsigned long ctrl; }; -check_member(rk3288_pwm, ctrl, 0xc); + +#define PWM_CTRL_TIMER_EN (1 << 0) +#define PWM_CTRL_OUTPUT_EN (1 << 3) #define RK_PWM_DISABLE (0 << 0) #define RK_PWM_ENABLE (1 << 0) @@ -33,6 +35,9 @@ check_member(rk3288_pwm, ctrl, 0xc); #define PWM_OUTPUT_LEFT (0 << 5) #define PWM_OUTPUT_CENTER (1 << 5) +#define PWM_LOCK (1 << 6) +#define PWM_UNLOCK (0 << 6) + #define PWM_LP_ENABLE (1 << 8) #define PWM_LP_DISABLE (0 << 8) diff --git a/drivers/pwm/rk_pwm.c b/drivers/pwm/rk_pwm.c index 88db294cf1..c9d9b7c11b 100644 --- a/drivers/pwm/rk_pwm.c +++ b/drivers/pwm/rk_pwm.c @@ -15,22 +15,38 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + +struct rockchip_pwm_data { + struct rockchip_pwm_regs regs; + unsigned int prescaler; + bool supports_polarity; + bool supports_lock; + u32 enable_conf; + u32 enable_conf_mask; +}; + struct rk_pwm_priv { - struct rk3288_pwm *regs; + fdt_addr_t base; ulong freq; - uint enable_conf; + u32 conf_polarity; + const struct rockchip_pwm_data *data; }; static int rk_pwm_set_invert(struct udevice *dev, uint channel, bool polarity) { struct rk_pwm_priv *priv = dev_get_priv(dev); + if (!priv->data->supports_polarity) { + debug("%s: Do not support polarity\n", __func__); + return 0; + } + debug("%s: polarity=%u\n", __func__, polarity); - priv->enable_conf &= ~(PWM_DUTY_MASK | PWM_INACTIVE_MASK); if (polarity) - priv->enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSTIVE; + priv->conf_polarity = PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSTIVE; else - priv->enable_conf |= PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE; + priv->conf_polarity = PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE; return 0; } @@ -39,20 +55,44 @@ static int rk_pwm_set_config(struct udevice *dev, uint channel, uint period_ns, uint duty_ns) { struct rk_pwm_priv *priv = dev_get_priv(dev); - struct rk3288_pwm *regs = priv->regs; + const struct rockchip_pwm_regs *regs = >data->regs; unsigned long period, duty; + u32 ctrl; debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns); - writel(PWM_SEL_SRC_CLK | PWM_OUTPUT_LEFT | PWM_LP_DISABLE | - PWM_CONTINUOUS | priv->enable_conf | - RK_PWM_DISABLE, - >ctrl); - period = lldiv((uint64_t)(priv->freq / 1000) * period_ns, 100); - duty = lldiv((uint64_t)(priv->freq / 1000) * duty_ns, 100); + ctrl = readl(priv->base + regs->ctrl); + /* +* Lock the period and duty of previous configuration, then +* change the duty and period, that would not be effective. +*/ + if (priv->data->supports_lock) { + ctrl |= PWM_LOCK; + writel(ctrl, priv->base + regs->ctrl); + } + + period = lldiv((uint64_t)priv->freq * period_ns, + priv->data->prescaler * 10); + duty = lldiv((uint64_t)priv->freq * duty_ns, +priv->data->prescaler * 10); + + writel(period, priv->base + regs->period); + writel(duty, priv->base + regs->duty); + + if (priv->data->supports_polarity) { + ctrl &= ~(PWM_DUTY_MASK | PWM_INACTIVE_MASK); + ctrl |= priv->conf_polarity; + } + + /* +* Unlock and set polarity at the same time, +* the configuration of duty, period and polarity +* would be effective together at next period. +*/ + if (priv->data->supports_lock) + ctrl &= ~PWM_LOCK; + writel(ctrl, priv->base + regs->ctrl); - writel(period, >period_hpr); - writel(duty, >duty_lpr); debug("%s: period=%lu, duty=%lu\n", __func__, period, duty); return 0; @@ -61,10 +101,20 @@ static int rk_pwm_set_config(struct udevice