/* * Calculate width of low and high period in terms of input clock * periods and check are the result within HW limits between 1 and * 2^32 periods.
*/
tmp = DIV_ROUND_CLOSEST_ULL(state->duty_cycle, dwc->clk_ns); if (tmp < 1 || tmp > (1ULL << 32)) return -ERANGE;
low = tmp - 1;
/* * Specification says timer usage flow is to disable timer, then * program it followed by enable. It also says Load Count is loaded * into timer after it is enabled - either after a disable or * a reset. Based on measurements it happens also without disable * whenever Load Count is updated. But follow the specification.
*/
__dwc_pwm_set_enable(dwc, pwm->hwpwm, false);
/* * Write Load Count and Load Count 2 registers. Former defines the * width of low period and latter the width of high period in terms * multiple of input clock periods: * Width = ((Count + 1) * input clock period).
*/
dwc_pwm_writel(dwc, low, DWC_TIM_LD_CNT(pwm->hwpwm));
dwc_pwm_writel(dwc, high, DWC_TIM_LD_CNT2(pwm->hwpwm));
/* * Set user-defined mode, timer reloads from Load Count registers * when it counts down to 0. * Set PWM mode, it makes output to toggle and width of low and high * periods are set by Load Count registers.
*/
ctrl = DWC_TIM_CTRL_MODE_USER | DWC_TIM_CTRL_PWM;
dwc_pwm_writel(dwc, ctrl, DWC_TIM_CTRL(pwm->hwpwm));
/* * If we're not in PWM, technically the output is a 50-50 * based on the timer load-count only.
*/ if (ctrl & DWC_TIM_CTRL_PWM) {
duty = (ld + 1) * dwc->clk_ns;
period = (ld2 + 1) * dwc->clk_ns;
period += duty;
} else {
duty = (ld + 1) * dwc->clk_ns;
period = duty * 2;
}
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.