/* * Find period count, duty count and prescale to suit duty_cycle and * period. This is done according to formulas described below: * * period_ns = 10^9 * (PRESCALE + 1) * PC / PWM_CLK_RATE * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE * * PC = (PWM_CLK_RATE * period_ns) / (10^9 * (PRESCALE + 1)) * DC = (PWM_CLK_RATE * duty_ns) / (10^9 * (PRESCALE + 1))
*/ while (1) {
u64 value, div;
div = NSEC_PER_SEC * (prescale + 1);
value = rate * state->period;
period = div64_u64(value, div);
value = rate * state->duty_cycle;
duty = div64_u64(value, div);
if (period < IPROC_PWM_PERIOD_MIN) return -EINVAL;
if (period <= IPROC_PWM_PERIOD_MAX &&
duty <= IPROC_PWM_DUTY_CYCLE_MAX) break;
/* Otherwise, increase prescale and recalculate counts */ if (++prescale > IPROC_PWM_PRESCALE_MAX) return -EINVAL;
}
iproc_pwmc_disable(ip, pwm->hwpwm);
/* Set prescale */
value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
value &= ~IPROC_PWM_PRESCALE_MASK(pwm->hwpwm);
value |= prescale << IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm);
writel(value, ip->base + IPROC_PWM_PRESCALE_OFFSET);
/* set period and duty cycle */
writel(period, ip->base + IPROC_PWM_PERIOD_OFFSET(pwm->hwpwm));
writel(duty, ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm));
/* set polarity */
value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
if (state->polarity == PWM_POLARITY_NORMAL)
value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm); else
value &= ~(1 << IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm));
writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
if (state->enabled)
iproc_pwmc_enable(ip, pwm->hwpwm);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.