From: kernel test robot <lkp@intel.com>
To: "Stephane Lepain" <stephanelepain@gmail.com>,
"Uwe Kleine-König" <ukleinek@kernel.org>
Cc: llvm@lists.linux.dev, oe-kbuild-all@lists.linux.dev,
linux-pwm@vger.kernel.org, Kenneth Kasilag <kenneth@kasilag.me>,
George Moussalem <george.moussalem@outlook.com>,
Devi Priya <quic_devipriy@quicinc.com>,
Baruch Siach <baruch.siach@siklu.com>,
linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org,
Stephane Lepain <stephanelepain@gmail.com>
Subject: Re: [PATCH] pwm: ipq: fix period calculation
Date: Sat, 1 Aug 2026 03:29:20 +0800 [thread overview]
Message-ID: <202608010336.m82kvZZ8-lkp@intel.com> (raw)
In-Reply-To: <20260731070542.155398-1-stephanelepain@gmail.com>
Hi Stephane,
kernel test robot noticed the following build warnings:
[auto build test WARNING on linus/master]
[also build test WARNING on v7.2-rc5 next-20260731]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Stephane-Lepain/pwm-ipq-fix-period-calculation/20260731-152907
base: linus/master
patch link: https://lore.kernel.org/r/20260731070542.155398-1-stephanelepain%40gmail.com
patch subject: [PATCH] pwm: ipq: fix period calculation
config: arm-randconfig-004-20260731 (https://download.01.org/0day-ci/archive/20260801/202608010336.m82kvZZ8-lkp@intel.com/config)
compiler: clang version 24.0.0git (https://github.com/llvm/llvm-project bacfe2950f8218268fcc0a8765644ea0c15f0360)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260801/202608010336.m82kvZZ8-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202608010336.m82kvZZ8-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/pwm/pwm-ipq.c:123:25: warning: result of comparison of constant 16000000000 with expression of type 'unsigned long' is always false [-Wtautological-constant-out-of-range-compare]
123 | if (ipq_chip->clk_rate > 16ULL * GIGA)
| ~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
1 warning generated.
vim +123 drivers/pwm/pwm-ipq.c
87
88 static int ipq_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
89 const struct pwm_state *state)
90 {
91 struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip);
92 unsigned int pre_div, pwm_div, best_pre_div, best_pwm_div;
93 u64 period_ns, duty_ns, period_rate, min_diff;
94 unsigned long val = 0;
95 u64 hi_dur;
96
97 if (!state->enabled) {
98 /* clear IPQ_PWM_REG1_ENABLE */
99 ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, IPQ_PWM_REG1_UPDATE);
100 return 0;
101 }
102
103 if (state->polarity != PWM_POLARITY_NORMAL)
104 return -EINVAL;
105
106 /*
107 * Check the upper and lower bounds for the period as per
108 * hardware limits
109 */
110 if (state->period < IPQ_PWM_MIN_PERIOD_NS)
111 return -ERANGE;
112 period_ns = min(state->period, IPQ_PWM_MAX_PERIOD_NS);
113 duty_ns = min(state->duty_cycle, period_ns);
114
115 /*
116 * The period spans (pre_div + 1) * (pwm_div + 1) input clocks. Rather
117 * than fixing pwm_div at its maximum (which gives usable duty
118 * resolution only for long periods and collapses to ~0% for short
119 * periods) search for the (pre_div, pwm_div) split whose period best
120 * approximates the request while leaving pwm_div large enough to
121 * resolve the duty cycle.
122 */
> 123 if (ipq_chip->clk_rate > 16ULL * GIGA)
124 return -EINVAL;
125 period_rate = period_ns * ipq_chip->clk_rate;
126
127 best_pre_div = IPQ_PWM_MAX_DIV;
128 best_pwm_div = IPQ_PWM_MAX_DIV;
129 min_diff = period_rate;
130
131 /*
132 * Smaller pre_div than this cannot represent the period (pwm_div would
133 * have to exceed its field), so start the search there.
134 */
135 pre_div = div64_u64(period_rate,
136 (u64)NSEC_PER_SEC * (IPQ_PWM_MAX_DIV + 1));
137
138 for (; pre_div <= IPQ_PWM_MAX_DIV; pre_div++) {
139 u64 remainder;
140
141 pwm_div = div64_u64_rem(period_rate,
142 (u64)NSEC_PER_SEC * (pre_div + 1),
143 &remainder);
144 /* pwm_div is unsigned; the swap check below catches underflow */
145 pwm_div--;
146
147 /*
148 * Swapping pre_div and pwm_div yields the same period but a
149 * larger pwm_div gives finer duty resolution, so once pre_div
150 * exceeds pwm_div every further candidate is strictly worse.
151 */
152 if (pre_div > pwm_div)
153 break;
154
155 /* need room for 100% duty, where hi_dur == pwm_div + 1 */
156 if (pwm_div > IPQ_PWM_MAX_DIV - 1)
157 continue;
158
159 if (remainder < min_diff) {
160 best_pre_div = pre_div;
161 best_pwm_div = pwm_div;
162 min_diff = remainder;
163
164 if (min_diff == 0)
165 break;
166 }
167 }
168
169 pre_div = best_pre_div;
170 pwm_div = best_pwm_div;
171
172 /*
173 * If the search found no usable candidate, best_pwm_div is left at
174 * IPQ_PWM_MAX_DIV; cap it so pwm_div + 1 still fits the 16-bit field
175 * and 100% duty remains expressible.
176 */
177 if (pwm_div > IPQ_PWM_MAX_DIV - 1)
178 pwm_div = IPQ_PWM_MAX_DIV - 1;
179
180 /*
181 * high duration = duty_ratio * (pwm_div + 1)
182 * = duty_ns * clk_rate / ((pre_div + 1) * NSEC_PER_SEC)
183 *
184 * Round to nearest to avoid biasing every duty cycle low, then clamp
185 * to (pwm_div + 1): rounding or a 100% duty request can otherwise push
186 * hi_dur past the period length and overflow the 16-bit HI_DURATION field
187 * (which would alias a full-on request down to a near-zero high time)
188 * and asking the hardware to stay high beyond one period. pwm_div is
189 * at most IPQ_PWM_MAX_DIV - 1, so pwm_div + 1 always fits the field.
190 */
191 hi_dur = DIV64_U64_ROUND_CLOSEST(duty_ns * ipq_chip->clk_rate,
192 (u64)(pre_div + 1) * NSEC_PER_SEC);
193 if (hi_dur > (u64)pwm_div + 1)
194 hi_dur = (u64)pwm_div + 1;
195
196 val = FIELD_PREP(IPQ_PWM_REG0_HI_DURATION, hi_dur) |
197 FIELD_PREP(IPQ_PWM_REG0_PWM_DIV, pwm_div);
198 ipq_pwm_reg_write(pwm, IPQ_PWM_REG0, val);
199
200 val = FIELD_PREP(IPQ_PWM_REG1_PRE_DIV, pre_div);
201 ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val);
202
203 /* PWM enable toggle needs a separate write to REG1 */
204 val |= IPQ_PWM_REG1_UPDATE | IPQ_PWM_REG1_ENABLE;
205 ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val);
206
207 return 0;
208 }
209
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
parent reply other threads:[~2026-07-31 19:29 UTC|newest]
Thread overview: expand[flat|nested] mbox.gz Atom feed
[parent not found: <20260731070542.155398-1-stephanelepain@gmail.com>]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=202608010336.m82kvZZ8-lkp@intel.com \
--to=lkp@intel.com \
--cc=baruch.siach@siklu.com \
--cc=george.moussalem@outlook.com \
--cc=kenneth@kasilag.me \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pwm@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=oe-kbuild-all@lists.linux.dev \
--cc=quic_devipriy@quicinc.com \
--cc=stephanelepain@gmail.com \
--cc=ukleinek@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox