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; };