summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pwm/core.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index cf6d91f1a9e6..8acbcf5b6673 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -137,6 +137,25 @@ static void pwm_apply_debug(struct pwm_device *pwm,
}
}
+static bool pwm_state_valid(const struct pwm_state *state)
+{
+ /*
+ * For a disabled state all other state description is irrelevant and
+ * and supposed to be ignored. So also ignore any strange values and
+ * consider the state ok.
+ */
+ if (state->enabled)
+ return true;
+
+ if (!state->period)
+ return false;
+
+ if (state->duty_cycle > state->period)
+ return false;
+
+ return true;
+}
+
/**
* __pwm_apply() - atomically apply a new state to a PWM device
* @pwm: PWM device
@@ -147,10 +166,26 @@ static int __pwm_apply(struct pwm_device *pwm, const struct pwm_state *state)
struct pwm_chip *chip;
int err;
- if (!pwm || !state || !state->period ||
- state->duty_cycle > state->period)
+ if (!pwm || !state)
return -EINVAL;
+ if (!pwm_state_valid(state)) {
+ /*
+ * Allow to transition from one invalid state to another.
+ * This ensures that you can e.g. change the polarity while
+ * the period is zero. (This happens on stm32 when the hardware
+ * is in its poweron default state.) This greatly simplifies
+ * working with the sysfs API where you can only change one
+ * parameter at a time.
+ */
+ if (!pwm_state_valid(&pwm->state)) {
+ pwm->state = *state;
+ return 0;
+ }
+
+ return -EINVAL;
+ }
+
chip = pwm->chip;
if (state->period == pwm->state.period &&