/* * The list of clocks required by PWM channels, and each channel has 2 clocks: * enable clock and pwm clock.
*/ staticconstchar * const sprd_pwm_clks[] = { "enable0", "pwm0", "enable1", "pwm1", "enable2", "pwm2", "enable3", "pwm3",
};
/* * The clocks to PWM channel has to be enabled first before * reading to the registers.
*/
ret = clk_bulk_prepare_enable(SPRD_PWM_CHN_CLKS_NUM, chn->clks); if (ret) {
dev_err(pwmchip_parent(chip), "failed to enable pwm%u clocks\n",
pwm->hwpwm); return ret;
}
val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_ENABLE); if (val & SPRD_PWM_ENABLE_BIT)
state->enabled = true; else
state->enabled = false;
/* * The hardware provides a counter that is feed by the source clock. * The period length is (PRESCALE + 1) * MOD counter steps. * The duty cycle length is (PRESCALE + 1) * DUTY counter steps. * Thus the period_ns and duty_ns calculation formula should be: * period_ns = NSEC_PER_SEC * (prescale + 1) * mod / clk_rate * duty_ns = NSEC_PER_SEC * (prescale + 1) * duty / clk_rate
*/
val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_PRESCALE);
prescale = val & SPRD_PWM_PRESCALE_MSK;
tmp = (prescale + 1) * NSEC_PER_SEC * SPRD_PWM_MOD_MAX;
state->period = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate);
/* * The hardware provides a counter that is feed by the source clock. * The period length is (PRESCALE + 1) * MOD counter steps. * The duty cycle length is (PRESCALE + 1) * DUTY counter steps. * * To keep the maths simple we're always using MOD = SPRD_PWM_MOD_MAX. * The value for PRESCALE is selected such that the resulting period * gets the maximal length not bigger than the requested one with the * given settings (MOD = SPRD_PWM_MOD_MAX and input clock).
*/
duty = duty_ns * SPRD_PWM_MOD_MAX / period_ns;
/* * Note: Writing DUTY triggers the hardware to actually apply the * values written to MOD and DUTY to the output, so must keep writing * DUTY last. * * The hardware can ensures that current running period is completed * before changing a new configuration to avoid mixed settings.
*/
sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_PRESCALE, prescale);
sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_MOD, SPRD_PWM_MOD_MAX);
sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_DUTY, duty);
if (state->polarity != PWM_POLARITY_NORMAL) return -EINVAL;
if (state->enabled) { if (!cstate->enabled) { /* * The clocks to PWM channel has to be enabled first * before writing to the registers.
*/
ret = clk_bulk_prepare_enable(SPRD_PWM_CHN_CLKS_NUM,
chn->clks); if (ret) {
dev_err(pwmchip_parent(chip), "failed to enable pwm%u clocks\n",
pwm->hwpwm); return ret;
}
}
ret = sprd_pwm_config(spc, pwm, state->duty_cycle,
state->period); if (ret) return ret;
sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_ENABLE, 1);
} elseif (cstate->enabled) { /* * Note: After setting SPRD_PWM_ENABLE to zero, the controller * will not wait for current period to be completed, instead it * will stop the PWM channel immediately.
*/
sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_ENABLE, 0);
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.