[PATCH] pwm: imx27: workaround of the pwm output bug when decrease the duty cycle
kernel test robot
lkp at intel.com
Thu Dec 9 09:49:51 PST 2021
Hi Clark,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on thierry-reding-pwm/for-next]
[also build test WARNING on v5.16-rc4 next-20211208]
[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]
url: https://github.com/0day-ci/linux/commits/Clark-Wang/pwm-imx27-workaround-of-the-pwm-output-bug-when-decrease-the-duty-cycle/20211208-165523
base: https://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm.git for-next
config: riscv-randconfig-s031-20211209 (https://download.01.org/0day-ci/archive/20211210/202112100135.Qng8J561-lkp@intel.com/config)
compiler: riscv64-linux-gcc (GCC) 11.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.4-dirty
# https://github.com/0day-ci/linux/commit/e56186a9b8501a89d138d2072cc63d107fb303a0
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Clark-Wang/pwm-imx27-workaround-of-the-pwm-output-bug-when-decrease-the-duty-cycle/20211208-165523
git checkout e56186a9b8501a89d138d2072cc63d107fb303a0
# save the config file to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=riscv SHELL=/bin/bash drivers/pwm/
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp at intel.com>
sparse warnings: (new ones prefixed by >>)
>> drivers/pwm/pwm-imx27.c:301:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] sar_last @@ got restricted __le32 [usertype] @@
drivers/pwm/pwm-imx27.c:301:26: sparse: expected unsigned int [usertype] sar_last
drivers/pwm/pwm-imx27.c:301:26: sparse: got restricted __le32 [usertype]
>> drivers/pwm/pwm-imx27.c:302:29: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [usertype] sar_current @@ got restricted __le32 [usertype] @@
drivers/pwm/pwm-imx27.c:302:29: sparse: expected unsigned int [usertype] sar_current
drivers/pwm/pwm-imx27.c:302:29: sparse: got restricted __le32 [usertype]
vim +301 drivers/pwm/pwm-imx27.c
217
218 static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
219 const struct pwm_state *state)
220 {
221 unsigned long period_cycles, duty_cycles, prescale, counter_check, flags;
222 struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
223 void __iomem *reg_sar = imx->mmio_base + MX3_PWMSAR;
224 __force u32 sar_last, sar_current;
225 struct pwm_state cstate;
226 unsigned long long c;
227 unsigned long long clkrate;
228 int ret;
229 u32 cr, timeout = 1000;
230
231 pwm_get_state(pwm, &cstate);
232
233 clkrate = clk_get_rate(imx->clk_per);
234 c = clkrate * state->period;
235
236 do_div(c, NSEC_PER_SEC);
237 period_cycles = c;
238
239 prescale = period_cycles / 0x10000 + 1;
240
241 period_cycles /= prescale;
242 c = clkrate * state->duty_cycle;
243 do_div(c, NSEC_PER_SEC);
244 duty_cycles = c;
245 duty_cycles /= prescale;
246
247 /*
248 * according to imx pwm RM, the real period value should be PERIOD
249 * value in PWMPR plus 2.
250 */
251 if (period_cycles > 2)
252 period_cycles -= 2;
253 else
254 period_cycles = 0;
255
256 /*
257 * Wait for a free FIFO slot if the PWM is already enabled, and flush
258 * the FIFO if the PWM was disabled and is about to be enabled.
259 */
260 if (cstate.enabled) {
261 pwm_imx27_wait_fifo_slot(chip, pwm);
262 } else {
263 ret = pwm_imx27_clk_prepare_enable(imx);
264 if (ret)
265 return ret;
266
267 pwm_imx27_sw_reset(chip);
268 }
269
270 /*
271 * This is a limited workaround. When the SAR FIFO is empty, the new
272 * write value will be directly applied to SAR even the current period
273 * is not over.
274 * If the new SAR value is less than the old one, and the counter is
275 * greater than the new SAR value, the current period will not filp
276 * the level. This will result in a pulse with a duty cycle of 100%.
277 * So, writing the current value of the SAR to SAR here before updating
278 * the new SAR value can avoid this issue.
279 *
280 * Add a spin lock and turn off the interrupt to ensure that the
281 * real-time performance can be guaranteed as much as possible when
282 * operating the following operations.
283 *
284 * 1. Add a threshold of 1.5us. If the time T between the read current
285 * count value CNR and the end of the cycle is less than 1.5us, wait
286 * for T to be longer than 1.5us before updating the SAR register.
287 * This is to avoid the situation that when the first SAR is written,
288 * the current cycle just ends and the SAR FIFO that just be written
289 * is emptied again.
290 *
291 * 2. Use __raw_writel() to minimize the interval between two writes to
292 * the SAR register to increase the fastest pwm frequency supported.
293 *
294 * When the PWM period is longer than 2us(or <500KHz), this workaround
295 * can solve this problem.
296 */
297 if (duty_cycles < imx->duty_cycle) {
298 c = clkrate * 1500;
299 do_div(c, NSEC_PER_SEC);
300 counter_check = c;
> 301 sar_last = cpu_to_le32(imx->duty_cycle);
> 302 sar_current = cpu_to_le32(duty_cycles);
303
304 spin_lock_irqsave(&imx->lock, flags);
305 if (state->period >= 2000) {
306 while ((period_cycles -
307 readl_relaxed(imx->mmio_base + MX3_PWMCNR))
308 < counter_check) {
309 if (!--timeout)
310 break;
311 };
312 }
313 if (!(MX3_PWMSR_FIFOAV &
314 readl_relaxed(imx->mmio_base + MX3_PWMSR)))
315 __raw_writel(sar_last, reg_sar);
316 __raw_writel(sar_current, reg_sar);
317 spin_unlock_irqrestore(&imx->lock, flags);
318 } else
319 writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
320
321 writel(period_cycles, imx->mmio_base + MX3_PWMPR);
322
323 /*
324 * Store the duty cycle for future reference in cases where the
325 * MX3_PWMSAR register can't be read (i.e. when the PWM is disabled).
326 */
327 imx->duty_cycle = duty_cycles;
328
329 cr = MX3_PWMCR_PRESCALER_SET(prescale) |
330 MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEN | MX3_PWMCR_WAITEN |
331 FIELD_PREP(MX3_PWMCR_CLKSRC, MX3_PWMCR_CLKSRC_IPG_HIGH) |
332 MX3_PWMCR_DBGEN;
333
334 if (state->polarity == PWM_POLARITY_INVERSED)
335 cr |= FIELD_PREP(MX3_PWMCR_POUTC,
336 MX3_PWMCR_POUTC_INVERTED);
337
338 if (state->enabled)
339 cr |= MX3_PWMCR_EN;
340
341 writel(cr, imx->mmio_base + MX3_PWMCR);
342
343 if (!state->enabled)
344 pwm_imx27_clk_disable_unprepare(imx);
345
346 return 0;
347 }
348
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
More information about the linux-arm-kernel
mailing list