From ea419b14d67d66e7512d4ea1f98cee6f2541c65a Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 20 Oct 2020 15:19:21 +0800 Subject: [PATCH] pwm: rockchip: Support pwm oneshot mode for specified number of cycles. The oneshot_count value should be less than PWM_ONESHOT_COUNT_MAX. If oneshot_count == 0, this pwm channel works in continuous mode. Signed-off-by: Steven Liu Change-Id: I45857fb5762e0365cce5278502479c580638e40c --- drivers/pwm/Kconfig | 6 ++++++ drivers/pwm/pwm-rockchip.c | 24 ++++++++++++++++++++++-- include/linux/pwm.h | 3 +++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 63be5362fd3a..ca5db43118d4 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -408,6 +408,12 @@ config PWM_ROCKCHIP Generic PWM framework driver for the PWM controller found on Rockchip SoCs. +config PWM_ROCKCHIP_ONESHOT + bool "Rockchip PWM oneshot mode support" + depends on PWM_ROCKCHIP && NO_GKI + help + Support Rockchip pwm oneshot mode for specified number of cycles. + config PWM_SAMSUNG tristate "Samsung PWM support" depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 1f0131235561..157cf01cae69 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -30,6 +30,9 @@ #define PWM_LOCK_EN (1 << 6) #define PWM_LP_DISABLE (0 << 8) +#define PWM_ONESHOT_COUNT_SHIFT 24 +#define PWM_ONESHOT_COUNT_MAX 256 + struct rockchip_pwm_chip { struct pwm_chip chip; struct clk *clk; @@ -39,6 +42,7 @@ struct rockchip_pwm_chip { unsigned long clk_rate; bool vop_pwm_en; /* indicate voppwm mirror register state */ bool center_aligned; + bool oneshot; }; struct rockchip_pwm_regs { @@ -130,6 +134,19 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ctrl &= ~PWM_ENABLE; } +#ifdef CONFIG_PWM_ROCKCHIP_ONESHOT + if (state->oneshot_count > PWM_ONESHOT_COUNT_MAX) { + pc->oneshot = false; + dev_err(chip->dev, "Oneshot_count value overflow.\n"); + } else if (state->oneshot_count > 0) { + pc->oneshot = true; + ctrl |= (state->oneshot_count - 1) << PWM_ONESHOT_COUNT_SHIFT; + } else { + pc->oneshot = false; + ctrl |= PWM_CONTINUOUS; + } +#endif + if (pc->data->supports_lock) { ctrl |= PWM_LOCK_EN; writel_relaxed(ctrl, pc->base + pc->data->regs.ctrl); @@ -181,10 +198,13 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, val |= PWM_OUTPUT_CENTER; } - if (enable) + if (enable) { val |= enable_conf; - else + if (pc->oneshot) + val &= ~PWM_CONTINUOUS; + } else { val &= ~enable_conf; + } writel_relaxed(val, pc->base + pc->data->regs.ctrl); if (pc->data->vop_pwm) diff --git a/include/linux/pwm.h b/include/linux/pwm.h index f0a7329ba3b2..9212c2e80435 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -71,6 +71,9 @@ struct pwm_state { u64 duty_cycle; enum pwm_polarity polarity; enum pwm_output_type output_type; +#ifdef CONFIG_PWM_ROCKCHIP_ONESHOT + u64 oneshot_count; +#endif /* CONFIG_PWM_ROCKCHIP_ONESHOT */ bool enabled; };