summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-07-08 12:18:04 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2021-07-08 12:18:04 -0700
commit8c1bfd746030a14435c9b60d08a81af61332089b (patch)
tree91f3cf34eac8b319342dd54c600d3adf8cf3e0b3
parentb0dfd9af28b60d7ec42c359ae84c1ba97e093100 (diff)
parentbebedf2bb4a9e0cb4ffa72cbc960728051b338a4 (diff)
downloadlinux-8c1bfd746030a14435c9b60d08a81af61332089b.tar.gz
linux-8c1bfd746030a14435c9b60d08a81af61332089b.tar.bz2
linux-8c1bfd746030a14435c9b60d08a81af61332089b.zip
Merge tag 'pwm/for-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm
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() ...
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-tiecap.txt51
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-tiecap.yaml64
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt50
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.yaml65
-rw-r--r--Documentation/driver-api/driver-model/devres.rst3
-rw-r--r--Documentation/driver-api/pwm.rst7
-rw-r--r--Documentation/firmware-guide/acpi/enumeration.rst32
-rw-r--r--drivers/pwm/core.c222
-rw-r--r--drivers/pwm/pwm-atmel-hlcdc.c2
-rw-r--r--drivers/pwm/pwm-atmel-tcb.c2
-rw-r--r--drivers/pwm/pwm-atmel.c2
-rw-r--r--drivers/pwm/pwm-bcm-iproc.c2
-rw-r--r--drivers/pwm/pwm-bcm-kona.c2
-rw-r--r--drivers/pwm/pwm-bcm2835.c2
-rw-r--r--drivers/pwm/pwm-berlin.c165
-rw-r--r--drivers/pwm/pwm-clps711x.c12
-rw-r--r--drivers/pwm/pwm-crc.c12
-rw-r--r--drivers/pwm/pwm-ep93xx.c167
-rw-r--r--drivers/pwm/pwm-fsl-ftm.c2
-rw-r--r--drivers/pwm/pwm-hibvt.c2
-rw-r--r--drivers/pwm/pwm-img.c2
-rw-r--r--drivers/pwm/pwm-imx-tpm.c2
-rw-r--r--drivers/pwm/pwm-imx1.c14
-rw-r--r--drivers/pwm/pwm-imx27.c3
-rw-r--r--drivers/pwm/pwm-jz4740.c2
-rw-r--r--drivers/pwm/pwm-lpc18xx-sct.c2
-rw-r--r--drivers/pwm/pwm-lpss-pci.c4
-rw-r--r--drivers/pwm/pwm-lpss-platform.c4
-rw-r--r--drivers/pwm/pwm-lpss.c8
-rw-r--r--drivers/pwm/pwm-lpss.h1
-rw-r--r--drivers/pwm/pwm-meson.c14
-rw-r--r--drivers/pwm/pwm-mxs.c2
-rw-r--r--drivers/pwm/pwm-omap-dmtimer.c2
-rw-r--r--drivers/pwm/pwm-pca9685.c198
-rw-r--r--drivers/pwm/pwm-pxa.c40
-rw-r--r--drivers/pwm/pwm-renesas-tpu.c2
-rw-r--r--drivers/pwm/pwm-rockchip.c5
-rw-r--r--drivers/pwm/pwm-samsung.c3
-rw-r--r--drivers/pwm/pwm-sifive.c2
-rw-r--r--drivers/pwm/pwm-spear.c40
-rw-r--r--drivers/pwm/pwm-sprd.c4
-rw-r--r--drivers/pwm/pwm-stm32-lp.c2
-rw-r--r--drivers/pwm/pwm-stm32.c2
-rw-r--r--drivers/pwm/pwm-sun4i.c2
-rw-r--r--drivers/pwm/pwm-tegra.c24
-rw-r--r--drivers/pwm/pwm-tiecap.c58
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c2
-rw-r--r--drivers/pwm/pwm-visconti.c17
-rw-r--r--drivers/pwm/pwm-vt8500.c10
-rw-r--r--include/linux/pwm.h15
50 files changed, 710 insertions, 642 deletions
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
deleted file mode 100644
index c7c4347a769a..000000000000
--- a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
+++ /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
index 000000000000..ed35b6cc48d5
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.yaml
@@ -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
index c7e28f6d28be..000000000000
--- a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
+++ /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
index 000000000000..ee312cb210e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.yaml
@@ -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";
+ };
diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst
index 0fe1fffa295e..650096523f4f 100644
--- a/Documentation/driver-api/driver-model/devres.rst
+++ b/Documentation/driver-api/driver-model/devres.rst
@@ -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()
diff --git a/Documentation/driver-api/pwm.rst b/Documentation/driver-api/pwm.rst
index a7ca4f58305a..ccb06e485756 100644
--- a/Documentation/driver-api/pwm.rst
+++ b/Documentation/driver-api/pwm.rst
@@ -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
diff --git a/Documentation/firmware-guide/acpi/enumeration.rst b/Documentation/firmware-guide/acpi/enumeration.rst
index 18074eb71860..74b830b2fd59 100644
--- a/Documentation/firmware-guide/acpi/enumeration.rst
+++ b/Documentation/firmware-guide/acpi/enumeration.rst
@@ -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
============
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index c4d5c0667137..35e894f4a379 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -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 *