pwm: jz4740: Apply configuration atomically
This is cleaner, more future-proof, and incidentally it also fixes the PWM resetting its config when stopped/started several times. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
This commit is contained in:
parent
93808aca34
commit
1ac99c58bd
@ -83,17 +83,16 @@ static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
|||||||
jz4740_timer_disable(pwm->hwpwm);
|
jz4740_timer_disable(pwm->hwpwm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||||
int duty_ns, int period_ns)
|
struct pwm_state *state)
|
||||||
{
|
{
|
||||||
struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
|
struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
|
||||||
unsigned long long tmp;
|
unsigned long long tmp;
|
||||||
unsigned long period, duty;
|
unsigned long period, duty;
|
||||||
unsigned int prescaler = 0;
|
unsigned int prescaler = 0;
|
||||||
uint16_t ctrl;
|
uint16_t ctrl;
|
||||||
bool is_enabled;
|
|
||||||
|
|
||||||
tmp = (unsigned long long)clk_get_rate(jz4740->clk) * period_ns;
|
tmp = (unsigned long long)clk_get_rate(jz4740->clk) * state->period;
|
||||||
do_div(tmp, 1000000000);
|
do_div(tmp, 1000000000);
|
||||||
period = tmp;
|
period = tmp;
|
||||||
|
|
||||||
@ -105,16 +104,14 @@ static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
|||||||
if (prescaler == 6)
|
if (prescaler == 6)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
tmp = (unsigned long long)period * duty_ns;
|
tmp = (unsigned long long)period * state->duty_cycle;
|
||||||
do_div(tmp, period_ns);
|
do_div(tmp, state->period);
|
||||||
duty = period - tmp;
|
duty = period - tmp;
|
||||||
|
|
||||||
if (duty >= period)
|
if (duty >= period)
|
||||||
duty = period - 1;
|
duty = period - 1;
|
||||||
|
|
||||||
is_enabled = jz4740_timer_is_enabled(pwm->hwpwm);
|
jz4740_pwm_disable(chip, pwm);
|
||||||
if (is_enabled)
|
|
||||||
jz4740_pwm_disable(chip, pwm);
|
|
||||||
|
|
||||||
jz4740_timer_set_count(pwm->hwpwm, 0);
|
jz4740_timer_set_count(pwm->hwpwm, 0);
|
||||||
jz4740_timer_set_duty(pwm->hwpwm, duty);
|
jz4740_timer_set_duty(pwm->hwpwm, duty);
|
||||||
@ -125,18 +122,7 @@ static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
|||||||
|
|
||||||
jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
|
jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
|
||||||
|
|
||||||
if (is_enabled)
|
switch (state->polarity) {
|
||||||
jz4740_pwm_enable(chip, pwm);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int jz4740_pwm_set_polarity(struct pwm_chip *chip,
|
|
||||||
struct pwm_device *pwm, enum pwm_polarity polarity)
|
|
||||||
{
|
|
||||||
uint32_t ctrl = jz4740_timer_get_ctrl(pwm->pwm);
|
|
||||||
|
|
||||||
switch (polarity) {
|
|
||||||
case PWM_POLARITY_NORMAL:
|
case PWM_POLARITY_NORMAL:
|
||||||
ctrl &= ~JZ_TIMER_CTRL_PWM_ACTIVE_LOW;
|
ctrl &= ~JZ_TIMER_CTRL_PWM_ACTIVE_LOW;
|
||||||
break;
|
break;
|
||||||
@ -146,16 +132,17 @@ static int jz4740_pwm_set_polarity(struct pwm_chip *chip,
|
|||||||
}
|
}
|
||||||
|
|
||||||
jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
|
jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
|
||||||
|
|
||||||
|
if (state->enabled)
|
||||||
|
jz4740_pwm_enable(chip, pwm);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pwm_ops jz4740_pwm_ops = {
|
static const struct pwm_ops jz4740_pwm_ops = {
|
||||||
.request = jz4740_pwm_request,
|
.request = jz4740_pwm_request,
|
||||||
.free = jz4740_pwm_free,
|
.free = jz4740_pwm_free,
|
||||||
.config = jz4740_pwm_config,
|
.apply = jz4740_pwm_apply,
|
||||||
.set_polarity = jz4740_pwm_set_polarity,
|
|
||||||
.enable = jz4740_pwm_enable,
|
|
||||||
.disable = jz4740_pwm_disable,
|
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user