/* * The Kona PWM has some unusual characteristics. Here are the main points. * * 1) There is no disable bit and the hardware docs advise programming a zero * duty to achieve output equivalent to that of a normal disable operation. * * 2) Changes to prescale, duty, period, and polarity do not take effect until * a subsequent rising edge of the trigger bit. * * 3) If the smooth bit and trigger bit are both low, the output is a constant * high signal. Otherwise, the earlier waveform continues to be output. * * 4) If the smooth bit is set on the rising edge of the trigger bit, output * will transition to the new settings on a period boundary (which could be * seconds away). If the smooth bit is clear, new settings will be applied * as soon as possible (the hardware always has a 400ns delay). * * 5) When the external clock that feeds the PWM is disabled, output is pegged * high or low depending on its state at that exact instant.
*/
/* * Clear trigger bit but set smooth bit to maintain old output.
*/ staticvoid kona_pwmc_prepare_for_settings(struct kona_pwmc *kp, unsignedint chan)
{ unsignedint value = readl(kp->base + PWM_CONTROL_OFFSET);
value |= 1 << PWM_CONTROL_SMOOTH_SHIFT(chan);
value &= ~(1 << PWM_CONTROL_TRIGGER_SHIFT(chan));
writel(value, kp->base + PWM_CONTROL_OFFSET);
/* * There must be a min 400ns delay between clearing trigger and setting * it. Failing to do this may result in no PWM signal.
*/
ndelay(400);
}
/* Set trigger bit and clear smooth bit to apply new settings */
value &= ~(1 << PWM_CONTROL_SMOOTH_SHIFT(chan));
value |= 1 << PWM_CONTROL_TRIGGER_SHIFT(chan);
writel(value, kp->base + PWM_CONTROL_OFFSET);
/* Trigger bit must be held high for at least 400 ns. */
ndelay(400);
}
/* Simulate a disable by configuring for zero duty */
writel(0, kp->base + DUTY_CYCLE_HIGH_OFFSET(chan));
writel(0, kp->base + PERIOD_COUNT_OFFSET(chan));
/* Set prescale to 0 for this channel */
value = readl(kp->base + PRESCALE_OFFSET);
value &= ~PRESCALE_MASK(chan);
writel(value, kp->base + PRESCALE_OFFSET);
if (state->polarity != pwm->state.polarity) { if (enabled) {
kona_pwmc_disable(chip, pwm);
enabled = false;
}
err = kona_pwmc_set_polarity(chip, pwm, state->polarity); if (err) return err;
pwm->state.polarity = state->polarity;
}
if (!state->enabled) { if (enabled)
kona_pwmc_disable(chip, pwm); return 0;
} elseif (!enabled) { /* * This is a bit special here, usually the PWM should only be * enabled when duty and period are setup. But before this * driver was converted to .apply it was done the other way * around and so this behaviour was kept even though this might * result in a glitch. This might be improvable by someone with * hardware and/or documentation.
*/
err = kona_pwmc_enable(chip, pwm); if (err) return err;
}
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.