pwm: pwm-tiehrpwm: Fix conflicting channel period setting

EHRPWM hardware supports 2 independent PWM channels. However the device
uses only one register to handle period setting for both channels. So
both channels should be configured for same period (in nsec).

Fix the same by returning error for conflicting period values.

However, allow
1. Configuration of period settings if not conflicting with other
channels
2. Re-configuring of period settings if no other channels being
configured

Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>

authored by Philip, Avinash and committed by Thierry Reding 01b2d453 c06fad9d

Changed files
+29
drivers
+29
drivers/pwm/pwm-tiehrpwm.c
··· 104 104 struct pwm_chip chip; 105 105 unsigned int clk_rate; 106 106 void __iomem *mmio_base; 107 + unsigned long period_cycles[NUM_PWM_CHANNEL]; 107 108 }; 108 109 109 110 static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) ··· 211 210 unsigned long long c; 212 211 unsigned long period_cycles, duty_cycles; 213 212 unsigned short ps_divval, tb_divval; 213 + int i; 214 214 215 215 if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) 216 216 return -ERANGE; ··· 230 228 do_div(c, NSEC_PER_SEC); 231 229 duty_cycles = (unsigned long)c; 232 230 } 231 + 232 + /* 233 + * Period values should be same for multiple PWM channels as IP uses 234 + * same period register for multiple channels. 235 + */ 236 + for (i = 0; i < NUM_PWM_CHANNEL; i++) { 237 + if (pc->period_cycles[i] && 238 + (pc->period_cycles[i] != period_cycles)) { 239 + /* 240 + * Allow channel to reconfigure period if no other 241 + * channels being configured. 242 + */ 243 + if (i == pwm->hwpwm) 244 + continue; 245 + 246 + dev_err(chip->dev, "Period value conflicts with channel %d\n", 247 + i); 248 + return -EINVAL; 249 + } 250 + } 251 + 252 + pc->period_cycles[pwm->hwpwm] = period_cycles; 233 253 234 254 /* Configure clock prescaler to support Low frequency PWM wave */ 235 255 if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval, ··· 344 320 345 321 static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) 346 322 { 323 + struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); 324 + 347 325 if (test_bit(PWMF_ENABLED, &pwm->flags)) { 348 326 dev_warn(chip->dev, "Removing PWM device without disabling\n"); 349 327 pm_runtime_put_sync(chip->dev); 350 328 } 329 + 330 + /* set period value to zero on free */ 331 + pc->period_cycles[pwm->hwpwm] = 0; 351 332 } 352 333 353 334 static const struct pwm_ops ehrpwm_pwm_ops = {