pwm: Changes for v4.1-rc1

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.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJVOOwlAAoJEN0jrNd/PrOhrh4P/RqehL4BADO9PelU58wcudc4
 gjyk93HNobhJmTPnvl6/GflYhqtRn/KQL0PoA7aeg+mDJ311d11JpDABBpd4iRmT
 djvzhekkVtEXfI0TzFjI/RQ78KjN5Zbs39qNIsFQW9IO2nQgAqiprzPqvttN0ZHG
 BMMU6ZCbzDX2TcCDntM59SS2EEoCQ0rPswFkYykiDcslql1IIKlziY6MGw6LFdWO
 WKeRA6vKDAMrv2kcZy55kg5ONamAN1VYmJUeEf0tuSOqcPLT8i4xf9oj+TxySWn2
 56y/Kw7ZRCmHHRvAnjUyfZKxaXy3Dxl7H3Wk/qz51EYXKwxPQoXpXUHpkNOhHuVY
 SVvQ3j6AAe+6Te/pds87STuLRsiFFwVchAvCftF1DIDZyUgxzTJzUz8viJGe7Urk
 OSoQWTMINsCRc/sgSHFf9ZtmLATTO+0L98N980bKTAKng2P/pp/ZbhArHwGLsrYD
 ofNYj9YCO7ZE0zdM/V0cyW2OCrl8qwSSA2Kt97XN8YVWdJXXFxjMXdSS+llWrZVm
 usTk9fB9vJWhmP7ILnFsQ4+v06fwq4+t/ggXPK6l6+GQx91W6WYdo2/x1rq27UnJ
 o4zK1K7ClW2K+Xfag/nRXJOPOBPis9V19J/vKi0EbV9QFyUH2VW87hbqVncOP2ue
 tv+KHMkKgqqoc8/3GCFK
 =X+q2
 -----END PGP SIGNATURE-----

Merge tag 'pwm/for-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/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
This commit is contained in:
Linus Torvalds 2015-04-24 10:11:24 -07:00
commit 06b45f2aa7
6 changed files with 54 additions and 6 deletions

View File

@ -1,10 +1,17 @@
Freescale i.MX PWM controller Freescale i.MX PWM controller
Required properties: 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 - 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 - #pwm-cells: should be 2. See pwm.txt in this directory for a description of
the cells format. 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 - interrupts: The interrupt for the pwm controller
Example: Example:
@ -13,5 +20,8 @@ pwm1: pwm@53fb4000 {
#pwm-cells = <2>; #pwm-cells = <2>;
compatible = "fsl,imx53-pwm", "fsl,imx27-pwm"; compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
reg = <0x53fb4000 0x4000>; reg = <0x53fb4000 0x4000>;
clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
<&clks IMX5_CLK_PWM1_HF_GATE>;
clock-names = "ipg", "per";
interrupts = <61>; interrupts = <61>;
}; };

View File

@ -573,7 +573,7 @@ EXPORT_SYMBOL_GPL(of_pwm_get);
* @table: array of consumers to register * @table: array of consumers to register
* @num: number of consumers in table * @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); mutex_lock(&pwm_lookup_lock);

View File

@ -225,6 +225,10 @@ static const struct of_device_id atmel_hlcdc_dt_ids[] = {
.compatible = "atmel,sama5d3-hlcdc", .compatible = "atmel,sama5d3-hlcdc",
.data = &atmel_hlcdc_pwm_sama5d3_errata, .data = &atmel_hlcdc_pwm_sama5d3_errata,
}, },
{
.compatible = "atmel,sama5d4-hlcdc",
.data = &atmel_hlcdc_pwm_sama5d3_errata,
},
{ /* sentinel */ }, { /* sentinel */ },
}; };

View File

@ -35,6 +35,10 @@
#define PERIOD_CDIV(div) (((div) & 0x7) << 20) #define PERIOD_CDIV(div) (((div) & 0x7) << 20)
#define PERIOD_CDIV_MAX 8 #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 mxs_pwm_chip {
struct pwm_chip chip; struct pwm_chip chip;
struct clk *clk; struct clk *clk;
@ -54,13 +58,13 @@ static int mxs_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
rate = clk_get_rate(mxs->clk); rate = clk_get_rate(mxs->clk);
while (1) { while (1) {
c = rate / (1 << div); c = rate / cdiv[div];
c = c * period_ns; c = c * period_ns;
do_div(c, 1000000000); do_div(c, 1000000000);
if (c < PERIOD_PERIOD_MAX) if (c < PERIOD_PERIOD_MAX)
break; break;
div++; div++;
if (div > PERIOD_CDIV_MAX) if (div >= PERIOD_CDIV_MAX)
return -EINVAL; return -EINVAL;
} }

View File

@ -202,7 +202,7 @@ static const struct pwm_ops pca9685_pwm_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static struct regmap_config pca9685_regmap_i2c_config = { static const struct regmap_config pca9685_regmap_i2c_config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
.max_register = PCA9685_NUMREGS, .max_register = PCA9685_NUMREGS,

View File

@ -269,12 +269,31 @@ static void pwm_samsung_disable(struct pwm_chip *chip, struct pwm_device *pwm)
spin_unlock_irqrestore(&samsung_pwm_lock, flags); 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, static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns) int duty_ns, int period_ns)
{ {
struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip); struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip);
struct samsung_pwm_channel *chan = pwm_get_chip_data(pwm); 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 * We currently avoid using 64bit arithmetic by using the
@ -288,6 +307,7 @@ static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
return 0; return 0;
tcnt = readl(our_chip->base + REG_TCNTB(pwm->hwpwm)); 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. */ /* We need tick count for calculation, not last tick. */
++tcnt; ++tcnt;
@ -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(tcnt, our_chip->base + REG_TCNTB(pwm->hwpwm));
writel(tcmp, our_chip->base + REG_TCMPB(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->period_ns = period_ns;
chan->tin_ns = tin_ns; chan->tin_ns = tin_ns;
chan->duty_ns = duty_ns; chan->duty_ns = duty_ns;