Hi Uwe, Gentle ping, I'm sorry for wasting your time, and I look forward to your feedback. > > > + if (tem < PWM_CV1800_MINPERIOD) > > > + return -EINVAL; > > > + > > > + if (tem > PWM_CV1800_MAXPERIOD) > > > + tem = PWM_CV1800_MAXPERIOD; > > > + > > > + period_val = (u32)tem; > > > + > > > + /* > > > + * The meaning of HLPERIOD is the number of beats in the low or high level > > > + * of the PERIOD. When the value of the POLARITY register is 0, HLPERIOD > > > + * represents a low level. > > > + * HLPERIOD = period_val - rate(MHz) / duty(MHz) > > > + * HLPERIOD = period_val - duty(ns) * rate(Hz) / NSEC_PER_SEC > > > > So HLPERIOD defines the second part of each period, right? This isn't > > considered in .get_state(). > > I am so sorry about this. I made a mess of the duty cycle. > According to the PWM_DEBUG, it can be inferred that configure the > biggest duty_cycle not > bigger than the requested value, so in .apply duty_cycle should round down and > in .get_state duty_cycle should round up. However, when the polarity is normal, > This hardware requires a low-level beat count. So the corrected code > is as follows. > > in .apply() > > ticks = mul_u64_u64_div_u64(state->duty_cycle , priv->clk_rate,NSEC_PER_SEC); > ... > hlperiod_val =period_val- (u32)ticks; > > in .get_state() > > u32 hlperiod_val=0; > > period_ns = DIV_ROUND_UP_ULL(period_val * NSEC_PER_SEC,priv->clk_rate); > duty_ns = DIV_ROUND_UP_ULL(hlperiod_val * period_ns, period_val); > hlperiod_val = period_ns - duty_ns; > > I tested this code with PWM_DEBUG. no warning output. What do you > think about this? > > in .apply() ticks = mul_u64_u64_div_u64(state->duty_cycle, priv->clk_rate, NSEC_PER_SEC); if (ticks > period_val) ticks = period_val; hlperiod_val = period_val - (u32)ticks; ... regmap_write(priv->map, PWM_CV1800_HLPERIOD(pwm->hwpwm), hlperiod_val); in .get_state() u64 hlperiod_ns = 0; regmap_read(priv->map, PWM_CV1800_HLPERIOD(pwm->hwpwm), &hlperiod_val); ... period_ns = DIV_ROUND_UP_ULL(period_val * NSEC_PER_SEC, priv->clk_rate); hlperiod_ns = DIV_ROUND_UP_ULL(hlperiod_val * NSEC_PER_SEC, priv->clk_rate); duty_ns = period_ns - hlperiod_ns; I tested this code with PWM_DEBUG. no warning output. > > > > > + */ > > > + tem = mul_u64_u64_div_u64(state->duty_cycle, priv->clk_rate, > > > + NSEC_PER_SEC); > > > + if (tem > period_val) > > > + return -EINVAL; > > > > if (tem > period_val) > > tem = period_val; > > > > > + hlperiod_val = period_val - (u32)tem; > > > > Wrong rounding I think. Did you test your driver with PWM_DEBUG enabled? > > ditto. > Best regards Jingbao Qiu