projects/linux·commit a157b3aa

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

a157b3aa · Linus Torvalds <[email protected]> · 2016-08-06 00:01:33 -04:00

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
  ...
Commit
a157b3aaa44829998d5a079174df989e5d8c20ff
Parents
32199ec3 · 53de7c26

Merge commit. Changes below are compared with the first parent: 32199ec3.

Changes

29 files changed · +1561 −283

FileStatusAddDelContent
Documentation/ABI/testing/sysfs-class-pwmmodified+9−0View file
Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txtadded+21−0View file
Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txtadded+23−0View file
Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txtmodified+8−4View file
Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txtmodified+1−0View file
Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txtadded+18−0View file
Documentation/devicetree/bindings/regulator/pwm-regulator.txtmodified+19−0View file
drivers/platform/chrome/cros_ec_proto.cmodified+17−0View file
drivers/pwm/Kconfigmodified+25−1View file
drivers/pwm/Makefilemodified+3−0View file
drivers/pwm/core.cmodified+27−0View file
drivers/pwm/pwm-atmel.cmodified+17−13View file
drivers/pwm/pwm-bcm-iproc.cadded+277−0View file
drivers/pwm/pwm-cros-ec.cadded+260−0View file
drivers/pwm/pwm-lpc32xx.cmodified+7−0View file
drivers/pwm/pwm-lpss-pci.cmodified+1−0View file
drivers/pwm/pwm-lpss.cmodified+14−12View file
drivers/pwm/pwm-rockchip.cmodified+132−46View file
drivers/pwm/pwm-stmpe.cadded+319−0View file
drivers/pwm/pwm-tegra.cmodified+52−17View file
drivers/pwm/pwm-tiecap.cmodified+9−28View file
drivers/pwm/pwm-tiehrpwm.cmodified+9−29View file
drivers/pwm/pwm-tipwmss.cmodified+0−49View file
drivers/pwm/pwm-tipwmss.hdeleted+0−39View before deletion
drivers/pwm/sysfs.cmodified+17−0View file
drivers/regulator/pwm-regulator.cmodified+118−44View file
include/linux/mfd/cros_ec.hmodified+15−0View file
include/linux/mfd/cros_ec_commands.hmodified+31−0View file
include/linux/pwm.hmodified+112−1View file

Only the first 600 diff lines are shown. Download the complete patch.

Documentation/ABI/testing/sysfs-class-pwm

View file
diff --git a/Documentation/ABI/testing/sysfs-class-pwm b/Documentation/ABI/testing/sysfs-class-pwm
index c479d77..c20e613 100644
--- a/Documentation/ABI/testing/sysfs-class-pwm
+++ b/Documentation/ABI/testing/sysfs-class-pwm
@@ -77,3 +77,12 @@ Description:
Enable/disable the PWM signal.
0 is disabled
1 is enabled
+
+What: /sys/class/pwm/pwmchipN/pwmX/capture
+Date: June 2016
+KernelVersion: 4.8
+Contact: Lee Jones <[email protected]>
+Description:
+ Capture information about a PWM signal. The output format is a
+ pair unsigned integers (period and duty cycle), separated by a
+ single space.

Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt

View file
diff --git a/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt b/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
new file mode 100644
index 0000000..21f75bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
@@ -0,0 +1,21 @@
+Broadcom iProc PWM controller device tree bindings
+
+This controller has 4 channels.
+
+Required Properties :
+- compatible: must be "brcm,iproc-pwm"
+- reg: physical base address and length of the controller's registers
+- clocks: phandle + clock specifier pair for the external clock
+- #pwm-cells: Should be 3. See pwm.txt in this directory for a
+ description of the cells format.
+
+Refer to clocks/clock-bindings.txt for generic clock consumer properties.
+
+Example:
+
+pwm: pwm@18031000 {
+ compatible = "brcm,iproc-pwm";
+ reg = <0x18031000 0x28>;
+ clocks = <&osc>;
+ #pwm-cells = <3>;
+};

Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt

View file
diff --git a/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt b/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt
new file mode 100644
index 0000000..472bd46
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt
@@ -0,0 +1,23 @@
+* PWM controlled by ChromeOS EC
+
+Google's ChromeOS EC PWM is a simple PWM attached to the Embedded Controller
+(EC) and controlled via a host-command interface.
+
+An EC PWM node should be only found as a sub-node of the EC node (see
+Documentation/devicetree/bindings/mfd/cros-ec.txt).
+
+Required properties:
+- compatible: Must contain "google,cros-ec-pwm"
+- #pwm-cells: Should be 1. The cell specifies the PWM index.
+
+Example:
+ cros-ec@0 {
+ compatible = "google,cros-ec-spi";
+
+ ...
+
+ cros_ec_pwm: ec-pwm {
+ compatible = "google,cros-ec-pwm";
+ #pwm-cells = <1>;
+ };
+ };

Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt

View file
diff --git a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
index c52f03b..b4e7377 100644
--- a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
@@ -1,10 +1,14 @@
Tegra SoC PWFM controller
Required properties:
-- compatible: For Tegra20, must contain "nvidia,tegra20-pwm". For Tegra30,
- must contain "nvidia,tegra30-pwm". Otherwise, must contain
- "nvidia,<chip>-pwm", plus one of the above, where <chip> is tegra114,
- tegra124, tegra132, or tegra210.
+- compatible: Must be:
+ - "nvidia,tegra20-pwm": for Tegra20
+ - "nvidia,tegra30-pwm", "nvidia,tegra20-pwm": for Tegra30
+ - "nvidia,tegra114-pwm", "nvidia,tegra20-pwm": for Tegra114
+ - "nvidia,tegra124-pwm", "nvidia,tegra20-pwm": for Tegra124
+ - "nvidia,tegra132-pwm", "nvidia,tegra20-pwm": for Tegra132
+ - "nvidia,tegra210-pwm", "nvidia,tegra20-pwm": for Tegra210
+ - "nvidia,tegra186-pwm": for Tegra186
- 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.

Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt

View file
diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
index 0822a08..d6de643 100644
--- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
+++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
@@ -7,6 +7,7 @@ Required Properties:
- "renesas,pwm-r8a7790": for R-Car H2
- "renesas,pwm-r8a7791": for R-Car M2-W
- "renesas,pwm-r8a7794": for R-Car E2
+ - "renesas,pwm-r8a7795": for R-Car H3
- reg: base address and length of the registers block for the PWM.
- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
the cells format.

Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt

View file
diff --git a/Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt b/Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt
new file mode 100644
index 0000000..cb20964
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt
@@ -0,0 +1,18 @@
+== ST STMPE PWM controller ==
+
+This is a PWM block embedded in the ST Microelectronics STMPE
+(ST Multi-Purpose Expander) chips. The PWM is registered as a
+subdevices of the STMPE MFD device.
+
+Required properties:
+- compatible: should be:
+ - "st,stmpe-pwm"
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+ the cells format.
+
+Example:
+
+pwm0: pwm {
+ compatible = "st,stmpe-pwm";
+ #pwm-cells = <2>;
+};

Documentation/devicetree/bindings/regulator/pwm-regulator.txt

View file
diff --git a/Documentation/devicetree/bindings/regulator/pwm-regulator.txt b/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
index dd6f59c..3aeba9f 100644
--- a/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
@@ -34,6 +34,18 @@ Only required for Voltage Table Mode:
First cell is voltage in microvolts (uV)
Second cell is duty-cycle in percent (%)
+Optional properties for Continuous mode:
+- pwm-dutycycle-unit: Integer value encoding the duty cycle unit. If not
+ defined, <100> is assumed, meaning that
+ pwm-dutycycle-range contains values expressed in
+ percent.
+
+- pwm-dutycycle-range: Should contain 2 entries. The first entry is encoding
+ the dutycycle for regulator-min-microvolt and the
+ second one the dutycycle for regulator-max-microvolt.
+ Duty cycle values are expressed in pwm-dutycycle-unit.
+ If not defined, <0 100> is assumed.
+
NB: To be clear, if voltage-table is provided, then the device will be used
in Voltage Table Mode. If no voltage-table is provided, then the device will
be used in Continuous Voltage Mode.
@@ -53,6 +65,13 @@ Continuous Voltage With Enable GPIO Example:
regulator-min-microvolt = <1016000>;
regulator-max-microvolt = <1114000>;
regulator-name = "vdd_logic";
+ /* unit == per-mille */
+ pwm-dutycycle-unit = <1000>;
+ /*
+ * Inverted PWM logic, and the duty cycle range is limited
+ * to 30%-70%.
+ */
+ pwm-dutycycle-range <700 300>; /* */
};
Voltage Table Example:

drivers/platform/chrome/cros_ec_proto.c

View file
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
index b6e161f..6c084b2 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -380,3 +380,20 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
return ret;
}
EXPORT_SYMBOL(cros_ec_cmd_xfer);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *msg)
+{
+ int ret;
+
+ ret = cros_ec_cmd_xfer(ec_dev, msg);
+ if (ret < 0) {
+ dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+ } else if (msg->result != EC_RES_SUCCESS) {
+ dev_dbg(ec_dev->dev, "Command result (err: %d)\n", msg->result);
+ return -EPROTO;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);

drivers/pwm/Kconfig

View file
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index c182efc..80a566a 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -74,6 +74,16 @@ config PWM_ATMEL_TCB
To compile this driver as a module, choose M here: the module
will be called pwm-atmel-tcb.
+config PWM_BCM_IPROC
+ tristate "iProc PWM support"
+ depends on ARCH_BCM_IPROC
+ help
+ Generic PWM framework driver for Broadcom iProc PWM block. This
+ block is used in Broadcom iProc SoC's.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-bcm-iproc.
+
config PWM_BCM_KONA
tristate "Kona PWM support"
depends on ARCH_BCM_MOBILE
@@ -137,6 +147,13 @@ config PWM_CRC
Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM
control.
+config PWM_CROS_EC
+ tristate "ChromeOS EC PWM driver"
+ depends on MFD_CROS_EC
+ help
+ PWM driver for exposing a PWM attached to the ChromeOS Embedded
+ Controller.
+
config PWM_EP93XX
tristate "Cirrus Logic EP93xx PWM support"
depends on ARCH_EP93XX
@@ -305,7 +322,7 @@ config PWM_PXA
config PWM_RCAR
tristate "Renesas R-Car PWM support"
- depends on ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || COMPILE_TEST
+ depends on ARCH_RENESAS || COMPILE_TEST
depends on HAS_IOMEM
help
This driver exposes the PWM Timer controller found in Renesas
@@ -362,6 +379,13 @@ config PWM_STI
To compile this driver as a module, choose M here: the module
will be called pwm-sti.
+config PWM_STMPE
+ bool "STMPE expander PWM export"
+ depends on MFD_STMPE
+ help
+ This enables support for the PWMs found in the STMPE I/O
+ expanders.
+
config PWM_SUN4I
tristate "Allwinner PWM support"
depends on ARCH_SUNXI || COMPILE_TEST

drivers/pwm/Makefile

View file
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index dd35bc1..feef1dd 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o
obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o
obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o
+obj-$(CONFIG_PWM_BCM_IPROC) += pwm-bcm-iproc.o
obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o
obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o
obj-$(CONFIG_PWM_BERLIN) += pwm-berlin.o
@@ -11,6 +12,7 @@ obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o
obj-$(CONFIG_PWM_BRCMSTB) += pwm-brcmstb.o
obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o
obj-$(CONFIG_PWM_CRC) += pwm-crc.o
+obj-$(CONFIG_PWM_CROS_EC) += pwm-cros-ec.o
obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o
obj-$(CONFIG_PWM_IMG) += pwm-img.o
@@ -34,6 +36,7 @@ obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o
obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o
obj-$(CONFIG_PWM_STI) += pwm-sti.o
+obj-$(CONFIG_PWM_STMPE) += pwm-stmpe.o
obj-$(CONFIG_PWM_SUN4I) += pwm-sun4i.o
obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o
obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o

drivers/pwm/core.c

View file
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index ed337a8..0dbd29e 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -526,6 +526,33 @@ int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state)
EXPORT_SYMBOL_GPL(pwm_apply_state);
/**
+ * pwm_capture() - capture and report a PWM signal
+ * @pwm: PWM device
+ * @result: structure to fill with capture result
+ * @timeout: time to wait, in milliseconds, before giving up on capture
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
+ unsigned long timeout)
+{
+ int err;
+
+ if (!pwm || !pwm->chip->ops)
+ return -EINVAL;
+
+ if (!pwm->chip->ops->capture)
+ return -ENOSYS;
+
+ mutex_lock(&pwm_lock);
+ err = pwm->chip->ops->capture(pwm->chip, pwm, result, timeout);
+ mutex_unlock(&pwm_lock);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(pwm_capture);
+
+/**
* pwm_adjust_config() - adjust the current PWM config to the PWM arguments
* @pwm: PWM device
*

drivers/pwm/pwm-atmel.c

View file
diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c
index 0e4bd4e..e6b8b1b 100644
--- a/drivers/pwm/pwm-atmel.c
+++ b/drivers/pwm/pwm-atmel.c
@@ -64,7 +64,8 @@ struct atmel_pwm_chip {
void __iomem *base;
unsigned int updated_pwms;
- struct mutex isr_lock; /* ISR is cleared when read, ensure only one thread does that */
+ /* ISR is cleared when read, ensure only one thread does that */
+ struct mutex isr_lock;
void (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
unsigned long dty, unsigned long prd);
@@ -271,6 +272,16 @@ static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
mutex_unlock(&atmel_pwm->isr_lock);
atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << pwm->hwpwm);
+ /*
+ * Wait for the PWM channel disable operation to be effective before
+ * stopping the clock.
+ */
+ timeout = jiffies + 2 * HZ;
+
+ while ((atmel_pwm_readl(atmel_pwm, PWM_SR) & (1 << pwm->hwpwm)) &&
+ time_before(jiffies, timeout))
+ usleep_range(10, 100);
+
clk_disable(atmel_pwm->clk);
}
@@ -324,21 +335,14 @@ MODULE_DEVICE_TABLE(of, atmel_pwm_dt_ids);
static inline const struct atmel_pwm_data *
atmel_pwm_get_driver_data(struct platform_device *pdev)
{
- if (pdev->dev.of_node) {
- const struct of_device_id *match;
-
- match = of_match_device(atmel_pwm_dt_ids, &pdev->dev);
- if (!match)
- return NULL;
+ const struct platform_device_id *id;
- return match->data;
- } else {
- const struct platform_device_id *id;
+ if (pdev->dev.of_node)
+ return of_device_get_match_data(&pdev->dev);
- id = platform_get_device_id(pdev);
+ id = platform_get_device_id(pdev);
- return (struct atmel_pwm_data *)id->driver_data;
- }
+ return (struct atmel_pwm_data *)id->driver_data;
}
static int atmel_pwm_probe(struct platform_device *pdev)

drivers/pwm/pwm-bcm-iproc.c

View file
diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c
new file mode 100644
index 0000000..d961a82
--- /dev/null
+++ b/drivers/pwm/pwm-bcm-iproc.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+
+#define IPROC_PWM_CTRL_OFFSET 0x00
+#define IPROC_PWM_CTRL_TYPE_SHIFT(ch) (15 + (ch))
+#define IPROC_PWM_CTRL_POLARITY_SHIFT(ch) (8 + (ch))
+#define IPROC_PWM_CTRL_EN_SHIFT(ch) (ch)
+
+#define IPROC_PWM_PERIOD_OFFSET(ch) (0x04 + ((ch) << 3))
+#define IPROC_PWM_PERIOD_MIN 0x02
+#define IPROC_PWM_PERIOD_MAX 0xffff
+
+#define IPROC_PWM_DUTY_CYCLE_OFFSET(ch) (0x08 + ((ch) << 3))
+#define IPROC_PWM_DUTY_CYCLE_MIN 0x00
+#define IPROC_PWM_DUTY_CYCLE_MAX 0xffff
+
+#define IPROC_PWM_PRESCALE_OFFSET 0x24
+#define IPROC_PWM_PRESCALE_BITS 0x06
+#define IPROC_PWM_PRESCALE_SHIFT(ch) ((3 - (ch)) * \
+ IPROC_PWM_PRESCALE_BITS)
+#define IPROC_PWM_PRESCALE_MASK(ch) (IPROC_PWM_PRESCALE_MAX << \
+ IPROC_PWM_PRESCALE_SHIFT(ch))
+#define IPROC_PWM_PRESCALE_MIN 0x00
+#define IPROC_PWM_PRESCALE_MAX 0x3f
+
+struct iproc_pwmc {
+ struct pwm_chip chip;
+ void __iomem *base;
+ struct clk *clk;
+};
+
+static inline struct iproc_pwmc *to_iproc_pwmc(struct pwm_chip *chip)
+{
+ return container_of(chip, struct iproc_pwmc, chip);
+}
+
+static void iproc_pwmc_enable(struct iproc_pwmc *ip, unsigned int channel)
+{
+ u32 value;
+
+ value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+ value |= 1 << IPROC_PWM_CTRL_EN_SHIFT(channel);
+ writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ /* must be a 400 ns delay between clearing and setting enable bit */
+ ndelay(400);
+}
+
+static void iproc_pwmc_disable(struct iproc_pwmc *ip, unsigned int channel)
+{
+ u32 value;
+
+ value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+ value &= ~(1 << IPROC_PWM_CTRL_EN_SHIFT(channel));
+ writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ /* must be a 400 ns delay between clearing and setting enable bit */
+ ndelay(400);
+}
+
+static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+ u64 tmp, multi, rate;
+ u32 value, prescale;
+
+ rate = clk_get_rate(ip->clk);
+
+ value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ if (value & BIT(IPROC_PWM_CTRL_EN_SHIFT(pwm->hwpwm)))
+ state->enabled = true;
+ else
+ state->enabled = false;
+
+ if (value & BIT(IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm)))
+ state->polarity = PWM_POLARITY_NORMAL;
+ else
+ state->polarity = PWM_POLARITY_INVERSED;
+
+ value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
+ prescale = value >> IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm);
+ prescale &= IPROC_PWM_PRESCALE_MAX;
+
+ multi = NSEC_PER_SEC * (prescale + 1);
+
+ value = readl(ip->base + IPROC_PWM_PERIOD_OFFSET(pwm->hwpwm));
+ tmp = (value & IPROC_PWM_PERIOD_MAX) * multi;
+ state->period = div64_u64(tmp, rate);
+
+ value = readl(ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm));
+ tmp = (value & IPROC_PWM_PERIOD_MAX) * multi;
+ state->duty_cycle = div64_u64(tmp, rate);
+}
+
+static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ unsigned long prescale = IPROC_PWM_PRESCALE_MIN;
+ struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+ u32 value, period, duty;
+ u64 rate;
+
+ rate = clk_get_rate(ip->clk);
+
+ /*
+ * Find period count, duty count and prescale to suit duty_cycle and
+ * period. This is done according to formulas described below:
+ *
+ * period_ns = 10^9 * (PRESCALE + 1) * PC / PWM_CLK_RATE
+ * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
+ *
+ * PC = (PWM_CLK_RATE * period_ns) / (10^9 * (PRESCALE + 1))
+ * DC = (PWM_CLK_RATE * duty_ns) / (10^9 * (PRESCALE + 1))
+ */
+ while (1) {
+ u64 value, div;
+
+ div = NSEC_PER_SEC * (prescale + 1);
+ value = rate * state->period;
+ period = div64_u64(value, div);
+ value = rate * state->duty_cycle;
+ duty = div64_u64(value, div);
+
+ if (period < IPROC_PWM_PERIOD_MIN ||
+ duty < IPROC_PWM_DUTY_CYCLE_MIN)
+ return -EINVAL;
+
+ if (period <= IPROC_PWM_PERIOD_MAX &&
+ duty <= IPROC_PWM_DUTY_CYCLE_MAX)
+ break;
+
+ /* Otherwise, increase prescale and recalculate counts */
+ if (++prescale > IPROC_PWM_PRESCALE_MAX)
+ return -EINVAL;
+ }
+
+ iproc_pwmc_disable(ip, pwm->hwpwm);
+
+ /* Set prescale */
+ value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
+ value &= ~IPROC_PWM_PRESCALE_MASK(pwm->hwpwm);
+ value |= prescale << IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm);
+ writel(value, ip->base + IPROC_PWM_PRESCALE_OFFSET);
+
+ /* set period and duty cycle */
+ writel(period, ip->base + IPROC_PWM_PERIOD_OFFSET(pwm->hwpwm));
+ writel(duty, ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm));
+
+ /* set polarity */
+ value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ if (state->polarity == PWM_POLARITY_NORMAL)
+ value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm);
+ else
+ value &= ~(1 << IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm));
+
+ writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ if (state->enabled)
+ iproc_pwmc_enable(ip, pwm->hwpwm);
+
+ return 0;
+}
+
+static const struct pwm_ops iproc_pwm_ops = {
+ .apply = iproc_pwmc_apply,
+ .get_state = iproc_pwmc_get_state,
+};
+
+static int iproc_pwmc_probe(struct platform_device *pdev)
+{
+ struct iproc_pwmc *ip;
+ struct resource *res;
+ unsigned int i;
+ u32 value;
+ int ret;
+
+ ip = devm_kzalloc(&pdev->dev, sizeof(*ip), GFP_KERNEL);
+ if (!ip)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, ip);
+
+ ip->chip.dev = &pdev->dev;
+ ip->chip.ops = &iproc_pwm_ops;
+ ip->chip.base = -1;
+ ip->chip.npwm = 4;
+ ip->chip.of_xlate = of_pwm_xlate_with_flags;
+ ip->chip.of_pwm_n_cells = 3;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ip->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ip->base))
+ return PTR_ERR(ip->base);
+
+ ip->clk = devm_clk_get(&pdev->dev, NULL);

This diff is incomplete. Download the complete patch.

drivers/pwm/pwm-cros-ec.c

View file

This diff is incomplete. Download the complete patch.

drivers/pwm/pwm-lpc32xx.c

View file

This diff is incomplete. Download the complete patch.

drivers/pwm/pwm-lpss-pci.c

View file

This diff is incomplete. Download the complete patch.

drivers/pwm/pwm-lpss.c

View file

This diff is incomplete. Download the complete patch.

drivers/pwm/pwm-rockchip.c

View file

This diff is incomplete. Download the complete patch.

drivers/pwm/pwm-stmpe.c

View file

This diff is incomplete. Download the complete patch.

drivers/pwm/pwm-tegra.c

View file

This diff is incomplete. Download the complete patch.

drivers/pwm/pwm-tiecap.c

View file

This diff is incomplete. Download the complete patch.

drivers/pwm/pwm-tiehrpwm.c

View file

This diff is incomplete. Download the complete patch.

drivers/pwm/pwm-tipwmss.c

View file

This diff is incomplete. Download the complete patch.

drivers/pwm/pwm-tipwmss.h

View before deletion

This diff is incomplete. Download the complete patch.

drivers/pwm/sysfs.c

View file

This diff is incomplete. Download the complete patch.

drivers/regulator/pwm-regulator.c

View file

This diff is incomplete. Download the complete patch.

include/linux/mfd/cros_ec.h

View file

This diff is incomplete. Download the complete patch.

include/linux/mfd/cros_ec_commands.h

View file

This diff is incomplete. Download the complete patch.

include/linux/pwm.h

View file

This diff is incomplete. Download the complete patch.