Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+54 -6
+11 -1
Documentation/devicetree/bindings/pwm/imx-pwm.txt
··· 1 1 Freescale i.MX PWM controller 2 2 3 3 Required properties: 4 - - compatible: should be "fsl,<soc>-pwm" 4 + - compatible : should be "fsl,<soc>-pwm" and one of the following 5 + compatible strings: 6 + - "fsl,imx1-pwm" for PWM compatible with the one integrated on i.MX1 7 + - "fsl,imx27-pwm" for PWM compatible with the one integrated on i.MX27 5 8 - reg: physical base address and length of the controller's registers 6 9 - #pwm-cells: should be 2. See pwm.txt in this directory for a description of 7 10 the cells format. 11 + - clocks : Clock specifiers for both ipg and per clocks. 12 + - clock-names : Clock names should include both "ipg" and "per" 13 + See the clock consumer binding, 14 + Documentation/devicetree/bindings/clock/clock-bindings.txt 8 15 - interrupts: The interrupt for the pwm controller 9 16 10 17 Example: ··· 20 13 #pwm-cells = <2>; 21 14 compatible = "fsl,imx53-pwm", "fsl,imx27-pwm"; 22 15 reg = <0x53fb4000 0x4000>; 16 + clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>, 17 + <&clks IMX5_CLK_PWM1_HF_GATE>; 18 + clock-names = "ipg", "per"; 23 19 interrupts = <61>; 24 20 };
+1 -1
drivers/pwm/core.c
··· 573 573 * @table: array of consumers to register 574 574 * @num: number of consumers in table 575 575 */ 576 - void __init pwm_add_table(struct pwm_lookup *table, size_t num) 576 + void pwm_add_table(struct pwm_lookup *table, size_t num) 577 577 { 578 578 mutex_lock(&pwm_lookup_lock); 579 579
+4
drivers/pwm/pwm-atmel-hlcdc.c
··· 225 225 .compatible = "atmel,sama5d3-hlcdc", 226 226 .data = &atmel_hlcdc_pwm_sama5d3_errata, 227 227 }, 228 + { 229 + .compatible = "atmel,sama5d4-hlcdc", 230 + .data = &atmel_hlcdc_pwm_sama5d3_errata, 231 + }, 228 232 { /* sentinel */ }, 229 233 }; 230 234
+6 -2
drivers/pwm/pwm-mxs.c
··· 35 35 #define PERIOD_CDIV(div) (((div) & 0x7) << 20) 36 36 #define PERIOD_CDIV_MAX 8 37 37 38 + static const unsigned int cdiv[PERIOD_CDIV_MAX] = { 39 + 1, 2, 4, 8, 16, 64, 256, 1024 40 + }; 41 + 38 42 struct mxs_pwm_chip { 39 43 struct pwm_chip chip; 40 44 struct clk *clk; ··· 58 54 59 55 rate = clk_get_rate(mxs->clk); 60 56 while (1) { 61 - c = rate / (1 << div); 57 + c = rate / cdiv[div]; 62 58 c = c * period_ns; 63 59 do_div(c, 1000000000); 64 60 if (c < PERIOD_PERIOD_MAX) 65 61 break; 66 62 div++; 67 - if (div > PERIOD_CDIV_MAX) 63 + if (div >= PERIOD_CDIV_MAX) 68 64 return -EINVAL; 69 65 } 70 66
+1 -1
drivers/pwm/pwm-pca9685.c
··· 202 202 .owner = THIS_MODULE, 203 203 }; 204 204 205 - static struct regmap_config pca9685_regmap_i2c_config = { 205 + static const struct regmap_config pca9685_regmap_i2c_config = { 206 206 .reg_bits = 8, 207 207 .val_bits = 8, 208 208 .max_register = PCA9685_NUMREGS,
+31 -1
drivers/pwm/pwm-samsung.c
··· 269 269 spin_unlock_irqrestore(&samsung_pwm_lock, flags); 270 270 } 271 271 272 + static void pwm_samsung_manual_update(struct samsung_pwm_chip *chip, 273 + struct pwm_device *pwm) 274 + { 275 + unsigned int tcon_chan = to_tcon_channel(pwm->hwpwm); 276 + u32 tcon; 277 + unsigned long flags; 278 + 279 + spin_lock_irqsave(&samsung_pwm_lock, flags); 280 + 281 + tcon = readl(chip->base + REG_TCON); 282 + tcon |= TCON_MANUALUPDATE(tcon_chan); 283 + writel(tcon, chip->base + REG_TCON); 284 + 285 + tcon &= ~TCON_MANUALUPDATE(tcon_chan); 286 + writel(tcon, chip->base + REG_TCON); 287 + 288 + spin_unlock_irqrestore(&samsung_pwm_lock, flags); 289 + } 290 + 272 291 static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm, 273 292 int duty_ns, int period_ns) 274 293 { 275 294 struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip); 276 295 struct samsung_pwm_channel *chan = pwm_get_chip_data(pwm); 277 - u32 tin_ns = chan->tin_ns, tcnt, tcmp; 296 + u32 tin_ns = chan->tin_ns, tcnt, tcmp, oldtcmp; 278 297 279 298 /* 280 299 * We currently avoid using 64bit arithmetic by using the ··· 307 288 return 0; 308 289 309 290 tcnt = readl(our_chip->base + REG_TCNTB(pwm->hwpwm)); 291 + oldtcmp = readl(our_chip->base + REG_TCMPB(pwm->hwpwm)); 310 292 311 293 /* We need tick count for calculation, not last tick. */ 312 294 ++tcnt; ··· 354 334 /* Update PWM registers. */ 355 335 writel(tcnt, our_chip->base + REG_TCNTB(pwm->hwpwm)); 356 336 writel(tcmp, our_chip->base + REG_TCMPB(pwm->hwpwm)); 337 + 338 + /* 339 + * In case the PWM is currently at 100% duty cycle, force a manual 340 + * update to prevent the signal staying high if the PWM is disabled 341 + * shortly afer this update (before it autoreloaded the new values). 342 + */ 343 + if (oldtcmp == (u32) -1) { 344 + dev_dbg(our_chip->chip.dev, "Forcing manual update"); 345 + pwm_samsung_manual_update(our_chip, pwm); 346 + } 357 347 358 348 chan->period_ns = period_ns; 359 349 chan->tin_ns = tin_ns;