Skip to content

Commit

Permalink
pwm: npcx: only reconfigure PWM if necessary
Browse files Browse the repository at this point in the history
Currently pwm_npcx_pin_set() disables and reconfigures the PWM
controller every time its called, causing the PWM line to pulse even if
only the duty cycle is changed.

Modify the function so that controller is only disabled if any of the
configuration has to be changed, only set the new DCR otherwise.

Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
  • Loading branch information
fabiobaltieri authored and nashif committed Feb 22, 2022
1 parent 57b55c3 commit 61ef77a
Showing 1 changed file with 42 additions and 20 deletions.
62 changes: 42 additions & 20 deletions drivers/pwm/pwm_npcx.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,47 +97,69 @@ static int pwm_npcx_pin_set(const struct device *dev, uint32_t pwm,
struct pwm_npcx_data *const data = dev->data;
struct pwm_reg *const inst = HAL_INSTANCE(dev);
int prescaler;
uint32_t ctl;
uint32_t ctr;
uint32_t dcr;
uint32_t prsc;

if (pulse_cycles > period_cycles)
if (pulse_cycles > period_cycles) {
return -EINVAL;
}

/* Disable PWM before configuring */
inst->PWMCTL &= ~BIT(NPCX_PWMCTL_PWR);
ctl = inst->PWMCTL | BIT(NPCX_PWMCTL_PWR);

/* Select PWM inverted polarity (ie. active-low pulse). */
if (flags & PWM_POLARITY_INVERTED)
inst->PWMCTL |= BIT(NPCX_PWMCTL_INVP);
else
inst->PWMCTL &= ~BIT(NPCX_PWMCTL_INVP);
if (flags & PWM_POLARITY_INVERTED) {
ctl |= BIT(NPCX_PWMCTL_INVP);
} else {
ctl &= ~BIT(NPCX_PWMCTL_INVP);
}

/* If pulse_cycles is 0, return directly since PWM is already off */
if (pulse_cycles == 0)
/* If pulse_cycles is 0, switch PWM off and return. */
if (pulse_cycles == 0) {
ctl &= ~BIT(NPCX_PWMCTL_PWR);
inst->PWMCTL = ctl;
return 0;
}

/*
* Calculate PWM prescaler that let period_cycles map to
* maximum pwm period cycles and won't exceed it.
* Then prescaler = ceil (period_cycles / pwm_max_period_cycles)
*/
prescaler = ceiling_fraction(period_cycles, NPCX_PWM_MAX_PERIOD_CYCLES);
if (prescaler > NPCX_PWM_MAX_PRESCALER)
if (prescaler > NPCX_PWM_MAX_PRESCALER) {
return -EINVAL;
}

/* Set PWM prescaler.*/
inst->PRSC = prescaler - 1;
/* Set PWM prescaler. */
prsc = prescaler - 1;

/* Set PWM period cycles */
inst->CTR = (period_cycles / prescaler) - 1;
/* Set PWM period cycles. */
ctr = (period_cycles / prescaler) - 1;

/* Set PWM pulse cycles */
inst->DCR = (pulse_cycles / prescaler) - 1;
/* Set PWM pulse cycles. */
dcr = (pulse_cycles / prescaler) - 1;

LOG_DBG("freq %d, pre %d, period %d, pulse %d",
data->cycles_per_sec / period_cycles,
inst->PRSC + 1, inst->CTR + 1, inst->DCR + 1);
data->cycles_per_sec / period_cycles, prsc, ctr, dcr);

/* Reconfigure only if necessary. */
if (inst->PWMCTL != ctl || inst->PRSC != prsc || inst->CTR != ctr) {
/* Disable PWM before configuring. */
inst->PWMCTL &= ~BIT(NPCX_PWMCTL_PWR);

inst->PRSC = prsc;
inst->CTR = ctr;
inst->DCR = dcr;

/* Enable PWM now. */
inst->PWMCTL = ctl;

return 0;
}

/* Enable PWM now */
inst->PWMCTL |= BIT(NPCX_PWMCTL_PWR);
inst->DCR = dcr;

return 0;
}
Expand Down

0 comments on commit 61ef77a

Please sign in to comment.