Skip to content

Commit

Permalink
Merge tag 'pwm/for-4.1-rc1' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/thierry.reding/linux-pwm

Pull pwm changes from Thierry Reding:
 "Not much has been happening in PWM land lately, so this contains
  mostly minor fixes that didn't seem urgent enough for a late
  pull-request last cycle"

* tag 'pwm/for-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm:
  pwm: Remove __init initializer for pwm_add_table()
  pwm: samsung: Fix output race on disabling
  pwm: mxs: Fix period divider computation
  pwm: atmel-hlcdc: Add errata handling for sama5d4
  pwm: pca9685: Constify struct regmap_config
  pwm: imx-pwm: add explicit compatible strings and required clock properties
  • Loading branch information
torvalds committed Apr 24, 2015
2 parents b3f4ef0 + c264f11 commit 06b45f2
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 6 deletions.
12 changes: 11 additions & 1 deletion Documentation/devicetree/bindings/pwm/imx-pwm.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
Freescale i.MX PWM controller

Required properties:
- compatible: should be "fsl,<soc>-pwm"
- compatible : should be "fsl,<soc>-pwm" and one of the following
compatible strings:
- "fsl,imx1-pwm" for PWM compatible with the one integrated on i.MX1
- "fsl,imx27-pwm" for PWM compatible with the one integrated on i.MX27
- reg: physical base address and length of the controller's registers
- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
the cells format.
- clocks : Clock specifiers for both ipg and per clocks.
- clock-names : Clock names should include both "ipg" and "per"
See the clock consumer binding,
Documentation/devicetree/bindings/clock/clock-bindings.txt
- interrupts: The interrupt for the pwm controller

Example:
Expand All @@ -13,5 +20,8 @@ pwm1: pwm@53fb4000 {
#pwm-cells = <2>;
compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
reg = <0x53fb4000 0x4000>;
clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
<&clks IMX5_CLK_PWM1_HF_GATE>;
clock-names = "ipg", "per";
interrupts = <61>;
};
2 changes: 1 addition & 1 deletion drivers/pwm/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ EXPORT_SYMBOL_GPL(of_pwm_get);
* @table: array of consumers to register
* @num: number of consumers in table
*/
void __init pwm_add_table(struct pwm_lookup *table, size_t num)
void pwm_add_table(struct pwm_lookup *table, size_t num)
{
mutex_lock(&pwm_lookup_lock);

Expand Down
4 changes: 4 additions & 0 deletions drivers/pwm/pwm-atmel-hlcdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ static const struct of_device_id atmel_hlcdc_dt_ids[] = {
.compatible = "atmel,sama5d3-hlcdc",
.data = &atmel_hlcdc_pwm_sama5d3_errata,
},
{
.compatible = "atmel,sama5d4-hlcdc",
.data = &atmel_hlcdc_pwm_sama5d3_errata,
},
{ /* sentinel */ },
};

Expand Down
8 changes: 6 additions & 2 deletions drivers/pwm/pwm-mxs.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
#define PERIOD_CDIV(div) (((div) & 0x7) << 20)
#define PERIOD_CDIV_MAX 8

static const unsigned int cdiv[PERIOD_CDIV_MAX] = {
1, 2, 4, 8, 16, 64, 256, 1024
};

struct mxs_pwm_chip {
struct pwm_chip chip;
struct clk *clk;
Expand All @@ -54,13 +58,13 @@ static int mxs_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,

rate = clk_get_rate(mxs->clk);
while (1) {
c = rate / (1 << div);
c = rate / cdiv[div];
c = c * period_ns;
do_div(c, 1000000000);
if (c < PERIOD_PERIOD_MAX)
break;
div++;
if (div > PERIOD_CDIV_MAX)
if (div >= PERIOD_CDIV_MAX)
return -EINVAL;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/pwm/pwm-pca9685.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ static const struct pwm_ops pca9685_pwm_ops = {
.owner = THIS_MODULE,
};

static struct regmap_config pca9685_regmap_i2c_config = {
static const struct regmap_config pca9685_regmap_i2c_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = PCA9685_NUMREGS,
Expand Down
32 changes: 31 additions & 1 deletion drivers/pwm/pwm-samsung.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,31 @@ static void pwm_samsung_disable(struct pwm_chip *chip, struct pwm_device *pwm)
spin_unlock_irqrestore(&samsung_pwm_lock, flags);
}

static void pwm_samsung_manual_update(struct samsung_pwm_chip *chip,
struct pwm_device *pwm)
{
unsigned int tcon_chan = to_tcon_channel(pwm->hwpwm);
u32 tcon;
unsigned long flags;

spin_lock_irqsave(&samsung_pwm_lock, flags);

tcon = readl(chip->base + REG_TCON);
tcon |= TCON_MANUALUPDATE(tcon_chan);
writel(tcon, chip->base + REG_TCON);

tcon &= ~TCON_MANUALUPDATE(tcon_chan);
writel(tcon, chip->base + REG_TCON);

spin_unlock_irqrestore(&samsung_pwm_lock, flags);
}

static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns)
{
struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip);
struct samsung_pwm_channel *chan = pwm_get_chip_data(pwm);
u32 tin_ns = chan->tin_ns, tcnt, tcmp;
u32 tin_ns = chan->tin_ns, tcnt, tcmp, oldtcmp;

/*
* We currently avoid using 64bit arithmetic by using the
Expand All @@ -288,6 +307,7 @@ static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;

tcnt = readl(our_chip->base + REG_TCNTB(pwm->hwpwm));
oldtcmp = readl(our_chip->base + REG_TCMPB(pwm->hwpwm));

/* We need tick count for calculation, not last tick. */
++tcnt;
Expand Down Expand Up @@ -335,6 +355,16 @@ static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
writel(tcnt, our_chip->base + REG_TCNTB(pwm->hwpwm));
writel(tcmp, our_chip->base + REG_TCMPB(pwm->hwpwm));

/*
* In case the PWM is currently at 100% duty cycle, force a manual
* update to prevent the signal staying high if the PWM is disabled
* shortly afer this update (before it autoreloaded the new values).
*/
if (oldtcmp == (u32) -1) {
dev_dbg(our_chip->chip.dev, "Forcing manual update");
pwm_samsung_manual_update(our_chip, pwm);
}

chan->period_ns = period_ns;
chan->tin_ns = tin_ns;
chan->duty_ns = duty_ns;
Expand Down

0 comments on commit 06b45f2

Please sign in to comment.