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

Merge tag 'pwm/for-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm

Pull pwm updates from Thierry Reding:
"This set of changes improve some aspects of the atomic API as well as
make use of this new API in the regulator framework to allow properly
dealing with critical regulators controlled by a PWM.

Aside from that there's a bunch of updates and cleanups for existing
drivers, as well as the addition of new drivers for the Broadcom
iProc, STMPE and ChromeOS EC controllers"

* tag 'pwm/for-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (44 commits)
regulator: pwm: Document pwm-dutycycle-unit and pwm-dutycycle-range
regulator: pwm: Support extra continuous mode cases
pwm: Add ChromeOS EC PWM driver
dt-bindings: pwm: Add binding for ChromeOS EC PWM
mfd: cros_ec: Add EC_PWM function definitions
mfd: cros_ec: Add cros_ec_cmd_xfer_status() helper
pwm: atmel: Use of_device_get_match_data()
pwm: atmel: Fix checkpatch warnings
pwm: atmel: Fix disabling of PWM channels
dt-bindings: pwm: Add R-Car H3 device tree bindings
pwm: rcar: Use ARCH_RENESAS
pwm: tegra: Add support for Tegra186
dt-bindings: pwm: tegra: Add compatible string for Tegra186
pwm: tegra: Avoid overflow when calculating duty cycle
pwm: tegra: Allow 100 % duty cycle
pwm: tegra: Add support for reset control
pwm: tegra: Rename mmio_base to regs
pwm: tegra: Remove useless padding
pwm: tegra: Drop NUM_PWM macro
pwm: lpc32xx: Set PWM_PIN_LEVEL bit to default value
...

+1561 -283
+9
Documentation/ABI/testing/sysfs-class-pwm
··· 77 77 Enable/disable the PWM signal. 78 78 0 is disabled 79 79 1 is enabled 80 + 81 + What: /sys/class/pwm/pwmchipN/pwmX/capture 82 + Date: June 2016 83 + KernelVersion: 4.8 84 + Contact: Lee Jones <lee.jones@linaro.org> 85 + Description: 86 + Capture information about a PWM signal. The output format is a 87 + pair unsigned integers (period and duty cycle), separated by a 88 + single space.
+21
Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
··· 1 + Broadcom iProc PWM controller device tree bindings 2 + 3 + This controller has 4 channels. 4 + 5 + Required Properties : 6 + - compatible: must be "brcm,iproc-pwm" 7 + - reg: physical base address and length of the controller's registers 8 + - clocks: phandle + clock specifier pair for the external clock 9 + - #pwm-cells: Should be 3. See pwm.txt in this directory for a 10 + description of the cells format. 11 + 12 + Refer to clocks/clock-bindings.txt for generic clock consumer properties. 13 + 14 + Example: 15 + 16 + pwm: pwm@18031000 { 17 + compatible = "brcm,iproc-pwm"; 18 + reg = <0x18031000 0x28>; 19 + clocks = <&osc>; 20 + #pwm-cells = <3>; 21 + };
+23
Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt
··· 1 + * PWM controlled by ChromeOS EC 2 + 3 + Google's ChromeOS EC PWM is a simple PWM attached to the Embedded Controller 4 + (EC) and controlled via a host-command interface. 5 + 6 + An EC PWM node should be only found as a sub-node of the EC node (see 7 + Documentation/devicetree/bindings/mfd/cros-ec.txt). 8 + 9 + Required properties: 10 + - compatible: Must contain "google,cros-ec-pwm" 11 + - #pwm-cells: Should be 1. The cell specifies the PWM index. 12 + 13 + Example: 14 + cros-ec@0 { 15 + compatible = "google,cros-ec-spi"; 16 + 17 + ... 18 + 19 + cros_ec_pwm: ec-pwm { 20 + compatible = "google,cros-ec-pwm"; 21 + #pwm-cells = <1>; 22 + }; 23 + };
+8 -4
Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
··· 1 1 Tegra SoC PWFM controller 2 2 3 3 Required properties: 4 - - compatible: For Tegra20, must contain "nvidia,tegra20-pwm". For Tegra30, 5 - must contain "nvidia,tegra30-pwm". Otherwise, must contain 6 - "nvidia,<chip>-pwm", plus one of the above, where <chip> is tegra114, 7 - tegra124, tegra132, or tegra210. 4 + - compatible: Must be: 5 + - "nvidia,tegra20-pwm": for Tegra20 6 + - "nvidia,tegra30-pwm", "nvidia,tegra20-pwm": for Tegra30 7 + - "nvidia,tegra114-pwm", "nvidia,tegra20-pwm": for Tegra114 8 + - "nvidia,tegra124-pwm", "nvidia,tegra20-pwm": for Tegra124 9 + - "nvidia,tegra132-pwm", "nvidia,tegra20-pwm": for Tegra132 10 + - "nvidia,tegra210-pwm", "nvidia,tegra20-pwm": for Tegra210 11 + - "nvidia,tegra186-pwm": for Tegra186 8 12 - reg: physical base address and length of the controller's registers 9 13 - #pwm-cells: should be 2. See pwm.txt in this directory for a description of 10 14 the cells format.
+1
Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
··· 7 7 - "renesas,pwm-r8a7790": for R-Car H2 8 8 - "renesas,pwm-r8a7791": for R-Car M2-W 9 9 - "renesas,pwm-r8a7794": for R-Car E2 10 + - "renesas,pwm-r8a7795": for R-Car H3 10 11 - reg: base address and length of the registers block for the PWM. 11 12 - #pwm-cells: should be 2. See pwm.txt in this directory for a description of 12 13 the cells format.
+18
Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt
··· 1 + == ST STMPE PWM controller == 2 + 3 + This is a PWM block embedded in the ST Microelectronics STMPE 4 + (ST Multi-Purpose Expander) chips. The PWM is registered as a 5 + subdevices of the STMPE MFD device. 6 + 7 + Required properties: 8 + - compatible: should be: 9 + - "st,stmpe-pwm" 10 + - #pwm-cells: should be 2. See pwm.txt in this directory for a description of 11 + the cells format. 12 + 13 + Example: 14 + 15 + pwm0: pwm { 16 + compatible = "st,stmpe-pwm"; 17 + #pwm-cells = <2>; 18 + };
+19
Documentation/devicetree/bindings/regulator/pwm-regulator.txt
··· 34 34 First cell is voltage in microvolts (uV) 35 35 Second cell is duty-cycle in percent (%) 36 36 37 + Optional properties for Continuous mode: 38 + - pwm-dutycycle-unit: Integer value encoding the duty cycle unit. If not 39 + defined, <100> is assumed, meaning that 40 + pwm-dutycycle-range contains values expressed in 41 + percent. 42 + 43 + - pwm-dutycycle-range: Should contain 2 entries. The first entry is encoding 44 + the dutycycle for regulator-min-microvolt and the 45 + second one the dutycycle for regulator-max-microvolt. 46 + Duty cycle values are expressed in pwm-dutycycle-unit. 47 + If not defined, <0 100> is assumed. 48 + 37 49 NB: To be clear, if voltage-table is provided, then the device will be used 38 50 in Voltage Table Mode. If no voltage-table is provided, then the device will 39 51 be used in Continuous Voltage Mode. ··· 65 53 regulator-min-microvolt = <1016000>; 66 54 regulator-max-microvolt = <1114000>; 67 55 regulator-name = "vdd_logic"; 56 + /* unit == per-mille */ 57 + pwm-dutycycle-unit = <1000>; 58 + /* 59 + * Inverted PWM logic, and the duty cycle range is limited 60 + * to 30%-70%. 61 + */ 62 + pwm-dutycycle-range <700 300>; /* */ 68 63 }; 69 64 70 65 Voltage Table Example:
+17
drivers/platform/chrome/cros_ec_proto.c
··· 380 380 return ret; 381 381 } 382 382 EXPORT_SYMBOL(cros_ec_cmd_xfer); 383 + 384 + int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, 385 + struct cros_ec_command *msg) 386 + { 387 + int ret; 388 + 389 + ret = cros_ec_cmd_xfer(ec_dev, msg); 390 + if (ret < 0) { 391 + dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret); 392 + } else if (msg->result != EC_RES_SUCCESS) { 393 + dev_dbg(ec_dev->dev, "Command result (err: %d)\n", msg->result); 394 + return -EPROTO; 395 + } 396 + 397 + return ret; 398 + } 399 + EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
+25 -1
drivers/pwm/Kconfig
··· 74 74 To compile this driver as a module, choose M here: the module 75 75 will be called pwm-atmel-tcb. 76 76 77 + config PWM_BCM_IPROC 78 + tristate "iProc PWM support" 79 + depends on ARCH_BCM_IPROC 80 + help 81 + Generic PWM framework driver for Broadcom iProc PWM block. This 82 + block is used in Broadcom iProc SoC's. 83 + 84 + To compile this driver as a module, choose M here: the module 85 + will be called pwm-bcm-iproc. 86 + 77 87 config PWM_BCM_KONA 78 88 tristate "Kona PWM support" 79 89 depends on ARCH_BCM_MOBILE ··· 146 136 help 147 137 Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM 148 138 control. 139 + 140 + config PWM_CROS_EC 141 + tristate "ChromeOS EC PWM driver" 142 + depends on MFD_CROS_EC 143 + help 144 + PWM driver for exposing a PWM attached to the ChromeOS Embedded 145 + Controller. 149 146 150 147 config PWM_EP93XX 151 148 tristate "Cirrus Logic EP93xx PWM support" ··· 322 305 323 306 config PWM_RCAR 324 307 tristate "Renesas R-Car PWM support" 325 - depends on ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || COMPILE_TEST 308 + depends on ARCH_RENESAS || COMPILE_TEST 326 309 depends on HAS_IOMEM 327 310 help 328 311 This driver exposes the PWM Timer controller found in Renesas ··· 378 361 379 362 To compile this driver as a module, choose M here: the module 380 363 will be called pwm-sti. 364 + 365 + config PWM_STMPE 366 + bool "STMPE expander PWM export" 367 + depends on MFD_STMPE 368 + help 369 + This enables support for the PWMs found in the STMPE I/O 370 + expanders. 381 371 382 372 config PWM_SUN4I 383 373 tristate "Allwinner PWM support"
+3
drivers/pwm/Makefile
··· 4 4 obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o 5 5 obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o 6 6 obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o 7 + obj-$(CONFIG_PWM_BCM_IPROC) += pwm-bcm-iproc.o 7 8 obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o 8 9 obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o 9 10 obj-$(CONFIG_PWM_BERLIN) += pwm-berlin.o ··· 12 11 obj-$(CONFIG_PWM_BRCMSTB) += pwm-brcmstb.o 13 12 obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o 14 13 obj-$(CONFIG_PWM_CRC) += pwm-crc.o 14 + obj-$(CONFIG_PWM_CROS_EC) += pwm-cros-ec.o 15 15 obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o 16 16 obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o 17 17 obj-$(CONFIG_PWM_IMG) += pwm-img.o ··· 36 34 obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o 37 35 obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o 38 36 obj-$(CONFIG_PWM_STI) += pwm-sti.o 37 + obj-$(CONFIG_PWM_STMPE) += pwm-stmpe.o 39 38 obj-$(CONFIG_PWM_SUN4I) += pwm-sun4i.o 40 39 obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o 41 40 obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o
+27
drivers/pwm/core.c
··· 526 526 EXPORT_SYMBOL_GPL(pwm_apply_state); 527 527 528 528 /** 529 + * pwm_capture() - capture and report a PWM signal 530 + * @pwm: PWM device 531 + * @result: structure to fill with capture result 532 + * @timeout: time to wait, in milliseconds, before giving up on capture 533 + * 534 + * Returns: 0 on success or a negative error code on failure. 535 + */ 536 + int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result, 537 + unsigned long timeout) 538 + { 539 + int err; 540 + 541 + if (!pwm || !pwm->chip->ops) 542 + return -EINVAL; 543 + 544 + if (!pwm->chip->ops->capture) 545 + return -ENOSYS; 546 + 547 + mutex_lock(&pwm_lock); 548 + err = pwm->chip->ops->capture(pwm->chip, pwm, result, timeout); 549 + mutex_unlock(&pwm_lock); 550 + 551 + return err; 552 + } 553 + EXPORT_SYMBOL_GPL(pwm_capture); 554 + 555 + /** 529 556 * pwm_adjust_config() - adjust the current PWM config to the PWM arguments 530 557 * @pwm: PWM device 531 558 *
+17 -13
drivers/pwm/pwm-atmel.c
··· 64 64 void __iomem *base; 65 65 66 66 unsigned int updated_pwms; 67 - struct mutex isr_lock; /* ISR is cleared when read, ensure only one thread does that */ 67 + /* ISR is cleared when read, ensure only one thread does that */ 68 + struct mutex isr_lock; 68 69 69 70 void (*config)(struct pwm_chip *chip, struct pwm_device *pwm, 70 71 unsigned long dty, unsigned long prd); ··· 272 271 mutex_unlock(&atmel_pwm->isr_lock); 273 272 atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << pwm->hwpwm); 274 273 274 + /* 275 + * Wait for the PWM channel disable operation to be effective before 276 + * stopping the clock. 277 + */ 278 + timeout = jiffies + 2 * HZ; 279 + 280 + while ((atmel_pwm_readl(atmel_pwm, PWM_SR) & (1 << pwm->hwpwm)) && 281 + time_before(jiffies, timeout)) 282 + usleep_range(10, 100); 283 + 275 284 clk_disable(atmel_pwm->clk); 276 285 } 277 286 ··· 335 324 static inline const struct atmel_pwm_data * 336 325 atmel_pwm_get_driver_data(struct platform_device *pdev) 337 326 { 338 - if (pdev->dev.of_node) { 339 - const struct of_device_id *match; 327 + const struct platform_device_id *id; 340 328 341 - match = of_match_device(atmel_pwm_dt_ids, &pdev->dev); 342 - if (!match) 343 - return NULL; 329 + if (pdev->dev.of_node) 330 + return of_device_get_match_data(&pdev->dev); 344 331 345 - return match->data; 346 - } else { 347 - const struct platform_device_id *id; 332 + id = platform_get_device_id(pdev); 348 333 349 - id = platform_get_device_id(pdev); 350 - 351 - return (struct atmel_pwm_data *)id->driver_data; 352 - } 334 + return (struct atmel_pwm_data *)id->driver_data; 353 335 } 354 336 355 337 static int atmel_pwm_probe(struct platform_device *pdev)
+277
drivers/pwm/pwm-bcm-iproc.c
··· 1 + /* 2 + * Copyright (C) 2016 Broadcom 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License as 6 + * published by the Free Software Foundation version 2. 7 + * 8 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any 9 + * kind, whether express or implied; without even the implied warranty 10 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + #include <linux/clk.h> 15 + #include <linux/delay.h> 16 + #include <linux/err.h> 17 + #include <linux/io.h> 18 + #include <linux/math64.h> 19 + #include <linux/module.h> 20 + #include <linux/of.h> 21 + #include <linux/platform_device.h> 22 + #include <linux/pwm.h> 23 + 24 + #define IPROC_PWM_CTRL_OFFSET 0x00 25 + #define IPROC_PWM_CTRL_TYPE_SHIFT(ch) (15 + (ch)) 26 + #define IPROC_PWM_CTRL_POLARITY_SHIFT(ch) (8 + (ch)) 27 + #define IPROC_PWM_CTRL_EN_SHIFT(ch) (ch) 28 + 29 + #define IPROC_PWM_PERIOD_OFFSET(ch) (0x04 + ((ch) << 3)) 30 + #define IPROC_PWM_PERIOD_MIN 0x02 31 + #define IPROC_PWM_PERIOD_MAX 0xffff 32 + 33 + #define IPROC_PWM_DUTY_CYCLE_OFFSET(ch) (0x08 + ((ch) << 3)) 34 + #define IPROC_PWM_DUTY_CYCLE_MIN 0x00 35 + #define IPROC_PWM_DUTY_CYCLE_MAX 0xffff 36 + 37 + #define IPROC_PWM_PRESCALE_OFFSET 0x24 38 + #define IPROC_PWM_PRESCALE_BITS 0x06 39 + #define IPROC_PWM_PRESCALE_SHIFT(ch) ((3 - (ch)) * \ 40 + IPROC_PWM_PRESCALE_BITS) 41 + #define IPROC_PWM_PRESCALE_MASK(ch) (IPROC_PWM_PRESCALE_MAX << \ 42 + IPROC_PWM_PRESCALE_SHIFT(ch)) 43 + #define IPROC_PWM_PRESCALE_MIN 0x00 44 + #define IPROC_PWM_PRESCALE_MAX 0x3f 45 + 46 + struct iproc_pwmc { 47 + struct pwm_chip chip; 48 + void __iomem *base; 49 + struct clk *clk; 50 + }; 51 + 52 + static inline struct iproc_pwmc *to_iproc_pwmc(struct pwm_chip *chip) 53 + { 54 + return container_of(chip, struct iproc_pwmc, chip); 55 + } 56 + 57 + static void iproc_pwmc_enable(struct iproc_pwmc *ip, unsigned int channel) 58 + { 59 + u32 value; 60 + 61 + value = readl(ip->base + IPROC_PWM_CTRL_OFFSET); 62 + value |= 1 << IPROC_PWM_CTRL_EN_SHIFT(channel); 63 + writel(value, ip->base + IPROC_PWM_CTRL_OFFSET); 64 + 65 + /* must be a 400 ns delay between clearing and setting enable bit */ 66 + ndelay(400); 67 + } 68 + 69 + static void iproc_pwmc_disable(struct iproc_pwmc *ip, unsigned int channel) 70 + { 71 + u32 value; 72 + 73 + value = readl(ip->base + IPROC_PWM_CTRL_OFFSET); 74 + value &= ~(1 << IPROC_PWM_CTRL_EN_SHIFT(channel)); 75 + writel(value, ip->base + IPROC_PWM_CTRL_OFFSET); 76 + 77 + /* must be a 400 ns delay between clearing and setting enable bit */ 78 + ndelay(400); 79 + } 80 + 81 + static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, 82 + struct pwm_state *state) 83 + { 84 + struct iproc_pwmc *ip = to_iproc_pwmc(chip); 85 + u64 tmp, multi, rate; 86 + u32 value, prescale; 87 + 88 + rate = clk_get_rate(ip->clk); 89 + 90 + value = readl(ip->base + IPROC_PWM_CTRL_OFFSET); 91 + 92 + if (value & BIT(IPROC_PWM_CTRL_EN_SHIFT(pwm->hwpwm))) 93 + state->enabled = true; 94 + else 95 + state->enabled = false; 96 + 97 + if (value & BIT(IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm))) 98 + state->polarity = PWM_POLARITY_NORMAL; 99 + else 100 + state->polarity = PWM_POLARITY_INVERSED; 101 + 102 + value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET); 103 + prescale = value >> IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm); 104 + prescale &= IPROC_PWM_PRESCALE_MAX; 105 + 106 + multi = NSEC_PER_SEC * (prescale + 1); 107 + 108 + value = readl(ip->base + IPROC_PWM_PERIOD_OFFSET(pwm->hwpwm)); 109 + tmp = (value & IPROC_PWM_PERIOD_MAX) * multi; 110 + state->period = div64_u64(tmp, rate); 111 + 112 + value = readl(ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm)); 113 + tmp = (value & IPROC_PWM_PERIOD_MAX) * multi; 114 + state->duty_cycle = div64_u64(tmp, rate); 115 + } 116 + 117 + static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm, 118 + struct pwm_state *state) 119 + { 120 + unsigned long prescale = IPROC_PWM_PRESCALE_MIN; 121 + struct iproc_pwmc *ip = to_iproc_pwmc(chip); 122 + u32 value, period, duty; 123 + u64 rate; 124 + 125 + rate = clk_get_rate(ip->clk); 126 + 127 + /* 128 + * Find period count, duty count and prescale to suit duty_cycle and 129 + * period. This is done according to formulas described below: 130 + * 131 + * period_ns = 10^9 * (PRESCALE + 1) * PC / PWM_CLK_RATE 132 + * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE 133 + * 134 + * PC = (PWM_CLK_RATE * period_ns) / (10^9 * (PRESCALE + 1)) 135 + * DC = (PWM_CLK_RATE * duty_ns) / (10^9 * (PRESCALE + 1)) 136 + */ 137 + while (1) { 138 + u64 value, div; 139 + 140 + div = NSEC_PER_SEC * (prescale + 1); 141 + value = rate * state->period; 142 + period = div64_u64(value, div); 143 + value = rate * state->duty_cycle; 144 + duty = div64_u64(value, div); 145 + 146 + if (period < IPROC_PWM_PERIOD_MIN || 147 + duty < IPROC_PWM_DUTY_CYCLE_MIN) 148 + return -EINVAL; 149 + 150 + if (period <= IPROC_PWM_PERIOD_MAX && 151 + duty <= IPROC_PWM_DUTY_CYCLE_MAX) 152 + break; 153 + 154 + /* Otherwise, increase prescale and recalculate counts */ 155 + if (++prescale > IPROC_PWM_PRESCALE_MAX) 156 + return -EINVAL; 157 + } 158 + 159 + iproc_pwmc_disable(ip, pwm->hwpwm); 160 + 161 + /* Set prescale */ 162 + value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET); 163 + value &= ~IPROC_PWM_PRESCALE_MASK(pwm->hwpwm); 164 + value |= prescale << IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm); 165 + writel(value, ip->base + IPROC_PWM_PRESCALE_OFFSET); 166 + 167 + /* set period and duty cycle */ 168 + writel(period, ip->base + IPROC_PWM_PERIOD_OFFSET(pwm->hwpwm)); 169 + writel(duty, ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm)); 170 + 171 + /* set polarity */ 172 + value = readl(ip->base + IPROC_PWM_CTRL_OFFSET); 173 + 174 + if (state->polarity == PWM_POLARITY_NORMAL) 175 + value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm); 176 + else 177 + value &= ~(1 << IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm)); 178 + 179 + writel(value, ip->base + IPROC_PWM_CTRL_OFFSET); 180 + 181 + if (state->enabled) 182 + iproc_pwmc_enable(ip, pwm->hwpwm); 183 + 184 + return 0; 185 + } 186 + 187 + static const struct pwm_ops iproc_pwm_ops = { 188 + .apply = iproc_pwmc_apply, 189 + .get_state = iproc_pwmc_get_state, 190 + }; 191 + 192 + static int iproc_pwmc_probe(struct platform_device *pdev) 193 + { 194 + struct iproc_pwmc *ip; 195 + struct resource *res; 196 + unsigned int i; 197 + u32 value; 198 + int ret; 199 + 200 + ip = devm_kzalloc(&pdev->dev, sizeof(*ip), GFP_KERNEL); 201 + if (!ip) 202 + return -ENOMEM; 203 + 204 + platform_set_drvdata(pdev, ip); 205 + 206 + ip->chip.dev = &pdev->dev; 207 + ip->chip.ops = &iproc_pwm_ops; 208 + ip->chip.base = -1; 209 + ip->chip.npwm = 4; 210 + ip->chip.of_xlate = of_pwm_xlate_with_flags; 211 + ip->chip.of_pwm_n_cells = 3; 212 + 213 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 214 + ip->base = devm_ioremap_resource(&pdev->dev, res); 215 + if (IS_ERR(ip->base)) 216 + return PTR_ERR(ip->base); 217 + 218 + ip->clk = devm_clk_get(&pdev->dev, NULL); 219 + if (IS_ERR(ip->clk)) { 220 + dev_err(&pdev->dev, "failed to get clock: %ld\n", 221 + PTR_ERR(ip->clk)); 222 + return PTR_ERR(ip->clk); 223 + } 224 + 225 + ret = clk_prepare_enable(ip->clk); 226 + if (ret < 0) { 227 + dev_err(&pdev->dev, "failed to enable clock: %d\n", ret); 228 + return ret; 229 + } 230 + 231 + /* Set full drive and normal polarity for all channels */ 232 + value = readl(ip->base + IPROC_PWM_CTRL_OFFSET); 233 + 234 + for (i = 0; i < ip->chip.npwm; i++) { 235 + value &= ~(1 << IPROC_PWM_CTRL_TYPE_SHIFT(i)); 236 + value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(i); 237 + } 238 + 239 + writel(value, ip->base + IPROC_PWM_CTRL_OFFSET); 240 + 241 + ret = pwmchip_add(&ip->chip); 242 + if (ret < 0) { 243 + dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); 244 + clk_disable_unprepare(ip->clk); 245 + } 246 + 247 + return ret; 248 + } 249 + 250 + static int iproc_pwmc_remove(struct platform_device *pdev) 251 + { 252 + struct iproc_pwmc *ip = platform_get_drvdata(pdev); 253 + 254 + clk_disable_unprepare(ip->clk); 255 + 256 + return pwmchip_remove(&ip->chip); 257 + } 258 + 259 + static const struct of_device_id bcm_iproc_pwmc_dt[] = { 260 + { .compatible = "brcm,iproc-pwm" }, 261 + { }, 262 + }; 263 + MODULE_DEVICE_TABLE(of, bcm_iproc_pwmc_dt); 264 + 265 + static struct platform_driver iproc_pwmc_driver = { 266 + .driver = { 267 + .name = "bcm-iproc-pwm", 268 + .of_match_table = bcm_iproc_pwmc_dt, 269 + }, 270 + .probe = iproc_pwmc_probe, 271 + .remove = iproc_pwmc_remove, 272 + }; 273 + module_platform_driver(iproc_pwmc_driver); 274 + 275 + MODULE_AUTHOR("Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>"); 276 + MODULE_DESCRIPTION("Broadcom iProc PWM driver"); 277 + MODULE_LICENSE("GPL v2");
+260
drivers/pwm/pwm-cros-ec.c
··· 1 + /* 2 + * Copyright (C) 2016 Google, Inc 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2, as published by 6 + * the Free Software Foundation. 7 + * 8 + * Expose a PWM controlled by the ChromeOS EC to the host processor. 9 + */ 10 + 11 + #include <linux/module.h> 12 + #include <linux/mfd/cros_ec.h> 13 + #include <linux/mfd/cros_ec_commands.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/pwm.h> 16 + #include <linux/slab.h> 17 + 18 + /** 19 + * struct cros_ec_pwm_device - Driver data for EC PWM 20 + * 21 + * @dev: Device node 22 + * @ec: Pointer to EC device 23 + * @chip: PWM controller chip 24 + */ 25 + struct cros_ec_pwm_device { 26 + struct device *dev; 27 + struct cros_ec_device *ec; 28 + struct pwm_chip chip; 29 + }; 30 + 31 + static inline struct cros_ec_pwm_device *pwm_to_cros_ec_pwm(struct pwm_chip *c) 32 + { 33 + return container_of(c, struct cros_ec_pwm_device, chip); 34 + } 35 + 36 + static int cros_ec_pwm_set_duty(struct cros_ec_device *ec, u8 index, u16 duty) 37 + { 38 + struct { 39 + struct cros_ec_command msg; 40 + struct ec_params_pwm_set_duty params; 41 + } buf; 42 + struct ec_params_pwm_set_duty *params = &buf.params; 43 + struct cros_ec_command *msg = &buf.msg; 44 + 45 + memset(&buf, 0, sizeof(buf)); 46 + 47 + msg->version = 0; 48 + msg->command = EC_CMD_PWM_SET_DUTY; 49 + msg->insize = 0; 50 + msg->outsize = sizeof(*params); 51 + 52 + params->duty = duty; 53 + params->pwm_type = EC_PWM_TYPE_GENERIC; 54 + params->index = index; 55 + 56 + return cros_ec_cmd_xfer_status(ec, msg); 57 + } 58 + 59 + static int __cros_ec_pwm_get_duty(struct cros_ec_device *ec, u8 index, 60 + u32 *result) 61 + { 62 + struct { 63 + struct cros_ec_command msg; 64 + union { 65 + struct ec_params_pwm_get_duty params; 66 + struct ec_response_pwm_get_duty resp; 67 + }; 68 + } buf; 69 + struct ec_params_pwm_get_duty *params = &buf.params; 70 + struct ec_response_pwm_get_duty *resp = &buf.resp; 71 + struct cros_ec_command *msg = &buf.msg; 72 + int ret; 73 + 74 + memset(&buf, 0, sizeof(buf)); 75 + 76 + msg->version = 0; 77 + msg->command = EC_CMD_PWM_GET_DUTY; 78 + msg->insize = sizeof(*params); 79 + msg->outsize = sizeof(*resp); 80 + 81 + params->pwm_type = EC_PWM_TYPE_GENERIC; 82 + params->index = index; 83 + 84 + ret = cros_ec_cmd_xfer_status(ec, msg); 85 + if (result) 86 + *result = msg->result; 87 + if (ret < 0) 88 + return ret; 89 + 90 + return resp->duty; 91 + } 92 + 93 + static int cros_ec_pwm_get_duty(struct cros_ec_device *ec, u8 index) 94 + { 95 + return __cros_ec_pwm_get_duty(ec, index, NULL); 96 + } 97 + 98 + static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 99 + struct pwm_state *state) 100 + { 101 + struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip); 102 + int duty_cycle; 103 + 104 + /* The EC won't let us change the period */ 105 + if (state->period != EC_PWM_MAX_DUTY) 106 + return -EINVAL; 107 + 108 + /* 109 + * EC doesn't separate the concept of duty cycle and enabled, but 110 + * kernel does. Translate. 111 + */ 112 + duty_cycle = state->enabled ? state->duty_cycle : 0; 113 + 114 + return cros_ec_pwm_set_duty(ec_pwm->ec, pwm->hwpwm, duty_cycle); 115 + } 116 + 117 + static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, 118 + struct pwm_state *state) 119 + { 120 + struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip); 121 + int ret; 122 + 123 + ret = cros_ec_pwm_get_duty(ec_pwm->ec, pwm->hwpwm); 124 + if (ret < 0) { 125 + dev_err(chip->dev, "error getting initial duty: %d\n", ret); 126 + return; 127 + } 128 + 129 + state->enabled = (ret > 0); 130 + state->period = EC_PWM_MAX_DUTY; 131 + 132 + /* Note that "disabled" and "duty cycle == 0" are treated the same */ 133 + state->duty_cycle = ret; 134 + } 135 + 136 + static struct pwm_device * 137 + cros_ec_pwm_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) 138 + { 139 + struct pwm_device *pwm; 140 + 141 + if (args->args[0] >= pc->npwm) 142 + return ERR_PTR(-EINVAL); 143 + 144 + pwm = pwm_request_from_chip(pc, args->args[0], NULL); 145 + if (IS_ERR(pwm)) 146 + return pwm; 147 + 148 + /* The EC won't let us change the period */ 149 + pwm->args.period = EC_PWM_MAX_DUTY; 150 + 151 + return pwm; 152 + } 153 + 154 + static const struct pwm_ops cros_ec_pwm_ops = { 155 + .get_state = cros_ec_pwm_get_state, 156 + .apply = cros_ec_pwm_apply, 157 + .owner = THIS_MODULE, 158 + }; 159 + 160 + static int cros_ec_num_pwms(struct cros_ec_device *ec) 161 + { 162 + int i, ret; 163 + 164 + /* The index field is only 8 bits */ 165 + for (i = 0; i <= U8_MAX; i++) { 166 + u32 result = 0; 167 + 168 + ret = __cros_ec_pwm_get_duty(ec, i, &result); 169 + /* We want to parse EC protocol errors */ 170 + if (ret < 0 && !(ret == -EPROTO && result)) 171 + return ret; 172 + 173 + /* 174 + * We look for SUCCESS, INVALID_COMMAND, or INVALID_PARAM 175 + * responses; everything else is treated as an error. 176 + */ 177 + if (result == EC_RES_INVALID_COMMAND) 178 + return -ENODEV; 179 + else if (result == EC_RES_INVALID_PARAM) 180 + return i; 181 + else if (result) 182 + return -EPROTO; 183 + } 184 + 185 + return U8_MAX; 186 + } 187 + 188 + static int cros_ec_pwm_probe(struct platform_device *pdev) 189 + { 190 + struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); 191 + struct device *dev = &pdev->dev; 192 + struct cros_ec_pwm_device *ec_pwm; 193 + struct pwm_chip *chip; 194 + int ret; 195 + 196 + if (!ec) { 197 + dev_err(dev, "no parent EC device\n"); 198 + return -EINVAL; 199 + } 200 + 201 + ec_pwm = devm_kzalloc(dev, sizeof(*ec_pwm), GFP_KERNEL); 202 + if (!ec_pwm) 203 + return -ENOMEM; 204 + chip = &ec_pwm->chip; 205 + ec_pwm->ec = ec; 206 + 207 + /* PWM chip */ 208 + chip->dev = dev; 209 + chip->ops = &cros_ec_pwm_ops; 210 + chip->of_xlate = cros_ec_pwm_xlate; 211 + chip->of_pwm_n_cells = 1; 212 + chip->base = -1; 213 + ret = cros_ec_num_pwms(ec); 214 + if (ret < 0) { 215 + dev_err(dev, "Couldn't find PWMs: %d\n", ret); 216 + return ret; 217 + } 218 + chip->npwm = ret; 219 + dev_dbg(dev, "Probed %u PWMs\n", chip->npwm); 220 + 221 + ret = pwmchip_add(chip); 222 + if (ret < 0) { 223 + dev_err(dev, "cannot register PWM: %d\n", ret); 224 + return ret; 225 + } 226 + 227 + platform_set_drvdata(pdev, ec_pwm); 228 + 229 + return ret; 230 + } 231 + 232 + static int cros_ec_pwm_remove(struct platform_device *dev) 233 + { 234 + struct cros_ec_pwm_device *ec_pwm = platform_get_drvdata(dev); 235 + struct pwm_chip *chip = &ec_pwm->chip; 236 + 237 + return pwmchip_remove(chip); 238 + } 239 + 240 + #ifdef CONFIG_OF 241 + static const struct of_device_id cros_ec_pwm_of_match[] = { 242 + { .compatible = "google,cros-ec-pwm" }, 243 + {}, 244 + }; 245 + MODULE_DEVICE_TABLE(of, cros_ec_pwm_of_match); 246 + #endif 247 + 248 + static struct platform_driver cros_ec_pwm_driver = { 249 + .probe = cros_ec_pwm_probe, 250 + .remove = cros_ec_pwm_remove, 251 + .driver = { 252 + .name = "cros-ec-pwm", 253 + .of_match_table = of_match_ptr(cros_ec_pwm_of_match), 254 + }, 255 + }; 256 + module_platform_driver(cros_ec_pwm_driver); 257 + 258 + MODULE_ALIAS("platform:cros-ec-pwm"); 259 + MODULE_DESCRIPTION("ChromeOS EC PWM driver"); 260 + MODULE_LICENSE("GPL v2");
+7
drivers/pwm/pwm-lpc32xx.c
··· 25 25 }; 26 26 27 27 #define PWM_ENABLE BIT(31) 28 + #define PWM_PIN_LEVEL BIT(30) 28 29 29 30 #define to_lpc32xx_pwm_chip(_chip) \ 30 31 container_of(_chip, struct lpc32xx_pwm_chip, chip) ··· 104 103 struct lpc32xx_pwm_chip *lpc32xx; 105 104 struct resource *res; 106 105 int ret; 106 + u32 val; 107 107 108 108 lpc32xx = devm_kzalloc(&pdev->dev, sizeof(*lpc32xx), GFP_KERNEL); 109 109 if (!lpc32xx) ··· 129 127 dev_err(&pdev->dev, "failed to add PWM chip, error %d\n", ret); 130 128 return ret; 131 129 } 130 + 131 + /* When PWM is disable, configure the output to the default value */ 132 + val = readl(lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2)); 133 + val &= ~PWM_PIN_LEVEL; 134 + writel(val, lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2)); 132 135 133 136 platform_set_drvdata(pdev, lpc32xx); 134 137
+1
drivers/pwm/pwm-lpss-pci.c
··· 76 76 { PCI_VDEVICE(INTEL, 0x0ac8), (unsigned long)&pwm_lpss_bxt_info}, 77 77 { PCI_VDEVICE(INTEL, 0x0f08), (unsigned long)&pwm_lpss_byt_info}, 78 78 { PCI_VDEVICE(INTEL, 0x0f09), (unsigned long)&pwm_lpss_byt_info}, 79 + { PCI_VDEVICE(INTEL, 0x11a5), (unsigned long)&pwm_lpss_bxt_info}, 79 80 { PCI_VDEVICE(INTEL, 0x1ac8), (unsigned long)&pwm_lpss_bxt_info}, 80 81 { PCI_VDEVICE(INTEL, 0x2288), (unsigned long)&pwm_lpss_bsw_info}, 81 82 { PCI_VDEVICE(INTEL, 0x2289), (unsigned long)&pwm_lpss_bsw_info},
+14 -12
drivers/pwm/pwm-lpss.c
··· 27 27 #define PWM_SW_UPDATE BIT(30) 28 28 #define PWM_BASE_UNIT_SHIFT 8 29 29 #define PWM_ON_TIME_DIV_MASK 0x000000ff 30 - #define PWM_DIVISION_CORRECTION 0x2 31 30 32 31 /* Size of each PWM register space if multiple */ 33 32 #define PWM_SIZE 0x400 ··· 91 92 int duty_ns, int period_ns) 92 93 { 93 94 struct pwm_lpss_chip *lpwm = to_lpwm(chip); 94 - u8 on_time_div; 95 - unsigned long c, base_unit_range; 95 + unsigned long long on_time_div; 96 + unsigned long c = lpwm->info->clk_rate, base_unit_range; 96 97 unsigned long long base_unit, freq = NSEC_PER_SEC; 97 98 u32 ctrl; 98 99 ··· 100 101 101 102 /* 102 103 * The equation is: 103 - * base_unit = ((freq / c) * base_unit_range) + correction 104 + * base_unit = round(base_unit_range * freq / c) 104 105 */ 105 106 base_unit_range = BIT(lpwm->info->base_unit_bits); 106 - base_unit = freq * base_unit_range; 107 + freq *= base_unit_range; 107 108 108 - c = lpwm->info->clk_rate; 109 - if (!c) 110 - return -EINVAL; 111 - 112 - do_div(base_unit, c); 113 - base_unit += PWM_DIVISION_CORRECTION; 109 + base_unit = DIV_ROUND_CLOSEST_ULL(freq, c); 114 110 115 111 if (duty_ns <= 0) 116 112 duty_ns = 1; 117 - on_time_div = 255 - (255 * duty_ns / period_ns); 113 + on_time_div = 255ULL * duty_ns; 114 + do_div(on_time_div, period_ns); 115 + on_time_div = 255ULL - on_time_div; 118 116 119 117 pm_runtime_get_sync(chip->dev); 120 118 ··· 165 169 const struct pwm_lpss_boardinfo *info) 166 170 { 167 171 struct pwm_lpss_chip *lpwm; 172 + unsigned long c; 168 173 int ret; 169 174 170 175 lpwm = devm_kzalloc(dev, sizeof(*lpwm), GFP_KERNEL); ··· 177 180 return ERR_CAST(lpwm->regs); 178 181 179 182 lpwm->info = info; 183 + 184 + c = lpwm->info->clk_rate; 185 + if (!c) 186 + return ERR_PTR(-EINVAL); 187 + 180 188 lpwm->chip.dev = dev; 181 189 lpwm->chip.ops = &pwm_lpss_ops; 182 190 lpwm->chip.base = -1;
+132 -46
drivers/pwm/pwm-rockchip.c
··· 47 47 struct rockchip_pwm_data { 48 48 struct rockchip_pwm_regs regs; 49 49 unsigned int prescaler; 50 + bool supports_polarity; 50 51 const struct pwm_ops *ops; 51 52 52 53 void (*set_enable)(struct pwm_chip *chip, 53 - struct pwm_device *pwm, bool enable); 54 + struct pwm_device *pwm, bool enable, 55 + enum pwm_polarity polarity); 56 + void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm, 57 + struct pwm_state *state); 54 58 }; 55 59 56 60 static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) ··· 63 59 } 64 60 65 61 static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, 66 - struct pwm_device *pwm, bool enable) 62 + struct pwm_device *pwm, bool enable, 63 + enum pwm_polarity polarity) 67 64 { 68 65 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 69 66 u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN; ··· 80 75 writel_relaxed(val, pc->base + pc->data->regs.ctrl); 81 76 } 82 77 78 + static void rockchip_pwm_get_state_v1(struct pwm_chip *chip, 79 + struct pwm_device *pwm, 80 + struct pwm_state *state) 81 + { 82 + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 83 + u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN; 84 + u32 val; 85 + 86 + val = readl_relaxed(pc->base + pc->data->regs.ctrl); 87 + if ((val & enable_conf) == enable_conf) 88 + state->enabled = true; 89 + } 90 + 83 91 static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, 84 - struct pwm_device *pwm, bool enable) 92 + struct pwm_device *pwm, bool enable, 93 + enum pwm_polarity polarity) 85 94 { 86 95 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 87 96 u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | 88 97 PWM_CONTINUOUS; 89 98 u32 val; 90 99 91 - if (pwm_get_polarity(pwm) == PWM_POLARITY_INVERSED) 100 + if (polarity == PWM_POLARITY_INVERSED) 92 101 enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE; 93 102 else 94 103 enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE; ··· 117 98 writel_relaxed(val, pc->base + pc->data->regs.ctrl); 118 99 } 119 100 101 + static void rockchip_pwm_get_state_v2(struct pwm_chip *chip, 102 + struct pwm_device *pwm, 103 + struct pwm_state *state) 104 + { 105 + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 106 + u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | 107 + PWM_CONTINUOUS; 108 + u32 val; 109 + 110 + val = readl_relaxed(pc->base + pc->data->regs.ctrl); 111 + if ((val & enable_conf) != enable_conf) 112 + return; 113 + 114 + state->enabled = true; 115 + 116 + if (!(val & PWM_DUTY_POSITIVE)) 117 + state->polarity = PWM_POLARITY_INVERSED; 118 + } 119 + 120 + static void rockchip_pwm_get_state(struct pwm_chip *chip, 121 + struct pwm_device *pwm, 122 + struct pwm_state *state) 123 + { 124 + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 125 + unsigned long clk_rate; 126 + u64 tmp; 127 + int ret; 128 + 129 + ret = clk_enable(pc->clk); 130 + if (ret) 131 + return; 132 + 133 + clk_rate = clk_get_rate(pc->clk); 134 + 135 + tmp = readl_relaxed(pc->base + pc->data->regs.period); 136 + tmp *= pc->data->prescaler * NSEC_PER_SEC; 137 + state->period = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate); 138 + 139 + tmp = readl_relaxed(pc->base + pc->data->regs.duty); 140 + tmp *= pc->data->prescaler * NSEC_PER_SEC; 141 + state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate); 142 + 143 + pc->data->get_state(chip, pwm, state); 144 + 145 + clk_disable(pc->clk); 146 + } 147 + 120 148 static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 121 149 int duty_ns, int period_ns) 122 150 { 123 151 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 124 152 unsigned long period, duty; 125 153 u64 clk_rate, div; 126 - int ret; 127 154 128 155 clk_rate = clk_get_rate(pc->clk); 129 156 ··· 179 114 * default prescaler value for all practical clock rate values. 180 115 */ 181 116 div = clk_rate * period_ns; 182 - do_div(div, pc->data->prescaler * NSEC_PER_SEC); 183 - period = div; 117 + period = DIV_ROUND_CLOSEST_ULL(div, 118 + pc->data->prescaler * NSEC_PER_SEC); 184 119 185 120 div = clk_rate * duty_ns; 186 - do_div(div, pc->data->prescaler * NSEC_PER_SEC); 187 - duty = div; 188 - 189 - ret = clk_enable(pc->clk); 190 - if (ret) 191 - return ret; 121 + duty = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC); 192 122 193 123 writel(period, pc->base + pc->data->regs.period); 194 124 writel(duty, pc->base + pc->data->regs.duty); 195 - writel(0, pc->base + pc->data->regs.cntr); 196 - 197 - clk_disable(pc->clk); 198 125 199 126 return 0; 200 127 } 201 128 202 - static int rockchip_pwm_set_polarity(struct pwm_chip *chip, 203 - struct pwm_device *pwm, 204 - enum pwm_polarity polarity) 205 - { 206 - /* 207 - * No action needed here because pwm->polarity will be set by the core 208 - * and the core will only change polarity when the PWM is not enabled. 209 - * We'll handle things in set_enable(). 210 - */ 211 - 212 - return 0; 213 - } 214 - 215 - static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 129 + static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 130 + struct pwm_state *state) 216 131 { 217 132 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 133 + struct pwm_state curstate; 134 + bool enabled; 218 135 int ret; 136 + 137 + pwm_get_state(pwm, &curstate); 138 + enabled = curstate.enabled; 219 139 220 140 ret = clk_enable(pc->clk); 221 141 if (ret) 222 142 return ret; 223 143 224 - pc->data->set_enable(chip, pwm, true); 144 + if (state->polarity != curstate.polarity && enabled) { 145 + pc->data->set_enable(chip, pwm, false, state->polarity); 146 + enabled = false; 147 + } 225 148 226 - return 0; 227 - } 149 + ret = rockchip_pwm_config(chip, pwm, state->duty_cycle, state->period); 150 + if (ret) { 151 + if (enabled != curstate.enabled) 152 + pc->data->set_enable(chip, pwm, !enabled, 153 + state->polarity); 228 154 229 - static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 230 - { 231 - struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 155 + goto out; 156 + } 232 157 233 - pc->data->set_enable(chip, pwm, false); 158 + if (state->enabled != enabled) 159 + pc->data->set_enable(chip, pwm, state->enabled, 160 + state->polarity); 234 161 162 + /* 163 + * Update the state with the real hardware, which can differ a bit 164 + * because of period/duty_cycle approximation. 165 + */ 166 + rockchip_pwm_get_state(chip, pwm, state); 167 + 168 + out: 235 169 clk_disable(pc->clk); 170 + 171 + return ret; 236 172 } 237 173 238 174 static const struct pwm_ops rockchip_pwm_ops_v1 = { 239 - .config = rockchip_pwm_config, 240 - .enable = rockchip_pwm_enable, 241 - .disable = rockchip_pwm_disable, 175 + .get_state = rockchip_pwm_get_state, 176 + .apply = rockchip_pwm_apply, 242 177 .owner = THIS_MODULE, 243 178 }; 244 179 245 180 static const struct pwm_ops rockchip_pwm_ops_v2 = { 246 - .config = rockchip_pwm_config, 247 - .set_polarity = rockchip_pwm_set_polarity, 248 - .enable = rockchip_pwm_enable, 249 - .disable = rockchip_pwm_disable, 181 + .get_state = rockchip_pwm_get_state, 182 + .apply = rockchip_pwm_apply, 250 183 .owner = THIS_MODULE, 251 184 }; 252 185 ··· 258 195 .prescaler = 2, 259 196 .ops = &rockchip_pwm_ops_v1, 260 197 .set_enable = rockchip_pwm_set_enable_v1, 198 + .get_state = rockchip_pwm_get_state_v1, 261 199 }; 262 200 263 201 static const struct rockchip_pwm_data pwm_data_v2 = { ··· 269 205 .ctrl = 0x0c, 270 206 }, 271 207 .prescaler = 1, 208 + .supports_polarity = true, 272 209 .ops = &rockchip_pwm_ops_v2, 273 210 .set_enable = rockchip_pwm_set_enable_v2, 211 + .get_state = rockchip_pwm_get_state_v2, 274 212 }; 275 213 276 214 static const struct rockchip_pwm_data pwm_data_vop = { ··· 283 217 .ctrl = 0x00, 284 218 }, 285 219 .prescaler = 1, 220 + .supports_polarity = true, 286 221 .ops = &rockchip_pwm_ops_v2, 287 222 .set_enable = rockchip_pwm_set_enable_v2, 223 + .get_state = rockchip_pwm_get_state_v2, 288 224 }; 289 225 290 226 static const struct of_device_id rockchip_pwm_dt_ids[] = { ··· 321 253 if (IS_ERR(pc->clk)) 322 254 return PTR_ERR(pc->clk); 323 255 324 - ret = clk_prepare(pc->clk); 256 + ret = clk_prepare_enable(pc->clk); 325 257 if (ret) 326 258 return ret; 327 259 ··· 333 265 pc->chip.base = -1; 334 266 pc->chip.npwm = 1; 335 267 336 - if (pc->data->ops->set_polarity) { 268 + if (pc->data->supports_polarity) { 337 269 pc->chip.of_xlate = of_pwm_xlate_with_flags; 338 270 pc->chip.of_pwm_n_cells = 3; 339 271 } ··· 344 276 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); 345 277 } 346 278 279 + /* Keep the PWM clk enabled if the PWM appears to be up and running. */ 280 + if (!pwm_is_enabled(pc->chip.pwms)) 281 + clk_disable(pc->clk); 282 + 347 283 return ret; 348 284 } 349 285 350 286 static int rockchip_pwm_remove(struct platform_device *pdev) 351 287 { 352 288 struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev); 289 + 290 + /* 291 + * Disable the PWM clk before unpreparing it if the PWM device is still 292 + * running. This should only happen when the last PWM user left it 293 + * enabled, or when nobody requested a PWM that was previously enabled 294 + * by the bootloader. 295 + * 296 + * FIXME: Maybe the core should disable all PWM devices in 297 + * pwmchip_remove(). In this case we'd only have to call 298 + * clk_unprepare() after pwmchip_remove(). 299 + * 300 + */ 301 + if (pwm_is_enabled(pc->chip.pwms)) 302 + clk_disable(pc->clk); 353 303 354 304 clk_unprepare(pc->clk); 355 305
+319
drivers/pwm/pwm-stmpe.c
··· 1 + /* 2 + * Copyright (C) 2016 Linaro Ltd. 3 + * 4 + * Author: Linus Walleij <linus.walleij@linaro.org> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2, as 8 + * published by the Free Software Foundation. 9 + * 10 + */ 11 + 12 + #include <linux/bitops.h> 13 + #include <linux/delay.h> 14 + #include <linux/err.h> 15 + #include <linux/mfd/stmpe.h> 16 + #include <linux/module.h> 17 + #include <linux/of.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/pwm.h> 20 + #include <linux/slab.h> 21 + 22 + #define STMPE24XX_PWMCS 0x30 23 + #define PWMCS_EN_PWM0 BIT(0) 24 + #define PWMCS_EN_PWM1 BIT(1) 25 + #define PWMCS_EN_PWM2 BIT(2) 26 + #define STMPE24XX_PWMIC0 0x38 27 + #define STMPE24XX_PWMIC1 0x39 28 + #define STMPE24XX_PWMIC2 0x3a 29 + 30 + #define STMPE_PWM_24XX_PINBASE 21 31 + 32 + struct stmpe_pwm { 33 + struct stmpe *stmpe; 34 + struct pwm_chip chip; 35 + u8 last_duty; 36 + }; 37 + 38 + static inline struct stmpe_pwm *to_stmpe_pwm(struct pwm_chip *chip) 39 + { 40 + return container_of(chip, struct stmpe_pwm, chip); 41 + } 42 + 43 + static int stmpe_24xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 44 + { 45 + struct stmpe_pwm *stmpe_pwm = to_stmpe_pwm(chip); 46 + u8 value; 47 + int ret; 48 + 49 + ret = stmpe_reg_read(stmpe_pwm->stmpe, STMPE24XX_PWMCS); 50 + if (ret < 0) { 51 + dev_err(chip->dev, "error reading PWM#%u control\n", 52 + pwm->hwpwm); 53 + return ret; 54 + } 55 + 56 + value = ret | BIT(pwm->hwpwm); 57 + 58 + ret = stmpe_reg_write(stmpe_pwm->stmpe, STMPE24XX_PWMCS, value); 59 + if (ret) { 60 + dev_err(chip->dev, "error writing PWM#%u control\n", 61 + pwm->hwpwm); 62 + return ret; 63 + } 64 + 65 + return 0; 66 + } 67 + 68 + static void stmpe_24xx_pwm_disable(struct pwm_chip *chip, 69 + struct pwm_device *pwm) 70 + { 71 + struct stmpe_pwm *stmpe_pwm = to_stmpe_pwm(chip); 72 + u8 value; 73 + int ret; 74 + 75 + ret = stmpe_reg_read(stmpe_pwm->stmpe, STMPE24XX_PWMCS); 76 + if (ret < 0) { 77 + dev_err(chip->dev, "error reading PWM#%u control\n", 78 + pwm->hwpwm); 79 + return; 80 + } 81 + 82 + value = ret & ~BIT(pwm->hwpwm); 83 + 84 + ret = stmpe_reg_write(stmpe_pwm->stmpe, STMPE24XX_PWMCS, value); 85 + if (ret) { 86 + dev_err(chip->dev, "error writing PWM#%u control\n", 87 + pwm->hwpwm); 88 + return; 89 + } 90 + } 91 + 92 + /* STMPE 24xx PWM instructions */ 93 + #define SMAX 0x007f 94 + #define SMIN 0x00ff 95 + #define GTS 0x0000 96 + #define LOAD BIT(14) /* Only available on 2403 */ 97 + #define RAMPUP 0x0000 98 + #define RAMPDOWN BIT(7) 99 + #define PRESCALE_512 BIT(14) 100 + #define STEPTIME_1 BIT(8) 101 + #define BRANCH (BIT(15) | BIT(13)) 102 + 103 + static int stmpe_24xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 104 + int duty_ns, int period_ns) 105 + { 106 + struct stmpe_pwm *stmpe_pwm = to_stmpe_pwm(chip); 107 + unsigned int i, pin; 108 + u16 program[3] = { 109 + SMAX, 110 + GTS, 111 + GTS, 112 + }; 113 + u8 offset; 114 + int ret; 115 + 116 + /* Make sure we are disabled */ 117 + if (pwm_is_enabled(pwm)) { 118 + stmpe_24xx_pwm_disable(chip, pwm); 119 + } else { 120 + /* Connect the PWM to the pin */ 121 + pin = pwm->hwpwm; 122 + 123 + /* On STMPE2401 and 2403 pins 21,22,23 are used */ 124 + if (stmpe_pwm->stmpe->partnum == STMPE2401 || 125 + stmpe_pwm->stmpe->partnum == STMPE2403) 126 + pin += STMPE_PWM_24XX_PINBASE; 127 + 128 + ret = stmpe_set_altfunc(stmpe_pwm->stmpe, BIT(pin), 129 + STMPE_BLOCK_PWM); 130 + if (ret) { 131 + dev_err(chip->dev, "unable to connect PWM#%u to pin\n", 132 + pwm->hwpwm); 133 + return ret; 134 + } 135 + } 136 + 137 + /* STMPE24XX */ 138 + switch (pwm->hwpwm) { 139 + case 0: 140 + offset = STMPE24XX_PWMIC0; 141 + break; 142 + 143 + case 1: 144 + offset = STMPE24XX_PWMIC1; 145 + break; 146 + 147 + case 2: 148 + offset = STMPE24XX_PWMIC1; 149 + break; 150 + 151 + default: 152 + /* Should not happen as npwm is 3 */ 153 + return -ENODEV; 154 + } 155 + 156 + dev_dbg(chip->dev, "PWM#%u: config duty %d ns, period %d ns\n", 157 + pwm->hwpwm, duty_ns, period_ns); 158 + 159 + if (duty_ns == 0) { 160 + if (stmpe_pwm->stmpe->partnum == STMPE2401) 161 + program[0] = SMAX; /* off all the time */ 162 + 163 + if (stmpe_pwm->stmpe->partnum == STMPE2403) 164 + program[0] = LOAD | 0xff; /* LOAD 0xff */ 165 + 166 + stmpe_pwm->last_duty = 0x00; 167 + } else if (duty_ns == period_ns) { 168 + if (stmpe_pwm->stmpe->partnum == STMPE2401) 169 + program[0] = SMIN; /* on all the time */ 170 + 171 + if (stmpe_pwm->stmpe->partnum == STMPE2403) 172 + program[0] = LOAD | 0x00; /* LOAD 0x00 */ 173 + 174 + stmpe_pwm->last_duty = 0xff; 175 + } else { 176 + u8 value, last = stmpe_pwm->last_duty; 177 + unsigned long duty; 178 + 179 + /* 180 + * Counter goes from 0x00 to 0xff repeatedly at 32768 Hz, 181 + * (means a period of 30517 ns) then this is compared to the 182 + * counter from the ramp, if this is >= PWM counter the output 183 + * is high. With LOAD we can define how much of the cycle it 184 + * is on. 185 + * 186 + * Prescale = 0 -> 2 kHz -> T = 1/f = 488281.25 ns 187 + */ 188 + 189 + /* Scale to 0..0xff */ 190 + duty = duty_ns * 256; 191 + duty = DIV_ROUND_CLOSEST(duty, period_ns); 192 + value = duty; 193 + 194 + if (value == last) { 195 + /* Run the old program */ 196 + if (pwm_is_enabled(pwm)) 197 + stmpe_24xx_pwm_enable(chip, pwm); 198 + 199 + return 0; 200 + } else if (stmpe_pwm->stmpe->partnum == STMPE2403) { 201 + /* STMPE2403 can simply set the right PWM value */ 202 + program[0] = LOAD | value; 203 + program[1] = 0x0000; 204 + } else if (stmpe_pwm->stmpe->partnum == STMPE2401) { 205 + /* STMPE2401 need a complex program */ 206 + u16 incdec = 0x0000; 207 + 208 + if (last < value) 209 + /* Count up */ 210 + incdec = RAMPUP | (value - last); 211 + else 212 + /* Count down */ 213 + incdec = RAMPDOWN | (last - value); 214 + 215 + /* Step to desired value, smoothly */ 216 + program[0] = PRESCALE_512 | STEPTIME_1 | incdec; 217 + 218 + /* Loop eternally to 0x00 */ 219 + program[1] = BRANCH; 220 + } 221 + 222 + dev_dbg(chip->dev, 223 + "PWM#%u: value = %02x, last_duty = %02x, program=%04x,%04x,%04x\n", 224 + pwm->hwpwm, value, last, program[0], program[1], 225 + program[2]); 226 + stmpe_pwm->last_duty = value; 227 + } 228 + 229 + /* 230 + * We can write programs of up to 64 16-bit words into this channel. 231 + */ 232 + for (i = 0; i < ARRAY_SIZE(program); i++) { 233 + u8 value; 234 + 235 + value = (program[i] >> 8) & 0xff; 236 + 237 + ret = stmpe_reg_write(stmpe_pwm->stmpe, offset, value); 238 + if (ret) { 239 + dev_err(chip->dev, "error writing register %02x: %d\n", 240 + offset, ret); 241 + return ret; 242 + } 243 + 244 + value = program[i] & 0xff; 245 + 246 + ret = stmpe_reg_write(stmpe_pwm->stmpe, offset, value); 247 + if (ret) { 248 + dev_err(chip->dev, "error writing register %02x: %d\n", 249 + offset, ret); 250 + return ret; 251 + } 252 + } 253 + 254 + /* If we were enabled, re-enable this PWM */ 255 + if (pwm_is_enabled(pwm)) 256 + stmpe_24xx_pwm_enable(chip, pwm); 257 + 258 + /* Sleep for 200ms so we're sure it will take effect */ 259 + msleep(200); 260 + 261 + dev_dbg(chip->dev, "programmed PWM#%u, %u bytes\n", pwm->hwpwm, i); 262 + 263 + return 0; 264 + } 265 + 266 + static const struct pwm_ops stmpe_24xx_pwm_ops = { 267 + .config = stmpe_24xx_pwm_config, 268 + .enable = stmpe_24xx_pwm_enable, 269 + .disable = stmpe_24xx_pwm_disable, 270 + .owner = THIS_MODULE, 271 + }; 272 + 273 + static int __init stmpe_pwm_probe(struct platform_device *pdev) 274 + { 275 + struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); 276 + struct stmpe_pwm *pwm; 277 + int ret; 278 + 279 + pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); 280 + if (!pwm) 281 + return -ENOMEM; 282 + 283 + pwm->stmpe = stmpe; 284 + pwm->chip.dev = &pdev->dev; 285 + pwm->chip.base = -1; 286 + 287 + if (stmpe->partnum == STMPE2401 || stmpe->partnum == STMPE2403) { 288 + pwm->chip.ops = &stmpe_24xx_pwm_ops; 289 + pwm->chip.npwm = 3; 290 + } else { 291 + if (stmpe->partnum == STMPE1601) 292 + dev_err(&pdev->dev, "STMPE1601 not yet supported\n"); 293 + else 294 + dev_err(&pdev->dev, "Unknown STMPE PWM\n"); 295 + 296 + return -ENODEV; 297 + } 298 + 299 + ret = stmpe_enable(stmpe, STMPE_BLOCK_PWM); 300 + if (ret) 301 + return ret; 302 + 303 + ret = pwmchip_add(&pwm->chip); 304 + if (ret) { 305 + stmpe_disable(stmpe, STMPE_BLOCK_PWM); 306 + return ret; 307 + } 308 + 309 + platform_set_drvdata(pdev, pwm); 310 + 311 + return 0; 312 + } 313 + 314 + static struct platform_driver stmpe_pwm_driver = { 315 + .driver = { 316 + .name = "stmpe-pwm", 317 + }, 318 + }; 319 + builtin_platform_driver_probe(stmpe_pwm_driver, stmpe_pwm_probe);
+52 -17
drivers/pwm/pwm-tegra.c
··· 26 26 #include <linux/io.h> 27 27 #include <linux/module.h> 28 28 #include <linux/of.h> 29 + #include <linux/of_device.h> 29 30 #include <linux/pwm.h> 30 31 #include <linux/platform_device.h> 31 32 #include <linux/slab.h> 33 + #include <linux/reset.h> 32 34 33 35 #define PWM_ENABLE (1 << 31) 34 36 #define PWM_DUTY_WIDTH 8 ··· 38 36 #define PWM_SCALE_WIDTH 13 39 37 #define PWM_SCALE_SHIFT 0 40 38 41 - #define NUM_PWM 4 39 + struct tegra_pwm_soc { 40 + unsigned int num_channels; 41 + }; 42 42 43 43 struct tegra_pwm_chip { 44 - struct pwm_chip chip; 45 - struct device *dev; 44 + struct pwm_chip chip; 45 + struct device *dev; 46 46 47 - struct clk *clk; 47 + struct clk *clk; 48 + struct reset_control*rst; 48 49 49 - void __iomem *mmio_base; 50 + void __iomem *regs; 51 + 52 + const struct tegra_pwm_soc *soc; 50 53 }; 51 54 52 55 static inline struct tegra_pwm_chip *to_tegra_pwm_chip(struct pwm_chip *chip) ··· 61 54 62 55 static inline u32 pwm_readl(struct tegra_pwm_chip *chip, unsigned int num) 63 56 { 64 - return readl(chip->mmio_base + (num << 4)); 57 + return readl(chip->regs + (num << 4)); 65 58 } 66 59 67 60 static inline void pwm_writel(struct tegra_pwm_chip *chip, unsigned int num, 68 61 unsigned long val) 69 62 { 70 - writel(val, chip->mmio_base + (num << 4)); 63 + writel(val, chip->regs + (num << 4)); 71 64 } 72 65 73 66 static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 74 67 int duty_ns, int period_ns) 75 68 { 76 69 struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip); 77 - unsigned long long c; 70 + unsigned long long c = duty_ns; 78 71 unsigned long rate, hz; 79 72 u32 val = 0; 80 73 int err; ··· 84 77 * per (1 << PWM_DUTY_WIDTH) cycles and make sure to round to the 85 78 * nearest integer during division. 86 79 */ 87 - c = duty_ns * ((1 << PWM_DUTY_WIDTH) - 1) + period_ns / 2; 80 + c *= (1 << PWM_DUTY_WIDTH); 81 + c += period_ns / 2; 88 82 do_div(c, period_ns); 89 83 90 84 val = (u32)c << PWM_DUTY_SHIFT; ··· 184 176 if (!pwm) 185 177 return -ENOMEM; 186 178 179 + pwm->soc = of_device_get_match_data(&pdev->dev); 187 180 pwm->dev = &pdev->dev; 188 181 189 182 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 190 - pwm->mmio_base = devm_ioremap_resource(&pdev->dev, r); 191 - if (IS_ERR(pwm->mmio_base)) 192 - return PTR_ERR(pwm->mmio_base); 183 + pwm->regs = devm_ioremap_resource(&pdev->dev, r); 184 + if (IS_ERR(pwm->regs)) 185 + return PTR_ERR(pwm->regs); 193 186 194 187 platform_set_drvdata(pdev, pwm); 195 188 ··· 198 189 if (IS_ERR(pwm->clk)) 199 190 return PTR_ERR(pwm->clk); 200 191 192 + pwm->rst = devm_reset_control_get(&pdev->dev, "pwm"); 193 + if (IS_ERR(pwm->rst)) { 194 + ret = PTR_ERR(pwm->rst); 195 + dev_err(&pdev->dev, "Reset control is not found: %d\n", ret); 196 + return ret; 197 + } 198 + 199 + reset_control_deassert(pwm->rst); 200 + 201 201 pwm->chip.dev = &pdev->dev; 202 202 pwm->chip.ops = &tegra_pwm_ops; 203 203 pwm->chip.base = -1; 204 - pwm->chip.npwm = NUM_PWM; 204 + pwm->chip.npwm = pwm->soc->num_channels; 205 205 206 206 ret = pwmchip_add(&pwm->chip); 207 207 if (ret < 0) { 208 208 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); 209 + reset_control_assert(pwm->rst); 209 210 return ret; 210 211 } 211 212 ··· 225 206 static int tegra_pwm_remove(struct platform_device *pdev) 226 207 { 227 208 struct tegra_pwm_chip *pc = platform_get_drvdata(pdev); 228 - int i; 209 + unsigned int i; 210 + int err; 229 211 230 212 if (WARN_ON(!pc)) 231 213 return -ENODEV; 232 214 233 - for (i = 0; i < NUM_PWM; i++) { 215 + err = clk_prepare_enable(pc->clk); 216 + if (err < 0) 217 + return err; 218 + 219 + for (i = 0; i < pc->chip.npwm; i++) { 234 220 struct pwm_device *pwm = &pc->chip.pwms[i]; 235 221 236 222 if (!pwm_is_enabled(pwm)) ··· 247 223 clk_disable_unprepare(pc->clk); 248 224 } 249 225 226 + reset_control_assert(pc->rst); 227 + clk_disable_unprepare(pc->clk); 228 + 250 229 return pwmchip_remove(&pc->chip); 251 230 } 252 231 232 + static const struct tegra_pwm_soc tegra20_pwm_soc = { 233 + .num_channels = 4, 234 + }; 235 + 236 + static const struct tegra_pwm_soc tegra186_pwm_soc = { 237 + .num_channels = 1, 238 + }; 239 + 253 240 static const struct of_device_id tegra_pwm_of_match[] = { 254 - { .compatible = "nvidia,tegra20-pwm" }, 255 - { .compatible = "nvidia,tegra30-pwm" }, 241 + { .compatible = "nvidia,tegra20-pwm", .data = &tegra20_pwm_soc }, 242 + { .compatible = "nvidia,tegra186-pwm", .data = &tegra186_pwm_soc }, 256 243 { } 257 244 }; 258 245
+9 -28
drivers/pwm/pwm-tiecap.c
··· 27 27 #include <linux/pwm.h> 28 28 #include <linux/of_device.h> 29 29 30 - #include "pwm-tipwmss.h" 31 - 32 30 /* ECAP registers and bits definitions */ 33 31 #define CAP1 0x08 34 32 #define CAP2 0x0C ··· 193 195 }; 194 196 195 197 static const struct of_device_id ecap_of_match[] = { 198 + { .compatible = "ti,am3352-ecap" }, 196 199 { .compatible = "ti,am33xx-ecap" }, 197 200 {}, 198 201 }; ··· 201 202 202 203 static int ecap_pwm_probe(struct platform_device *pdev) 203 204 { 205 + struct device_node *np = pdev->dev.of_node; 204 206 int ret; 205 207 struct resource *r; 206 208 struct clk *clk; 207 209 struct ecap_pwm_chip *pc; 208 - u16 status; 209 210 210 211 pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); 211 212 if (!pc) 212 213 return -ENOMEM; 213 214 214 215 clk = devm_clk_get(&pdev->dev, "fck"); 216 + if (IS_ERR(clk)) { 217 + if (of_device_is_compatible(np, "ti,am33xx-ecap")) { 218 + dev_warn(&pdev->dev, "Binding is obsolete.\n"); 219 + clk = devm_clk_get(pdev->dev.parent, "fck"); 220 + } 221 + } 222 + 215 223 if (IS_ERR(clk)) { 216 224 dev_err(&pdev->dev, "failed to get clock\n"); 217 225 return PTR_ERR(clk); ··· 249 243 } 250 244 251 245 pm_runtime_enable(&pdev->dev); 252 - pm_runtime_get_sync(&pdev->dev); 253 - 254 - status = pwmss_submodule_state_change(pdev->dev.parent, 255 - PWMSS_ECAPCLK_EN); 256 - if (!(status & PWMSS_ECAPCLK_EN_ACK)) { 257 - dev_err(&pdev->dev, "PWMSS config space clock enable failed\n"); 258 - ret = -EINVAL; 259 - goto pwmss_clk_failure; 260 - } 261 - 262 - pm_runtime_put_sync(&pdev->dev); 263 246 264 247 platform_set_drvdata(pdev, pc); 265 248 return 0; 266 - 267 - pwmss_clk_failure: 268 - pm_runtime_put_sync(&pdev->dev); 269 - pm_runtime_disable(&pdev->dev); 270 - pwmchip_remove(&pc->chip); 271 - return ret; 272 249 } 273 250 274 251 static int ecap_pwm_remove(struct platform_device *pdev) 275 252 { 276 253 struct ecap_pwm_chip *pc = platform_get_drvdata(pdev); 277 - 278 - pm_runtime_get_sync(&pdev->dev); 279 - /* 280 - * Due to hardware misbehaviour, acknowledge of the stop_req 281 - * is missing. Hence checking of the status bit skipped. 282 - */ 283 - pwmss_submodule_state_change(pdev->dev.parent, PWMSS_ECAPCLK_STOP_REQ); 284 - pm_runtime_put_sync(&pdev->dev); 285 254 286 255 pm_runtime_disable(&pdev->dev); 287 256 return pwmchip_remove(&pc->chip);
+9 -29
drivers/pwm/pwm-tiehrpwm.c
··· 27 27 #include <linux/pm_runtime.h> 28 28 #include <linux/of_device.h> 29 29 30 - #include "pwm-tipwmss.h" 31 - 32 30 /* EHRPWM registers and bits definitions */ 33 31 34 32 /* Time base module registers */ ··· 424 426 }; 425 427 426 428 static const struct of_device_id ehrpwm_of_match[] = { 429 + { .compatible = "ti,am3352-ehrpwm" }, 427 430 { .compatible = "ti,am33xx-ehrpwm" }, 428 431 {}, 429 432 }; ··· 432 433 433 434 static int ehrpwm_pwm_probe(struct platform_device *pdev) 434 435 { 436 + struct device_node *np = pdev->dev.of_node; 435 437 int ret; 436 438 struct resource *r; 437 439 struct clk *clk; 438 440 struct ehrpwm_pwm_chip *pc; 439 - u16 status; 440 441 441 442 pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); 442 443 if (!pc) 443 444 return -ENOMEM; 444 445 445 446 clk = devm_clk_get(&pdev->dev, "fck"); 447 + if (IS_ERR(clk)) { 448 + if (of_device_is_compatible(np, "ti,am33xx-ecap")) { 449 + dev_warn(&pdev->dev, "Binding is obsolete.\n"); 450 + clk = devm_clk_get(pdev->dev.parent, "fck"); 451 + } 452 + } 453 + 446 454 if (IS_ERR(clk)) { 447 455 dev_err(&pdev->dev, "failed to get clock\n"); 448 456 return PTR_ERR(clk); ··· 493 487 } 494 488 495 489 pm_runtime_enable(&pdev->dev); 496 - pm_runtime_get_sync(&pdev->dev); 497 - 498 - status = pwmss_submodule_state_change(pdev->dev.parent, 499 - PWMSS_EPWMCLK_EN); 500 - if (!(status & PWMSS_EPWMCLK_EN_ACK)) { 501 - dev_err(&pdev->dev, "PWMSS config space clock enable failed\n"); 502 - ret = -EINVAL; 503 - goto pwmss_clk_failure; 504 - } 505 - 506 - pm_runtime_put_sync(&pdev->dev); 507 490 508 491 platform_set_drvdata(pdev, pc); 509 492 return 0; 510 - 511 - pwmss_clk_failure: 512 - pm_runtime_put_sync(&pdev->dev); 513 - pm_runtime_disable(&pdev->dev); 514 - pwmchip_remove(&pc->chip); 515 - clk_unprepare(pc->tbclk); 516 - return ret; 517 493 } 518 494 519 495 static int ehrpwm_pwm_remove(struct platform_device *pdev) ··· 503 515 struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev); 504 516 505 517 clk_unprepare(pc->tbclk); 506 - 507 - pm_runtime_get_sync(&pdev->dev); 508 - /* 509 - * Due to hardware misbehaviour, acknowledge of the stop_req 510 - * is missing. Hence checking of the status bit skipped. 511 - */ 512 - pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EPWMCLK_STOP_REQ); 513 - pm_runtime_put_sync(&pdev->dev); 514 518 515 519 pm_runtime_put_sync(&pdev->dev); 516 520 pm_runtime_disable(&pdev->dev);
-49
drivers/pwm/pwm-tipwmss.c
··· 22 22 #include <linux/pm_runtime.h> 23 23 #include <linux/of_device.h> 24 24 25 - #include "pwm-tipwmss.h" 26 - 27 - #define PWMSS_CLKCONFIG 0x8 /* Clock gating reg */ 28 - #define PWMSS_CLKSTATUS 0xc /* Clock gating status reg */ 29 - 30 - struct pwmss_info { 31 - void __iomem *mmio_base; 32 - struct mutex pwmss_lock; 33 - u16 pwmss_clkconfig; 34 - }; 35 - 36 - u16 pwmss_submodule_state_change(struct device *dev, int set) 37 - { 38 - struct pwmss_info *info = dev_get_drvdata(dev); 39 - u16 val; 40 - 41 - mutex_lock(&info->pwmss_lock); 42 - val = readw(info->mmio_base + PWMSS_CLKCONFIG); 43 - val |= set; 44 - writew(val , info->mmio_base + PWMSS_CLKCONFIG); 45 - mutex_unlock(&info->pwmss_lock); 46 - 47 - return readw(info->mmio_base + PWMSS_CLKSTATUS); 48 - } 49 - EXPORT_SYMBOL(pwmss_submodule_state_change); 50 - 51 25 static const struct of_device_id pwmss_of_match[] = { 52 26 { .compatible = "ti,am33xx-pwmss" }, 53 27 {}, ··· 31 57 static int pwmss_probe(struct platform_device *pdev) 32 58 { 33 59 int ret; 34 - struct resource *r; 35 - struct pwmss_info *info; 36 60 struct device_node *node = pdev->dev.of_node; 37 - 38 - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); 39 - if (!info) 40 - return -ENOMEM; 41 - 42 - mutex_init(&info->pwmss_lock); 43 - 44 - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 45 - info->mmio_base = devm_ioremap_resource(&pdev->dev, r); 46 - if (IS_ERR(info->mmio_base)) 47 - return PTR_ERR(info->mmio_base); 48 61 49 62 pm_runtime_enable(&pdev->dev); 50 63 pm_runtime_get_sync(&pdev->dev); 51 - platform_set_drvdata(pdev, info); 52 64 53 65 /* Populate all the child nodes here... */ 54 66 ret = of_platform_populate(node, NULL, NULL, &pdev->dev); ··· 46 86 47 87 static int pwmss_remove(struct platform_device *pdev) 48 88 { 49 - struct pwmss_info *info = platform_get_drvdata(pdev); 50 - 51 89 pm_runtime_put_sync(&pdev->dev); 52 90 pm_runtime_disable(&pdev->dev); 53 - mutex_destroy(&info->pwmss_lock); 54 91 return 0; 55 92 } 56 93 57 94 #ifdef CONFIG_PM_SLEEP 58 95 static int pwmss_suspend(struct device *dev) 59 96 { 60 - struct pwmss_info *info = dev_get_drvdata(dev); 61 - 62 - info->pwmss_clkconfig = readw(info->mmio_base + PWMSS_CLKCONFIG); 63 97 pm_runtime_put_sync(dev); 64 98 return 0; 65 99 } 66 100 67 101 static int pwmss_resume(struct device *dev) 68 102 { 69 - struct pwmss_info *info = dev_get_drvdata(dev); 70 - 71 103 pm_runtime_get_sync(dev); 72 - writew(info->pwmss_clkconfig, info->mmio_base + PWMSS_CLKCONFIG); 73 104 return 0; 74 105 } 75 106 #endif
-39
drivers/pwm/pwm-tipwmss.h
··· 1 - /* 2 - * TI PWM Subsystem driver 3 - * 4 - * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; either version 2 of the License, or 9 - * (at your option) any later version. 10 - * 11 - * This program is distributed in the hope that it will be useful, 12 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 - * GNU General Public License for more details. 15 - * 16 - */ 17 - 18 - #ifndef __TIPWMSS_H 19 - #define __TIPWMSS_H 20 - 21 - /* PWM substem clock gating */ 22 - #define PWMSS_ECAPCLK_EN BIT(0) 23 - #define PWMSS_ECAPCLK_STOP_REQ BIT(1) 24 - #define PWMSS_EPWMCLK_EN BIT(8) 25 - #define PWMSS_EPWMCLK_STOP_REQ BIT(9) 26 - 27 - #define PWMSS_ECAPCLK_EN_ACK BIT(0) 28 - #define PWMSS_EPWMCLK_EN_ACK BIT(8) 29 - 30 - #ifdef CONFIG_PWM_TIPWMSS 31 - extern u16 pwmss_submodule_state_change(struct device *dev, int set); 32 - #else 33 - static inline u16 pwmss_submodule_state_change(struct device *dev, int set) 34 - { 35 - /* return success status value */ 36 - return 0xFFFF; 37 - } 38 - #endif 39 - #endif /* __TIPWMSS_H */
+17
drivers/pwm/sysfs.c
··· 208 208 return ret ? : size; 209 209 } 210 210 211 + static ssize_t capture_show(struct device *child, 212 + struct device_attribute *attr, 213 + char *buf) 214 + { 215 + struct pwm_device *pwm = child_to_pwm_device(child); 216 + struct pwm_capture result; 217 + int ret; 218 + 219 + ret = pwm_capture(pwm, &result, jiffies_to_msecs(HZ)); 220 + if (ret) 221 + return ret; 222 + 223 + return sprintf(buf, "%u %u\n", result.period, result.duty_cycle); 224 + } 225 + 211 226 static DEVICE_ATTR_RW(period); 212 227 static DEVICE_ATTR_RW(duty_cycle); 213 228 static DEVICE_ATTR_RW(enable); 214 229 static DEVICE_ATTR_RW(polarity); 230 + static DEVICE_ATTR_RO(capture); 215 231 216 232 static struct attribute *pwm_attrs[] = { 217 233 &dev_attr_period.attr, 218 234 &dev_attr_duty_cycle.attr, 219 235 &dev_attr_enable.attr, 220 236 &dev_attr_polarity.attr, 237 + &dev_attr_capture.attr, 221 238 NULL 222 239 }; 223 240 ATTRIBUTE_GROUPS(pwm);
+118 -44
drivers/regulator/pwm-regulator.c
··· 22 22 #include <linux/pwm.h> 23 23 #include <linux/gpio/consumer.h> 24 24 25 + struct pwm_continuous_reg_data { 26 + unsigned int min_uV_dutycycle; 27 + unsigned int max_uV_dutycycle; 28 + unsigned int dutycycle_unit; 29 + }; 30 + 25 31 struct pwm_regulator_data { 26 32 /* Shared */ 27 33 struct pwm_device *pwm; 28 34 29 35 /* Voltage table */ 30 36 struct pwm_voltages *duty_cycle_table; 37 + 38 + /* Continuous mode info */ 39 + struct pwm_continuous_reg_data continuous; 31 40 32 41 /* regulator descriptor */ 33 42 struct regulator_desc desc; ··· 45 36 struct regulator_ops ops; 46 37 47 38 int state; 48 - 49 - /* Continuous voltage */ 50 - int volt_uV; 51 39 52 40 /* Enable GPIO */ 53 41 struct gpio_desc *enb_gpio; ··· 58 52 /** 59 53 * Voltage table call-backs 60 54 */ 55 + static void pwm_regulator_init_state(struct regulator_dev *rdev) 56 + { 57 + struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 58 + struct pwm_state pwm_state; 59 + unsigned int dutycycle; 60 + int i; 61 + 62 + pwm_get_state(drvdata->pwm, &pwm_state); 63 + dutycycle = pwm_get_relative_duty_cycle(&pwm_state, 100); 64 + 65 + for (i = 0; i < rdev->desc->n_voltages; i++) { 66 + if (dutycycle == drvdata->duty_cycle_table[i].dutycycle) { 67 + drvdata->state = i; 68 + return; 69 + } 70 + } 71 + } 72 + 61 73 static int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev) 62 74 { 63 75 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 76 + 77 + if (drvdata->state < 0) 78 + pwm_regulator_init_state(rdev); 64 79 65 80 return drvdata->state; 66 81 } ··· 90 63 unsigned selector) 91 64 { 92 65 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 93 - struct pwm_args pargs; 94 - int dutycycle; 66 + struct pwm_state pstate; 95 67 int ret; 96 68 97 - pwm_get_args(drvdata->pwm, &pargs); 69 + pwm_init_state(drvdata->pwm, &pstate); 70 + pwm_set_relative_duty_cycle(&pstate, 71 + drvdata->duty_cycle_table[selector].dutycycle, 100); 98 72 99 - dutycycle = (pargs.period * 100 - drvdata->duty_cycle_table[selector].dutycycle) / 100; 101 - 102 - ret = pwm_config(drvdata->pwm, dutycycle, pargs.period); 73 + ret = pwm_apply_state(drvdata->pwm, &pstate); 103 74 if (ret) { 104 75 dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); 105 76 return ret; ··· 154 129 static int pwm_regulator_get_voltage(struct regulator_dev *rdev) 155 130 { 156 131 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 132 + unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle; 133 + unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle; 134 + unsigned int duty_unit = drvdata->continuous.dutycycle_unit; 135 + int min_uV = rdev->constraints->min_uV; 136 + int max_uV = rdev->constraints->max_uV; 137 + int diff_uV = max_uV - min_uV; 138 + struct pwm_state pstate; 139 + unsigned int diff_duty; 140 + unsigned int voltage; 157 141 158 - return drvdata->volt_uV; 142 + pwm_get_state(drvdata->pwm, &pstate); 143 + 144 + voltage = pwm_get_relative_duty_cycle(&pstate, duty_unit); 145 + 146 + /* 147 + * The dutycycle for min_uV might be greater than the one for max_uV. 148 + * This is happening when the user needs an inversed polarity, but the 149 + * PWM device does not support inversing it in hardware. 150 + */ 151 + if (max_uV_duty < min_uV_duty) { 152 + voltage = min_uV_duty - voltage; 153 + diff_duty = min_uV_duty - max_uV_duty; 154 + } else { 155 + voltage = voltage - min_uV_duty; 156 + diff_duty = max_uV_duty - min_uV_duty; 157 + } 158 + 159 + voltage = DIV_ROUND_CLOSEST_ULL((u64)voltage * diff_uV, diff_duty); 160 + 161 + return voltage + min_uV; 159 162 } 160 163 161 164 static int pwm_regulator_set_voltage(struct regulator_dev *rdev, 162 - int min_uV, int max_uV, 163 - unsigned *selector) 165 + int req_min_uV, int req_max_uV, 166 + unsigned int *selector) 164 167 { 165 168 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 169 + unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle; 170 + unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle; 171 + unsigned int duty_unit = drvdata->continuous.dutycycle_unit; 166 172 unsigned int ramp_delay = rdev->constraints->ramp_delay; 167 - struct pwm_args pargs; 168 - unsigned int req_diff = min_uV - rdev->constraints->min_uV; 169 - unsigned int diff; 170 - unsigned int duty_pulse; 171 - u64 req_period; 172 - u32 rem; 173 + int min_uV = rdev->constraints->min_uV; 174 + int max_uV = rdev->constraints->max_uV; 175 + int diff_uV = max_uV - min_uV; 176 + struct pwm_state pstate; 173 177 int old_uV = pwm_regulator_get_voltage(rdev); 178 + unsigned int diff_duty; 179 + unsigned int dutycycle; 174 180 int ret; 175 181 176 - pwm_get_args(drvdata->pwm, &pargs); 177 - diff = rdev->constraints->max_uV - rdev->constraints->min_uV; 182 + pwm_init_state(drvdata->pwm, &pstate); 178 183 179 - /* First try to find out if we get the iduty cycle time which is 180 - * factor of PWM period time. If (request_diff_to_min * pwm_period) 181 - * is perfect divided by voltage_range_diff then it is possible to 182 - * get duty cycle time which is factor of PWM period. This will help 183 - * to get output voltage nearer to requested value as there is no 184 - * calculation loss. 184 + /* 185 + * The dutycycle for min_uV might be greater than the one for max_uV. 186 + * This is happening when the user needs an inversed polarity, but the 187 + * PWM device does not support inversing it in hardware. 185 188 */ 186 - req_period = req_diff * pargs.period; 187 - div_u64_rem(req_period, diff, &rem); 188 - if (!rem) { 189 - do_div(req_period, diff); 190 - duty_pulse = (unsigned int)req_period; 191 - } else { 192 - duty_pulse = (pargs.period / 100) * ((req_diff * 100) / diff); 193 - } 189 + if (max_uV_duty < min_uV_duty) 190 + diff_duty = min_uV_duty - max_uV_duty; 191 + else 192 + diff_duty = max_uV_duty - min_uV_duty; 194 193 195 - ret = pwm_config(drvdata->pwm, duty_pulse, pargs.period); 194 + dutycycle = DIV_ROUND_CLOSEST_ULL((u64)(req_min_uV - min_uV) * 195 + diff_duty, 196 + diff_uV); 197 + 198 + if (max_uV_duty < min_uV_duty) 199 + dutycycle = min_uV_duty - dutycycle; 200 + else 201 + dutycycle = min_uV_duty + dutycycle; 202 + 203 + pwm_set_relative_duty_cycle(&pstate, dutycycle, duty_unit); 204 + 205 + ret = pwm_apply_state(drvdata->pwm, &pstate); 196 206 if (ret) { 197 207 dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); 198 208 return ret; 199 209 } 200 210 201 - drvdata->volt_uV = min_uV; 202 - 203 211 if ((ramp_delay == 0) || !pwm_regulator_is_enabled(rdev)) 204 212 return 0; 205 213 206 214 /* Ramp delay is in uV/uS. Adjust to uS and delay */ 207 - ramp_delay = DIV_ROUND_UP(abs(min_uV - old_uV), ramp_delay); 215 + ramp_delay = DIV_ROUND_UP(abs(req_min_uV - old_uV), ramp_delay); 208 216 usleep_range(ramp_delay, ramp_delay + DIV_ROUND_UP(ramp_delay, 10)); 209 217 210 218 return 0; ··· 297 239 return ret; 298 240 } 299 241 242 + drvdata->state = -EINVAL; 300 243 drvdata->duty_cycle_table = duty_cycle_table; 301 244 memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops, 302 245 sizeof(drvdata->ops)); ··· 310 251 static int pwm_regulator_init_continuous(struct platform_device *pdev, 311 252 struct pwm_regulator_data *drvdata) 312 253 { 254 + u32 dutycycle_range[2] = { 0, 100 }; 255 + u32 dutycycle_unit = 100; 256 + 313 257 memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops, 314 258 sizeof(drvdata->ops)); 315 259 drvdata->desc.ops = &drvdata->ops; 316 260 drvdata->desc.continuous_voltage_range = true; 261 + 262 + of_property_read_u32_array(pdev->dev.of_node, 263 + "pwm-dutycycle-range", 264 + dutycycle_range, 2); 265 + of_property_read_u32(pdev->dev.of_node, "pwm-dutycycle-unit", 266 + &dutycycle_unit); 267 + 268 + if (dutycycle_range[0] > dutycycle_unit || 269 + dutycycle_range[1] > dutycycle_unit) 270 + return -EINVAL; 271 + 272 + drvdata->continuous.dutycycle_unit = dutycycle_unit; 273 + drvdata->continuous.min_uV_dutycycle = dutycycle_range[0]; 274 + drvdata->continuous.max_uV_dutycycle = dutycycle_range[1]; 317 275 318 276 return 0; 319 277 } ··· 392 316 return ret; 393 317 } 394 318 395 - /* 396 - * FIXME: pwm_apply_args() should be removed when switching to the 397 - * atomic PWM API. 398 - */ 399 - pwm_apply_args(drvdata->pwm); 319 + ret = pwm_adjust_config(drvdata->pwm); 320 + if (ret) 321 + return ret; 400 322 401 323 regulator = devm_regulator_register(&pdev->dev, 402 324 &drvdata->desc, &config);
+15
include/linux/mfd/cros_ec.h
··· 226 226 struct cros_ec_command *msg); 227 227 228 228 /** 229 + * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC 230 + * 231 + * This function is identical to cros_ec_cmd_xfer, except it returns success 232 + * status only if both the command was transmitted successfully and the EC 233 + * replied with success status. It's not necessary to check msg->result when 234 + * using this function. 235 + * 236 + * @ec_dev: EC device 237 + * @msg: Message to write 238 + * @return: Num. of bytes transferred on success, <0 on failure 239 + */ 240 + int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, 241 + struct cros_ec_command *msg); 242 + 243 + /** 229 244 * cros_ec_remove - Remove a ChromeOS EC 230 245 * 231 246 * Call this to deregister a ChromeOS EC, then clean up any private data.
+31
include/linux/mfd/cros_ec_commands.h
··· 949 949 uint32_t percent; 950 950 } __packed; 951 951 952 + #define EC_CMD_PWM_SET_DUTY 0x25 953 + /* 16 bit duty cycle, 0xffff = 100% */ 954 + #define EC_PWM_MAX_DUTY 0xffff 955 + 956 + enum ec_pwm_type { 957 + /* All types, indexed by board-specific enum pwm_channel */ 958 + EC_PWM_TYPE_GENERIC = 0, 959 + /* Keyboard backlight */ 960 + EC_PWM_TYPE_KB_LIGHT, 961 + /* Display backlight */ 962 + EC_PWM_TYPE_DISPLAY_LIGHT, 963 + EC_PWM_TYPE_COUNT, 964 + }; 965 + 966 + struct ec_params_pwm_set_duty { 967 + uint16_t duty; /* Duty cycle, EC_PWM_MAX_DUTY = 100% */ 968 + uint8_t pwm_type; /* ec_pwm_type */ 969 + uint8_t index; /* Type-specific index, or 0 if unique */ 970 + } __packed; 971 + 972 + #define EC_CMD_PWM_GET_DUTY 0x26 973 + 974 + struct ec_params_pwm_get_duty { 975 + uint8_t pwm_type; /* ec_pwm_type */ 976 + uint8_t index; /* Type-specific index, or 0 if unique */ 977 + } __packed; 978 + 979 + struct ec_response_pwm_get_duty { 980 + uint16_t duty; /* Duty cycle, EC_PWM_MAX_DUTY = 100% */ 981 + } __packed; 982 + 952 983 /*****************************************************************************/ 953 984 /* 954 985 * Lightbar commands. This looks worse than it is. Since we only use one HOST
+112 -1
include/linux/pwm.h
··· 5 5 #include <linux/mutex.h> 6 6 #include <linux/of.h> 7 7 8 + struct pwm_capture; 8 9 struct seq_file; 10 + 9 11 struct pwm_chip; 10 12 11 13 /** ··· 150 148 } 151 149 152 150 /** 151 + * pwm_init_state() - prepare a new state to be applied with pwm_apply_state() 152 + * @pwm: PWM device 153 + * @state: state to fill with the prepared PWM state 154 + * 155 + * This functions prepares a state that can later be tweaked and applied 156 + * to the PWM device with pwm_apply_state(). This is a convenient function 157 + * that first retrieves the current PWM state and the replaces the period 158 + * and polarity fields with the reference values defined in pwm->args. 159 + * Once the function returns, you can adjust the ->enabled and ->duty_cycle 160 + * fields according to your needs before calling pwm_apply_state(). 161 + * 162 + * ->duty_cycle is initially set to zero to avoid cases where the current 163 + * ->duty_cycle value exceed the pwm_args->period one, which would trigger 164 + * an error if the user calls pwm_apply_state() without adjusting ->duty_cycle 165 + * first. 166 + */ 167 + static inline void pwm_init_state(const struct pwm_device *pwm, 168 + struct pwm_state *state) 169 + { 170 + struct pwm_args args; 171 + 172 + /* First get the current state. */ 173 + pwm_get_state(pwm, state); 174 + 175 + /* Then fill it with the reference config */ 176 + pwm_get_args(pwm, &args); 177 + 178 + state->period = args.period; 179 + state->polarity = args.polarity; 180 + state->duty_cycle = 0; 181 + } 182 + 183 + /** 184 + * pwm_get_relative_duty_cycle() - Get a relative duty cycle value 185 + * @state: PWM state to extract the duty cycle from 186 + * @scale: target scale of the relative duty cycle 187 + * 188 + * This functions converts the absolute duty cycle stored in @state (expressed 189 + * in nanosecond) into a value relative to the period. 190 + * 191 + * For example if you want to get the duty_cycle expressed in percent, call: 192 + * 193 + * pwm_get_state(pwm, &state); 194 + * duty = pwm_get_relative_duty_cycle(&state, 100); 195 + */ 196 + static inline unsigned int 197 + pwm_get_relative_duty_cycle(const struct pwm_state *state, unsigned int scale) 198 + { 199 + if (!state->period) 200 + return 0; 201 + 202 + return DIV_ROUND_CLOSEST_ULL((u64)state->duty_cycle * scale, 203 + state->period); 204 + } 205 + 206 + /** 207 + * pwm_set_relative_duty_cycle() - Set a relative duty cycle value 208 + * @state: PWM state to fill 209 + * @duty_cycle: relative duty cycle value 210 + * @scale: scale in which @duty_cycle is expressed 211 + * 212 + * This functions converts a relative into an absolute duty cycle (expressed 213 + * in nanoseconds), and puts the result in state->duty_cycle. 214 + * 215 + * For example if you want to configure a 50% duty cycle, call: 216 + * 217 + * pwm_init_state(pwm, &state); 218 + * pwm_set_relative_duty_cycle(&state, 50, 100); 219 + * pwm_apply_state(pwm, &state); 220 + * 221 + * This functions returns -EINVAL if @duty_cycle and/or @scale are 222 + * inconsistent (@scale == 0 or @duty_cycle > @scale). 223 + */ 224 + static inline int 225 + pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle, 226 + unsigned int scale) 227 + { 228 + if (!scale || duty_cycle > scale) 229 + return -EINVAL; 230 + 231 + state->duty_cycle = DIV_ROUND_CLOSEST_ULL((u64)duty_cycle * 232 + state->period, 233 + scale); 234 + 235 + return 0; 236 + } 237 + 238 + /** 153 239 * struct pwm_ops - PWM controller operations 154 240 * @request: optional hook for requesting a PWM 155 241 * @free: optional hook for freeing a PWM 156 242 * @config: configure duty cycles and period length for this PWM 157 243 * @set_polarity: configure the polarity of this PWM 244 + * @capture: capture and report PWM signal 158 245 * @enable: enable PWM output toggling 159 246 * @disable: disable PWM output toggling 160 247 * @apply: atomically apply a new PWM config. The state argument ··· 263 172 int duty_ns, int period_ns); 264 173 int (*set_polarity)(struct pwm_chip *chip, struct pwm_device *pwm, 265 174 enum pwm_polarity polarity); 175 + int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm, 176 + struct pwm_capture *result, unsigned long timeout); 266 177 int (*enable)(struct pwm_chip *chip, struct pwm_device *pwm); 267 178 void (*disable)(struct pwm_chip *chip, struct pwm_device *pwm); 268 179 int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm, ··· 303 210 const struct of_phandle_args *args); 304 211 unsigned int of_pwm_n_cells; 305 212 bool can_sleep; 213 + }; 214 + 215 + /** 216 + * struct pwm_capture - PWM capture data 217 + * @period: period of the PWM signal (in nanoseconds) 218 + * @duty_cycle: duty cycle of the PWM signal (in nanoseconds) 219 + */ 220 + struct pwm_capture { 221 + unsigned int period; 222 + unsigned int duty_cycle; 306 223 }; 307 224 308 225 #if IS_ENABLED(CONFIG_PWM) ··· 426 323 pwm_apply_state(pwm, &state); 427 324 } 428 325 429 - 430 326 /* PWM provider APIs */ 327 + int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result, 328 + unsigned long timeout); 431 329 int pwm_set_chip_data(struct pwm_device *pwm, void *data); 432 330 void *pwm_get_chip_data(struct pwm_device *pwm); 433 331 ··· 476 372 477 373 static inline int pwm_config(struct pwm_device *pwm, int duty_ns, 478 374 int period_ns) 375 + { 376 + return -EINVAL; 377 + } 378 + 379 + static inline int pwm_capture(struct pwm_device *pwm, 380 + struct pwm_capture *result, 381 + unsigned long timeout) 479 382 { 480 383 return -EINVAL; 481 384 }