forked from Minki/linux
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
|
||||
|
||||
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:
|
||||
@ -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>;
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */ },
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user