if (active_channels(priv) & ~TIM_CCER_CCxE(ch + 1)) {
u64 arr;
/* * Other channels are already enabled, so the configured PSC and * ARR must be used for this channel, too.
*/
ret = regmap_read(priv->regmap, TIM_PSC, &wfhw->psc); if (ret) goto out;
ret = regmap_read(priv->regmap, TIM_ARR, &wfhw->arr); if (ret) goto out;
arr = mul_u64_u64_div_u64(wf->period_length_ns, rate,
(u64)NSEC_PER_SEC * (wfhw->psc + 1)); if (arr <= wfhw->arr) { /* * requested period is smaller than the currently * configured and unchangable period, report back the smallest * possible period, i.e. the current state and return 1 * to indicate the wrong rounding direction.
*/
ret = 1;
}
} else { /* * .probe() asserted that clk_get_rate() is not bigger than 1 GHz, so * the calculations here won't overflow. * First we need to find the minimal value for prescaler such that * * period_ns * clkrate * ------------------------------ < max_arr + 1 * NSEC_PER_SEC * (prescaler + 1) * * This equation is equivalent to * * period_ns * clkrate * ---------------------------- < prescaler + 1 * NSEC_PER_SEC * (max_arr + 1) * * Using integer division and knowing that the right hand side is * integer, this is further equivalent to * * (period_ns * clkrate) // (NSEC_PER_SEC * (max_arr + 1)) ≤ prescaler
*/
u64 psc = mul_u64_u64_div_u64(wf->period_length_ns, rate,
(u64)NSEC_PER_SEC * ((u64)priv->max_arr + 1));
u64 arr;
wfhw->psc = min_t(u64, psc, MAX_TIM_PSC);
arr = mul_u64_u64_div_u64(wf->period_length_ns, rate,
(u64)NSEC_PER_SEC * (wfhw->psc + 1)); if (!arr) { /* * requested period is too small, report back the smallest * possible period, i.e. ARR = 0. The only valid CCR * value is then zero, too.
*/
wfhw->arr = 0;
wfhw->ccr = 0;
ret = 1; goto out;
}
/* * ARR is limited intentionally to values less than * priv->max_arr to allow 100% duty cycle.
*/
wfhw->arr = min_t(u64, arr, priv->max_arr) - 1;
}
/* * This should be moved to lib/math/div64.c. Currently there are some changes * pending to mul_u64_u64_div_u64. Uwe will care for that when the dust settles.
*/ static u64 stm32_pwm_mul_u64_u64_div_u64_roundup(u64 a, u64 b, u64 c)
{
u64 res = mul_u64_u64_div_u64(a, b, c); /* Those multiplications might overflow but it doesn't matter */
u64 rem = a * b - c * res;
ret = regmap_read(priv->regmap, TIM_CCER, &ccer); if (ret) goto out;
if (ccer & mask) {
ccer = ccer & ~mask;
ret = regmap_write(priv->regmap, TIM_CCER, ccer); if (ret) goto out;
if (!(ccer & TIM_CCER_CCXE)) { /* When all channels are disabled, we can disable the controller */
ret = regmap_clear_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN); if (ret) goto out;
}
/* * Timer DMA burst mode. Request 2 registers, 2 bursts, to get both * CCR1 & CCR2 (or CCR3 & CCR4) on each capture event. * We'll get two capture snapchots: { CCR1, CCR2 }, { CCR1, CCR2 } * or { CCR3, CCR4 }, { CCR3, CCR4 }
*/
ret = stm32_timers_dma_burst_read(parent, priv->capture, dma_id, ccr, 2,
2, tmo_ms); if (ret) goto stop;
/* Period: t2 - t0 (take care of counter overflow) */ if (priv->capture[0] <= priv->capture[2])
*raw_prd = priv->capture[2] - priv->capture[0]; else
*raw_prd = priv->max_arr - priv->capture[0] + priv->capture[2];
/* Duty cycle capture requires at least two capture units */ if (pwm->chip->npwm < 2)
*raw_dty = 0; elseif (priv->capture[0] <= priv->capture[3])
*raw_dty = priv->capture[3] - priv->capture[0]; else
*raw_dty = priv->max_arr - priv->capture[0] + priv->capture[3];
if (*raw_dty > *raw_prd) { /* * Race beetween PWM input and DMA: it may happen * falling edge triggers new capture on TI2/4 before DMA * had a chance to read CCR2/4. It means capture[1] * contains period + duty_cycle. So, subtract period.
*/
*raw_dty -= *raw_prd;
}
/* Capture period on IC1/3 rising edge, duty cycle on IC2/4 falling. */
regmap_update_bits(priv->regmap, TIM_CCER, pwm->hwpwm < 2 ?
TIM_CCER_CC12P : TIM_CCER_CC34P, pwm->hwpwm < 2 ?
TIM_CCER_CC2P : TIM_CCER_CC4P);
ret = stm32_pwm_raw_capture(chip, pwm, tmo_ms, &raw_prd, &raw_dty); if (ret) goto stop;
/* * Got a capture. Try to improve accuracy at high rates: * - decrease counter clock prescaler, scale up to max rate. * - use input prescaler, capture once every /2 /4 or /8 edges.
*/ if (raw_prd) {
u32 max_arr = priv->max_arr - 0x1000; /* arbitrary margin */
scale = max_arr / min(max_arr, raw_prd);
} else {
scale = priv->max_arr; /* below resolution, use max scale */
}
if (psc && scale > 1) { /* 2nd measure with new scale */
psc /= scale;
regmap_write(priv->regmap, TIM_PSC, psc);
ret = stm32_pwm_raw_capture(chip, pwm, tmo_ms, &raw_prd,
&raw_dty); if (ret) goto stop;
}
/* Compute intermediate period not to exceed timeout at low rates */
prd = (unsignedlonglong)raw_prd * (psc + 1) * NSEC_PER_SEC;
do_div(prd, rate);
/* Simply read from HWCFGR the number of complementary outputs (MP25). */
regmap_read(priv->regmap, TIM_HWCFGR1, &val);
priv->have_complementary_output = !!FIELD_GET(TIM_HWCFGR1_NB_OF_DT, val); return;
}
/* * If complementary bit doesn't exist writing 1 will have no * effect so we can detect it.
*/
regmap_set_bits(priv->regmap, TIM_CCER, TIM_CCER_CC1NE);
regmap_read(priv->regmap, TIM_CCER, &ccer);
regmap_clear_bits(priv->regmap, TIM_CCER, TIM_CCER_CC1NE);
/* Deduce from HWCFGR the number of outputs (MP25). */
regmap_read(regmap, TIM_HWCFGR1, &hwcfgr);
/* * Timers may have more capture/compare channels than the * actual number of PWM channel outputs (e.g. TIM_CH[1..4]).
*/
npwm = FIELD_GET(TIM_HWCFGR1_NB_OF_CC, hwcfgr);
/* * If channels enable bits don't exist writing 1 will have no * effect so we can detect and count them.
*/
regmap_set_bits(regmap, TIM_CCER, TIM_CCER_CCXE);
regmap_read(regmap, TIM_CCER, &ccer);
regmap_write(regmap, TIM_CCER, ccer_backup);
if (!priv->regmap || !priv->clk) return dev_err_probe(dev, -EINVAL, "Failed to get %s\n",
priv->regmap ? "clk" : "regmap");
ret = stm32_pwm_probe_breakinputs(priv, np); if (ret) return dev_err_probe(dev, ret, "Failed to configure breakinputs\n");
stm32_pwm_detect_complementary(priv, ddata);
ret = devm_clk_rate_exclusive_get(dev, priv->clk); if (ret) return dev_err_probe(dev, ret, "Failed to lock clock\n");
/* * With the clk running with not more than 1 GHz the calculations in * .apply() won't overflow.
*/ if (clk_get_rate(priv->clk) > 1000000000) return dev_err_probe(dev, -EINVAL, "Clock freq too high (%lu)\n",
clk_get_rate(priv->clk));
chip->ops = &stm32pwm_ops;
/* Initialize clock refcount to number of enabled PWM channels. */ for (i = 0; i < num_enabled; i++) {
ret = clk_enable(priv->clk); if (ret) return ret;
}
ret = devm_pwmchip_add(dev, chip); if (ret < 0) return dev_err_probe(dev, ret, "Failed to register pwmchip\n");
/* Look for active channels */
ccer = active_channels(priv);
for (i = 0; i < chip->npwm; i++) {
mask = TIM_CCER_CCxE(i + 1); if (ccer & mask) {
dev_err(dev, "PWM %u still in use by consumer %s\n",
i, chip->pwms[i].label); return -EBUSY;
}
}
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.