Merge tag 'pwm/for-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 8 Jul 2021 19:18:04 +0000 (12:18 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 8 Jul 2021 19:18:04 +0000 (12:18 -0700)
Pull pwm updates from Thierry Reding:
 "This contains mostly various fixes, cleanups and some conversions to
  the atomic API. One noteworthy change is that PWM consumers can now
  pass a hint to the PWM core about the PWM usage, enabling PWM
  providers to implement various optimizations.

  There's also a fair bit of simplification here with the addition of
  some device-managed helpers as well as unification between the DT and
  ACPI firmware interfaces"

* tag 'pwm/for-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (50 commits)
  pwm: Remove redundant assignment to pointer pwm
  pwm: ep93xx: Fix read of uninitialized variable ret
  pwm: ep93xx: Prepare clock before using it
  pwm: ep93xx: Unfold legacy callbacks into ep93xx_pwm_apply()
  pwm: ep93xx: Implement .apply callback
  pwm: vt8500: Only unprepare the clock after the pwmchip was removed
  pwm: vt8500: Drop if with an always false condition
  pwm: tegra: Assert reset only after the PWM was unregistered
  pwm: tegra: Don't needlessly enable and disable the clock in .remove()
  pwm: tegra: Don't modify HW state in .remove callback
  pwm: tegra: Drop an if block with an always false condition
  pwm: core: Simplify some devm_*pwm*() functions
  pwm: core: Remove unused devm_pwm_put()
  pwm: core: Unify fwnode checks in the module
  pwm: core: Reuse fwnode_to_pwmchip() in ACPI case
  pwm: core: Convert to use fwnode for matching
  docs: firmware-guide: ACPI: Add a PWM example
  dt-bindings: pwm: pwm-tiecap: Add compatible string for AM64 SoC
  dt-bindings: pwm: pwm-tiecap: Convert to json schema
  pwm: sprd: Don't check the return code of pwmchip_remove()
  ...

50 files changed:
Documentation/devicetree/bindings/pwm/pwm-tiecap.txt [deleted file]
Documentation/devicetree/bindings/pwm/pwm-tiecap.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt [deleted file]
Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.yaml [new file with mode: 0644]
Documentation/driver-api/driver-model/devres.rst
Documentation/driver-api/pwm.rst
Documentation/firmware-guide/acpi/enumeration.rst
drivers/pwm/core.c
drivers/pwm/pwm-atmel-hlcdc.c
drivers/pwm/pwm-atmel-tcb.c
drivers/pwm/pwm-atmel.c
drivers/pwm/pwm-bcm-iproc.c
drivers/pwm/pwm-bcm-kona.c
drivers/pwm/pwm-bcm2835.c
drivers/pwm/pwm-berlin.c
drivers/pwm/pwm-clps711x.c
drivers/pwm/pwm-crc.c
drivers/pwm/pwm-ep93xx.c
drivers/pwm/pwm-fsl-ftm.c
drivers/pwm/pwm-hibvt.c
drivers/pwm/pwm-img.c
drivers/pwm/pwm-imx-tpm.c
drivers/pwm/pwm-imx1.c
drivers/pwm/pwm-imx27.c
drivers/pwm/pwm-jz4740.c
drivers/pwm/pwm-lpc18xx-sct.c
drivers/pwm/pwm-lpss-pci.c
drivers/pwm/pwm-lpss-platform.c
drivers/pwm/pwm-lpss.c
drivers/pwm/pwm-lpss.h
drivers/pwm/pwm-meson.c
drivers/pwm/pwm-mxs.c
drivers/pwm/pwm-omap-dmtimer.c
drivers/pwm/pwm-pca9685.c
drivers/pwm/pwm-pxa.c
drivers/pwm/pwm-renesas-tpu.c
drivers/pwm/pwm-rockchip.c
drivers/pwm/pwm-samsung.c
drivers/pwm/pwm-sifive.c
drivers/pwm/pwm-spear.c
drivers/pwm/pwm-sprd.c
drivers/pwm/pwm-stm32-lp.c
drivers/pwm/pwm-stm32.c
drivers/pwm/pwm-sun4i.c
drivers/pwm/pwm-tegra.c
drivers/pwm/pwm-tiecap.c
drivers/pwm/pwm-tiehrpwm.c
drivers/pwm/pwm-visconti.c
drivers/pwm/pwm-vt8500.c
include/linux/pwm.h

diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
deleted file mode 100644 (file)
index c7c4347..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-TI SOC ECAP based APWM controller
-
-Required properties:
-- compatible: Must be "ti,<soc>-ecap".
-  for am33xx - compatible = "ti,am3352-ecap", "ti,am33xx-ecap";
-  for am4372 - compatible = "ti,am4372-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
-  for da850  - compatible = "ti,da850-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
-  for dra746 - compatible = "ti,dra746-ecap", "ti,am3352-ecap";
-  for 66ak2g - compatible = "ti,k2g-ecap", "ti,am3352-ecap";
-  for am654  - compatible = "ti,am654-ecap", "ti,am3352-ecap";
-- #pwm-cells: should be 3. See pwm.yaml in this directory for a description of
-  the cells format. The PWM channel index ranges from 0 to 4. The only third
-  cell flag supported by this binding is PWM_POLARITY_INVERTED.
-- reg: physical base address and size of the registers map.
-
-Optional properties:
-- clocks: Handle to the ECAP's functional clock.
-- clock-names: Must be set to "fck".
-
-Example:
-
-ecap0: ecap@48300100 { /* ECAP on am33xx */
-       compatible = "ti,am3352-ecap", "ti,am33xx-ecap";
-       #pwm-cells = <3>;
-       reg = <0x48300100 0x80>;
-       clocks = <&l4ls_gclk>;
-       clock-names = "fck";
-};
-
-ecap0: ecap@48300100 { /* ECAP on am4372 */
-       compatible = "ti,am4372-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
-       #pwm-cells = <3>;
-       reg = <0x48300100 0x80>;
-       ti,hwmods = "ecap0";
-       clocks = <&l4ls_gclk>;
-       clock-names = "fck";
-};
-
-ecap0: ecap@1f06000 { /* ECAP on da850 */
-       compatible = "ti,da850-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
-       #pwm-cells = <3>;
-       reg = <0x1f06000 0x80>;
-};
-
-ecap0: ecap@4843e100 {
-       compatible = "ti,dra746-ecap", "ti,am3352-ecap";
-       #pwm-cells = <3>;
-       reg = <0x4843e100 0x80>;
-       clocks = <&l4_root_clk_div>;
-       clock-names = "fck";
-};
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.yaml b/Documentation/devicetree/bindings/pwm/pwm-tiecap.yaml
new file mode 100644 (file)
index 0000000..ed35b6c
--- /dev/null
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/pwm-tiecap.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI SOC ECAP based APWM controller
+
+maintainers:
+  - Vignesh R <vigneshr@ti.com>
+
+allOf:
+  - $ref: pwm.yaml#
+
+properties:
+  compatible:
+    oneOf:
+      - const: ti,am3352-ecap
+      - items:
+          - enum:
+              - ti,da850-ecap
+              - ti,am4372-ecap
+              - ti,dra746-ecap
+              - ti,k2g-ecap
+              - ti,am654-ecap
+              - ti,am64-ecap
+          - const: ti,am3352-ecap
+
+  reg:
+    maxItems: 1
+
+  "#pwm-cells":
+    const: 3
+    description: |
+      See pwm.yaml in this directory for a description of the cells format.
+      The only third cell flag supported by this binding is PWM_POLARITY_INVERTED.
+
+  clock-names:
+    const: fck
+
+  clocks:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - "#pwm-cells"
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    ecap0: pwm@48300100 { /* ECAP on am33xx */
+        compatible = "ti,am3352-ecap";
+        #pwm-cells = <3>;
+        reg = <0x48300100 0x80>;
+        clocks = <&l4ls_gclk>;
+        clock-names = "fck";
+    };
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
deleted file mode 100644 (file)
index c7e28f6..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-TI SOC EHRPWM based PWM controller
-
-Required properties:
-- compatible: Must be "ti,<soc>-ehrpwm".
-  for am33xx  - compatible = "ti,am3352-ehrpwm", "ti,am33xx-ehrpwm";
-  for am4372  - compatible = "ti,am4372-ehrpwm", "ti-am3352-ehrpwm", "ti,am33xx-ehrpwm";
-  for am654   - compatible = "ti,am654-ehrpwm", "ti-am3352-ehrpwm";
-  for da850   - compatible = "ti,da850-ehrpwm", "ti-am3352-ehrpwm", "ti,am33xx-ehrpwm";
-  for dra746 - compatible = "ti,dra746-ehrpwm", "ti-am3352-ehrpwm";
-- #pwm-cells: should be 3. See pwm.yaml in this directory for a description of
-  the cells format. The only third cell flag supported by this binding is
-  PWM_POLARITY_INVERTED.
-- reg: physical base address and size of the registers map.
-
-Optional properties:
-- clocks: Handle to the PWM's time-base and functional clock.
-- clock-names: Must be set to "tbclk" and "fck".
-
-Example:
-
-ehrpwm0: pwm@48300200 { /* EHRPWM on am33xx */
-       compatible = "ti,am3352-ehrpwm", "ti,am33xx-ehrpwm";
-       #pwm-cells = <3>;
-       reg = <0x48300200 0x100>;
-       clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>;
-       clock-names = "tbclk", "fck";
-};
-
-ehrpwm0: pwm@48300200 { /* EHRPWM on am4372 */
-       compatible = "ti,am4372-ehrpwm", "ti,am3352-ehrpwm", "ti,am33xx-ehrpwm";
-       #pwm-cells = <3>;
-       reg = <0x48300200 0x80>;
-       clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>;
-       clock-names = "tbclk", "fck";
-       ti,hwmods = "ehrpwm0";
-};
-
-ehrpwm0: pwm@1f00000 { /* EHRPWM on da850 */
-       compatible = "ti,da850-ehrpwm", "ti,am3352-ehrpwm", "ti,am33xx-ehrpwm";
-       #pwm-cells = <3>;
-       reg = <0x1f00000 0x2000>;
-};
-
-ehrpwm0: pwm@4843e200 { /* EHRPWM on dra746 */
-       compatible = "ti,dra746-ehrpwm", "ti,am3352-ehrpwm";
-       #pwm-cells = <3>;
-       reg = <0x4843e200 0x80>;
-       clocks = <&ehrpwm0_tbclk>, <&l4_root_clk_div>;
-       clock-names = "tbclk", "fck";
-};
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.yaml b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.yaml
new file mode 100644 (file)
index 0000000..ee312cb
--- /dev/null
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/pwm-tiehrpwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI SOC EHRPWM based PWM controller
+
+maintainers:
+  - Vignesh R <vigneshr@ti.com>
+
+allOf:
+  - $ref: pwm.yaml#
+
+properties:
+  compatible:
+    oneOf:
+      - const: ti,am3352-ehrpwm
+      - items:
+          - enum:
+              - ti,da850-ehrpwm
+              - ti,am4372-ehrpwm
+              - ti,dra746-ehrpwm
+              - ti,am654-ehrpwm
+              - ti,am64-epwm
+          - const: ti,am3352-ehrpwm
+
+  reg:
+    maxItems: 1
+
+  "#pwm-cells":
+    const: 3
+    description: |
+      See pwm.yaml in this directory for a description of the cells format.
+      The only third cell flag supported by this binding is PWM_POLARITY_INVERTED.
+
+  clock-names:
+    items:
+      - const: tbclk
+      - const: fck
+
+  clocks:
+    maxItems: 2
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - "#pwm-cells"
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    ehrpwm0: pwm@48300200 { /* EHRPWM on am33xx */
+        compatible = "ti,am3352-ehrpwm";
+        #pwm-cells = <3>;
+        reg = <0x48300200 0x100>;
+        clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>;
+        clock-names = "tbclk", "fck";
+    };
index 0fe1fff..6500965 100644 (file)
@@ -400,7 +400,8 @@ POWER
 
 PWM
   devm_pwm_get()
-  devm_pwm_put()
+  devm_of_pwm_get()
+  devm_fwnode_pwm_get()
 
 REGULATOR
   devm_regulator_bulk_get()
index a7ca4f5..ccb06e4 100644 (file)
@@ -40,7 +40,8 @@ after usage with pwm_free().
 
 New users should use the pwm_get() function and pass to it the consumer
 device or a consumer name. pwm_put() is used to free the PWM device. Managed
-variants of these functions, devm_pwm_get() and devm_pwm_put(), also exist.
+variants of the getter, devm_pwm_get(), devm_of_pwm_get(),
+devm_fwnode_pwm_get(), also exist.
 
 After being requested, a PWM has to be configured using::
 
@@ -48,6 +49,10 @@ After being requested, a PWM has to be configured using::
 
 This API controls both the PWM period/duty_cycle config and the
 enable/disable state.
+There is also a usage_power setting: If set, the PWM driver is only required to
+maintain the power output but has more freedom regarding signal form.
+If supported by the driver, the signal can be optimized, for example to improve
+EMI by phase shifting the individual channels of a chip.
 
 The pwm_config(), pwm_enable() and pwm_disable() functions are just wrappers
 around pwm_apply_state() and should not be used if the user wants to change
index 18074eb..74b830b 100644 (file)
@@ -258,6 +258,38 @@ input driver::
                .id_table       = mpu3050_ids,
        };
 
+Reference to PWM device
+=======================
+
+Sometimes a device can be a consumer of PWM channel. Obviously OS would like
+to know which one. To provide this mapping the special property has been
+introduced, i.e.::
+
+    Device (DEV)
+    {
+        Name (_DSD, Package ()
+        {
+            ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+            Package () {
+                Package () { "compatible", Package () { "pwm-leds" } },
+                Package () { "label", "alarm-led" },
+                Package () { "pwms",
+                    Package () {
+                        "\\_SB.PCI0.PWM",  // <PWM device reference>
+                        0,                 // <PWM index>
+                        600000000,         // <PWM period>
+                        0,                 // <PWM flags>
+                    }
+                }
+            }
+
+        })
+        ...
+
+In the above example the PWM-based LED driver references to the PWM channel 0
+of \_SB.PCI0.PWM device with initial period setting equal to 600 ms (note that
+value is given in nanoseconds).
+
 GPIO support
 ============
 
index c4d5c06..35e894f 100644 (file)
@@ -126,8 +126,7 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
 {
        struct pwm_device *pwm;
 
-       /* check, whether the driver supports a third cell for flags */
-       if (pc->of_pwm_n_cells < 3)
+       if (pc->of_pwm_n_cells < 2)
                return ERR_PTR(-EINVAL);
 
        /* flags in the third cell are optional */
@@ -144,46 +143,29 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
        pwm->args.period = args->args[1];
        pwm->args.polarity = PWM_POLARITY_NORMAL;
 
-       if (args->args_count > 2 && args->args[2] & PWM_POLARITY_INVERTED)
-               pwm->args.polarity = PWM_POLARITY_INVERSED;
+       if (pc->of_pwm_n_cells >= 3) {
+               if (args->args_count > 2 && args->args[2] & PWM_POLARITY_INVERTED)
+                       pwm->args.polarity = PWM_POLARITY_INVERSED;
+       }
 
        return pwm;
 }
 EXPORT_SYMBOL_GPL(of_pwm_xlate_with_flags);
 
-static struct pwm_device *
-of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
-{
-       struct pwm_device *pwm;
-
-       /* sanity check driver support */
-       if (pc->of_pwm_n_cells < 2)
-               return ERR_PTR(-EINVAL);
-
-       /* all cells are required */
-       if (args->args_count != pc->of_pwm_n_cells)
-               return ERR_PTR(-EINVAL);
-
-       if (args->args[0] >= pc->npwm)
-               return ERR_PTR(-EINVAL);
-
-       pwm = pwm_request_from_chip(pc, args->args[0], NULL);
-       if (IS_ERR(pwm))
-               return pwm;
-
-       pwm->args.period = args->args[1];
-
-       return pwm;
-}
-
 static void of_pwmchip_add(struct pwm_chip *chip)
 {
        if (!chip->dev || !chip->dev->of_node)
                return;
 
        if (!chip->of_xlate) {
-               chip->of_xlate = of_pwm_simple_xlate;
-               chip->of_pwm_n_cells = 2;
+               u32 pwm_cells;
+
+               if (of_property_read_u32(chip->dev->of_node, "#pwm-cells",
+                                        &pwm_cells))
+                       pwm_cells = 2;
+
+               chip->of_xlate = of_pwm_xlate_with_flags;
+               chip->of_pwm_n_cells = pwm_cells;
        }
 
        of_node_get(chip->dev->of_node);
@@ -324,22 +306,10 @@ EXPORT_SYMBOL_GPL(pwmchip_add);
  */
 int pwmchip_remove(struct pwm_chip *chip)
 {
-       unsigned int i;
-       int ret = 0;
-
        pwmchip_sysfs_unexport(chip);
 
        mutex_lock(&pwm_lock);
 
-       for (i = 0; i < chip->npwm; i++) {
-               struct pwm_device *pwm = &chip->pwms[i];
-
-               if (test_bit(PWMF_REQUESTED, &pwm->flags)) {
-                       ret = -EBUSY;
-                       goto out;
-               }
-       }
-
        list_del_init(&chip->list);
 
        if (IS_ENABLED(CONFIG_OF))
@@ -347,12 +317,31 @@ int pwmchip_remove(struct pwm_chip *chip)
 
        free_pwms(chip);
 
-out:
        mutex_unlock(&pwm_lock);
-       return ret;
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(pwmchip_remove);
 
+static void devm_pwmchip_remove(void *data)
+{
+       struct pwm_chip *chip = data;
+
+       pwmchip_remove(chip);
+}
+
+int devm_pwmchip_add(struct device *dev, struct pwm_chip *chip)
+{
+       int ret;
+
+       ret = pwmchip_add(chip);
+       if (ret)
+               return ret;
+
+       return devm_add_action_or_reset(dev, devm_pwmchip_remove, chip);
+}
+EXPORT_SYMBOL_GPL(devm_pwmchip_add);
+
 /**
  * pwm_request() - request a PWM device
  * @pwm: global PWM device index
@@ -554,7 +543,8 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
        if (state->period == pwm->state.period &&
            state->duty_cycle == pwm->state.duty_cycle &&
            state->polarity == pwm->state.polarity &&
-           state->enabled == pwm->state.enabled)
+           state->enabled == pwm->state.enabled &&
+           state->usage_power == pwm->state.usage_power)
                return 0;
 
        if (chip->ops->apply) {
@@ -709,14 +699,14 @@ int pwm_adjust_config(struct pwm_device *pwm)
 }
 EXPORT_SYMBOL_GPL(pwm_adjust_config);
 
-static struct pwm_chip *of_node_to_pwmchip(struct device_node *np)
+static struct pwm_chip *fwnode_to_pwmchip(struct fwnode_handle *fwnode)
 {
        struct pwm_chip *chip;
 
        mutex_lock(&pwm_lock);
 
        list_for_each_entry(chip, &pwm_chips, list)
-               if (chip->dev && chip->dev->of_node == np) {
+               if (chip->dev && dev_fwnode(chip->dev) == fwnode) {
                        mutex_unlock(&pwm_lock);
                        return chip;
                }
@@ -795,7 +785,7 @@ struct pwm_device *of_pwm_get(struct device *dev, struct device_node *np,
                return ERR_PTR(err);
        }
 
-       pc = of_node_to_pwmchip(args.np);
+       pc = fwnode_to_pwmchip(of_fwnode_handle(args.np));
        if (IS_ERR(pc)) {
                if (PTR_ERR(pc) != -EPROBE_DEFER)
                        pr_err("%s(): PWM chip not found\n", __func__);
@@ -837,31 +827,9 @@ put:
 }
 EXPORT_SYMBOL_GPL(of_pwm_get);
 
-#if IS_ENABLED(CONFIG_ACPI)
-static struct pwm_chip *device_to_pwmchip(struct device *dev)
-{
-       struct pwm_chip *chip;
-
-       mutex_lock(&pwm_lock);
-
-       list_for_each_entry(chip, &pwm_chips, list) {
-               struct acpi_device *adev = ACPI_COMPANION(chip->dev);
-
-               if ((chip->dev == dev) || (adev && &adev->dev == dev)) {
-                       mutex_unlock(&pwm_lock);
-                       return chip;
-               }
-       }
-
-       mutex_unlock(&pwm_lock);
-
-       return ERR_PTR(-EPROBE_DEFER);
-}
-#endif
-
 /**
  * acpi_pwm_get() - request a PWM via parsing "pwms" property in ACPI
- * @fwnode: firmware node to get the "pwm" property from
+ * @fwnode: firmware node to get the "pwms" property from
  *
  * Returns the PWM device parsed from the fwnode and index specified in the
  * "pwms" property or a negative error-code on failure.
@@ -876,12 +844,10 @@ static struct pwm_chip *device_to_pwmchip(struct device *dev)
  * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded
  * error code on failure.
  */
-static struct pwm_device *acpi_pwm_get(struct fwnode_handle *fwnode)
+static struct pwm_device *acpi_pwm_get(const struct fwnode_handle *fwnode)
 {
-       struct pwm_device *pwm = ERR_PTR(-ENODEV);
-#if IS_ENABLED(CONFIG_ACPI)
+       struct pwm_device *pwm;
        struct fwnode_reference_args args;
-       struct acpi_device *acpi;
        struct pwm_chip *chip;
        int ret;
 
@@ -891,14 +857,10 @@ static struct pwm_device *acpi_pwm_get(struct fwnode_handle *fwnode)
        if (ret < 0)
                return ERR_PTR(ret);
 
-       acpi = to_acpi_device_node(args.fwnode);
-       if (!acpi)
-               return ERR_PTR(-EINVAL);
-
        if (args.nargs < 2)
                return ERR_PTR(-EPROTO);
 
-       chip = device_to_pwmchip(&acpi->dev);
+       chip = fwnode_to_pwmchip(args.fwnode);
        if (IS_ERR(chip))
                return ERR_CAST(chip);
 
@@ -911,7 +873,6 @@ static struct pwm_device *acpi_pwm_get(struct fwnode_handle *fwnode)
 
        if (args.nargs > 2 && args.args[2] & PWM_POLARITY_INVERTED)
                pwm->args.polarity = PWM_POLARITY_INVERSED;
-#endif
 
        return pwm;
 }
@@ -967,6 +928,7 @@ void pwm_remove_table(struct pwm_lookup *table, size_t num)
  */
 struct pwm_device *pwm_get(struct device *dev, const char *con_id)
 {
+       const struct fwnode_handle *fwnode = dev ? dev_fwnode(dev) : NULL;
        const char *dev_id = dev ? dev_name(dev) : NULL;
        struct pwm_device *pwm;
        struct pwm_chip *chip;
@@ -977,12 +939,12 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
        int err;
 
        /* look up via DT first */
-       if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
-               return of_pwm_get(dev, dev->of_node, con_id);
+       if (is_of_node(fwnode))
+               return of_pwm_get(dev, to_of_node(fwnode), con_id);
 
        /* then lookup via ACPI */
-       if (dev && is_acpi_node(dev->fwnode)) {
-               pwm = acpi_pwm_get(dev->fwnode);
+       if (is_acpi_node(fwnode)) {
+               pwm = acpi_pwm_get(fwnode);
                if (!IS_ERR(pwm) || PTR_ERR(pwm) != -ENOENT)
                        return pwm;
        }
@@ -1103,9 +1065,9 @@ out:
 }
 EXPORT_SYMBOL_GPL(pwm_put);
 
-static void devm_pwm_release(struct device *dev, void *res)
+static void devm_pwm_release(void *pwm)
 {
-       pwm_put(*(struct pwm_device **)res);
+       pwm_put(pwm);
 }
 
 /**
@@ -1121,19 +1083,16 @@ static void devm_pwm_release(struct device *dev, void *res)
  */
 struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id)
 {
-       struct pwm_device **ptr, *pwm;
-
-       ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return ERR_PTR(-ENOMEM);
+       struct pwm_device *pwm;
+       int ret;
 
        pwm = pwm_get(dev, con_id);
-       if (!IS_ERR(pwm)) {
-               *ptr = pwm;
-               devres_add(dev, ptr);
-       } else {
-               devres_free(ptr);
-       }
+       if (IS_ERR(pwm))
+               return pwm;
+
+       ret = devm_add_action_or_reset(dev, devm_pwm_release, pwm);
+       if (ret)
+               return ERR_PTR(ret);
 
        return pwm;
 }
@@ -1154,19 +1113,16 @@ EXPORT_SYMBOL_GPL(devm_pwm_get);
 struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np,
                                   const char *con_id)
 {
-       struct pwm_device **ptr, *pwm;
-
-       ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return ERR_PTR(-ENOMEM);
+       struct pwm_device *pwm;
+       int ret;
 
        pwm = of_pwm_get(dev, np, con_id);
-       if (!IS_ERR(pwm)) {
-               *ptr = pwm;
-               devres_add(dev, ptr);
-       } else {
-               devres_free(ptr);
-       }
+       if (IS_ERR(pwm))
+               return pwm;
+
+       ret = devm_add_action_or_reset(dev, devm_pwm_release, pwm);
+       if (ret)
+               return ERR_PTR(ret);
 
        return pwm;
 }
@@ -1188,53 +1144,24 @@ struct pwm_device *devm_fwnode_pwm_get(struct device *dev,
                                       struct fwnode_handle *fwnode,
                                       const char *con_id)
 {
-       struct pwm_device **ptr, *pwm = ERR_PTR(-ENODEV);
-
-       ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return ERR_PTR(-ENOMEM);
+       struct pwm_device *pwm = ERR_PTR(-ENODEV);
+       int ret;
 
        if (is_of_node(fwnode))
                pwm = of_pwm_get(dev, to_of_node(fwnode), con_id);
        else if (is_acpi_node(fwnode))
                pwm = acpi_pwm_get(fwnode);
+       if (IS_ERR(pwm))
+               return pwm;
 
-       if (!IS_ERR(pwm)) {
-               *ptr = pwm;
-               devres_add(dev, ptr);
-       } else {
-               devres_free(ptr);
-       }
+       ret = devm_add_action_or_reset(dev, devm_pwm_release, pwm);
+       if (ret)
+               return ERR_PTR(ret);
 
        return pwm;
 }
 EXPORT_SYMBOL_GPL(devm_fwnode_pwm_get);
 
-static int devm_pwm_match(struct device *dev, void *res, void *data)
-{
-       struct pwm_device **p = res;
-
-       if (WARN_ON(!p || !*p))
-               return 0;
-
-       return *p == data;
-}
-
-/**
- * devm_pwm_put() - resource managed pwm_put()
- * @dev: device for PWM consumer
- * @pwm: PWM device
- *
- * Release a PWM previously allocated using devm_pwm_get(). Calling this
- * function is usually not needed because devm-allocated resources are
- * automatically released on driver detach.
- */
-void devm_pwm_put(struct device *dev, struct pwm_device *pwm)
-{
-       WARN_ON(devres_release(dev, devm_pwm_release, devm_pwm_match, pwm));
-}
-EXPORT_SYMBOL_GPL(devm_pwm_put);
-
 #ifdef CONFIG_DEBUG_FS
 static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
 {
@@ -1259,6 +1186,9 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
                seq_printf(s, " polarity: %s",
                           state.polarity ? "inverse" : "normal");
 
+               if (state.usage_power)
+                       seq_puts(s, " usage_power");
+
                seq_puts(s, "\n");
        }
 }
index 6ab597e..4459325 100644 (file)
@@ -266,8 +266,6 @@ static int atmel_hlcdc_pwm_probe(struct platform_device *pdev)
        chip->chip.ops = &atmel_hlcdc_pwm_ops;
        chip->chip.dev = dev;
        chip->chip.npwm = 1;
-       chip->chip.of_xlate = of_pwm_xlate_with_flags;
-       chip->chip.of_pwm_n_cells = 3;
 
        ret = pwmchip_add(&chip->chip);
        if (ret) {
index 8451d3e..bf398f2 100644 (file)
@@ -469,8 +469,6 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
 
        tcbpwm->chip.dev = &pdev->dev;
        tcbpwm->chip.ops = &atmel_tcb_pwm_ops;
-       tcbpwm->chip.of_xlate = of_pwm_xlate_with_flags;
-       tcbpwm->chip.of_pwm_n_cells = 3;
        tcbpwm->chip.npwm = NPWM;
        tcbpwm->channel = channel;
        tcbpwm->regmap = regmap;
index 29b5ad0..a8162ba 100644 (file)
@@ -436,8 +436,6 @@ static int atmel_pwm_probe(struct platform_device *pdev)
 
        atmel_pwm->chip.dev = &pdev->dev;
        atmel_pwm->chip.ops = &atmel_pwm_ops;
-       atmel_pwm->chip.of_xlate = of_pwm_xlate_with_flags;
-       atmel_pwm->chip.of_pwm_n_cells = 3;
        atmel_pwm->chip.npwm = 4;
 
        ret = pwmchip_add(&atmel_pwm->chip);
index edd2ce1..0226bf6 100644 (file)
@@ -210,8 +210,6 @@ static int iproc_pwmc_probe(struct platform_device *pdev)
        ip->chip.dev = &pdev->dev;
        ip->chip.ops = &iproc_pwm_ops;
        ip->chip.npwm = 4;
-       ip->chip.of_xlate = of_pwm_xlate_with_flags;
-       ip->chip.of_pwm_n_cells = 3;
 
        ip->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(ip->base))
index 800b9ed..8c85c66 100644 (file)
@@ -272,8 +272,6 @@ static int kona_pwmc_probe(struct platform_device *pdev)
        kp->chip.dev = &pdev->dev;
        kp->chip.ops = &kona_pwm_ops;
        kp->chip.npwm = 6;
-       kp->chip.of_xlate = of_pwm_xlate_with_flags;
-       kp->chip.of_pwm_n_cells = 3;
 
        kp->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(kp->base))
index fc240d5..50b8594 100644 (file)
@@ -159,8 +159,6 @@ static int bcm2835_pwm_probe(struct platform_device *pdev)
        pc->chip.dev = &pdev->dev;
        pc->chip.ops = &bcm2835_pwm_ops;
        pc->chip.npwm = 2;
-       pc->chip.of_xlate = of_pwm_xlate_with_flags;
-       pc->chip.of_pwm_n_cells = 3;
 
        platform_set_drvdata(pdev, pc);
 
index acb6fbc..5537b5f 100644 (file)
@@ -56,17 +56,17 @@ static inline struct berlin_pwm_chip *to_berlin_pwm_chip(struct pwm_chip *chip)
        return container_of(chip, struct berlin_pwm_chip, chip);
 }
 
-static inline u32 berlin_pwm_readl(struct berlin_pwm_chip *chip,
+static inline u32 berlin_pwm_readl(struct berlin_pwm_chip *bpc,
                                   unsigned int channel, unsigned long offset)
 {
-       return readl_relaxed(chip->base + channel * 0x10 + offset);
+       return readl_relaxed(bpc->base + channel * 0x10 + offset);
 }
 
-static inline void berlin_pwm_writel(struct berlin_pwm_chip *chip,
+static inline void berlin_pwm_writel(struct berlin_pwm_chip *bpc,
                                     unsigned int channel, u32 value,
                                     unsigned long offset)
 {
-       writel_relaxed(value, chip->base + channel * 0x10 + offset);
+       writel_relaxed(value, bpc->base + channel * 0x10 + offset);
 }
 
 static int berlin_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -87,15 +87,15 @@ static void berlin_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
        kfree(channel);
 }
 
-static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev,
-                            int duty_ns, int period_ns)
+static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+                            u64 duty_ns, u64 period_ns)
 {
-       struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
+       struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip);
        bool prescale_4096 = false;
        u32 value, duty, period;
        u64 cycles;
 
-       cycles = clk_get_rate(pwm->clk);
+       cycles = clk_get_rate(bpc->clk);
        cycles *= period_ns;
        do_div(cycles, NSEC_PER_SEC);
 
@@ -112,68 +112,101 @@ static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev,
        do_div(cycles, period_ns);
        duty = cycles;
 
-       value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL);
+       value = berlin_pwm_readl(bpc, pwm->hwpwm, BERLIN_PWM_CONTROL);
        if (prescale_4096)
                value |= BERLIN_PWM_PRESCALE_4096;
        else
                value &= ~BERLIN_PWM_PRESCALE_4096;
-       berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL);
+       berlin_pwm_writel(bpc, pwm->hwpwm, value, BERLIN_PWM_CONTROL);
 
-       berlin_pwm_writel(pwm, pwm_dev->hwpwm, duty, BERLIN_PWM_DUTY);
-       berlin_pwm_writel(pwm, pwm_dev->hwpwm, period, BERLIN_PWM_TCNT);
+       berlin_pwm_writel(bpc, pwm->hwpwm, duty, BERLIN_PWM_DUTY);
+       berlin_pwm_writel(bpc, pwm->hwpwm, period, BERLIN_PWM_TCNT);
 
        return 0;
 }
 
 static int berlin_pwm_set_polarity(struct pwm_chip *chip,
-                                  struct pwm_device *pwm_dev,
+                                  struct pwm_device *pwm,
                                   enum pwm_polarity polarity)
 {
-       struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
+       struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip);
        u32 value;
 
-       value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL);
+       value = berlin_pwm_readl(bpc, pwm->hwpwm, BERLIN_PWM_CONTROL);
 
        if (polarity == PWM_POLARITY_NORMAL)
                value &= ~BERLIN_PWM_INVERT_POLARITY;
        else
                value |= BERLIN_PWM_INVERT_POLARITY;
 
-       berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL);
+       berlin_pwm_writel(bpc, pwm->hwpwm, value, BERLIN_PWM_CONTROL);
 
        return 0;
 }
 
-static int berlin_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm_dev)
+static int berlin_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
-       struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
+       struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip);
        u32 value;
 
-       value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN);
+       value = berlin_pwm_readl(bpc, pwm->hwpwm, BERLIN_PWM_EN);
        value |= BERLIN_PWM_ENABLE;
-       berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_EN);
+       berlin_pwm_writel(bpc, pwm->hwpwm, value, BERLIN_PWM_EN);
 
        return 0;
 }
 
 static void berlin_pwm_disable(struct pwm_chip *chip,
-                              struct pwm_device *pwm_dev)
+                              struct pwm_device *pwm)
 {
-       struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
+       struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip);
        u32 value;
 
-       value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN);
+       value = berlin_pwm_readl(bpc, pwm->hwpwm, BERLIN_PWM_EN);
        value &= ~BERLIN_PWM_ENABLE;
-       berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_EN);
+       berlin_pwm_writel(bpc, pwm->hwpwm, value, BERLIN_PWM_EN);
+}
+
+static int berlin_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+                           const struct pwm_state *state)
+{
+       int err;
+       bool enabled = pwm->state.enabled;
+
+       if (state->polarity != pwm->state.polarity) {
+               if (enabled) {
+                       berlin_pwm_disable(chip, pwm);
+                       enabled = false;
+               }
+
+               err = berlin_pwm_set_polarity(chip, pwm, state->polarity);
+               if (err)
+                       return err;
+       }
+
+       if (!state->enabled) {
+               if (enabled)
+                       berlin_pwm_disable(chip, pwm);
+               return 0;
+       }
+
+       if (state->period != pwm->state.period ||
+           state->duty_cycle != pwm->state.duty_cycle) {
+               err = berlin_pwm_config(chip, pwm, state->duty_cycle, state->period);
+               if (err)
+                       return err;
+       }
+
+       if (!enabled)
+               return berlin_pwm_enable(chip, pwm);
+
+       return 0;
 }
 
 static const struct pwm_ops berlin_pwm_ops = {
        .request = berlin_pwm_request,
        .free = berlin_pwm_free,
-       .config = berlin_pwm_config,
-       .set_polarity = berlin_pwm_set_polarity,
-       .enable = berlin_pwm_enable,
-       .disable = berlin_pwm_disable,
+       .apply = berlin_pwm_apply,
        .owner = THIS_MODULE,
 };
 
@@ -185,99 +218,97 @@ MODULE_DEVICE_TABLE(of, berlin_pwm_match);
 
 static int berlin_pwm_probe(struct platform_device *pdev)
 {
-       struct berlin_pwm_chip *pwm;
+       struct berlin_pwm_chip *bpc;
        int ret;
 
-       pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
-       if (!pwm)
+       bpc = devm_kzalloc(&pdev->dev, sizeof(*bpc), GFP_KERNEL);
+       if (!bpc)
                return -ENOMEM;
 
-       pwm->base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(pwm->base))
-               return PTR_ERR(pwm->base);
+       bpc->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(bpc->base))
+               return PTR_ERR(bpc->base);
 
-       pwm->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(pwm->clk))
-               return PTR_ERR(pwm->clk);
+       bpc->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(bpc->clk))
+               return PTR_ERR(bpc->clk);
 
-       ret = clk_prepare_enable(pwm->clk);
+       ret = clk_prepare_enable(bpc->clk);
        if (ret)
                return ret;
 
-       pwm->chip.dev = &pdev->dev;
-       pwm->chip.ops = &berlin_pwm_ops;
-       pwm->chip.npwm = 4;
-       pwm->chip.of_xlate = of_pwm_xlate_with_flags;
-       pwm->chip.of_pwm_n_cells = 3;
+       bpc->chip.dev = &pdev->dev;
+       bpc->chip.ops = &berlin_pwm_ops;
+       bpc->chip.npwm = 4;
 
-       ret = pwmchip_add(&pwm->chip);
+       ret = pwmchip_add(&bpc->chip);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
-               clk_disable_unprepare(pwm->clk);
+               clk_disable_unprepare(bpc->clk);
                return ret;
        }
 
-       platform_set_drvdata(pdev, pwm);
+       platform_set_drvdata(pdev, bpc);
 
        return 0;
 }
 
 static int berlin_pwm_remove(struct platform_device *pdev)
 {
-       struct berlin_pwm_chip *pwm = platform_get_drvdata(pdev);
-       int ret;
+       struct berlin_pwm_chip *bpc = platform_get_drvdata(pdev);
+
+       pwmchip_remove(&bpc->chip);
 
-       ret = pwmchip_remove(&pwm->chip);
-       clk_disable_unprepare(pwm->clk);
+       clk_disable_unprepare(bpc->clk);
 
-       return ret;
+       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
 static int berlin_pwm_suspend(struct device *dev)
 {
-       struct berlin_pwm_chip *pwm = dev_get_drvdata(dev);
+       struct berlin_pwm_chip *bpc = dev_get_drvdata(dev);
        unsigned int i;
 
-       for (i = 0; i < pwm->chip.npwm; i++) {
+       for (i = 0; i < bpc->chip.npwm; i++) {
                struct berlin_pwm_channel *channel;
 
-               channel = pwm_get_chip_data(&pwm->chip.pwms[i]);
+               channel = pwm_get_chip_data(&bpc->chip.pwms[i]);
                if (!channel)
                        continue;
 
-               channel->enable = berlin_pwm_readl(pwm, i, BERLIN_PWM_ENABLE);
-               channel->ctrl = berlin_pwm_readl(pwm, i, BERLIN_PWM_CONTROL);
-               channel->duty = berlin_pwm_readl(pwm, i, BERLIN_PWM_DUTY);
-               channel->tcnt = berlin_pwm_readl(pwm, i, BERLIN_PWM_TCNT);
+               channel->enable = berlin_pwm_readl(bpc, i, BERLIN_PWM_ENABLE);
+               channel->ctrl = berlin_pwm_readl(bpc, i, BERLIN_PWM_CONTROL);
+               channel->duty = berlin_pwm_readl(bpc, i, BERLIN_PWM_DUTY);
+               channel->tcnt = berlin_pwm_readl(bpc, i, BERLIN_PWM_TCNT);
        }
 
-       clk_disable_unprepare(pwm->clk);
+       clk_disable_unprepare(bpc->clk);
 
        return 0;
 }
 
 static int berlin_pwm_resume(struct device *dev)
 {
-       struct berlin_pwm_chip *pwm = dev_get_drvdata(dev);
+       struct berlin_pwm_chip *bpc = dev_get_drvdata(dev);
        unsigned int i;
        int ret;
 
-       ret = clk_prepare_enable(pwm->clk);
+       ret = clk_prepare_enable(bpc->clk);
        if (ret)
                return ret;
 
-       for (i = 0; i < pwm->chip.npwm; i++) {
+       for (i = 0; i < bpc->chip.npwm; i++) {
                struct berlin_pwm_channel *channel;
 
-               channel = pwm_get_chip_data(&pwm->chip.pwms[i]);
+               channel = pwm_get_chip_data(&bpc->chip.pwms[i]);
                if (!channel)
                        continue;
 
-               berlin_pwm_writel(pwm, i, channel->ctrl, BERLIN_PWM_CONTROL);
-               berlin_pwm_writel(pwm, i, channel->duty, BERLIN_PWM_DUTY);
-               berlin_pwm_writel(pwm, i, channel->tcnt, BERLIN_PWM_TCNT);
-               berlin_pwm_writel(pwm, i, channel->enable, BERLIN_PWM_ENABLE);
+               berlin_pwm_writel(bpc, i, channel->ctrl, BERLIN_PWM_CONTROL);
+               berlin_pwm_writel(bpc, i, channel->duty, BERLIN_PWM_DUTY);
+               berlin_pwm_writel(bpc, i, channel->tcnt, BERLIN_PWM_TCNT);
+               berlin_pwm_writel(bpc, i, channel->enable, BERLIN_PWM_ENABLE);
        }
 
        return 0;
index f3d17a5..d7ad886 100644 (file)
@@ -134,16 +134,7 @@ static int clps711x_pwm_probe(struct platform_device *pdev)
 
        spin_lock_init(&priv->lock);
 
-       platform_set_drvdata(pdev, priv);
-
-       return pwmchip_add(&priv->chip);
-}
-
-static int clps711x_pwm_remove(struct platform_device *pdev)
-{
-       struct clps711x_chip *priv = platform_get_drvdata(pdev);
-
-       return pwmchip_remove(&priv->chip);
+       return devm_pwmchip_add(&pdev->dev, &priv->chip);
 }
 
 static const struct of_device_id __maybe_unused clps711x_pwm_dt_ids[] = {
@@ -158,7 +149,6 @@ static struct platform_driver clps711x_pwm_driver = {
                .of_match_table = of_match_ptr(clps711x_pwm_dt_ids),
        },
        .probe = clps711x_pwm_probe,
-       .remove = clps711x_pwm_remove,
 };
 module_platform_driver(clps711x_pwm_driver);
 
index 02522a9..7b357d1 100644 (file)
@@ -173,21 +173,11 @@ static int crystalcove_pwm_probe(struct platform_device *pdev)
        /* get the PMIC regmap */
        pwm->regmap = pmic->regmap;
 
-       platform_set_drvdata(pdev, pwm);
-
-       return pwmchip_add(&pwm->chip);
-}
-
-static int crystalcove_pwm_remove(struct platform_device *pdev)
-{
-       struct crystalcove_pwm *pwm = platform_get_drvdata(pdev);
-
-       return pwmchip_remove(&pwm->chip);
+       return devm_pwmchip_add(&pdev->dev, &pwm->chip);
 }
 
 static struct platform_driver crystalcove_pwm_driver = {
        .probe = crystalcove_pwm_probe,
-       .remove = crystalcove_pwm_remove,
        .driver = {
                .name = "crystal_cove_pwm",
        },
index 4ca7079..8a3d781 100644 (file)
@@ -58,111 +58,112 @@ static void ep93xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
        ep93xx_pwm_release_gpio(pdev);
 }
 
-static int ep93xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-                            int duty_ns, int period_ns)
+static int ep93xx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+                           const struct pwm_state *state)
 {
+       int ret;
        struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
-       void __iomem *base = ep93xx_pwm->base;
-       unsigned long long c;
-       unsigned long period_cycles;
-       unsigned long duty_cycles;
-       unsigned long term;
-       int ret = 0;
-
-       /*
-        * The clock needs to be enabled to access the PWM registers.
-        * Configuration can be changed at any time.
-        */
-       if (!pwm_is_enabled(pwm)) {
-               ret = clk_enable(ep93xx_pwm->clk);
-               if (ret)
-                       return ret;
-       }
+       bool enabled = state->enabled;
 
-       c = clk_get_rate(ep93xx_pwm->clk);
-       c *= period_ns;
-       do_div(c, 1000000000);
-       period_cycles = c;
+       if (state->polarity != pwm->state.polarity) {
+               if (enabled) {
+                       writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE);
+                       clk_disable_unprepare(ep93xx_pwm->clk);
+                       enabled = false;
+               }
 
-       c = period_cycles;
-       c *= duty_ns;
-       do_div(c, period_ns);
-       duty_cycles = c;
+               /*
+                * The clock needs to be enabled to access the PWM registers.
+                * Polarity can only be changed when the PWM is disabled.
+                */
+               ret = clk_prepare_enable(ep93xx_pwm->clk);
+               if (ret)
+                       return ret;
 
-       if (period_cycles < 0x10000 && duty_cycles < 0x10000) {
-               term = readw(base + EP93XX_PWMx_TERM_COUNT);
+               if (state->polarity == PWM_POLARITY_INVERSED)
+                       writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_INVERT);
+               else
+                       writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_INVERT);
 
-               /* Order is important if PWM is running */
-               if (period_cycles > term) {
-                       writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT);
-                       writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE);
-               } else {
-                       writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE);
-                       writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT);
-               }
-       } else {
-               ret = -EINVAL;
+               clk_disable_unprepare(ep93xx_pwm->clk);
        }
 
-       if (!pwm_is_enabled(pwm))
-               clk_disable(ep93xx_pwm->clk);
-
-       return ret;
-}
-
-static int ep93xx_pwm_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
-                              enum pwm_polarity polarity)
-{
-       struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
-       int ret;
+       if (!state->enabled) {
+               if (enabled) {
+                       writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE);
+                       clk_disable_unprepare(ep93xx_pwm->clk);
+               }
 
-       /*
-        * The clock needs to be enabled to access the PWM registers.
-        * Polarity can only be changed when the PWM is disabled.
-        */
-       ret = clk_enable(ep93xx_pwm->clk);
-       if (ret)
-               return ret;
+               return 0;
+       }
 
-       if (polarity == PWM_POLARITY_INVERSED)
-               writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_INVERT);
-       else
-               writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_INVERT);
+       if (state->period != pwm->state.period ||
+           state->duty_cycle != pwm->state.duty_cycle) {
+               struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
+               void __iomem *base = ep93xx_pwm->base;
+               unsigned long long c;
+               unsigned long period_cycles;
+               unsigned long duty_cycles;
+               unsigned long term;
+
+               /*
+                * The clock needs to be enabled to access the PWM registers.
+                * Configuration can be changed at any time.
+                */
+               if (!pwm_is_enabled(pwm)) {
+                       ret = clk_prepare_enable(ep93xx_pwm->clk);
+                       if (ret)
+                               return ret;
+               }
 
-       clk_disable(ep93xx_pwm->clk);
+               c = clk_get_rate(ep93xx_pwm->clk);
+               c *= state->period;
+               do_div(c, 1000000000);
+               period_cycles = c;
+
+               c = period_cycles;
+               c *= state->duty_cycle;
+               do_div(c, state->period);
+               duty_cycles = c;
+
+               if (period_cycles < 0x10000 && duty_cycles < 0x10000) {
+                       term = readw(base + EP93XX_PWMx_TERM_COUNT);
+
+                       /* Order is important if PWM is running */
+                       if (period_cycles > term) {
+                               writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT);
+                               writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE);
+                       } else {
+                               writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE);
+                               writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT);
+                       }
+                       ret = 0;
+               } else {
+                       ret = -EINVAL;
+               }
 
-       return 0;
-}
+               if (!pwm_is_enabled(pwm))
+                       clk_disable_unprepare(ep93xx_pwm->clk);
 
-static int ep93xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
-       struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
-       int ret;
+               if (ret)
+                       return ret;
+       }
 
-       ret = clk_enable(ep93xx_pwm->clk);
-       if (ret)
-               return ret;
+       if (!enabled) {
+               ret = clk_prepare_enable(ep93xx_pwm->clk);
+               if (ret)
+                       return ret;
 
-       writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_ENABLE);
+               writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_ENABLE);
+       }
 
        return 0;
 }
 
-static void ep93xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
-       struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
-
-       writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE);
-       clk_disable(ep93xx_pwm->clk);
-}
-
 static const struct pwm_ops ep93xx_pwm_ops = {
        .request = ep93xx_pwm_request,
        .free = ep93xx_pwm_free,
-       .config = ep93xx_pwm_config,
-       .set_polarity = ep93xx_pwm_polarity,
-       .enable = ep93xx_pwm_enable,
-       .disable = ep93xx_pwm_disable,
+       .apply = ep93xx_pwm_apply,
        .owner = THIS_MODULE,
 };
 
index 0e1ae94..96ccd77 100644 (file)
@@ -451,8 +451,6 @@ static int fsl_pwm_probe(struct platform_device *pdev)
 
 
        fpc->chip.ops = &fsl_pwm_ops;
-       fpc->chip.of_xlate = of_pwm_xlate_with_flags;
-       fpc->chip.of_pwm_n_cells = 3;
        fpc->chip.npwm = 8;
 
        ret = pwmchip_add(&fpc->chip);
index 82d17fc..4a6e9ad 100644 (file)
@@ -206,8 +206,6 @@ static int hibvt_pwm_probe(struct platform_device *pdev)
        pwm_chip->chip.ops = &hibvt_pwm_ops;
        pwm_chip->chip.dev = &pdev->dev;
        pwm_chip->chip.npwm = soc->num_pwms;
-       pwm_chip->chip.of_xlate = of_pwm_xlate_with_flags;
-       pwm_chip->chip.of_pwm_n_cells = 3;
        pwm_chip->soc = soc;
 
        pwm_chip->base = devm_platform_ioremap_resource(pdev, 0);
index cc37054..11b16ec 100644 (file)
@@ -156,7 +156,7 @@ static int img_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
        struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip);
        int ret;
 
-       ret = pm_runtime_get_sync(chip->dev);
+       ret = pm_runtime_resume_and_get(chip->dev);
        if (ret < 0)
                return ret;
 
index 97c9133..dbb5049 100644 (file)
@@ -363,8 +363,6 @@ static int pwm_imx_tpm_probe(struct platform_device *pdev)
 
        tpm->chip.dev = &pdev->dev;
        tpm->chip.ops = &imx_tpm_pwm_ops;
-       tpm->chip.of_xlate = of_pwm_xlate_with_flags;
-       tpm->chip.of_pwm_n_cells = 3;
 
        /* get number of channels */
        val = readl(tpm->base + PWM_IMX_TPM_PARAM);
index c957b36..bcd8494 100644 (file)
@@ -141,8 +141,6 @@ static int pwm_imx1_probe(struct platform_device *pdev)
        if (!imx)
                return -ENOMEM;
 
-       platform_set_drvdata(pdev, imx);
-
        imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
        if (IS_ERR(imx->clk_ipg))
                return dev_err_probe(&pdev->dev, PTR_ERR(imx->clk_ipg),
@@ -161,16 +159,7 @@ static int pwm_imx1_probe(struct platform_device *pdev)
        if (IS_ERR(imx->mmio_base))
                return PTR_ERR(imx->mmio_base);
 
-       return pwmchip_add(&imx->chip);
-}
-
-static int pwm_imx1_remove(struct platform_device *pdev)
-{
-       struct pwm_imx1_chip *imx = platform_get_drvdata(pdev);
-
-       pwm_imx1_clk_disable_unprepare(&imx->chip);
-
-       return pwmchip_remove(&imx->chip);
+       return devm_pwmchip_add(&pdev->dev, &imx->chip);
 }
 
 static struct platform_driver pwm_imx1_driver = {
@@ -179,7 +168,6 @@ static struct platform_driver pwm_imx1_driver = {
                .of_match_table = pwm_imx1_dt_ids,
        },
        .probe = pwm_imx1_probe,
-       .remove = pwm_imx1_remove,
 };
 module_platform_driver(pwm_imx1_driver);
 
index ba69511..f6588a9 100644 (file)
@@ -329,9 +329,6 @@ static int pwm_imx27_probe(struct platform_device *pdev)
        imx->chip.dev = &pdev->dev;
        imx->chip.npwm = 1;
 
-       imx->chip.of_xlate = of_pwm_xlate_with_flags;
-       imx->chip.of_pwm_n_cells = 3;
-
        imx->mmio_base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(imx->mmio_base))
                return PTR_ERR(imx->mmio_base);
index 5b6bdcd..990e790 100644 (file)
@@ -244,8 +244,6 @@ static int jz4740_pwm_probe(struct platform_device *pdev)
        jz4740->chip.dev = dev;
        jz4740->chip.ops = &jz4740_pwm_ops;
        jz4740->chip.npwm = info->num_pwms;
-       jz4740->chip.of_xlate = of_pwm_xlate_with_flags;
-       jz4740->chip.of_pwm_n_cells = 3;
 
        platform_set_drvdata(pdev, jz4740);
 
index b643ac6..8e461f3 100644 (file)
@@ -371,8 +371,6 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev)
        lpc18xx_pwm->chip.dev = &pdev->dev;
        lpc18xx_pwm->chip.ops = &lpc18xx_pwm_ops;
        lpc18xx_pwm->chip.npwm = 16;
-       lpc18xx_pwm->chip.of_xlate = of_pwm_xlate_with_flags;
-       lpc18xx_pwm->chip.of_pwm_n_cells = 3;
 
        /* SCT counter must be in unify (32 bit) mode */
        lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG,
index cf749ea..c893ec3 100644 (file)
@@ -69,12 +69,8 @@ static int pwm_lpss_probe_pci(struct pci_dev *pdev,
 
 static void pwm_lpss_remove_pci(struct pci_dev *pdev)
 {
-       struct pwm_lpss_chip *lpwm = pci_get_drvdata(pdev);
-
        pm_runtime_forbid(&pdev->dev);
        pm_runtime_get_sync(&pdev->dev);
-
-       pwm_lpss_remove(lpwm);
 }
 
 #ifdef CONFIG_PM
index 986786b..9285704 100644 (file)
@@ -85,10 +85,8 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev)
 
 static int pwm_lpss_remove_platform(struct platform_device *pdev)
 {
-       struct pwm_lpss_chip *lpwm = platform_get_drvdata(pdev);
-
        pm_runtime_disable(&pdev->dev);
-       return pwm_lpss_remove(lpwm);
+       return 0;
 }
 
 static const struct acpi_device_id pwm_lpss_acpi_match[] = {
index 58b4031..36d4e83 100644 (file)
@@ -236,7 +236,7 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
        lpwm->chip.ops = &pwm_lpss_ops;
        lpwm->chip.npwm = info->npwm;
 
-       ret = pwmchip_add(&lpwm->chip);
+       ret = devm_pwmchip_add(dev, &lpwm->chip);
        if (ret) {
                dev_err(dev, "failed to add PWM chip: %d\n", ret);
                return ERR_PTR(ret);
@@ -252,12 +252,6 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
 }
 EXPORT_SYMBOL_GPL(pwm_lpss_probe);
 
-int pwm_lpss_remove(struct pwm_lpss_chip *lpwm)
-{
-       return pwmchip_remove(&lpwm->chip);
-}
-EXPORT_SYMBOL_GPL(pwm_lpss_remove);
-
 MODULE_DESCRIPTION("PWM driver for Intel LPSS");
 MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
 MODULE_LICENSE("GPL v2");
index 70db7e3..8b3476f 100644 (file)
@@ -35,6 +35,5 @@ struct pwm_lpss_boardinfo {
 
 struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
                                     const struct pwm_lpss_boardinfo *info);
-int pwm_lpss_remove(struct pwm_lpss_chip *lpwm);
 
 #endif /* __PWM_LPSS_H */
index 9eb0606..3cf3bcf 100644 (file)
@@ -551,8 +551,6 @@ static int meson_pwm_probe(struct platform_device *pdev)
        meson->chip.dev = &pdev->dev;
        meson->chip.ops = &meson_pwm_ops;
        meson->chip.npwm = MESON_NUM_PWMS;
-       meson->chip.of_xlate = of_pwm_xlate_with_flags;
-       meson->chip.of_pwm_n_cells = 3;
 
        meson->data = of_device_get_match_data(&pdev->dev);
 
@@ -560,31 +558,21 @@ static int meson_pwm_probe(struct platform_device *pdev)
        if (err < 0)
                return err;
 
-       err = pwmchip_add(&meson->chip);
+       err = devm_pwmchip_add(&pdev->dev, &meson->chip);
        if (err < 0) {
                dev_err(&pdev->dev, "failed to register PWM chip: %d\n", err);
                return err;
        }
 
-       platform_set_drvdata(pdev, meson);
-
        return 0;
 }
 
-static int meson_pwm_remove(struct platform_device *pdev)
-{
-       struct meson_pwm *meson = platform_get_drvdata(pdev);
-
-       return pwmchip_remove(&meson->chip);
-}
-
 static struct platform_driver meson_pwm_driver = {
        .driver = {
                .name = "meson-pwm",
                .of_match_table = meson_pwm_matches,
        },
        .probe = meson_pwm_probe,
-       .remove = meson_pwm_remove,
 };
 module_platform_driver(meson_pwm_driver);
 
index 0266e84..a221808 100644 (file)
@@ -138,8 +138,6 @@ static int mxs_pwm_probe(struct platform_device *pdev)
 
        mxs->chip.dev = &pdev->dev;
        mxs->chip.ops = &mxs_pwm_ops;
-       mxs->chip.of_xlate = of_pwm_xlate_with_flags;
-       mxs->chip.of_pwm_n_cells = 3;
 
        ret = of_property_read_u32(np, "fsl,pwm-number", &mxs->chip.npwm);
        if (ret < 0) {
index 612b3c8..507a2d9 100644 (file)
@@ -404,8 +404,6 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
        omap->chip.dev = &pdev->dev;
        omap->chip.ops = &pwm_omap_dmtimer_ops;
        omap->chip.npwm = 1;
-       omap->chip.of_xlate = of_pwm_xlate_with_flags;
-       omap->chip.of_pwm_n_cells = 3;
 
        mutex_init(&omap->mutex);
 
index 7c9f174..42ed770 100644 (file)
 #include <linux/bitmap.h>
 
 /*
- * Because the PCA9685 has only one prescaler per chip, changing the period of
- * one channel affects the period of all 16 PWM outputs!
- * However, the ratio between each configured duty cycle and the chip-wide
- * period remains constant, because the OFF time is set in proportion to the
- * counter range.
+ * Because the PCA9685 has only one prescaler per chip, only the first channel
+ * that is enabled is allowed to change the prescale register.
+ * PWM channels requested afterwards must use a period that results in the same
+ * prescale setting as the one set by the first requested channel.
+ * GPIOs do not count as enabled PWMs as they are not using the prescaler.
  */
 
 #define PCA9685_MODE1          0x00
@@ -78,8 +78,9 @@
 struct pca9685 {
        struct pwm_chip chip;
        struct regmap *regmap;
-#if IS_ENABLED(CONFIG_GPIOLIB)
        struct mutex lock;
+       DECLARE_BITMAP(pwms_enabled, PCA9685_MAXCHAN + 1);
+#if IS_ENABLED(CONFIG_GPIOLIB)
        struct gpio_chip gpio;
        DECLARE_BITMAP(pwms_inuse, PCA9685_MAXCHAN + 1);
 #endif
@@ -90,51 +91,120 @@ static inline struct pca9685 *to_pca(struct pwm_chip *chip)
        return container_of(chip, struct pca9685, chip);
 }
 
+/* This function is supposed to be called with the lock mutex held */
+static bool pca9685_prescaler_can_change(struct pca9685 *pca, int channel)
+{
+       /* No PWM enabled: Change allowed */
+       if (bitmap_empty(pca->pwms_enabled, PCA9685_MAXCHAN + 1))
+               return true;
+       /* More than one PWM enabled: Change not allowed */
+       if (bitmap_weight(pca->pwms_enabled, PCA9685_MAXCHAN + 1) > 1)
+               return false;
+       /*
+        * Only one PWM enabled: Change allowed if the PWM about to
+        * be changed is the one that is already enabled
+        */
+       return test_bit(channel, pca->pwms_enabled);
+}
+
+static int pca9685_read_reg(struct pca9685 *pca, unsigned int reg, unsigned int *val)
+{
+       struct device *dev = pca->chip.dev;
+       int err;
+
+       err = regmap_read(pca->regmap, reg, val);
+       if (err)
+               dev_err(dev, "regmap_read of register 0x%x failed: %pe\n", reg, ERR_PTR(err));
+
+       return err;
+}
+
+static int pca9685_write_reg(struct pca9685 *pca, unsigned int reg, unsigned int val)
+{
+       struct device *dev = pca->chip.dev;
+       int err;
+
+       err = regmap_write(pca->regmap, reg, val);
+       if (err)
+               dev_err(dev, "regmap_write to register 0x%x failed: %pe\n", reg, ERR_PTR(err));
+
+       return err;
+}
+
 /* Helper function to set the duty cycle ratio to duty/4096 (e.g. duty=2048 -> 50%) */
 static void pca9685_pwm_set_duty(struct pca9685 *pca, int channel, unsigned int duty)
 {
+       struct pwm_device *pwm = &pca->chip.pwms[channel];
+       unsigned int on, off;
+
        if (duty == 0) {
                /* Set the full OFF bit, which has the highest precedence */
-               regmap_write(pca->regmap, REG_OFF_H(channel), LED_FULL);
+               pca9685_write_reg(pca, REG_OFF_H(channel), LED_FULL);
+               return;
        } else if (duty >= PCA9685_COUNTER_RANGE) {
                /* Set the full ON bit and clear the full OFF bit */
-               regmap_write(pca->regmap, REG_ON_H(channel), LED_FULL);
-               regmap_write(pca->regmap, REG_OFF_H(channel), 0);
-       } else {
-               /* Set OFF time (clears the full OFF bit) */
-               regmap_write(pca->regmap, REG_OFF_L(channel), duty & 0xff);
-               regmap_write(pca->regmap, REG_OFF_H(channel), (duty >> 8) & 0xf);
-               /* Clear the full ON bit */
-               regmap_write(pca->regmap, REG_ON_H(channel), 0);
+               pca9685_write_reg(pca, REG_ON_H(channel), LED_FULL);
+               pca9685_write_reg(pca, REG_OFF_H(channel), 0);
+               return;
        }
+
+
+       if (pwm->state.usage_power && channel < PCA9685_MAXCHAN) {
+               /*
+                * If usage_power is set, the pca9685 driver will phase shift
+                * the individual channels relative to their channel number.
+                * This improves EMI because the enabled channels no longer
+                * turn on at the same time, while still maintaining the
+                * configured duty cycle / power output.
+                */
+               on = channel * PCA9685_COUNTER_RANGE / PCA9685_MAXCHAN;
+       } else
+               on = 0;
+
+       off = (on + duty) % PCA9685_COUNTER_RANGE;
+
+       /* Set ON time (clears full ON bit) */
+       pca9685_write_reg(pca, REG_ON_L(channel), on & 0xff);
+       pca9685_write_reg(pca, REG_ON_H(channel), (on >> 8) & 0xf);
+       /* Set OFF time (clears full OFF bit) */
+       pca9685_write_reg(pca, REG_OFF_L(channel), off & 0xff);
+       pca9685_write_reg(pca, REG_OFF_H(channel), (off >> 8) & 0xf);
 }
 
 static unsigned int pca9685_pwm_get_duty(struct pca9685 *pca, int channel)
 {
-       unsigned int off_h = 0, val = 0;
+       struct pwm_device *pwm = &pca->chip.pwms[channel];
+       unsigned int off = 0, on = 0, val = 0;
 
        if (WARN_ON(channel >= PCA9685_MAXCHAN)) {
                /* HW does not support reading state of "all LEDs" channel */
                return 0;
        }
 
-       regmap_read(pca->regmap, LED_N_OFF_H(channel), &off_h);
-       if (off_h & LED_FULL) {
+       pca9685_read_reg(pca, LED_N_OFF_H(channel), &off);
+       if (off & LED_FULL) {
                /* Full OFF bit is set */
                return 0;
        }
 
-       regmap_read(pca->regmap, LED_N_ON_H(channel), &val);
-       if (val & LED_FULL) {
+       pca9685_read_reg(pca, LED_N_ON_H(channel), &on);
+       if (on & LED_FULL) {
                /* Full ON bit is set */
                return PCA9685_COUNTER_RANGE;
        }
 
-       if (regmap_read(pca->regmap, LED_N_OFF_L(channel), &val)) {
-               /* Reset val to 0 in case reading LED_N_OFF_L failed */
+       pca9685_read_reg(pca, LED_N_OFF_L(channel), &val);
+       off = ((off & 0xf) << 8) | (val & 0xff);
+       if (!pwm->state.usage_power)
+               return off;
+
+       /* Read ON register to calculate duty cycle of staggered output */
+       if (pca9685_read_reg(pca, LED_N_ON_L(channel), &val)) {
+               /* Reset val to 0 in case reading LED_N_ON_L failed */
                val = 0;
        }
-       return ((off_h & 0xf) << 8) | (val & 0xff);
+       on = ((on & 0xf) << 8) | (val & 0xff);
+       return (off - on) & (PCA9685_COUNTER_RANGE - 1);
 }
 
 #if IS_ENABLED(CONFIG_GPIOLIB)
@@ -240,8 +310,6 @@ static int pca9685_pwm_gpio_probe(struct pca9685 *pca)
 {
        struct device *dev = pca->chip.dev;
 
-       mutex_init(&pca->lock);
-
        pca->gpio.label = dev_name(dev);
        pca->gpio.parent = dev;
        pca->gpio.request = pca9685_pwm_gpio_request;
@@ -277,16 +345,23 @@ static inline int pca9685_pwm_gpio_probe(struct pca9685 *pca)
 
 static void pca9685_set_sleep_mode(struct pca9685 *pca, bool enable)
 {
-       regmap_update_bits(pca->regmap, PCA9685_MODE1,
-                          MODE1_SLEEP, enable ? MODE1_SLEEP : 0);
+       struct device *dev = pca->chip.dev;
+       int err = regmap_update_bits(pca->regmap, PCA9685_MODE1,
+                                    MODE1_SLEEP, enable ? MODE1_SLEEP : 0);
+       if (err) {
+               dev_err(dev, "regmap_update_bits of register 0x%x failed: %pe\n",
+                       PCA9685_MODE1, ERR_PTR(err));
+               return;
+       }
+
        if (!enable) {
                /* Wait 500us for the oscillator to be back up */
                udelay(500);
        }
 }
 
-static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                            const struct pwm_state *state)
+static int __pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+                              const struct pwm_state *state)
 {
        struct pca9685 *pca = to_pca(chip);
        unsigned long long duty, prescale;
@@ -307,8 +382,14 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
                return 0;
        }
 
-       regmap_read(pca->regmap, PCA9685_PRESCALE, &val);
+       pca9685_read_reg(pca, PCA9685_PRESCALE, &val);
        if (prescale != val) {
+               if (!pca9685_prescaler_can_change(pca, pwm->hwpwm)) {
+                       dev_err(chip->dev,
+                               "pwm not changed: periods of enabled pwms must match!\n");
+                       return -EBUSY;
+               }
+
                /*
                 * Putting the chip briefly into SLEEP mode
                 * at this point won't interfere with the
@@ -319,7 +400,7 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
                pca9685_set_sleep_mode(pca, true);
 
                /* Change the chip-wide output frequency */
-               regmap_write(pca->regmap, PCA9685_PRESCALE, prescale);
+               pca9685_write_reg(pca, PCA9685_PRESCALE, prescale);
 
                /* Wake the chip up */
                pca9685_set_sleep_mode(pca, false);
@@ -331,6 +412,25 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
        return 0;
 }
 
+static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+                            const struct pwm_state *state)
+{
+       struct pca9685 *pca = to_pca(chip);
+       int ret;
+
+       mutex_lock(&pca->lock);
+       ret = __pca9685_pwm_apply(chip, pwm, state);
+       if (ret == 0) {
+               if (state->enabled)
+                       set_bit(pwm->hwpwm, pca->pwms_enabled);
+               else
+                       clear_bit(pwm->hwpwm, pca->pwms_enabled);
+       }
+       mutex_unlock(&pca->lock);
+
+       return ret;
+}
+
 static void pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
                                  struct pwm_state *state)
 {
@@ -339,7 +439,7 @@ static void pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
        unsigned int val = 0;
 
        /* Calculate (chip-wide) period from prescale value */
-       regmap_read(pca->regmap, PCA9685_PRESCALE, &val);
+       pca9685_read_reg(pca, PCA9685_PRESCALE, &val);
        /*
         * PCA9685_OSC_CLOCK_MHZ is 25, i.e. an integer divider of 1000.
         * The following calculation is therefore only a multiplication
@@ -372,6 +472,14 @@ static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
 
        if (pca9685_pwm_test_and_set_inuse(pca, pwm->hwpwm))
                return -EBUSY;
+
+       if (pwm->hwpwm < PCA9685_MAXCHAN) {
+               /* PWMs - except the "all LEDs" channel - default to enabled */
+               mutex_lock(&pca->lock);
+               set_bit(pwm->hwpwm, pca->pwms_enabled);
+               mutex_unlock(&pca->lock);
+       }
+
        pm_runtime_get_sync(chip->dev);
 
        return 0;
@@ -381,7 +489,11 @@ static void pca9685_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct pca9685 *pca = to_pca(chip);
 
+       mutex_lock(&pca->lock);
        pca9685_pwm_set_duty(pca, pwm->hwpwm, 0);
+       clear_bit(pwm->hwpwm, pca->pwms_enabled);
+       mutex_unlock(&pca->lock);
+
        pm_runtime_put(chip->dev);
        pca9685_pwm_clear_inuse(pca, pwm->hwpwm);
 }
@@ -422,7 +534,11 @@ static int pca9685_pwm_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, pca);
 
-       regmap_read(pca->regmap, PCA9685_MODE2, &reg);
+       mutex_init(&pca->lock);
+
+       ret = pca9685_read_reg(pca, PCA9685_MODE2, &reg);
+       if (ret)
+               return ret;
 
        if (device_property_read_bool(&client->dev, "invert"))
                reg |= MODE2_INVRT;
@@ -434,16 +550,20 @@ static int pca9685_pwm_probe(struct i2c_client *client,
        else
                reg |= MODE2_OUTDRV;
 
-       regmap_write(pca->regmap, PCA9685_MODE2, reg);
+       ret = pca9685_write_reg(pca, PCA9685_MODE2, reg);
+       if (ret)
+               return ret;
 
        /* Disable all LED ALLCALL and SUBx addresses to avoid bus collisions */
-       regmap_read(pca->regmap, PCA9685_MODE1, &reg);
+       pca9685_read_reg(pca, PCA9685_MODE1, &reg);
        reg &= ~(MODE1_ALLCALL | MODE1_SUB1 | MODE1_SUB2 | MODE1_SUB3);
-       regmap_write(pca->regmap, PCA9685_MODE1, reg);
+       pca9685_write_reg(pca, PCA9685_MODE1, reg);
 
-       /* Reset OFF registers to POR default */
-       regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_L, LED_FULL);
-       regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_H, LED_FULL);
+       /* Reset OFF/ON registers to POR default */
+       pca9685_write_reg(pca, PCA9685_ALL_LED_OFF_L, LED_FULL);
+       pca9685_write_reg(pca, PCA9685_ALL_LED_OFF_H, LED_FULL);
+       pca9685_write_reg(pca, PCA9685_ALL_LED_ON_L, 0);
+       pca9685_write_reg(pca, PCA9685_ALL_LED_ON_H, 0);
 
        pca->chip.ops = &pca9685_pwm_ops;
        /* Add an extra channel for ALL_LED */
index cfb6838..e091a52 100644 (file)
@@ -165,7 +165,7 @@ pxa_pwm_of_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
 static int pwm_probe(struct platform_device *pdev)
 {
        const struct platform_device_id *id = platform_get_device_id(pdev);
-       struct pxa_pwm_chip *pwm;
+       struct pxa_pwm_chip *pc;
        int ret = 0;
 
        if (IS_ENABLED(CONFIG_OF) && id == NULL)
@@ -174,46 +174,44 @@ static int pwm_probe(struct platform_device *pdev)
        if (id == NULL)
                return -EINVAL;
 
-       pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
-       if (pwm == NULL)
+       pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
+       if (pc == NULL)
                return -ENOMEM;
 
-       pwm->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(pwm->clk))
-               return PTR_ERR(pwm->clk);
+       pc->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(pc->clk))
+               return PTR_ERR(pc->clk);
 
-       pwm->chip.dev = &pdev->dev;
-       pwm->chip.ops = &pxa_pwm_ops;
-       pwm->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1;
+       pc->chip.dev = &pdev->dev;
+       pc->chip.ops = &pxa_pwm_ops;
+       pc->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1;
 
        if (IS_ENABLED(CONFIG_OF)) {
-               pwm->chip.of_xlate = pxa_pwm_of_xlate;
-               pwm->chip.of_pwm_n_cells = 1;
+               pc->chip.of_xlate = pxa_pwm_of_xlate;
+               pc->chip.of_pwm_n_cells = 1;
        }
 
-       pwm->mmio_base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(pwm->mmio_base))
-               return PTR_ERR(pwm->mmio_base);
+       pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(pc->mmio_base))
+               return PTR_ERR(pc->mmio_base);
 
-       ret = pwmchip_add(&pwm->chip);
+       ret = pwmchip_add(&pc->chip);
        if (ret < 0) {
                dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
                return ret;
        }
 
-       platform_set_drvdata(pdev, pwm);
+       platform_set_drvdata(pdev, pc);
        return 0;
 }
 
 static int pwm_remove(struct platform_device *pdev)
 {
-       struct pxa_pwm_chip *chip;
+       struct pxa_pwm_chip *pc;
 
-       chip = platform_get_drvdata(pdev);
-       if (chip == NULL)
-               return -ENODEV;
+       pc = platform_get_drvdata(pdev);
 
-       return pwmchip_remove(&chip->chip);
+       return pwmchip_remove(&pc->chip);
 }
 
 static struct platform_driver pwm_driver = {
index e2959fa..b853e79 100644 (file)
@@ -408,8 +408,6 @@ static int tpu_probe(struct platform_device *pdev)
 
        tpu->chip.dev = &pdev->dev;
        tpu->chip.ops = &tpu_pwm_ops;
-       tpu->chip.of_xlate = of_pwm_xlate_with_flags;
-       tpu->chip.of_pwm_n_cells = 3;
        tpu->chip.npwm = TPU_CHANNEL_MAX;
 
        pm_runtime_enable(&pdev->dev);
index 301785f..cbe9008 100644 (file)
@@ -354,11 +354,6 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
        pc->chip.ops = &rockchip_pwm_ops;
        pc->chip.npwm = 1;
 
-       if (pc->data->supports_polarity) {
-               pc->chip.of_xlate = of_pwm_xlate_with_flags;
-               pc->chip.of_pwm_n_cells = 3;
-       }
-
        enable_conf = pc->data->enable_conf;
        ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl);
        enabled = (ctrl & enable_conf) == enable_conf;
index 515489f..f6c528f 100644 (file)
@@ -526,9 +526,6 @@ static int pwm_samsung_probe(struct platform_device *pdev)
                ret = pwm_samsung_parse_dt(chip);
                if (ret)
                        return ret;
-
-               chip->chip.of_xlate = of_pwm_xlate_with_flags;
-               chip->chip.of_pwm_n_cells = 3;
        } else {
                if (!pdev->dev.platform_data) {
                        dev_err(&pdev->dev, "no platform data specified\n");
index 688737f..420edc4 100644 (file)
@@ -242,8 +242,6 @@ static int pwm_sifive_probe(struct platform_device *pdev)
        chip = &ddata->chip;
        chip->dev = dev;
        chip->ops = &pwm_sifive_ops;
-       chip->of_xlate = of_pwm_xlate_with_flags;
-       chip->of_pwm_n_cells = 3;
        chip->npwm = 4;
 
        ddata->regs = devm_platform_ioremap_resource(pdev, 0);
index 1a1cedf..48c31da 100644 (file)
@@ -75,7 +75,7 @@ static inline void spear_pwm_writel(struct spear_pwm_chip *chip,
 }
 
 static int spear_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-                           int duty_ns, int period_ns)
+                           u64 duty_ns, u64 period_ns)
 {
        struct spear_pwm_chip *pc = to_spear_pwm_chip(chip);
        u64 val, div, clk_rate;
@@ -163,10 +163,35 @@ static void spear_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
        clk_disable(pc->clk);
 }
 
+static int spear_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+                          const struct pwm_state *state)
+{
+       int err;
+
+       if (state->polarity != PWM_POLARITY_NORMAL)
+               return -EINVAL;
+
+       if (!state->enabled) {
+               if (pwm->state.enabled)
+                       spear_pwm_disable(chip, pwm);
+               return 0;
+       }
+
+       if (state->period != pwm->state.period ||
+           state->duty_cycle != pwm->state.duty_cycle) {
+               err = spear_pwm_config(chip, pwm, state->duty_cycle, state->period);
+               if (err)
+                       return err;
+       }
+
+       if (!pwm->state.enabled)
+               return spear_pwm_enable(chip, pwm);
+
+       return 0;
+}
+
 static const struct pwm_ops spear_pwm_ops = {
-       .config = spear_pwm_config,
-       .enable = spear_pwm_enable,
-       .disable = spear_pwm_disable,
+       .apply = spear_pwm_apply,
        .owner = THIS_MODULE,
 };
 
@@ -228,14 +253,13 @@ static int spear_pwm_probe(struct platform_device *pdev)
 static int spear_pwm_remove(struct platform_device *pdev)
 {
        struct spear_pwm_chip *pc = platform_get_drvdata(pdev);
-       int i;
 
-       for (i = 0; i < NUM_PWM; i++)
-               pwm_disable(&pc->chip.pwms[i]);
+       pwmchip_remove(&pc->chip);
 
        /* clk was prepared in probe, hence unprepare it here */
        clk_unprepare(pc->clk);
-       return pwmchip_remove(&pc->chip);
+
+       return 0;
 }
 
 static const struct of_device_id spear_pwm_of_match[] = {
index 98c479d..f2a85e8 100644 (file)
@@ -284,7 +284,9 @@ static int sprd_pwm_remove(struct platform_device *pdev)
 {
        struct sprd_pwm_chip *spc = platform_get_drvdata(pdev);
 
-       return pwmchip_remove(&spc->chip);
+       pwmchip_remove(&spc->chip);
+
+       return 0;
 }
 
 static const struct of_device_id sprd_pwm_of_match[] = {
index af08f56..93dd036 100644 (file)
@@ -208,8 +208,6 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
        priv->chip.dev = &pdev->dev;
        priv->chip.ops = &stm32_pwm_lp_ops;
        priv->chip.npwm = 1;
-       priv->chip.of_xlate = of_pwm_xlate_with_flags;
-       priv->chip.of_pwm_n_cells = 3;
 
        ret = pwmchip_add(&priv->chip);
        if (ret < 0)
index c46fb90..794ca5b 100644 (file)
@@ -621,8 +621,6 @@ static int stm32_pwm_probe(struct platform_device *pdev)
        priv->regmap = ddata->regmap;
        priv->clk = ddata->clk;
        priv->max_arr = ddata->max_arr;
-       priv->chip.of_xlate = of_pwm_xlate_with_flags;
-       priv->chip.of_pwm_n_cells = 3;
 
        if (!priv->regmap || !priv->clk)
                return -EINVAL;
index e01becd..c952604 100644 (file)
@@ -460,8 +460,6 @@ static int sun4i_pwm_probe(struct platform_device *pdev)
        pwm->chip.dev = &pdev->dev;
        pwm->chip.ops = &sun4i_pwm_ops;
        pwm->chip.npwm = pwm->data->npwm;
-       pwm->chip.of_xlate = of_pwm_xlate_with_flags;
-       pwm->chip.of_pwm_n_cells = 3;
 
        spin_lock_init(&pwm->ctrl_lock);
 
index c529a17..11a10b5 100644 (file)
@@ -300,32 +300,12 @@ static int tegra_pwm_probe(struct platform_device *pdev)
 static int tegra_pwm_remove(struct platform_device *pdev)
 {
        struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
-       unsigned int i;
-       int err;
-
-       if (WARN_ON(!pc))
-               return -ENODEV;
-
-       err = clk_prepare_enable(pc->clk);
-       if (err < 0)
-               return err;
-
-       for (i = 0; i < pc->chip.npwm; i++) {
-               struct pwm_device *pwm = &pc->chip.pwms[i];
-
-               if (!pwm_is_enabled(pwm))
-                       if (clk_prepare_enable(pc->clk) < 0)
-                               continue;
 
-               pwm_writel(pc, i, 0);
-
-               clk_disable_unprepare(pc->clk);
-       }
+       pwmchip_remove(&pc->chip);
 
        reset_control_assert(pc->rst);
-       clk_disable_unprepare(pc->clk);
 
-       return pwmchip_remove(&pc->chip);
+       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index b9a17ab..dec3f1f 100644 (file)
@@ -48,16 +48,13 @@ static inline struct ecap_pwm_chip *to_ecap_pwm_chip(struct pwm_chip *chip)
  * duty_ns   = 10^9 * duty_cycles / PWM_CLK_RATE
  */
 static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-               int duty_ns, int period_ns)
+                          int duty_ns, int period_ns, int enabled)
 {
        struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
        u32 period_cycles, duty_cycles;
        unsigned long long c;
        u16 value;
 
-       if (period_ns > NSEC_PER_SEC)
-               return -ERANGE;
-
        c = pc->clk_rate;
        c = c * period_ns;
        do_div(c, NSEC_PER_SEC);
@@ -82,7 +79,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 
        writew(value, pc->mmio_base + ECCTL2);
 
-       if (!pwm_is_enabled(pwm)) {
+       if (!enabled) {
                /* Update active registers if not running */
                writel(duty_cycles, pc->mmio_base + CAP2);
                writel(period_cycles, pc->mmio_base + CAP1);
@@ -96,7 +93,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
                writel(period_cycles, pc->mmio_base + CAP3);
        }
 
-       if (!pwm_is_enabled(pwm)) {
+       if (!enabled) {
                value = readw(pc->mmio_base + ECCTL2);
                /* Disable APWM mode to put APWM output Low */
                value &= ~ECCTL2_APWM_MODE;
@@ -168,20 +165,49 @@ static void ecap_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
        pm_runtime_put_sync(pc->chip.dev);
 }
 
-static void ecap_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+static int ecap_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+                         const struct pwm_state *state)
 {
-       if (pwm_is_enabled(pwm)) {
-               dev_warn(chip->dev, "Removing PWM device without disabling\n");
-               pm_runtime_put_sync(chip->dev);
+       int err;
+       int enabled = pwm->state.enabled;
+
+       if (state->polarity != pwm->state.polarity) {
+
+               if (enabled) {
+                       ecap_pwm_disable(chip, pwm);
+                       enabled = false;
+               }
+
+               err = ecap_pwm_set_polarity(chip, pwm, state->polarity);
+               if (err)
+                       return err;
+       }
+
+       if (!state->enabled) {
+               if (enabled)
+                       ecap_pwm_disable(chip, pwm);
+               return 0;
        }
+
+       if (state->period != pwm->state.period ||
+           state->duty_cycle != pwm->state.duty_cycle) {
+               if (state->period > NSEC_PER_SEC)
+                       return -ERANGE;
+
+               err = ecap_pwm_config(chip, pwm, state->duty_cycle,
+                                     state->period, enabled);
+               if (err)
+                       return err;
+       }
+
+       if (!enabled)
+               return ecap_pwm_enable(chip, pwm);
+
+       return 0;
 }
 
 static const struct pwm_ops ecap_pwm_ops = {
-       .free = ecap_pwm_free,
-       .config = ecap_pwm_config,
-       .set_polarity = ecap_pwm_set_polarity,
-       .enable = ecap_pwm_enable,
-       .disable = ecap_pwm_disable,
+       .apply = ecap_pwm_apply,
        .owner = THIS_MODULE,
 };
 
@@ -224,8 +250,6 @@ static int ecap_pwm_probe(struct platform_device *pdev)
 
        pc->chip.dev = &pdev->dev;
        pc->chip.ops = &ecap_pwm_ops;
-       pc->chip.of_xlate = of_pwm_xlate_with_flags;
-       pc->chip.of_pwm_n_cells = 3;
        pc->chip.npwm = 1;
 
        pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
index 90095a1..17909fa 100644 (file)
@@ -447,8 +447,6 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
 
        pc->chip.dev = &pdev->dev;
        pc->chip.ops = &ehrpwm_pwm_ops;
-       pc->chip.of_xlate = of_pwm_xlate_with_flags;
-       pc->chip.of_pwm_n_cells = 3;
        pc->chip.npwm = NUM_PWM_CHANNEL;
 
        pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
index 46d9037..af4e37d 100644 (file)
@@ -82,17 +82,14 @@ static int visconti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
                return -ERANGE;
 
        /*
-        * PWMC controls a divider that divides the input clk by a
-        * power of two between 1 and 8. As a smaller divider yields
-        * higher precision, pick the smallest possible one.
+        * PWMC controls a divider that divides the input clk by a power of two
+        * between 1 and 8. As a smaller divider yields higher precision, pick
+        * the smallest possible one. As period is at most 0xffff << 3, pwmc0 is
+        * in the intended range [0..3].
         */
-       if (period > 0xffff) {
-               pwmc0 = ilog2(period >> 16);
-               if (WARN_ON(pwmc0 > 3))
-                       return -EINVAL;
-       } else {
-               pwmc0 = 0;
-       }
+       pwmc0 = fls(period >> 16);
+       if (WARN_ON(pwmc0 > 3))
+               return -EINVAL;
 
        period >>= pwmc0;
        duty_cycle >>= pwmc0;
index 52fe5d1..ea2aa15 100644 (file)
@@ -207,8 +207,6 @@ static int vt8500_pwm_probe(struct platform_device *pdev)
 
        chip->chip.dev = &pdev->dev;
        chip->chip.ops = &vt8500_pwm_ops;
-       chip->chip.of_xlate = of_pwm_xlate_with_flags;
-       chip->chip.of_pwm_n_cells = 3;
        chip->chip.npwm = VT8500_NR_PWMS;
 
        chip->clk = devm_clk_get(&pdev->dev, NULL);
@@ -240,15 +238,13 @@ static int vt8500_pwm_probe(struct platform_device *pdev)
 
 static int vt8500_pwm_remove(struct platform_device *pdev)
 {
-       struct vt8500_chip *chip;
+       struct vt8500_chip *chip = platform_get_drvdata(pdev);
 
-       chip = platform_get_drvdata(pdev);
-       if (chip == NULL)
-               return -ENODEV;
+       pwmchip_remove(&chip->chip);
 
        clk_unprepare(chip->clk);
 
-       return pwmchip_remove(&chip->chip);
+       return 0;
 }
 
 static struct platform_driver vt8500_pwm_driver = {
index 5bb90af..a0b7e43 100644 (file)
@@ -54,12 +54,17 @@ enum {
  * @duty_cycle: PWM duty cycle (in nanoseconds)
  * @polarity: PWM polarity
  * @enabled: PWM enabled status
+ * @usage_power: If set, the PWM driver is only required to maintain the power
+ *               output but has more freedom regarding signal form.
+ *               If supported, the signal can be optimized, for example to
+ *               improve EMI by phase shifting individual channels.
  */
 struct pwm_state {
        u64 period;
        u64 duty_cycle;
        enum pwm_polarity polarity;
        bool enabled;
+       bool usage_power;
 };
 
 /**
@@ -188,6 +193,7 @@ static inline void pwm_init_state(const struct pwm_device *pwm,
        state->period = args.period;
        state->polarity = args.polarity;
        state->duty_cycle = 0;
+       state->usage_power = false;
 }
 
 /**
@@ -399,6 +405,9 @@ void *pwm_get_chip_data(struct pwm_device *pwm);
 
 int pwmchip_add(struct pwm_chip *chip);
 int pwmchip_remove(struct pwm_chip *chip);
+
+int devm_pwmchip_add(struct device *dev, struct pwm_chip *chip);
+
 struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
                                         unsigned int index,
                                         const char *label);
@@ -417,7 +426,6 @@ struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np,
 struct pwm_device *devm_fwnode_pwm_get(struct device *dev,
                                       struct fwnode_handle *fwnode,
                                       const char *con_id);
-void devm_pwm_put(struct device *dev, struct pwm_device *pwm);
 #else
 static inline struct pwm_device *pwm_request(int pwm_id, const char *label)
 {
@@ -524,10 +532,6 @@ devm_fwnode_pwm_get(struct device *dev, struct fwnode_handle *fwnode,
 {
        return ERR_PTR(-ENODEV);
 }
-
-static inline void devm_pwm_put(struct device *dev, struct pwm_device *pwm)
-{
-}
 #endif
 
 static inline void pwm_apply_args(struct pwm_device *pwm)
@@ -558,6 +562,7 @@ static inline void pwm_apply_args(struct pwm_device *pwm)
        state.enabled = false;
        state.polarity = pwm->args.polarity;
        state.period = pwm->args.period;
+       state.usage_power = false;
 
        pwm_apply_state(pwm, &state);
 }