|
26 | 26 | #define MX3_PWMSR 0x04 /* PWM Status Register */
|
27 | 27 | #define MX3_PWMSAR 0x0C /* PWM Sample Register */
|
28 | 28 | #define MX3_PWMPR 0x10 /* PWM Period Register */
|
| 29 | +#define MX3_PWMCNR 0x14 /* PWM Counter Register */ |
29 | 30 |
|
30 | 31 | #define MX3_PWMCR_FWM GENMASK(27, 26)
|
31 | 32 | #define MX3_PWMCR_STOPEN BIT(25)
|
@@ -219,10 +220,12 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
|
219 | 220 | static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
220 | 221 | const struct pwm_state *state)
|
221 | 222 | {
|
222 |
| - unsigned long period_cycles, duty_cycles, prescale; |
| 223 | + unsigned long period_cycles, duty_cycles, prescale, period_us, tmp; |
223 | 224 | struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
|
224 | 225 | unsigned long long c;
|
225 | 226 | unsigned long long clkrate;
|
| 227 | + unsigned long flags; |
| 228 | + int val; |
226 | 229 | int ret;
|
227 | 230 | u32 cr;
|
228 | 231 |
|
@@ -263,7 +266,98 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
263 | 266 | pwm_imx27_sw_reset(chip);
|
264 | 267 | }
|
265 | 268 |
|
266 |
| - writel(duty_cycles, imx->mmio_base + MX3_PWMSAR); |
| 269 | + val = readl(imx->mmio_base + MX3_PWMPR); |
| 270 | + val = val >= MX3_PWMPR_MAX ? MX3_PWMPR_MAX : val; |
| 271 | + cr = readl(imx->mmio_base + MX3_PWMCR); |
| 272 | + tmp = NSEC_PER_SEC * (u64)(val + 2) * MX3_PWMCR_PRESCALER_GET(cr); |
| 273 | + tmp = DIV_ROUND_UP_ULL(tmp, clkrate); |
| 274 | + period_us = DIV_ROUND_UP_ULL(tmp, 1000); |
| 275 | + |
| 276 | + /* |
| 277 | + * ERR051198: |
| 278 | + * PWM: PWM output may not function correctly if the FIFO is empty when |
| 279 | + * a new SAR value is programmed |
| 280 | + * |
| 281 | + * Description: |
| 282 | + * When the PWM FIFO is empty, a new value programmed to the PWM Sample |
| 283 | + * register (PWM_PWMSAR) will be directly applied even if the current |
| 284 | + * timer period has not expired. |
| 285 | + * |
| 286 | + * If the new SAMPLE value programmed in the PWM_PWMSAR register is |
| 287 | + * less than the previous value, and the PWM counter register |
| 288 | + * (PWM_PWMCNR) that contains the current COUNT value is greater than |
| 289 | + * the new programmed SAMPLE value, the current period will not flip |
| 290 | + * the level. This may result in an output pulse with a duty cycle of |
| 291 | + * 100%. |
| 292 | + * |
| 293 | + * Consider a change from |
| 294 | + * ________ |
| 295 | + * / \______/ |
| 296 | + * ^ * ^ |
| 297 | + * to |
| 298 | + * ____ |
| 299 | + * / \__________/ |
| 300 | + * ^ ^ |
| 301 | + * At the time marked by *, the new write value will be directly applied |
| 302 | + * to SAR even the current period is not over if FIFO is empty. |
| 303 | + * |
| 304 | + * ________ ____________________ |
| 305 | + * / \______/ \__________/ |
| 306 | + * ^ ^ * ^ ^ |
| 307 | + * |<-- old SAR -->| |<-- new SAR -->| |
| 308 | + * |
| 309 | + * That is the output is active for a whole period. |
| 310 | + * |
| 311 | + * Workaround: |
| 312 | + * Check new SAR less than old SAR and current counter is in errata |
| 313 | + * windows, write extra old SAR into FIFO and new SAR will effect at |
| 314 | + * next period. |
| 315 | + * |
| 316 | + * Sometime period is quite long, such as over 1 second. If add old SAR |
| 317 | + * into FIFO unconditional, new SAR have to wait for next period. It |
| 318 | + * may be too long. |
| 319 | + * |
| 320 | + * Turn off the interrupt to ensure that not IRQ and schedule happen |
| 321 | + * during above operations. If any irq and schedule happen, counter |
| 322 | + * in PWM will be out of data and take wrong action. |
| 323 | + * |
| 324 | + * Add a safety margin 1.5us because it needs some time to complete |
| 325 | + * IO write. |
| 326 | + * |
| 327 | + * Use writel_relaxed() to minimize the interval between two writes to |
| 328 | + * the SAR register to increase the fastest PWM frequency supported. |
| 329 | + * |
| 330 | + * When the PWM period is longer than 2us(or <500kHz), this workaround |
| 331 | + * can solve this problem. No software workaround is available if PWM |
| 332 | + * period is shorter than IO write. Just try best to fill old data |
| 333 | + * into FIFO. |
| 334 | + */ |
| 335 | + c = clkrate * 1500; |
| 336 | + do_div(c, NSEC_PER_SEC); |
| 337 | + |
| 338 | + local_irq_save(flags); |
| 339 | + val = FIELD_GET(MX3_PWMSR_FIFOAV, readl_relaxed(imx->mmio_base + MX3_PWMSR)); |
| 340 | + |
| 341 | + if (duty_cycles < imx->duty_cycle && (cr & MX3_PWMCR_EN)) { |
| 342 | + if (period_us < 2) { /* 2us = 500 kHz */ |
| 343 | + /* Best effort attempt to fix up >500 kHz case */ |
| 344 | + udelay(3 * period_us); |
| 345 | + writel_relaxed(imx->duty_cycle, imx->mmio_base + MX3_PWMSAR); |
| 346 | + writel_relaxed(imx->duty_cycle, imx->mmio_base + MX3_PWMSAR); |
| 347 | + } else if (val < MX3_PWMSR_FIFOAV_2WORDS) { |
| 348 | + val = readl_relaxed(imx->mmio_base + MX3_PWMCNR); |
| 349 | + /* |
| 350 | + * If counter is close to period, controller may roll over when |
| 351 | + * next IO write. |
| 352 | + */ |
| 353 | + if ((val + c >= duty_cycles && val < imx->duty_cycle) || |
| 354 | + val + c >= period_cycles) |
| 355 | + writel_relaxed(imx->duty_cycle, imx->mmio_base + MX3_PWMSAR); |
| 356 | + } |
| 357 | + } |
| 358 | + writel_relaxed(duty_cycles, imx->mmio_base + MX3_PWMSAR); |
| 359 | + local_irq_restore(flags); |
| 360 | + |
267 | 361 | writel(period_cycles, imx->mmio_base + MX3_PWMPR);
|
268 | 362 |
|
269 | 363 | /*
|
|
0 commit comments