mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-20 08:38:24 +08:00
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>
This commit is contained in:
parent
c06fad9d28
commit
01b2d4536f
@ -104,6 +104,7 @@ struct ehrpwm_pwm_chip {
|
||||
struct pwm_chip chip;
|
||||
unsigned int clk_rate;
|
||||
void __iomem *mmio_base;
|
||||
unsigned long period_cycles[NUM_PWM_CHANNEL];
|
||||
};
|
||||
|
||||
static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
|
||||
@ -210,6 +211,7 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
unsigned long long c;
|
||||
unsigned long period_cycles, duty_cycles;
|
||||
unsigned short ps_divval, tb_divval;
|
||||
int i;
|
||||
|
||||
if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC)
|
||||
return -ERANGE;
|
||||
@ -229,6 +231,28 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
duty_cycles = (unsigned long)c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Period values should be same for multiple PWM channels as IP uses
|
||||
* same period register for multiple channels.
|
||||
*/
|
||||
for (i = 0; i < NUM_PWM_CHANNEL; i++) {
|
||||
if (pc->period_cycles[i] &&
|
||||
(pc->period_cycles[i] != period_cycles)) {
|
||||
/*
|
||||
* Allow channel to reconfigure period if no other
|
||||
* channels being configured.
|
||||
*/
|
||||
if (i == pwm->hwpwm)
|
||||
continue;
|
||||
|
||||
dev_err(chip->dev, "Period value conflicts with channel %d\n",
|
||||
i);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
pc->period_cycles[pwm->hwpwm] = period_cycles;
|
||||
|
||||
/* Configure clock prescaler to support Low frequency PWM wave */
|
||||
if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval,
|
||||
&tb_divval)) {
|
||||
@ -320,10 +344,15 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
|
||||
static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
|
||||
|
||||
if (test_bit(PWMF_ENABLED, &pwm->flags)) {
|
||||
dev_warn(chip->dev, "Removing PWM device without disabling\n");
|
||||
pm_runtime_put_sync(chip->dev);
|
||||
}
|
||||
|
||||
/* set period value to zero on free */
|
||||
pc->period_cycles[pwm->hwpwm] = 0;
|
||||
}
|
||||
|
||||
static const struct pwm_ops ehrpwm_pwm_ops = {
|
||||
|
Loading…
Reference in New Issue
Block a user