Hello Abel, On Mon, Mar 03, 2025 at 06:14:36PM +0200, Abel Vesa wrote: > Currently, the implementation computes the best matched period based > on the requested one, by looping through all possible register > configurations. The best matched period is below the requested period. The best matched period *isn't above* the requested one. An exact match is fine. > This means the PWM consumer could request duty cycle values between > the best matched period and the requested period, which with the current > implementation for computing the PWM value, it will result in values out > of range with respect to the selected resolution. I still don't understand what you mean with resolution here. I guess you spend some time understanding the workings of the driver and you also have an example request that results in a hardware configuration you don't like. Please share the latter to a) support your case and b) make it easier for your reviewers to judge if your change is indeed an improvement. > So change the way the PWM value is determined as a ratio between the > requested period and duty cycle, mapped on the resolution interval. Is the intention here that (for the picked period) a duty_cycle is selected that approximates the requested relative duty_cycle (i.e. .duty_cycle / .period)? If it's that: Nack. This might be the right thing for your use case, but it's wrong for others, it complicates the driver because you have spend more effort in the calculation and (from my POV even worse) the driver's behaviour deviates from the usual one for pwm drivers. I admit there are some other lowlevel pwm drivers that are not aligned to the procedure I described that should be used to determine the register settings for a given request. But I target a common behaviour of all pwm drivers because that is the only way the pwm API functions can make a promise to its consumers about the resulting behaviour. Reaching this is difficult, because some consumers might depend on the "broken" behaviour of a given lowlevel driver (and also because analysing a driver to check and fix its behaviour is an effort). But "fixing" a driver to deviate from the declared right behaviour is wrong and includes all downsides that make me hesitate to align the old drivers to the common policy. The policy to pick a hardware setting is a compromise between consumer needs and what is straight forward to implement for (most) hardware drivers. Please stick to that. If you want more flexibility and precision in your consumer, please consider converting the pwm driver to the waveform API. > [...] > @@ -532,13 +534,15 @@ static void lpg_calc_duty(struct lpg_channel *chan, uint64_t duty) > if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { > max = BIT(lpg_pwm_resolution_hi_res[chan->pwm_resolution_sel]) - 1; > clk_rate = lpg_clk_rates_hi_res[chan->clk_sel]; > + pwm_resolution_arr = lpg_pwm_resolution_hi_res; > } else { > max = BIT(lpg_pwm_resolution[chan->pwm_resolution_sel]) - 1; > clk_rate = lpg_clk_rates[chan->clk_sel]; > + pwm_resolution_arr = lpg_pwm_resolution; > } > > - val = div64_u64(duty * clk_rate, > - (u64)NSEC_PER_SEC * lpg_pre_divs[chan->pre_div_sel] * (1 << chan->pre_div_exp)); > + step = div64_u64(period, max); > + val = div64_u64(duty, step); Such a pair of divisions is bound to loose precision. I didn't try to determine values that can happen in practise here, but consider: period = 999996 max = 500000 duty = 499998 The exact value for val is 250000. However with integer division you get 499998. What you can do about that is calculating val = duty * max / period instead which gives you a more exact result. The challenge here however is that the multiplication might overflow. If you know that the result fits into a u64, mul_u64_u64_div_u64() is the function that gets this right for you. > chan->pwm_value = min(val, max); > } > [...] > --- > base-commit: 0067a4b21c9ab441bbe6bf3635b3ddd21f6ca7c3 My git repo doesn't know that commit. Given that you said your patch bases on that other series, this isn't surprising. Please use a publicly available commit as base parameter, otherwise you (and I) don't benefit from the armada of build bots because they just silently fail to test in this case. Best regards Uwe
Attachment:
signature.asc
Description: PGP signature