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:
commit
06b45f2aa7
@ -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>;
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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 */ },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user