Skip to content

Commit

Permalink
Merge tag 'for-3.6-rc6' of git://gitorious.org/linux-pwm/linux-pwm
Browse files Browse the repository at this point in the history
Pull pwm fixes from Thierry Reding:
 "While this comes a bit later than I had wished, both patches are
  rather minor and touch only new drivers so I think these are still
  safe for merging."

* tag 'for-3.6-rc6' of git://gitorious.org/linux-pwm/linux-pwm:
  pwm: pwm-tiehrpwm: Fix conflicting channel period setting
  pwm: pwm-tiecap: Disable APWM mode after configure
  • Loading branch information
Linus Torvalds committed Sep 16, 2012
2 parents 76e77da + 01b2d45 commit c500ce3
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
7 changes: 7 additions & 0 deletions drivers/pwm/pwm-tiecap.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
writel(period_cycles, pc->mmio_base + CAP3);
}

if (!test_bit(PWMF_ENABLED, &pwm->flags)) {
reg_val = readw(pc->mmio_base + ECCTL2);
/* Disable APWM mode to put APWM output Low */
reg_val &= ~ECCTL2_APWM_MODE;
writew(reg_val, pc->mmio_base + ECCTL2);
}

pm_runtime_put_sync(pc->chip.dev);
return 0;
}
Expand Down
29 changes: 29 additions & 0 deletions drivers/pwm/pwm-tiehrpwm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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)) {
Expand Down Expand Up @@ -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 = {
Expand Down

0 comments on commit c500ce3

Please sign in to comment.