summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/pwm/atmel,hlcdc-pwm.yaml35
-rw-r--r--Documentation/devicetree/bindings/pwm/atmel-hlcdc-pwm.txt29
-rw-r--r--Documentation/devicetree/bindings/pwm/marvell,pxa-pwm.yaml51
-rw-r--r--Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml1
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-amlogic.yaml115
-rw-r--r--Documentation/devicetree/bindings/pwm/pxa-pwm.txt30
-rw-r--r--Documentation/driver-api/driver-model/devres.rst1
-rw-r--r--Documentation/driver-api/pwm.rst11
-rw-r--r--drivers/gpio/gpio-mvebu.c18
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi86.c32
-rw-r--r--drivers/leds/rgb/leds-qcom-lpg.c16
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c6
-rw-r--r--drivers/pwm/core.c724
-rw-r--r--drivers/pwm/pwm-ab8500.c36
-rw-r--r--drivers/pwm/pwm-apple.c18
-rw-r--r--drivers/pwm/pwm-atmel-hlcdc.c42
-rw-r--r--drivers/pwm/pwm-atmel-tcb.c32
-rw-r--r--drivers/pwm/pwm-atmel.c47
-rw-r--r--drivers/pwm/pwm-bcm-iproc.c19
-rw-r--r--drivers/pwm/pwm-bcm-kona.c23
-rw-r--r--drivers/pwm/pwm-bcm2835.c22
-rw-r--r--drivers/pwm/pwm-berlin.c29
-rw-r--r--drivers/pwm/pwm-brcmstb.c17
-rw-r--r--drivers/pwm/pwm-clk.c27
-rw-r--r--drivers/pwm/pwm-clps711x.c28
-rw-r--r--drivers/pwm/pwm-crc.c22
-rw-r--r--drivers/pwm/pwm-cros-ec.c57
-rw-r--r--drivers/pwm/pwm-dwc-core.c26
-rw-r--r--drivers/pwm/pwm-dwc.c77
-rw-r--r--drivers/pwm/pwm-dwc.h14
-rw-r--r--drivers/pwm/pwm-ep93xx.c21
-rw-r--r--drivers/pwm/pwm-fsl-ftm.c49
-rw-r--r--drivers/pwm/pwm-hibvt.c70
-rw-r--r--drivers/pwm/pwm-img.c60
-rw-r--r--drivers/pwm/pwm-imx-tpm.c44
-rw-r--r--drivers/pwm/pwm-imx1.c20
-rw-r--r--drivers/pwm/pwm-imx27.c35
-rw-r--r--drivers/pwm/pwm-intel-lgm.c17
-rw-r--r--drivers/pwm/pwm-iqs620a.c30
-rw-r--r--drivers/pwm/pwm-jz4740.c36
-rw-r--r--drivers/pwm/pwm-keembay.c17
-rw-r--r--drivers/pwm/pwm-lp3943.c17
-rw-r--r--drivers/pwm/pwm-lpc18xx-sct.c34
-rw-r--r--drivers/pwm/pwm-lpc32xx.c21
-rw-r--r--drivers/pwm/pwm-lpss-pci.c10
-rw-r--r--drivers/pwm/pwm-lpss-platform.c10
-rw-r--r--drivers/pwm/pwm-lpss.c38
-rw-r--r--drivers/pwm/pwm-lpss.h1
-rw-r--r--drivers/pwm/pwm-mediatek.c38
-rw-r--r--drivers/pwm/pwm-meson.c110
-rw-r--r--drivers/pwm/pwm-microchip-core.c17
-rw-r--r--drivers/pwm/pwm-mtk-disp.c25
-rw-r--r--drivers/pwm/pwm-mxs.c32
-rw-r--r--drivers/pwm/pwm-ntxec.c14
-rw-r--r--drivers/pwm/pwm-omap-dmtimer.c47
-rw-r--r--drivers/pwm/pwm-pca9685.c161
-rw-r--r--drivers/pwm/pwm-pxa.c25
-rw-r--r--drivers/pwm/pwm-raspberrypi-poe.c20
-rw-r--r--drivers/pwm/pwm-rcar.c27
-rw-r--r--drivers/pwm/pwm-renesas-tpu.c20
-rw-r--r--drivers/pwm/pwm-rockchip.c24
-rw-r--r--drivers/pwm/pwm-rz-mtu3.c60
-rw-r--r--drivers/pwm/pwm-samsung.c94
-rw-r--r--drivers/pwm/pwm-sifive.c30
-rw-r--r--drivers/pwm/pwm-sl28cpld.c13
-rw-r--r--drivers/pwm/pwm-spear.c18
-rw-r--r--drivers/pwm/pwm-sprd.c58
-rw-r--r--drivers/pwm/pwm-sti.c70
-rw-r--r--drivers/pwm/pwm-stm32-lp.c31
-rw-r--r--drivers/pwm/pwm-stm32.c56
-rw-r--r--drivers/pwm/pwm-stmpe.c58
-rw-r--r--drivers/pwm/pwm-sun4i.c100
-rw-r--r--drivers/pwm/pwm-sunplus.c17
-rw-r--r--drivers/pwm/pwm-tegra.c50
-rw-r--r--drivers/pwm/pwm-tiecap.c55
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c72
-rw-r--r--drivers/pwm/pwm-twl-led.c55
-rw-r--r--drivers/pwm/pwm-twl.c50
-rw-r--r--drivers/pwm/pwm-visconti.c17
-rw-r--r--drivers/pwm/pwm-vt8500.c43
-rw-r--r--drivers/pwm/pwm-xilinx.c34
-rw-r--r--drivers/pwm/sysfs.c4
-rw-r--r--drivers/staging/greybus/pwm.c133
-rw-r--r--include/linux/platform_data/x86/pwm-lpss.h4
-rw-r--r--include/linux/pwm.h49
85 files changed, 2018 insertions, 1848 deletions
diff --git a/Documentation/devicetree/bindings/pwm/atmel,hlcdc-pwm.yaml b/Documentation/devicetree/bindings/pwm/atmel,hlcdc-pwm.yaml
new file mode 100644
index 000000000000..0e92868a2b68
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/atmel,hlcdc-pwm.yaml
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/atmel,hlcdc-pwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Atmel's HLCDC's PWM controller
+
+maintainers:
+ - Nicolas Ferre <nicolas.ferre@microchip.com>
+ - Alexandre Belloni <alexandre.belloni@bootlin.com>
+ - Claudiu Beznea <claudiu.beznea@tuxon.dev>
+
+description:
+ The LCDC integrates a Pulse Width Modulation (PWM) Controller. This block
+ generates the LCD contrast control signal (LCD_PWM) that controls the
+ display's contrast by software. LCDC_PWM is an 8-bit PWM signal that can be
+ converted to an analog voltage with a simple passive filter. LCD display
+ panels have different backlight specifications in terms of minimum/maximum
+ values for PWM frequency. If the LCDC PWM frequency range does not match the
+ LCD display panel, it is possible to use the standalone PWM Controller to
+ drive the backlight.
+
+properties:
+ compatible:
+ const: atmel,hlcdc-pwm
+
+ "#pwm-cells":
+ const: 3
+
+required:
+ - compatible
+ - "#pwm-cells"
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/pwm/atmel-hlcdc-pwm.txt b/Documentation/devicetree/bindings/pwm/atmel-hlcdc-pwm.txt
deleted file mode 100644
index afa501bf7f94..000000000000
--- a/Documentation/devicetree/bindings/pwm/atmel-hlcdc-pwm.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-Device-Tree bindings for Atmel's HLCDC (High-end LCD Controller) PWM driver
-
-The Atmel HLCDC PWM is subdevice of the HLCDC MFD device.
-See ../mfd/atmel-hlcdc.txt for more details.
-
-Required properties:
- - compatible: value should be one of the following:
- "atmel,hlcdc-pwm"
- - pinctr-names: the pin control state names. Should contain "default".
- - pinctrl-0: should contain the pinctrl states described by pinctrl
- default.
- - #pwm-cells: should be set to 3. This PWM chip use the default 3 cells
- bindings defined in pwm.yaml in this directory.
-
-Example:
-
- hlcdc: hlcdc@f0030000 {
- compatible = "atmel,sama5d3-hlcdc";
- reg = <0xf0030000 0x2000>;
- clocks = <&lcdc_clk>, <&lcdck>, <&clk32k>;
- clock-names = "periph_clk","sys_clk", "slow_clk";
-
- hlcdc_pwm: hlcdc-pwm {
- compatible = "atmel,hlcdc-pwm";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_lcd_pwm>;
- #pwm-cells = <3>;
- };
- };
diff --git a/Documentation/devicetree/bindings/pwm/marvell,pxa-pwm.yaml b/Documentation/devicetree/bindings/pwm/marvell,pxa-pwm.yaml
new file mode 100644
index 000000000000..ba6325575ea0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/marvell,pxa-pwm.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/marvell,pxa-pwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Marvell PXA PWM
+
+maintainers:
+ - Duje Mihanović <duje.mihanovic@skole.hr>
+
+allOf:
+ - $ref: pwm.yaml#
+
+properties:
+ compatible:
+ enum:
+ - marvell,pxa250-pwm
+ - marvell,pxa270-pwm
+ - marvell,pxa168-pwm
+ - marvell,pxa910-pwm
+
+ reg:
+ # Length should be 0x10
+ maxItems: 1
+
+ "#pwm-cells":
+ # Used for specifying the period length in nanoseconds
+ const: 1
+
+ clocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - "#pwm-cells"
+ - clocks
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/pxa-clock.h>
+
+ pwm0: pwm@40b00000 {
+ compatible = "marvell,pxa250-pwm";
+ reg = <0x40b00000 0x10>;
+ #pwm-cells = <1>;
+ clocks = <&clks CLK_PWM0>;
+ };
diff --git a/Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml b/Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml
index 0fbe8a6469eb..a5c308801619 100644
--- a/Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml
+++ b/Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml
@@ -24,6 +24,7 @@ properties:
- mediatek,mt7629-pwm
- mediatek,mt7981-pwm
- mediatek,mt7986-pwm
+ - mediatek,mt7988-pwm
- mediatek,mt8183-pwm
- mediatek,mt8365-pwm
- mediatek,mt8516-pwm
diff --git a/Documentation/devicetree/bindings/pwm/pwm-amlogic.yaml b/Documentation/devicetree/bindings/pwm/pwm-amlogic.yaml
index 527864a4d855..1d71d4f8f328 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-amlogic.yaml
+++ b/Documentation/devicetree/bindings/pwm/pwm-amlogic.yaml
@@ -9,9 +9,6 @@ title: Amlogic PWM
maintainers:
- Heiner Kallweit <hkallweit1@gmail.com>
-allOf:
- - $ref: pwm.yaml#
-
properties:
compatible:
oneOf:
@@ -24,31 +21,40 @@ properties:
- amlogic,meson-g12a-ee-pwm
- amlogic,meson-g12a-ao-pwm-ab
- amlogic,meson-g12a-ao-pwm-cd
- - amlogic,meson-s4-pwm
+ deprecated: true
- items:
- const: amlogic,meson-gx-pwm
- const: amlogic,meson-gxbb-pwm
+ deprecated: true
- items:
- const: amlogic,meson-gx-ao-pwm
- const: amlogic,meson-gxbb-ao-pwm
+ deprecated: true
- items:
- const: amlogic,meson8-pwm
- const: amlogic,meson8b-pwm
+ deprecated: true
+ - enum:
+ - amlogic,meson8-pwm-v2
+ - amlogic,meson-s4-pwm
+ - items:
+ - enum:
+ - amlogic,meson8b-pwm-v2
+ - amlogic,meson-gxbb-pwm-v2
+ - amlogic,meson-axg-pwm-v2
+ - amlogic,meson-g12-pwm-v2
+ - const: amlogic,meson8-pwm-v2
reg:
maxItems: 1
clocks:
minItems: 1
- maxItems: 2
+ maxItems: 4
clock-names:
- oneOf:
- - items:
- - enum: [clkin0, clkin1]
- - items:
- - const: clkin0
- - const: clkin1
+ minItems: 1
+ maxItems: 2
"#pwm-cells":
const: 3
@@ -57,6 +63,79 @@ required:
- compatible
- reg
+allOf:
+ - $ref: pwm.yaml#
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - amlogic,meson8-pwm
+ - amlogic,meson8b-pwm
+ - amlogic,meson-gxbb-pwm
+ - amlogic,meson-gxbb-ao-pwm
+ - amlogic,meson-axg-ee-pwm
+ - amlogic,meson-axg-ao-pwm
+ - amlogic,meson-g12a-ee-pwm
+ - amlogic,meson-g12a-ao-pwm-ab
+ - amlogic,meson-g12a-ao-pwm-cd
+ then:
+ # Obsolete historic bindings tied to the driver implementation
+ # The clocks provided here are meant to be matched with the input
+ # known (hard-coded) in the driver and used to select pwm clock
+ # source. Currently, the linux driver ignores this.
+ # This is kept to maintain ABI backward compatibility.
+ properties:
+ clocks:
+ maxItems: 2
+ clock-names:
+ oneOf:
+ - items:
+ - enum: [clkin0, clkin1]
+ - items:
+ - const: clkin0
+ - const: clkin1
+
+ # Newer binding where clock describe the actual clock inputs of the pwm
+ # block. These are necessary but some inputs may be grounded.
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - amlogic,meson8-pwm-v2
+ then:
+ properties:
+ clocks:
+ minItems: 1
+ items:
+ - description: input clock 0 of the pwm block
+ - description: input clock 1 of the pwm block
+ - description: input clock 2 of the pwm block
+ - description: input clock 3 of the pwm block
+ clock-names: false
+ required:
+ - clocks
+
+ # Newer IP block take a single input per channel, instead of 4 inputs
+ # for both channels
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - amlogic,meson-s4-pwm
+ then:
+ properties:
+ clocks:
+ items:
+ - description: input clock of PWM channel A
+ - description: input clock of PWM channel B
+ clock-names: false
+ required:
+ - clocks
+
additionalProperties: false
examples:
@@ -68,3 +147,17 @@ examples:
clock-names = "clkin0", "clkin1";
#pwm-cells = <3>;
};
+ - |
+ pwm@2000 {
+ compatible = "amlogic,meson8-pwm-v2";
+ reg = <0x1000 0x10>;
+ clocks = <&xtal>, <0>, <&fdiv4>, <&fdiv5>;
+ #pwm-cells = <3>;
+ };
+ - |
+ pwm@1000 {
+ compatible = "amlogic,meson-s4-pwm";
+ reg = <0x1000 0x10>;
+ clocks = <&pwm_src_a>, <&pwm_src_b>;
+ #pwm-cells = <3>;
+ };
diff --git a/Documentation/devicetree/bindings/pwm/pxa-pwm.txt b/Documentation/devicetree/bindings/pwm/pxa-pwm.txt
deleted file mode 100644
index 5ae9f1e3c338..000000000000
--- a/Documentation/devicetree/bindings/pwm/pxa-pwm.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-Marvell PWM controller
-
-Required properties:
-- compatible: should be one or more of:
- - "marvell,pxa250-pwm"
- - "marvell,pxa270-pwm"
- - "marvell,pxa168-pwm"
- - "marvell,pxa910-pwm"
-- reg: Physical base address and length of the registers used by the PWM channel
- Note that one device instance must be created for each PWM that is used, so the
- length covers only the register window for one PWM output, not that of the
- entire PWM controller. Currently length is 0x10 for all supported devices.
-- #pwm-cells: Should be 1. This cell is used to specify the period in
- nanoseconds.
-
-Example PWM device node:
-
-pwm0: pwm@40b00000 {
- compatible = "marvell,pxa250-pwm";
- reg = <0x40b00000 0x10>;
- #pwm-cells = <1>;
-};
-
-Example PWM client node:
-
-backlight {
- compatible = "pwm-backlight";
- pwms = <&pwm0 5000000>;
- ...
-}
diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst
index c5f99d834ec5..e4df72c408d2 100644
--- a/Documentation/driver-api/driver-model/devres.rst
+++ b/Documentation/driver-api/driver-model/devres.rst
@@ -420,6 +420,7 @@ POWER
devm_reboot_mode_unregister()
PWM
+ devm_pwmchip_alloc()
devm_pwmchip_add()
devm_pwm_get()
devm_fwnode_pwm_get()
diff --git a/Documentation/driver-api/pwm.rst b/Documentation/driver-api/pwm.rst
index 3c28ccc4b611..b41b1c56477f 100644
--- a/Documentation/driver-api/pwm.rst
+++ b/Documentation/driver-api/pwm.rst
@@ -143,11 +143,12 @@ to implement the pwm_*() functions itself. This means that it's impossible
to have multiple PWM drivers in the system. For this reason it's mandatory
for new drivers to use the generic PWM framework.
-A new PWM controller/chip can be added using pwmchip_add() and removed
-again with pwmchip_remove(). pwmchip_add() takes a filled in struct
-pwm_chip as argument which provides a description of the PWM chip, the
-number of PWM devices provided by the chip and the chip-specific
-implementation of the supported PWM operations to the framework.
+A new PWM controller/chip can be allocated using pwmchip_alloc(), then
+registered using pwmchip_add() and removed again with pwmchip_remove(). To undo
+pwmchip_alloc() use pwmchip_put(). pwmchip_add() takes a filled in struct
+pwm_chip as argument which provides a description of the PWM chip, the number
+of PWM devices provided by the chip and the chip-specific implementation of the
+supported PWM operations to the framework.
When implementing polarity support in a PWM driver, make sure to respect the
signal conventions in the PWM framework. By definition, normal polarity
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index a13f3c18ccd4..8cfd3a89c018 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -99,7 +99,6 @@ struct mvebu_pwm {
u32 offset;
unsigned long clk_rate;
struct gpio_desc *gpiod;
- struct pwm_chip chip;
spinlock_t lock;
struct mvebu_gpio_chip *mvchip;
@@ -615,7 +614,7 @@ static const struct regmap_config mvebu_gpio_regmap_config = {
*/
static struct mvebu_pwm *to_mvebu_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct mvebu_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -789,6 +788,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
{
struct device *dev = &pdev->dev;
struct mvebu_pwm *mvpwm;
+ struct pwm_chip *chip;
void __iomem *base;
u32 offset;
u32 set;
@@ -813,9 +813,11 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
if (IS_ERR(mvchip->clk))
return PTR_ERR(mvchip->clk);
- mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL);
- if (!mvpwm)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(dev, mvchip->chip.ngpio, sizeof(*mvpwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ mvpwm = to_mvebu_pwm(chip);
+
mvchip->mvpwm = mvpwm;
mvpwm->mvchip = mvchip;
mvpwm->offset = offset;
@@ -868,13 +870,11 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
return -EINVAL;
}
- mvpwm->chip.dev = dev;
- mvpwm->chip.ops = &mvebu_pwm_ops;
- mvpwm->chip.npwm = mvchip->chip.ngpio;
+ chip->ops = &mvebu_pwm_ops;
spin_lock_init(&mvpwm->lock);
- return devm_pwmchip_add(dev, &mvpwm->chip);
+ return devm_pwmchip_add(dev, chip);
}
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 62cc3893dca5..7fbc307cc025 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -197,7 +197,7 @@ struct ti_sn65dsi86 {
DECLARE_BITMAP(gchip_output, SN_NUM_GPIOS);
#endif
#if defined(CONFIG_PWM)
- struct pwm_chip pchip;
+ struct pwm_chip *pchip;
bool pwm_enabled;
atomic_t pwm_pin_busy;
#endif
@@ -1374,7 +1374,7 @@ static void ti_sn_pwm_pin_release(struct ti_sn65dsi86 *pdata)
static struct ti_sn65dsi86 *pwm_chip_to_ti_sn_bridge(struct pwm_chip *chip)
{
- return container_of(chip, struct ti_sn65dsi86, pchip);
+ return pwmchip_get_drvdata(chip);
}
static int ti_sn_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -1415,7 +1415,7 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
int ret;
if (!pdata->pwm_enabled) {
- ret = pm_runtime_resume_and_get(chip->dev);
+ ret = pm_runtime_resume_and_get(pwmchip_parent(chip));
if (ret < 0)
return ret;
}
@@ -1431,7 +1431,7 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
SN_GPIO_MUX_MASK << (2 * SN_PWM_GPIO_IDX),
SN_GPIO_MUX_SPECIAL << (2 * SN_PWM_GPIO_IDX));
if (ret) {
- dev_err(chip->dev, "failed to mux in PWM function\n");
+ dev_err(pwmchip_parent(chip), "failed to mux in PWM function\n");
goto out;
}
}
@@ -1507,7 +1507,7 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
ret = regmap_write(pdata->regmap, SN_PWM_PRE_DIV_REG, pre_div);
if (ret) {
- dev_err(chip->dev, "failed to update PWM_PRE_DIV\n");
+ dev_err(pwmchip_parent(chip), "failed to update PWM_PRE_DIV\n");
goto out;
}
@@ -1519,7 +1519,7 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
FIELD_PREP(SN_PWM_INV_MASK, state->polarity == PWM_POLARITY_INVERSED);
ret = regmap_write(pdata->regmap, SN_PWM_EN_INV_REG, pwm_en_inv);
if (ret) {
- dev_err(chip->dev, "failed to update PWM_EN/PWM_INV\n");
+ dev_err(pwmchip_parent(chip), "failed to update PWM_EN/PWM_INV\n");
goto out;
}
@@ -1527,7 +1527,7 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
out:
if (!pdata->pwm_enabled)
- pm_runtime_put_sync(chip->dev);
+ pm_runtime_put_sync(pwmchip_parent(chip));
return ret;
}
@@ -1585,24 +1585,28 @@ static const struct pwm_ops ti_sn_pwm_ops = {
static int ti_sn_pwm_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
+ struct pwm_chip *chip;
struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
- pdata->pchip.dev = &adev->dev;
- pdata->pchip.ops = &ti_sn_pwm_ops;
- pdata->pchip.npwm = 1;
- pdata->pchip.of_xlate = of_pwm_single_xlate;
- pdata->pchip.of_pwm_n_cells = 1;
+ pdata->pchip = chip = devm_pwmchip_alloc(&adev->dev, 1, 0);
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+
+ pwmchip_set_drvdata(chip, pdata);
+
+ chip->ops = &ti_sn_pwm_ops;
+ chip->of_xlate = of_pwm_single_xlate;
devm_pm_runtime_enable(&adev->dev);
- return pwmchip_add(&pdata->pchip);
+ return pwmchip_add(chip);
}
static void ti_sn_pwm_remove(struct auxiliary_device *adev)
{
struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
- pwmchip_remove(&pdata->pchip);
+ pwmchip_remove(pdata->pchip);
if (pdata->pwm_enabled)
pm_runtime_put_sync(&adev->dev);
diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c
index 156b73d1f4a2..0a7acf59a420 100644
--- a/drivers/leds/rgb/leds-qcom-lpg.c
+++ b/drivers/leds/rgb/leds-qcom-lpg.c
@@ -77,7 +77,7 @@ struct lpg {
struct mutex lock;
- struct pwm_chip pwm;
+ struct pwm_chip *pwm;
const struct lpg_data *data;
@@ -978,7 +978,7 @@ static int lpg_pattern_mc_clear(struct led_classdev *cdev)
static inline struct lpg *lpg_pwm_from_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct lpg, pwm);
+ return pwmchip_get_drvdata(chip);
}
static int lpg_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -1093,13 +1093,17 @@ static const struct pwm_ops lpg_pwm_ops = {
static int lpg_add_pwm(struct lpg *lpg)
{
+ struct pwm_chip *chip;
int ret;
- lpg->pwm.dev = lpg->dev;
- lpg->pwm.npwm = lpg->num_channels;
- lpg->pwm.ops = &lpg_pwm_ops;
+ lpg->pwm = chip = devm_pwmchip_alloc(lpg->dev, lpg->num_channels, 0);
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
- ret = devm_pwmchip_add(lpg->dev, &lpg->pwm);
+ chip->ops = &lpg_pwm_ops;
+ pwmchip_set_drvdata(chip, lpg);
+
+ ret = devm_pwmchip_add(lpg->dev, chip);
if (ret)
dev_err_probe(lpg->dev, ret, "failed to add PWM chip\n");
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index d6f29e6faab7..89bd7ce6711a 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -1492,7 +1492,7 @@ static int intel_pinctrl_probe_pwm(struct intel_pinctrl *pctrl,
.base_unit_bits = 22,
.bypass = true,
};
- struct pwm_lpss_chip *pwm;
+ struct pwm_chip *chip;
if (!(community->features & PINCTRL_FEATURE_PWM))
return 0;
@@ -1500,8 +1500,8 @@ static int intel_pinctrl_probe_pwm(struct intel_pinctrl *pctrl,
if (!IS_REACHABLE(CONFIG_PWM_LPSS))
return 0;
- pwm = devm_pwm_lpss_probe(pctrl->dev, community->regs + PWMC, &info);
- return PTR_ERR_OR_ZERO(pwm);
+ chip = devm_pwm_lpss_probe(pctrl->dev, community->regs + PWMC, &info);
+ return PTR_ERR_OR_ZERO(chip);
}
int intel_pinctrl_probe(struct platform_device *pdev,
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index f2728ee787d7..d70f793ce4b3 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -24,310 +24,11 @@
#define CREATE_TRACE_POINTS
#include <trace/events/pwm.h>
-static DEFINE_MUTEX(pwm_lookup_lock);
-static LIST_HEAD(pwm_lookup_list);
-
/* protects access to pwm_chips */
static DEFINE_MUTEX(pwm_lock);
static DEFINE_IDR(pwm_chips);
-static struct pwm_chip *pwmchip_find_by_name(const char *name)
-{
- struct pwm_chip *chip;
- unsigned long id, tmp;
-
- if (!name)
- return NULL;
-
- mutex_lock(&pwm_lock);
-
- idr_for_each_entry_ul(&pwm_chips, chip, tmp, id) {
- const char *chip_name = dev_name(chip->dev);
-
- if (chip_name && strcmp(chip_name, name) == 0) {
- mutex_unlock(&pwm_lock);
- return chip;
- }
- }
-
- mutex_unlock(&pwm_lock);
-
- return NULL;
-}
-
-static int pwm_device_request(struct pwm_device *pwm, const char *label)
-{
- int err;
- struct pwm_chip *chip = pwm->chip;
- const struct pwm_ops *ops = chip->ops;
-
- if (test_bit(PWMF_REQUESTED, &pwm->flags))
- return -EBUSY;
-
- if (!try_module_get(chip->owner))
- return -ENODEV;
-
- if (ops->request) {
- err = ops->request(chip, pwm);
- if (err) {
- module_put(chip->owner);
- return err;
- }
- }
-
- if (ops->get_state) {
- /*
- * Zero-initialize state because most drivers are unaware of
- * .usage_power. The other members of state are supposed to be
- * set by lowlevel drivers. We still initialize the whole
- * structure for simplicity even though this might paper over
- * faulty implementations of .get_state().
- */
- struct pwm_state state = { 0, };
-
- err = ops->get_state(chip, pwm, &state);
- trace_pwm_get(pwm, &state, err);
-
- if (!err)
- pwm->state = state;
-
- if (IS_ENABLED(CONFIG_PWM_DEBUG))
- pwm->last = pwm->state;
- }
-
- set_bit(PWMF_REQUESTED, &pwm->flags);
- pwm->label = label;
-
- return 0;
-}
-
-struct pwm_device *
-of_pwm_xlate_with_flags(struct pwm_chip *chip, const struct of_phandle_args *args)
-{
- struct pwm_device *pwm;
-
- if (chip->of_pwm_n_cells < 2)
- return ERR_PTR(-EINVAL);
-
- /* flags in the third cell are optional */
- if (args->args_count < 2)
- return ERR_PTR(-EINVAL);
-
- if (args->args[0] >= chip->npwm)
- return ERR_PTR(-EINVAL);
-
- pwm = pwm_request_from_chip(chip, args->args[0], NULL);
- if (IS_ERR(pwm))
- return pwm;
-
- pwm->args.period = args->args[1];
- pwm->args.polarity = PWM_POLARITY_NORMAL;
-
- if (chip->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);
-
-struct pwm_device *
-of_pwm_single_xlate(struct pwm_chip *chip, const struct of_phandle_args *args)
-{
- struct pwm_device *pwm;
-
- if (chip->of_pwm_n_cells < 1)
- return ERR_PTR(-EINVAL);
-
- /* validate that one cell is specified, optionally with flags */
- if (args->args_count != 1 && args->args_count != 2)
- return ERR_PTR(-EINVAL);
-
- pwm = pwm_request_from_chip(chip, 0, NULL);
- if (IS_ERR(pwm))
- return pwm;
-
- pwm->args.period = args->args[0];
- pwm->args.polarity = PWM_POLARITY_NORMAL;
-
- if (args->args_count == 2 && args->args[1] & PWM_POLARITY_INVERTED)
- pwm->args.polarity = PWM_POLARITY_INVERSED;
-
- return pwm;
-}
-EXPORT_SYMBOL_GPL(of_pwm_single_xlate);
-
-static void of_pwmchip_add(struct pwm_chip *chip)
-{
- if (!chip->dev || !chip->dev->of_node)
- return;
-
- if (!chip->of_xlate) {
- 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);
-}
-
-static void of_pwmchip_remove(struct pwm_chip *chip)
-{
- if (chip->dev)
- of_node_put(chip->dev->of_node);
-}
-
-static bool pwm_ops_check(const struct pwm_chip *chip)
-{
- const struct pwm_ops *ops = chip->ops;
-
- if (!ops->apply)
- return false;
-
- if (IS_ENABLED(CONFIG_PWM_DEBUG) && !ops->get_state)
- dev_warn(chip->dev,
- "Please implement the .get_state() callback\n");
-
- return true;
-}
-
-/**
- * __pwmchip_add() - register a new PWM chip
- * @chip: the PWM chip to add
- * @owner: reference to the module providing the chip.
- *
- * Register a new PWM chip. @owner is supposed to be THIS_MODULE, use the
- * pwmchip_add wrapper to do this right.
- *
- * Returns: 0 on success or a negative error code on failure.
- */
-int __pwmchip_add(struct pwm_chip *chip, struct module *owner)
-{
- unsigned int i;
- int ret;
-
- if (!chip || !chip->dev || !chip->ops || !chip->npwm)
- return -EINVAL;
-
- if (!pwm_ops_check(chip))
- return -EINVAL;
-
- chip->owner = owner;
-
- chip->pwms = kcalloc(chip->npwm, sizeof(*chip->pwms), GFP_KERNEL);
- if (!chip->pwms)
- return -ENOMEM;
-
- mutex_lock(&pwm_lock);
-
- ret = idr_alloc(&pwm_chips, chip, 0, 0, GFP_KERNEL);
- if (ret < 0) {
- mutex_unlock(&pwm_lock);
- kfree(chip->pwms);
- return ret;
- }
-
- chip->id = ret;
-
- for (i = 0; i < chip->npwm; i++) {
- struct pwm_device *pwm = &chip->pwms[i];
-
- pwm->chip = chip;
- pwm->hwpwm = i;
- }
-
- mutex_unlock(&pwm_lock);
-
- if (IS_ENABLED(CONFIG_OF))
- of_pwmchip_add(chip);
-
- pwmchip_sysfs_export(chip);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(__pwmchip_add);
-
-/**
- * pwmchip_remove() - remove a PWM chip
- * @chip: the PWM chip to remove
- *
- * Removes a PWM chip.
- */
-void pwmchip_remove(struct pwm_chip *chip)
-{
- pwmchip_sysfs_unexport(chip);
-
- if (IS_ENABLED(CONFIG_OF))
- of_pwmchip_remove(chip);
-
- mutex_lock(&pwm_lock);
-
- idr_remove(&pwm_chips, chip->id);
-
- mutex_unlock(&pwm_lock);
-
- kfree(chip->pwms);
-}
-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, struct module *owner)
-{
- int ret;
-
- ret = __pwmchip_add(chip, owner);
- if (ret)
- return ret;
-
- return devm_add_action_or_reset(dev, devm_pwmchip_remove, chip);
-}
-EXPORT_SYMBOL_GPL(__devm_pwmchip_add);
-
-/**
- * pwm_request_from_chip() - request a PWM device relative to a PWM chip
- * @chip: PWM chip
- * @index: per-chip index of the PWM to request
- * @label: a literal description string of this PWM
- *
- * Returns: A pointer to the PWM device at the given index of the given PWM
- * chip. A negative error code is returned if the index is not valid for the
- * specified PWM chip or if the PWM device cannot be requested.
- */
-struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
- unsigned int index,
- const char *label)
-{
- struct pwm_device *pwm;
- int err;
-
- if (!chip || index >= chip->npwm)
- return ERR_PTR(-EINVAL);
-
- mutex_lock(&pwm_lock);
- pwm = &chip->pwms[index];
-
- err = pwm_device_request(pwm, label);
- if (err < 0)
- pwm = ERR_PTR(err);
-
- mutex_unlock(&pwm_lock);
- return pwm;
-}
-EXPORT_SYMBOL_GPL(pwm_request_from_chip);
-
static void pwm_apply_debug(struct pwm_device *pwm,
const struct pwm_state *state)
{
@@ -370,18 +71,18 @@ static void pwm_apply_debug(struct pwm_device *pwm,
if (s2.polarity != state->polarity &&
state->duty_cycle < state->period)
- dev_warn(chip->dev, ".apply ignored .polarity\n");
+ dev_warn(pwmchip_parent(chip), ".apply ignored .polarity\n");
if (state->enabled &&
last->polarity == state->polarity &&
last->period > s2.period &&
last->period <= state->period)
- dev_warn(chip->dev,
+ dev_warn(pwmchip_parent(chip),
".apply didn't pick the best available period (requested: %llu, applied: %llu, possible: %llu)\n",
state->period, s2.period, last->period);
if (state->enabled && state->period < s2.period)
- dev_warn(chip->dev,
+ dev_warn(pwmchip_parent(chip),
".apply is supposed to round down period (requested: %llu, applied: %llu)\n",
state->period, s2.period);
@@ -390,20 +91,20 @@ static void pwm_apply_debug(struct pwm_device *pwm,
last->period == s2.period &&
last->duty_cycle > s2.duty_cycle &&
last->duty_cycle <= state->duty_cycle)
- dev_warn(chip->dev,
+ dev_warn(pwmchip_parent(chip),
".apply didn't pick the best available duty cycle (requested: %llu/%llu, applied: %llu/%llu, possible: %llu/%llu)\n",
state->duty_cycle, state->period,
s2.duty_cycle, s2.period,
last->duty_cycle, last->period);
if (state->enabled && state->duty_cycle < s2.duty_cycle)
- dev_warn(chip->dev,
+ dev_warn(pwmchip_parent(chip),
".apply is supposed to round down duty_cycle (requested: %llu/%llu, applied: %llu/%llu)\n",
state->duty_cycle, state->period,
s2.duty_cycle, s2.period);
if (!state->enabled && s2.enabled && s2.duty_cycle > 0)
- dev_warn(chip->dev,
+ dev_warn(pwmchip_parent(chip),
"requested disabled, but yielded enabled with duty > 0\n");
/* reapply the state that the driver reported being configured. */
@@ -411,7 +112,7 @@ static void pwm_apply_debug(struct pwm_device *pwm,
trace_pwm_apply(pwm, &s1, err);
if (err) {
*last = s1;
- dev_err(chip->dev, "failed to reapply current setting\n");
+ dev_err(pwmchip_parent(chip), "failed to reapply current setting\n");
return;
}
@@ -426,7 +127,7 @@ static void pwm_apply_debug(struct pwm_device *pwm,
s1.polarity != last->polarity ||
(s1.enabled && s1.period != last->period) ||
(s1.enabled && s1.duty_cycle != last->duty_cycle)) {
- dev_err(chip->dev,
+ dev_err(pwmchip_parent(chip),
".apply is not idempotent (ena=%d pol=%d %llu/%llu) -> (ena=%d pol=%d %llu/%llu)\n",
s1.enabled, s1.polarity, s1.duty_cycle, s1.period,
last->enabled, last->polarity, last->duty_cycle,
@@ -524,33 +225,6 @@ int pwm_apply_atomic(struct pwm_device *pwm, const struct pwm_state *state)
EXPORT_SYMBOL_GPL(pwm_apply_atomic);
/**
- * pwm_capture() - capture and report a PWM signal
- * @pwm: PWM device
- * @result: structure to fill with capture result
- * @timeout: time to wait, in milliseconds, before giving up on capture
- *
- * Returns: 0 on success or a negative error code on failure.
- */
-int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
- unsigned long timeout)
-{
- int err;
-
- if (!pwm || !pwm->chip->ops)
- return -EINVAL;
-
- if (!pwm->chip->ops->capture)
- return -ENOSYS;
-
- mutex_lock(&pwm_lock);
- err = pwm->chip->ops->capture(pwm->chip, pwm, result, timeout);
- mutex_unlock(&pwm_lock);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(pwm_capture);
-
-/**
* pwm_adjust_config() - adjust the current PWM config to the PWM arguments
* @pwm: PWM device
*
@@ -606,24 +280,367 @@ int pwm_adjust_config(struct pwm_device *pwm)
}
EXPORT_SYMBOL_GPL(pwm_adjust_config);
-static struct pwm_chip *fwnode_to_pwmchip(struct fwnode_handle *fwnode)
+/**
+ * pwm_capture() - capture and report a PWM signal
+ * @pwm: PWM device
+ * @result: structure to fill with capture result
+ * @timeout: time to wait, in milliseconds, before giving up on capture
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
+ unsigned long timeout)
+{
+ int err;
+
+ if (!pwm || !pwm->chip->ops)
+ return -EINVAL;
+
+ if (!pwm->chip->ops->capture)
+ return -ENOSYS;
+
+ mutex_lock(&pwm_lock);
+ err = pwm->chip->ops->capture(pwm->chip, pwm, result, timeout);
+ mutex_unlock(&pwm_lock);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(pwm_capture);
+
+static struct pwm_chip *pwmchip_find_by_name(const char *name)
{
struct pwm_chip *chip;
unsigned long id, tmp;
+ if (!name)
+ return NULL;
+
mutex_lock(&pwm_lock);
- idr_for_each_entry_ul(&pwm_chips, chip, tmp, id)
- if (chip->dev && device_match_fwnode(chip->dev, fwnode)) {
+ idr_for_each_entry_ul(&pwm_chips, chip, tmp, id) {
+ const char *chip_name = dev_name(pwmchip_parent(chip));
+
+ if (chip_name && strcmp(chip_name, name) == 0) {
mutex_unlock(&pwm_lock);
return chip;
}
+ }
mutex_unlock(&pwm_lock);
- return ERR_PTR(-EPROBE_DEFER);
+ return NULL;
+}
+
+static int pwm_device_request(struct pwm_device *pwm, const char *label)
+{
+ int err;
+ struct pwm_chip *chip = pwm->chip;
+ const struct pwm_ops *ops = chip->ops;
+
+ if (test_bit(PWMF_REQUESTED, &pwm->flags))
+ return -EBUSY;
+
+ if (!try_module_get(chip->owner))
+ return -ENODEV;
+
+ if (ops->request) {
+ err = ops->request(chip, pwm);
+ if (err) {
+ module_put(chip->owner);
+ return err;
+ }
+ }
+
+ if (ops->get_state) {
+ /*
+ * Zero-initialize state because most drivers are unaware of
+ * .usage_power. The other members of state are supposed to be
+ * set by lowlevel drivers. We still initialize the whole
+ * structure for simplicity even though this might paper over
+ * faulty implementations of .get_state().
+ */
+ struct pwm_state state = { 0, };
+
+ err = ops->get_state(chip, pwm, &state);
+ trace_pwm_get(pwm, &state, err);
+
+ if (!err)
+ pwm->state = state;
+
+ if (IS_ENABLED(CONFIG_PWM_DEBUG))
+ pwm->last = pwm->state;
+ }
+
+ set_bit(PWMF_REQUESTED, &pwm->flags);
+ pwm->label = label;
+
+ return 0;
+}
+
+/**
+ * pwm_request_from_chip() - request a PWM device relative to a PWM chip
+ * @chip: PWM chip
+ * @index: per-chip index of the PWM to request
+ * @label: a literal description string of this PWM
+ *
+ * Returns: A pointer to the PWM device at the given index of the given PWM
+ * chip. A negative error code is returned if the index is not valid for the
+ * specified PWM chip or if the PWM device cannot be requested.
+ */
+struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
+ unsigned int index,
+ const char *label)
+{
+ struct pwm_device *pwm;
+ int err;
+
+ if (!chip || index >= chip->npwm)
+ return ERR_PTR(-EINVAL);
+
+ mutex_lock(&pwm_lock);
+ pwm = &chip->pwms[index];
+
+ err = pwm_device_request(pwm, label);
+ if (err < 0)
+ pwm = ERR_PTR(err);
+
+ mutex_unlock(&pwm_lock);
+ return pwm;
+}
+EXPORT_SYMBOL_GPL(pwm_request_from_chip);
+
+
+struct pwm_device *
+of_pwm_xlate_with_flags(struct pwm_chip *chip, const struct of_phandle_args *args)
+{
+ struct pwm_device *pwm;
+
+ /* period in the second cell and flags in the third cell are optional */
+ if (args->args_count < 1)
+ return ERR_PTR(-EINVAL);
+
+ pwm = pwm_request_from_chip(chip, args->args[0], NULL);
+ if (IS_ERR(pwm))
+ return pwm;
+
+ if (args->args_count > 1)
+ 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;
+
+ return pwm;
+}
+EXPORT_SYMBOL_GPL(of_pwm_xlate_with_flags);
+
+struct pwm_device *
+of_pwm_single_xlate(struct pwm_chip *chip, const struct of_phandle_args *args)
+{
+ struct pwm_device *pwm;
+
+ pwm = pwm_request_from_chip(chip, 0, NULL);
+ if (IS_ERR(pwm))
+ return pwm;
+
+ if (args->args_count > 1)
+ pwm->args.period = args->args[0];
+
+ pwm->args.polarity = PWM_POLARITY_NORMAL;
+ if (args->args_count > 1 && args->args[1] & PWM_POLARITY_INVERTED)
+ pwm->args.polarity = PWM_POLARITY_INVERSED;
+
+ return pwm;
+}
+EXPORT_SYMBOL_GPL(of_pwm_single_xlate);
+
+#define PWMCHIP_ALIGN ARCH_DMA_MINALIGN
+
+static void *pwmchip_priv(struct pwm_chip *chip)
+{
+ return (void *)chip + ALIGN(sizeof(*chip), PWMCHIP_ALIGN);
+}
+
+/* This is the counterpart to pwmchip_alloc() */
+void pwmchip_put(struct pwm_chip *chip)
+{
+ kfree(chip);
+}
+EXPORT_SYMBOL_GPL(pwmchip_put);
+
+struct pwm_chip *pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv)
+{
+ struct pwm_chip *chip;
+ size_t alloc_size;
+
+ alloc_size = size_add(ALIGN(sizeof(*chip), PWMCHIP_ALIGN), sizeof_priv);
+
+ chip = kzalloc(alloc_size, GFP_KERNEL);
+ if (!chip)
+ return ERR_PTR(-ENOMEM);
+
+ chip->dev = parent;
+ chip->npwm = npwm;
+
+ pwmchip_set_drvdata(chip, pwmchip_priv(chip));
+
+ return chip;
+}
+EXPORT_SYMBOL_GPL(pwmchip_alloc);
+
+static void devm_pwmchip_put(void *data)
+{
+ struct pwm_chip *chip = data;
+
+ pwmchip_put(chip);
+}
+
+struct pwm_chip *devm_pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv)
+{
+ struct pwm_chip *chip;
+ int ret;
+
+ chip = pwmchip_alloc(parent, npwm, sizeof_priv);
+ if (IS_ERR(chip))
+ return chip;
+
+ ret = devm_add_action_or_reset(parent, devm_pwmchip_put, chip);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return chip;
+}
+EXPORT_SYMBOL_GPL(devm_pwmchip_alloc);
+
+static void of_pwmchip_add(struct pwm_chip *chip)
+{
+ if (!pwmchip_parent(chip) || !pwmchip_parent(chip)->of_node)
+ return;
+
+ if (!chip->of_xlate)
+ chip->of_xlate = of_pwm_xlate_with_flags;
+
+ of_node_get(pwmchip_parent(chip)->of_node);
+}
+
+static void of_pwmchip_remove(struct pwm_chip *chip)
+{
+ if (pwmchip_parent(chip))
+ of_node_put(pwmchip_parent(chip)->of_node);
+}
+
+static bool pwm_ops_check(const struct pwm_chip *chip)
+{
+ const struct pwm_ops *ops = chip->ops;
+
+ if (!ops->apply)
+ return false;
+
+ if (IS_ENABLED(CONFIG_PWM_DEBUG) && !ops->get_state)
+ dev_warn(pwmchip_parent(chip),
+ "Please implement the .get_state() callback\n");
+
+ return true;
}
+/**
+ * __pwmchip_add() - register a new PWM chip
+ * @chip: the PWM chip to add
+ * @owner: reference to the module providing the chip.
+ *
+ * Register a new PWM chip. @owner is supposed to be THIS_MODULE, use the
+ * pwmchip_add wrapper to do this right.
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int __pwmchip_add(struct pwm_chip *chip, struct module *owner)
+{
+ unsigned int i;
+ int ret;
+
+ if (!chip || !pwmchip_parent(chip) || !chip->ops || !chip->npwm)
+ return -EINVAL;
+
+ if (!pwm_ops_check(chip))
+ return -EINVAL;
+
+ chip->owner = owner;
+
+ chip->pwms = kcalloc(chip->npwm, sizeof(*chip->pwms), GFP_KERNEL);
+ if (!chip->pwms)
+ return -ENOMEM;
+
+ mutex_lock(&pwm_lock);
+
+ ret = idr_alloc(&pwm_chips, chip, 0, 0, GFP_KERNEL);
+ if (ret < 0) {
+ mutex_unlock(&pwm_lock);
+ kfree(chip->pwms);
+ return ret;
+ }
+
+ chip->id = ret;
+
+ for (i = 0; i < chip->npwm; i++) {
+ struct pwm_device *pwm = &chip->pwms[i];
+
+ pwm->chip = chip;
+ pwm->hwpwm = i;
+ }
+
+ mutex_unlock(&pwm_lock);
+
+ if (IS_ENABLED(CONFIG_OF))
+ of_pwmchip_add(chip);
+
+ pwmchip_sysfs_export(chip);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__pwmchip_add);
+
+/**
+ * pwmchip_remove() - remove a PWM chip
+ * @chip: the PWM chip to remove
+ *
+ * Removes a PWM chip.
+ */
+void pwmchip_remove(struct pwm_chip *chip)
+{
+ pwmchip_sysfs_unexport(chip);
+
+ if (IS_ENABLED(CONFIG_OF))
+ of_pwmchip_remove(chip);
+
+ mutex_lock(&pwm_lock);
+
+ idr_remove(&pwm_chips, chip->id);
+
+ mutex_unlock(&pwm_lock);
+
+ kfree(chip->pwms);
+}
+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, struct module *owner)
+{
+ int ret;
+
+ ret = __pwmchip_add(chip, owner);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(dev, devm_pwmchip_remove, chip);
+}
+EXPORT_SYMBOL_GPL(__devm_pwmchip_add);
+
static struct device_link *pwm_device_link_add(struct device *dev,
struct pwm_device *pwm)
{
@@ -635,21 +652,39 @@ static struct device_link *pwm_device_link_add(struct device *dev,
* impact the PM sequence ordering: the PWM supplier may get
* suspended before the consumer.
*/
- dev_warn(pwm->chip->dev,
+ dev_warn(pwmchip_parent(pwm->chip),
"No consumer device specified to create a link to\n");
return NULL;
}
- dl = device_link_add(dev, pwm->chip->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+ dl = device_link_add(dev, pwmchip_parent(pwm->chip), DL_FLAG_AUTOREMOVE_CONSUMER);
if (!dl) {
dev_err(dev, "failed to create device link to %s\n",
- dev_name(pwm->chip->dev));
+ dev_name(pwmchip_parent(pwm->chip)));
return ERR_PTR(-EINVAL);
}
return dl;
}
+static struct pwm_chip *fwnode_to_pwmchip(struct fwnode_handle *fwnode)
+{
+ struct pwm_chip *chip;
+ unsigned long id, tmp;
+
+ mutex_lock(&pwm_lock);
+
+ idr_for_each_entry_ul(&pwm_chips, chip, tmp, id)
+ if (pwmchip_parent(chip) && device_match_fwnode(pwmchip_parent(chip), fwnode)) {
+ mutex_unlock(&pwm_lock);
+ return chip;
+ }
+
+ mutex_unlock(&pwm_lock);
+
+ return ERR_PTR(-EPROBE_DEFER);
+}
+
/**
* of_pwm_get() - request a PWM via the PWM framework
* @dev: device for PWM consumer
@@ -784,6 +819,9 @@ static struct pwm_device *acpi_pwm_get(const struct fwnode_handle *fwnode)
return pwm;
}
+static DEFINE_MUTEX(pwm_lookup_lock);
+static LIST_HEAD(pwm_lookup_list);
+
/**
* pwm_add_table() - register PWM device consumers
* @table: array of consumers to register
@@ -1105,8 +1143,8 @@ static int pwm_seq_show(struct seq_file *s, void *v)
seq_printf(s, "%s%d: %s/%s, %d PWM device%s\n",
(char *)s->private, chip->id,
- chip->dev->bus ? chip->dev->bus->name : "no-bus",
- dev_name(chip->dev), chip->npwm,
+ pwmchip_parent(chip)->bus ? pwmchip_parent(chip)->bus->name : "no-bus",
+ dev_name(pwmchip_parent(chip)), chip->npwm,
(chip->npwm != 1) ? "s" : "");
pwm_dbg_show(chip, s);
diff --git a/drivers/pwm/pwm-ab8500.c b/drivers/pwm/pwm-ab8500.c
index 670d33daea84..f000adab85b0 100644
--- a/drivers/pwm/pwm-ab8500.c
+++ b/drivers/pwm/pwm-ab8500.c
@@ -24,13 +24,12 @@
#define AB8500_PWM_CLKRATE 9600000
struct ab8500_pwm_chip {
- struct pwm_chip chip;
unsigned int hwid;
};
static struct ab8500_pwm_chip *ab8500_pwm_from_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct ab8500_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -92,12 +91,12 @@ static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
* when disabled.
*/
if (!state->enabled || duty_steps == 0) {
- ret = abx500_mask_and_set_register_interruptible(chip->dev,
+ ret = abx500_mask_and_set_register_interruptible(pwmchip_parent(chip),
AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
1 << ab8500->hwid, 0);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
+ dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM, Error %d\n",
pwm->label, ret);
return ret;
}
@@ -115,22 +114,22 @@ static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
reg = AB8500_PWM_OUT_CTRL1_REG + (ab8500->hwid * 2);
- ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
+ ret = abx500_set_register_interruptible(pwmchip_parent(chip), AB8500_MISC,
reg, lower_val);
if (ret < 0)
return ret;
- ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
+ ret = abx500_set_register_interruptible(pwmchip_parent(chip), AB8500_MISC,
(reg + 1), higher_val);
if (ret < 0)
return ret;
/* enable */
- ret = abx500_mask_and_set_register_interruptible(chip->dev,
+ ret = abx500_mask_and_set_register_interruptible(pwmchip_parent(chip),
AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
1 << ab8500->hwid, 1 << ab8500->hwid);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
+ dev_err(pwmchip_parent(chip), "%s: Failed to enable PWM, Error %d\n",
pwm->label, ret);
return ret;
@@ -144,7 +143,7 @@ static int ab8500_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct ab8500_pwm_chip *ab8500 = ab8500_pwm_from_chip(chip);
unsigned int div, duty_steps;
- ret = abx500_get_register_interruptible(chip->dev, AB8500_MISC,
+ ret = abx500_get_register_interruptible(pwmchip_parent(chip), AB8500_MISC,
AB8500_PWM_OUT_CTRL7_REG,
&ctrl7);
if (ret)
@@ -157,13 +156,13 @@ static int ab8500_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;
}
- ret = abx500_get_register_interruptible(chip->dev, AB8500_MISC,
+ ret = abx500_get_register_interruptible(pwmchip_parent(chip), AB8500_MISC,
AB8500_PWM_OUT_CTRL1_REG + (ab8500->hwid * 2),
&lower_val);
if (ret)
return ret;
- ret = abx500_get_register_interruptible(chip->dev, AB8500_MISC,
+ ret = abx500_get_register_interruptible(pwmchip_parent(chip), AB8500_MISC,
AB8500_PWM_OUT_CTRL2_REG + (ab8500->hwid * 2),
&higher_val);
if (ret)
@@ -185,6 +184,7 @@ static const struct pwm_ops ab8500_pwm_ops = {
static int ab8500_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct ab8500_pwm_chip *ab8500;
int err;
@@ -195,16 +195,16 @@ static int ab8500_pwm_probe(struct platform_device *pdev)
* Nothing to be done in probe, this is required to get the
* device which is required for ab8500 read and write
*/
- ab8500 = devm_kzalloc(&pdev->dev, sizeof(*ab8500), GFP_KERNEL);
- if (ab8500 == NULL)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*ab8500));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
- ab8500->chip.dev = &pdev->dev;
- ab8500->chip.ops = &ab8500_pwm_ops;
- ab8500->chip.npwm = 1;
+ ab8500 = ab8500_pwm_from_chip(chip);
+
+ chip->ops = &ab8500_pwm_ops;
ab8500->hwid = pdev->id - 1;
- err = devm_pwmchip_add(&pdev->dev, &ab8500->chip);
+ err = devm_pwmchip_add(&pdev->dev, chip);
if (err < 0)
return dev_err_probe(&pdev->dev, err, "Failed to add pwm chip\n");
diff --git a/drivers/pwm/pwm-apple.c b/drivers/pwm/pwm-apple.c
index 4d755b628d9e..6e58aca2f13c 100644
--- a/drivers/pwm/pwm-apple.c
+++ b/drivers/pwm/pwm-apple.c
@@ -32,14 +32,13 @@
#define APPLE_PWM_CTRL_OUTPUT_ENABLE BIT(14)
struct apple_pwm {
- struct pwm_chip chip;
void __iomem *base;
u64 clkrate;
};
static inline struct apple_pwm *to_apple_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct apple_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static int apple_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -103,13 +102,16 @@ static const struct pwm_ops apple_pwm_ops = {
static int apple_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct apple_pwm *fpwm;
struct clk *clk;
int ret;
- fpwm = devm_kzalloc(&pdev->dev, sizeof(*fpwm), GFP_KERNEL);
- if (!fpwm)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*fpwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+
+ fpwm = to_apple_pwm(chip);
fpwm->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(fpwm->base))
@@ -129,11 +131,9 @@ static int apple_pwm_probe(struct platform_device *pdev)
if (fpwm->clkrate > NSEC_PER_SEC)
return dev_err_probe(&pdev->dev, -EINVAL, "pwm clock out of range");
- fpwm->chip.dev = &pdev->dev;
- fpwm->chip.npwm = 1;
- fpwm->chip.ops = &apple_pwm_ops;
+ chip->ops = &apple_pwm_ops;
- ret = devm_pwmchip_add(&pdev->dev, &fpwm->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "unable to add pwm chip");
diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c
index 3f2c5031a3ba..2afb302be02c 100644
--- a/drivers/pwm/pwm-atmel-hlcdc.c
+++ b/drivers/pwm/pwm-atmel-hlcdc.c
@@ -28,7 +28,6 @@ struct atmel_hlcdc_pwm_errata {
};
struct atmel_hlcdc_pwm {
- struct pwm_chip chip;
struct atmel_hlcdc *hlcdc;
struct clk *cur_clk;
const struct atmel_hlcdc_pwm_errata *errata;
@@ -36,7 +35,7 @@ struct atmel_hlcdc_pwm {
static inline struct atmel_hlcdc_pwm *to_atmel_hlcdc_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct atmel_hlcdc_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static int atmel_hlcdc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -182,10 +181,12 @@ static const struct atmel_hlcdc_pwm_errata atmel_hlcdc_pwm_sama5d3_errata = {
static int atmel_hlcdc_pwm_suspend(struct device *dev)
{
- struct atmel_hlcdc_pwm *atmel = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct atmel_hlcdc_pwm *atmel = to_atmel_hlcdc_pwm(chip);
+ struct pwm_device *pwm = &chip->pwms[0];
/* Keep the periph clock enabled if the PWM is still running. */
- if (pwm_is_enabled(&atmel->chip.pwms[0]))
+ if (!pwm->state.enabled)
clk_disable_unprepare(atmel->hlcdc->periph_clk);
return 0;
@@ -193,21 +194,19 @@ static int atmel_hlcdc_pwm_suspend(struct device *dev)
static int atmel_hlcdc_pwm_resume(struct device *dev)
{
- struct atmel_hlcdc_pwm *atmel = dev_get_drvdata(dev);
- struct pwm_state state;
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct atmel_hlcdc_pwm *atmel = to_atmel_hlcdc_pwm(chip);
+ struct pwm_device *pwm = &chip->pwms[0];
int ret;
- pwm_get_state(&atmel->chip.pwms[0], &state);
-
/* Re-enable the periph clock it was stopped during suspend. */
- if (!state.enabled) {
+ if (!pwm->state.enabled) {
ret = clk_prepare_enable(atmel->hlcdc->periph_clk);
if (ret)
return ret;
}
- return atmel_hlcdc_pwm_apply(&atmel->chip, &atmel->chip.pwms[0],
- &state);
+ return atmel_hlcdc_pwm_apply(chip, pwm, &pwm->state);
}
static DEFINE_SIMPLE_DEV_PM_OPS(atmel_hlcdc_pwm_pm_ops,
@@ -243,15 +242,17 @@ static int atmel_hlcdc_pwm_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct device *dev = &pdev->dev;
+ struct pwm_chip *chip;
struct atmel_hlcdc_pwm *atmel;
struct atmel_hlcdc *hlcdc;
int ret;
hlcdc = dev_get_drvdata(dev->parent);
- atmel = devm_kzalloc(dev, sizeof(*atmel), GFP_KERNEL);
- if (!atmel)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(dev, 1, sizeof(*atmel));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ atmel = to_atmel_hlcdc_pwm(chip);
ret = clk_prepare_enable(hlcdc->periph_clk);
if (ret)
@@ -262,26 +263,25 @@ static int atmel_hlcdc_pwm_probe(struct platform_device *pdev)
atmel->errata = match->data;
atmel->hlcdc = hlcdc;
- atmel->chip.ops = &atmel_hlcdc_pwm_ops;
- atmel->chip.dev = dev;
- atmel->chip.npwm = 1;
+ chip->ops = &atmel_hlcdc_pwm_ops;
- ret = pwmchip_add(&atmel->chip);
+ ret = pwmchip_add(chip);
if (ret) {
clk_disable_unprepare(hlcdc->periph_clk);
return ret;
}
- platform_set_drvdata(pdev, atmel);
+ platform_set_drvdata(pdev, chip);
return 0;
}
static void atmel_hlcdc_pwm_remove(struct platform_device *pdev)
{
- struct atmel_hlcdc_pwm *atmel = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
+ struct atmel_hlcdc_pwm *atmel = to_atmel_hlcdc_pwm(chip);
- pwmchip_remove(&atmel->chip);
+ pwmchip_remove(chip);
clk_disable_unprepare(atmel->hlcdc->periph_clk);
}
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c
index d42c897cb85e..528e54c5999d 100644
--- a/drivers/pwm/pwm-atmel-tcb.c
+++ b/drivers/pwm/pwm-atmel-tcb.c
@@ -47,7 +47,6 @@ struct atmel_tcb_channel {
};
struct atmel_tcb_pwm_chip {
- struct pwm_chip chip;
spinlock_t lock;
u8 channel;
u8 width;
@@ -63,7 +62,7 @@ static const u8 atmel_tcb_divisors[] = { 2, 8, 32, 128, 0, };
static inline struct atmel_tcb_pwm_chip *to_tcb_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct atmel_tcb_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static int atmel_tcb_pwm_request(struct pwm_chip *chip,
@@ -327,7 +326,7 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
if ((atcbpwm && atcbpwm->duty > 0 &&
atcbpwm->duty != atcbpwm->period) &&
(atcbpwm->div != i || atcbpwm->period != period)) {
- dev_err(chip->dev,
+ dev_err(pwmchip_parent(chip),
"failed to configure period_ns: PWM group already configured with a different value\n");
return -EINVAL;
}
@@ -388,6 +387,7 @@ static const struct of_device_id atmel_tcb_of_match[] = {
static int atmel_tcb_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
const struct of_device_id *match;
struct atmel_tcb_pwm_chip *tcbpwm;
const struct atmel_tcb_config *config;
@@ -396,9 +396,10 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
int err;
int channel;
- tcbpwm = devm_kzalloc(&pdev->dev, sizeof(*tcbpwm), GFP_KERNEL);
- if (tcbpwm == NULL)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, NPWM, sizeof(*tcbpwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ tcbpwm = to_tcb_chip(chip);
err = of_property_read_u32(np, "reg", &channel);
if (err < 0) {
@@ -436,9 +437,7 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
}
}
- tcbpwm->chip.dev = &pdev->dev;
- tcbpwm->chip.ops = &atmel_tcb_pwm_ops;
- tcbpwm->chip.npwm = NPWM;
+ chip->ops = &atmel_tcb_pwm_ops;
tcbpwm->channel = channel;
tcbpwm->width = config->counter_width;
@@ -448,11 +447,11 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
spin_lock_init(&tcbpwm->lock);
- err = pwmchip_add(&tcbpwm->chip);
+ err = pwmchip_add(chip);
if (err < 0)
goto err_disable_clk;
- platform_set_drvdata(pdev, tcbpwm);
+ platform_set_drvdata(pdev, chip);
return 0;
@@ -473,9 +472,10 @@ err_slow_clk:
static void atmel_tcb_pwm_remove(struct platform_device *pdev)
{
- struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
+ struct atmel_tcb_pwm_chip *tcbpwm = to_tcb_chip(chip);
- pwmchip_remove(&tcbpwm->chip);
+ pwmchip_remove(chip);
clk_disable_unprepare(tcbpwm->slow_clk);
clk_put(tcbpwm->gclk);
@@ -491,7 +491,8 @@ MODULE_DEVICE_TABLE(of, atmel_tcb_pwm_dt_ids);
static int atmel_tcb_pwm_suspend(struct device *dev)
{
- struct atmel_tcb_pwm_chip *tcbpwm = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct atmel_tcb_pwm_chip *tcbpwm = to_tcb_chip(chip);
struct atmel_tcb_channel *chan = &tcbpwm->bkup;
unsigned int channel = tcbpwm->channel;
@@ -505,7 +506,8 @@ static int atmel_tcb_pwm_suspend(struct device *dev)
static int atmel_tcb_pwm_resume(struct device *dev)
{
- struct atmel_tcb_pwm_chip *tcbpwm = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct atmel_tcb_pwm_chip *tcbpwm = to_tcb_chip(chip);
struct atmel_tcb_channel *chan = &tcbpwm->bkup;
unsigned int channel = tcbpwm->channel;
diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c
index 47bcc8a3bf9d..b2f0abbbad63 100644
--- a/drivers/pwm/pwm-atmel.c
+++ b/drivers/pwm/pwm-atmel.c
@@ -77,7 +77,6 @@ struct atmel_pwm_data {
};
struct atmel_pwm_chip {
- struct pwm_chip chip;
struct clk *clk;
void __iomem *base;
const struct atmel_pwm_data *data;
@@ -99,7 +98,7 @@ struct atmel_pwm_chip {
static inline struct atmel_pwm_chip *to_atmel_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct atmel_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static inline u32 atmel_pwm_readl(struct atmel_pwm_chip *chip,
@@ -210,7 +209,7 @@ static int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip,
shift = fls(cycles) - atmel_pwm->data->cfg.period_bits;
if (shift > PWM_MAX_PRES) {
- dev_err(chip->dev, "pres exceeds the maximum value\n");
+ dev_err(pwmchip_parent(chip), "pres exceeds the maximum value\n");
return -EINVAL;
} else if (shift > 0) {
*pres = shift;
@@ -294,19 +293,16 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
- struct pwm_state cstate;
unsigned long cprd, cdty;
u32 pres, val;
int ret;
- pwm_get_state(pwm, &cstate);
-
if (state->enabled) {
unsigned long clkrate = clk_get_rate(atmel_pwm->clk);
- if (cstate.enabled &&
- cstate.polarity == state->polarity &&
- cstate.period == state->period) {
+ if (pwm->state.enabled &&
+ pwm->state.polarity == state->polarity &&
+ pwm->state.period == state->period) {
u32 cmr = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
cprd = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm,
@@ -321,19 +317,19 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
ret = atmel_pwm_calculate_cprd_and_pres(chip, clkrate, state, &cprd,
&pres);
if (ret) {
- dev_err(chip->dev,
+ dev_err(pwmchip_parent(chip),
"failed to calculate cprd and prescaler\n");
return ret;
}
atmel_pwm_calculate_cdty(state, clkrate, cprd, pres, &cdty);
- if (cstate.enabled) {
+ if (pwm->state.enabled) {
atmel_pwm_disable(chip, pwm, false);
} else {
ret = clk_enable(atmel_pwm->clk);
if (ret) {
- dev_err(chip->dev, "failed to enable clock\n");
+ dev_err(pwmchip_parent(chip), "failed to enable clock\n");
return ret;
}
}
@@ -348,7 +344,7 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
atmel_pwm_set_cprd_cdty(chip, pwm, cprd, cdty);
atmel_pwm_writel(atmel_pwm, PWM_ENA, 1 << pwm->hwpwm);
- } else if (cstate.enabled) {
+ } else if (pwm->state.enabled) {
atmel_pwm_disable(chip, pwm, true);
}
@@ -462,8 +458,9 @@ static const struct of_device_id atmel_pwm_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, atmel_pwm_dt_ids);
-static int atmel_pwm_enable_clk_if_on(struct atmel_pwm_chip *atmel_pwm, bool on)
+static int atmel_pwm_enable_clk_if_on(struct pwm_chip *chip, bool on)
{
+ struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
unsigned int i, cnt = 0;
unsigned long sr;
int ret = 0;
@@ -472,7 +469,7 @@ static int atmel_pwm_enable_clk_if_on(struct atmel_pwm_chip *atmel_pwm, bool on)
if (!sr)
return 0;
- cnt = bitmap_weight(&sr, atmel_pwm->chip.npwm);
+ cnt = bitmap_weight(&sr, chip->npwm);
if (!on)
goto disable_clk;
@@ -480,7 +477,7 @@ static int atmel_pwm_enable_clk_if_on(struct atmel_pwm_chip *atmel_pwm, bool on)
for (i = 0; i < cnt; i++) {
ret = clk_enable(atmel_pwm->clk);
if (ret) {
- dev_err(atmel_pwm->chip.dev,
+ dev_err(pwmchip_parent(chip),
"failed to enable clock for pwm %pe\n",
ERR_PTR(ret));
@@ -501,12 +498,14 @@ disable_clk:
static int atmel_pwm_probe(struct platform_device *pdev)
{
struct atmel_pwm_chip *atmel_pwm;
+ struct pwm_chip *chip;
int ret;
- atmel_pwm = devm_kzalloc(&pdev->dev, sizeof(*atmel_pwm), GFP_KERNEL);
- if (!atmel_pwm)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 4, sizeof(*atmel_pwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ atmel_pwm = to_atmel_pwm_chip(chip);
atmel_pwm->data = of_device_get_match_data(&pdev->dev);
atmel_pwm->update_pending = 0;
@@ -521,15 +520,13 @@ static int atmel_pwm_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(atmel_pwm->clk),
"failed to get prepared PWM clock\n");
- atmel_pwm->chip.dev = &pdev->dev;
- atmel_pwm->chip.ops = &atmel_pwm_ops;
- atmel_pwm->chip.npwm = 4;
+ chip->ops = &atmel_pwm_ops;
- ret = atmel_pwm_enable_clk_if_on(atmel_pwm, true);
+ ret = atmel_pwm_enable_clk_if_on(chip, true);
if (ret < 0)
return ret;
- ret = devm_pwmchip_add(&pdev->dev, &atmel_pwm->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0) {
dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n");
goto disable_clk;
@@ -538,7 +535,7 @@ static int atmel_pwm_probe(struct platform_device *pdev)
return 0;
disable_clk:
- atmel_pwm_enable_clk_if_on(atmel_pwm, false);
+ atmel_pwm_enable_clk_if_on(chip, false);
return ret;
}
diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c
index 758254025683..f4c9f10e490e 100644
--- a/drivers/pwm/pwm-bcm-iproc.c
+++ b/drivers/pwm/pwm-bcm-iproc.c
@@ -34,14 +34,13 @@
#define IPROC_PWM_PRESCALE_MAX 0x3f
struct iproc_pwmc {
- struct pwm_chip chip;
void __iomem *base;
struct clk *clk;
};
static inline struct iproc_pwmc *to_iproc_pwmc(struct pwm_chip *chip)
{
- return container_of(chip, struct iproc_pwmc, chip);
+ return pwmchip_get_drvdata(chip);
}
static void iproc_pwmc_enable(struct iproc_pwmc *ip, unsigned int channel)
@@ -187,20 +186,20 @@ static const struct pwm_ops iproc_pwm_ops = {
static int iproc_pwmc_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct iproc_pwmc *ip;
unsigned int i;
u32 value;
int ret;
- ip = devm_kzalloc(&pdev->dev, sizeof(*ip), GFP_KERNEL);
- if (!ip)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 4, sizeof(*ip));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ ip = to_iproc_pwmc(chip);
platform_set_drvdata(pdev, ip);
- ip->chip.dev = &pdev->dev;
- ip->chip.ops = &iproc_pwm_ops;
- ip->chip.npwm = 4;
+ chip->ops = &iproc_pwm_ops;
ip->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ip->base))
@@ -214,14 +213,14 @@ static int iproc_pwmc_probe(struct platform_device *pdev)
/* Set full drive and normal polarity for all channels */
value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
- for (i = 0; i < ip->chip.npwm; i++) {
+ for (i = 0; i < chip->npwm; i++) {
value &= ~(1 << IPROC_PWM_CTRL_TYPE_SHIFT(i));
value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(i);
}
writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
- ret = devm_pwmchip_add(&pdev->dev, &ip->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"failed to add PWM chip\n");
diff --git a/drivers/pwm/pwm-bcm-kona.c b/drivers/pwm/pwm-bcm-kona.c
index 45046a5c20a5..022c078aae84 100644
--- a/drivers/pwm/pwm-bcm-kona.c
+++ b/drivers/pwm/pwm-bcm-kona.c
@@ -56,14 +56,13 @@
#define DUTY_CYCLE_HIGH_MAX 0x00ffffff
struct kona_pwmc {
- struct pwm_chip chip;
void __iomem *base;
struct clk *clk;
};
static inline struct kona_pwmc *to_kona_pwmc(struct pwm_chip *chip)
{
- return container_of(chip, struct kona_pwmc, chip);
+ return pwmchip_get_drvdata(chip);
}
/*
@@ -164,7 +163,7 @@ static int kona_pwmc_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
ret = clk_prepare_enable(kp->clk);
if (ret < 0) {
- dev_err(chip->dev, "failed to enable clock: %d\n", ret);
+ dev_err(pwmchip_parent(chip), "failed to enable clock: %d\n", ret);
return ret;
}
@@ -193,7 +192,7 @@ static int kona_pwmc_enable(struct pwm_chip *chip, struct pwm_device *pwm)
ret = clk_prepare_enable(kp->clk);
if (ret < 0) {
- dev_err(chip->dev, "failed to enable clock: %d\n", ret);
+ dev_err(pwmchip_parent(chip), "failed to enable clock: %d\n", ret);
return ret;
}
@@ -273,18 +272,18 @@ static const struct pwm_ops kona_pwm_ops = {
static int kona_pwmc_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct kona_pwmc *kp;
unsigned int chan;
unsigned int value = 0;
int ret = 0;
- kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL);
- if (kp == NULL)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 6, sizeof(*kp));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ kp = to_kona_pwmc(chip);
- kp->chip.dev = &pdev->dev;
- kp->chip.ops = &kona_pwm_ops;
- kp->chip.npwm = 6;
+ chip->ops = &kona_pwm_ops;
kp->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(kp->base))
@@ -304,14 +303,14 @@ static int kona_pwmc_probe(struct platform_device *pdev)
}
/* Set push/pull for all channels */
- for (chan = 0; chan < kp->chip.npwm; chan++)
+ for (chan = 0; chan < chip->npwm; chan++)
value |= (1 << PWM_CONTROL_TYPE_SHIFT(chan));
writel(value, kp->base + PWM_CONTROL_OFFSET);
clk_disable_unprepare(kp->clk);
- ret = devm_pwmchip_add(&pdev->dev, &kp->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
diff --git a/drivers/pwm/pwm-bcm2835.c b/drivers/pwm/pwm-bcm2835.c
index 283cf27f25ba..aa35acbb0cbc 100644
--- a/drivers/pwm/pwm-bcm2835.c
+++ b/drivers/pwm/pwm-bcm2835.c
@@ -24,8 +24,6 @@
#define PERIOD_MIN 0x2
struct bcm2835_pwm {
- struct pwm_chip chip;
- struct device *dev;
void __iomem *base;
struct clk *clk;
unsigned long rate;
@@ -33,7 +31,7 @@ struct bcm2835_pwm {
static inline struct bcm2835_pwm *to_bcm2835_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct bcm2835_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static int bcm2835_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -135,14 +133,14 @@ static void devm_clk_rate_exclusive_put(void *data)
static int bcm2835_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct bcm2835_pwm *pc;
int ret;
- pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
- if (!pc)
- return -ENOMEM;
-
- pc->dev = &pdev->dev;
+ chip = devm_pwmchip_alloc(&pdev->dev, 2, sizeof(*pc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pc = to_bcm2835_pwm(chip);
pc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pc->base))
@@ -168,14 +166,12 @@ static int bcm2835_pwm_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, -EINVAL,
"failed to get clock rate\n");
- pc->chip.dev = &pdev->dev;
- pc->chip.ops = &bcm2835_pwm_ops;
- pc->chip.atomic = true;
- pc->chip.npwm = 2;
+ chip->ops = &bcm2835_pwm_ops;
+ chip->atomic = true;
platform_set_drvdata(pdev, pc);
- ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"failed to add pwmchip\n");
diff --git a/drivers/pwm/pwm-berlin.c b/drivers/pwm/pwm-berlin.c
index 442913232dc0..831aed228caf 100644
--- a/drivers/pwm/pwm-berlin.c
+++ b/drivers/pwm/pwm-berlin.c
@@ -49,7 +49,6 @@ struct berlin_pwm_channel {
};
struct berlin_pwm_chip {
- struct pwm_chip chip;
struct clk *clk;
void __iomem *base;
struct berlin_pwm_channel channel[BERLIN_PWM_NUMPWMS];
@@ -57,7 +56,7 @@ struct berlin_pwm_chip {
static inline struct berlin_pwm_chip *to_berlin_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct berlin_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static inline u32 berlin_pwm_readl(struct berlin_pwm_chip *bpc,
@@ -198,12 +197,14 @@ MODULE_DEVICE_TABLE(of, berlin_pwm_match);
static int berlin_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct berlin_pwm_chip *bpc;
int ret;
- bpc = devm_kzalloc(&pdev->dev, sizeof(*bpc), GFP_KERNEL);
- if (!bpc)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, BERLIN_PWM_NUMPWMS, sizeof(*bpc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ bpc = to_berlin_pwm_chip(chip);
bpc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(bpc->base))
@@ -213,25 +214,24 @@ static int berlin_pwm_probe(struct platform_device *pdev)
if (IS_ERR(bpc->clk))
return PTR_ERR(bpc->clk);
- bpc->chip.dev = &pdev->dev;
- bpc->chip.ops = &berlin_pwm_ops;
- bpc->chip.npwm = BERLIN_PWM_NUMPWMS;
+ chip->ops = &berlin_pwm_ops;
- ret = devm_pwmchip_add(&pdev->dev, &bpc->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n");
- platform_set_drvdata(pdev, bpc);
+ platform_set_drvdata(pdev, chip);
return 0;
}
static int berlin_pwm_suspend(struct device *dev)
{
- struct berlin_pwm_chip *bpc = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip);
unsigned int i;
- for (i = 0; i < bpc->chip.npwm; i++) {
+ for (i = 0; i < chip->npwm; i++) {
struct berlin_pwm_channel *channel = &bpc->channel[i];
channel->enable = berlin_pwm_readl(bpc, i, BERLIN_PWM_ENABLE);
@@ -247,7 +247,8 @@ static int berlin_pwm_suspend(struct device *dev)
static int berlin_pwm_resume(struct device *dev)
{
- struct berlin_pwm_chip *bpc = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip);
unsigned int i;
int ret;
@@ -255,7 +256,7 @@ static int berlin_pwm_resume(struct device *dev)
if (ret)
return ret;
- for (i = 0; i < bpc->chip.npwm; i++) {
+ for (i = 0; i < chip->npwm; i++) {
struct berlin_pwm_channel *channel = &bpc->channel[i];
berlin_pwm_writel(bpc, i, channel->ctrl, BERLIN_PWM_CONTROL);
diff --git a/drivers/pwm/pwm-brcmstb.c b/drivers/pwm/pwm-brcmstb.c
index 0fdeb0b2dbf3..82d27d07ba91 100644
--- a/drivers/pwm/pwm-brcmstb.c
+++ b/drivers/pwm/pwm-brcmstb.c
@@ -54,7 +54,6 @@
struct brcmstb_pwm {
void __iomem *base;
struct clk *clk;
- struct pwm_chip chip;
};
static inline u32 brcmstb_pwm_readl(struct brcmstb_pwm *p,
@@ -77,7 +76,7 @@ static inline void brcmstb_pwm_writel(struct brcmstb_pwm *p, u32 value,
static inline struct brcmstb_pwm *to_brcmstb_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct brcmstb_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
/*
@@ -230,12 +229,14 @@ MODULE_DEVICE_TABLE(of, brcmstb_pwm_of_match);
static int brcmstb_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct brcmstb_pwm *p;
int ret;
- p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
- if (!p)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 2, sizeof(*p));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ p = to_brcmstb_pwm(chip);
p->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(p->clk))
@@ -244,15 +245,13 @@ static int brcmstb_pwm_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, p);
- p->chip.dev = &pdev->dev;
- p->chip.ops = &brcmstb_pwm_ops;
- p->chip.npwm = 2;
+ chip->ops = &brcmstb_pwm_ops;
p->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(p->base))
return PTR_ERR(p->base);
- ret = devm_pwmchip_add(&pdev->dev, &p->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret)
return dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n");
diff --git a/drivers/pwm/pwm-clk.c b/drivers/pwm/pwm-clk.c
index 9dd88b386907..c19a482d7e28 100644
--- a/drivers/pwm/pwm-clk.c
+++ b/drivers/pwm/pwm-clk.c
@@ -28,12 +28,14 @@
#include <linux/pwm.h>
struct pwm_clk_chip {
- struct pwm_chip chip;
struct clk *clk;
bool clk_enabled;
};
-#define to_pwm_clk_chip(_chip) container_of(_chip, struct pwm_clk_chip, chip)
+static inline struct pwm_clk_chip *to_pwm_clk_chip(struct pwm_chip *chip)
+{
+ return pwmchip_get_drvdata(chip);
+}
static int pwm_clk_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
@@ -81,35 +83,36 @@ static const struct pwm_ops pwm_clk_ops = {
static int pwm_clk_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct pwm_clk_chip *pcchip;
int ret;
- pcchip = devm_kzalloc(&pdev->dev, sizeof(*pcchip), GFP_KERNEL);
- if (!pcchip)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*pcchip));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pcchip = to_pwm_clk_chip(chip);
pcchip->clk = devm_clk_get_prepared(&pdev->dev, NULL);
if (IS_ERR(pcchip->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(pcchip->clk),
"Failed to get clock\n");
- pcchip->chip.dev = &pdev->dev;
- pcchip->chip.ops = &pwm_clk_ops;
- pcchip->chip.npwm = 1;
+ chip->ops = &pwm_clk_ops;
- ret = pwmchip_add(&pcchip->chip);
+ ret = pwmchip_add(chip);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "Failed to add pwm chip\n");
- platform_set_drvdata(pdev, pcchip);
+ platform_set_drvdata(pdev, chip);
return 0;
}
static void pwm_clk_remove(struct platform_device *pdev)
{
- struct pwm_clk_chip *pcchip = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
+ struct pwm_clk_chip *pcchip = to_pwm_clk_chip(chip);
- pwmchip_remove(&pcchip->chip);
+ pwmchip_remove(chip);
if (pcchip->clk_enabled)
clk_disable(pcchip->clk);
diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c
index 42179b3f7ec3..c950e1dbd2b8 100644
--- a/drivers/pwm/pwm-clps711x.c
+++ b/drivers/pwm/pwm-clps711x.c
@@ -12,7 +12,6 @@
#include <linux/pwm.h>
struct clps711x_chip {
- struct pwm_chip chip;
void __iomem *pmpcon;
struct clk *clk;
spinlock_t lock;
@@ -20,7 +19,7 @@ struct clps711x_chip {
static inline struct clps711x_chip *to_clps711x_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct clps711x_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static int clps711x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -74,22 +73,15 @@ static const struct pwm_ops clps711x_pwm_ops = {
.apply = clps711x_pwm_apply,
};
-static struct pwm_device *clps711x_pwm_xlate(struct pwm_chip *chip,
- const struct of_phandle_args *args)
-{
- if (args->args[0] >= chip->npwm)
- return ERR_PTR(-EINVAL);
-
- return pwm_request_from_chip(chip, args->args[0], NULL);
-}
-
static int clps711x_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct clps711x_chip *priv;
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 2, sizeof(*priv));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ priv = to_clps711x_chip(chip);
priv->pmpcon = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->pmpcon))
@@ -99,15 +91,11 @@ static int clps711x_pwm_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
- priv->chip.ops = &clps711x_pwm_ops;
- priv->chip.dev = &pdev->dev;
- priv->chip.npwm = 2;
- priv->chip.of_xlate = clps711x_pwm_xlate;
- priv->chip.of_pwm_n_cells = 1;
+ chip->ops = &clps711x_pwm_ops;
spin_lock_init(&priv->lock);
- return devm_pwmchip_add(&pdev->dev, &priv->chip);
+ return devm_pwmchip_add(&pdev->dev, chip);
}
static const struct of_device_id __maybe_unused clps711x_pwm_dt_ids[] = {
diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c
index e09358901ab5..98ee5cdbd0ba 100644
--- a/drivers/pwm/pwm-crc.c
+++ b/drivers/pwm/pwm-crc.c
@@ -26,17 +26,15 @@
/**
* struct crystalcove_pwm - Crystal Cove PWM controller
- * @chip: the abstract pwm_chip structure.
* @regmap: the regmap from the parent device.
*/
struct crystalcove_pwm {
- struct pwm_chip chip;
struct regmap *regmap;
};
static inline struct crystalcove_pwm *to_crc_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct crystalcove_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static int crc_pwm_calc_clk_div(int period_ns)
@@ -55,7 +53,7 @@ static int crc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
struct crystalcove_pwm *crc_pwm = to_crc_pwm(chip);
- struct device *dev = crc_pwm->chip.dev;
+ struct device *dev = pwmchip_parent(chip);
int err;
if (state->period > PWM_MAX_PERIOD_NS) {
@@ -125,7 +123,7 @@ static int crc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
{
struct crystalcove_pwm *crc_pwm = to_crc_pwm(chip);
- struct device *dev = crc_pwm->chip.dev;
+ struct device *dev = pwmchip_parent(chip);
unsigned int clk_div, clk_div_reg, duty_cycle_reg;
int error;
@@ -160,22 +158,22 @@ static const struct pwm_ops crc_pwm_ops = {
static int crystalcove_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct crystalcove_pwm *crc_pwm;
struct device *dev = pdev->dev.parent;
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
- crc_pwm = devm_kzalloc(&pdev->dev, sizeof(*crc_pwm), GFP_KERNEL);
- if (!crc_pwm)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*crc_pwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ crc_pwm = to_crc_pwm(chip);
- crc_pwm->chip.dev = &pdev->dev;
- crc_pwm->chip.ops = &crc_pwm_ops;
- crc_pwm->chip.npwm = 1;
+ chip->ops = &crc_pwm_ops;
/* get the PMIC regmap */
crc_pwm->regmap = pmic->regmap;
- return devm_pwmchip_add(&pdev->dev, &crc_pwm->chip);
+ return devm_pwmchip_add(&pdev->dev, chip);
}
static struct platform_driver crystalcove_pwm_driver = {
diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c
index 5fe303b8656d..606ccfdaf4cc 100644
--- a/drivers/pwm/pwm-cros-ec.c
+++ b/drivers/pwm/pwm-cros-ec.c
@@ -19,13 +19,11 @@
* struct cros_ec_pwm_device - Driver data for EC PWM
*
* @ec: Pointer to EC device
- * @chip: PWM controller chip
* @use_pwm_type: Use PWM types instead of generic channels
* @channel: array with per-channel data
*/
struct cros_ec_pwm_device {
struct cros_ec_device *ec;
- struct pwm_chip chip;
bool use_pwm_type;
struct cros_ec_pwm *channel;
};
@@ -40,7 +38,7 @@ struct cros_ec_pwm {
static inline struct cros_ec_pwm_device *pwm_to_cros_ec_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct cros_ec_pwm_device, chip);
+ return pwmchip_get_drvdata(chip);
}
static int cros_ec_dt_type_to_pwm_type(u8 dt_index, u8 *pwm_type)
@@ -93,9 +91,8 @@ static int cros_ec_pwm_set_duty(struct cros_ec_pwm_device *ec_pwm, u8 index,
return cros_ec_cmd_xfer_status(ec, msg);
}
-static int cros_ec_pwm_get_duty(struct cros_ec_pwm_device *ec_pwm, u8 index)
+static int cros_ec_pwm_get_duty(struct cros_ec_device *ec, bool use_pwm_type, u8 index)
{
- struct cros_ec_device *ec = ec_pwm->ec;
struct {
struct cros_ec_command msg;
union {
@@ -115,7 +112,7 @@ static int cros_ec_pwm_get_duty(struct cros_ec_pwm_device *ec_pwm, u8 index)
msg->insize = sizeof(*resp);
msg->outsize = sizeof(*params);
- if (ec_pwm->use_pwm_type) {
+ if (use_pwm_type) {
ret = cros_ec_dt_type_to_pwm_type(index, &params->pwm_type);
if (ret) {
dev_err(ec->dev, "Invalid PWM type index: %d\n", index);
@@ -171,9 +168,9 @@ static int cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct cros_ec_pwm *channel = &ec_pwm->channel[pwm->hwpwm];
int ret;
- ret = cros_ec_pwm_get_duty(ec_pwm, pwm->hwpwm);
+ ret = cros_ec_pwm_get_duty(ec_pwm->ec, ec_pwm->use_pwm_type, pwm->hwpwm);
if (ret < 0) {
- dev_err(chip->dev, "error getting initial duty: %d\n", ret);
+ dev_err(pwmchip_parent(chip), "error getting initial duty: %d\n", ret);
return ret;
}
@@ -226,13 +223,17 @@ static const struct pwm_ops cros_ec_pwm_ops = {
* of PWMs it supports directly, so we have to read the pwm duty cycle for
* subsequent channels until we get an error.
*/
-static int cros_ec_num_pwms(struct cros_ec_pwm_device *ec_pwm)
+static int cros_ec_num_pwms(struct cros_ec_device *ec)
{
int i, ret;
/* The index field is only 8 bits */
for (i = 0; i <= U8_MAX; i++) {
- ret = cros_ec_pwm_get_duty(ec_pwm, i);
+ /*
+ * Note that this function is only called when use_pwm_type is
+ * false. With use_pwm_type == true the number of PWMs is fixed.
+ */
+ ret = cros_ec_pwm_get_duty(ec, false, i);
/*
* We look for SUCCESS, INVALID_COMMAND, or INVALID_PARAM
* responses; everything else is treated as an error.
@@ -261,34 +262,34 @@ static int cros_ec_pwm_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct cros_ec_pwm_device *ec_pwm;
struct pwm_chip *chip;
+ bool use_pwm_type = false;
+ unsigned int npwm;
int ret;
if (!ec)
return dev_err_probe(dev, -EINVAL, "no parent EC device\n");
- ec_pwm = devm_kzalloc(dev, sizeof(*ec_pwm), GFP_KERNEL);
- if (!ec_pwm)
- return -ENOMEM;
- chip = &ec_pwm->chip;
- ec_pwm->ec = ec;
+ if (of_device_is_compatible(np, "google,cros-ec-pwm-type")) {
+ use_pwm_type = true;
+ npwm = CROS_EC_PWM_DT_COUNT;
+ } else {
+ ret = cros_ec_num_pwms(ec);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Couldn't find PWMs\n");
+ npwm = ret;
+ }
+
+ chip = devm_pwmchip_alloc(dev, npwm, sizeof(*ec_pwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
- if (of_device_is_compatible(np, "google,cros-ec-pwm-type"))
- ec_pwm->use_pwm_type = true;
+ ec_pwm = pwm_to_cros_ec_pwm(chip);
+ ec_pwm->use_pwm_type = use_pwm_type;
+ ec_pwm->ec = ec;
/* PWM chip */
- chip->dev = dev;
chip->ops = &cros_ec_pwm_ops;
chip->of_xlate = cros_ec_pwm_xlate;
- chip->of_pwm_n_cells = 1;
-
- if (ec_pwm->use_pwm_type) {
- chip->npwm = CROS_EC_PWM_DT_COUNT;
- } else {
- ret = cros_ec_num_pwms(ec_pwm);
- if (ret < 0)
- return dev_err_probe(dev, ret, "Couldn't find PWMs\n");
- chip->npwm = ret;
- }
ec_pwm->channel = devm_kcalloc(dev, chip->npwm, sizeof(*ec_pwm->channel),
GFP_KERNEL);
diff --git a/drivers/pwm/pwm-dwc-core.c b/drivers/pwm/pwm-dwc-core.c
index ea63dd741f5c..043736972cb9 100644
--- a/drivers/pwm/pwm-dwc-core.c
+++ b/drivers/pwm/pwm-dwc-core.c
@@ -105,12 +105,12 @@ static int dwc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (state->enabled) {
if (!pwm->state.enabled)
- pm_runtime_get_sync(chip->dev);
+ pm_runtime_get_sync(pwmchip_parent(chip));
return __dwc_pwm_configure_timer(dwc, pwm, state);
} else {
if (pwm->state.enabled) {
__dwc_pwm_set_enable(dwc, pwm->hwpwm, false);
- pm_runtime_put_sync(chip->dev);
+ pm_runtime_put_sync(pwmchip_parent(chip));
}
}
@@ -124,7 +124,7 @@ static int dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
u64 duty, period;
u32 ctrl, ld, ld2;
- pm_runtime_get_sync(chip->dev);
+ pm_runtime_get_sync(pwmchip_parent(chip));
ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(pwm->hwpwm));
ld = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(pwm->hwpwm));
@@ -149,7 +149,7 @@ static int dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->period = period;
state->duty_cycle = duty;
- pm_runtime_put_sync(chip->dev);
+ pm_runtime_put_sync(pwmchip_parent(chip));
return 0;
}
@@ -159,21 +159,21 @@ static const struct pwm_ops dwc_pwm_ops = {
.get_state = dwc_pwm_get_state,
};
-struct dwc_pwm *dwc_pwm_alloc(struct device *dev)
+struct pwm_chip *dwc_pwm_alloc(struct device *dev)
{
+ struct pwm_chip *chip;
struct dwc_pwm *dwc;
- dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL);
- if (!dwc)
- return NULL;
+ chip = devm_pwmchip_alloc(dev, DWC_TIMERS_TOTAL, sizeof(*dwc));
+ if (IS_ERR(chip))
+ return chip;
+ dwc = to_dwc_pwm(chip);
dwc->clk_ns = 10;
- dwc->chip.dev = dev;
- dwc->chip.ops = &dwc_pwm_ops;
- dwc->chip.npwm = DWC_TIMERS_TOTAL;
+ chip->ops = &dwc_pwm_ops;
- dev_set_drvdata(dev, dwc);
- return dwc;
+ dev_set_drvdata(dev, chip);
+ return chip;
}
EXPORT_SYMBOL_GPL(dwc_pwm_alloc);
diff --git a/drivers/pwm/pwm-dwc.c b/drivers/pwm/pwm-dwc.c
index 4929354f8cd9..676eaf8d7a53 100644
--- a/drivers/pwm/pwm-dwc.c
+++ b/drivers/pwm/pwm-dwc.c
@@ -25,39 +25,54 @@
#include "pwm-dwc.h"
-static int dwc_pwm_probe(struct pci_dev *pci, const struct pci_device_id *id)
+/* Elkhart Lake */
+static const struct dwc_pwm_info ehl_pwm_info = {
+ .nr = 2,
+ .size = 0x1000,
+};
+
+static int dwc_pwm_init_one(struct device *dev, void __iomem *base, unsigned int offset)
{
- struct device *dev = &pci->dev;
+ struct pwm_chip *chip;
struct dwc_pwm *dwc;
- int ret;
- dwc = dwc_pwm_alloc(dev);
- if (!dwc)
- return -ENOMEM;
+ chip = dwc_pwm_alloc(dev);
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+
+ dwc = to_dwc_pwm(chip);
+ dwc->base = base + offset;
+
+ return devm_pwmchip_add(dev, chip);
+}
+
+static int dwc_pwm_probe(struct pci_dev *pci, const struct pci_device_id *id)
+{
+ const struct dwc_pwm_info *info;
+ struct device *dev = &pci->dev;
+ int i, ret;
ret = pcim_enable_device(pci);
- if (ret) {
- dev_err(dev, "Failed to enable device (%pe)\n", ERR_PTR(ret));
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable device\n");
pci_set_master(pci);
ret = pcim_iomap_regions(pci, BIT(0), pci_name(pci));
- if (ret) {
- dev_err(dev, "Failed to iomap PCI BAR (%pe)\n", ERR_PTR(ret));
- return ret;
- }
-
- dwc->base = pcim_iomap_table(pci)[0];
- if (!dwc->base) {
- dev_err(dev, "Base address missing\n");
- return -ENOMEM;
- }
-
- ret = devm_pwmchip_add(dev, &dwc->chip);
if (ret)
- return ret;
+ return dev_err_probe(dev, ret, "Failed to iomap PCI BAR\n");
+
+ info = (const struct dwc_pwm_info *)id->driver_data;
+
+ for (i = 0; i < info->nr; i++) {
+ /*
+ * No need to check for pcim_iomap_table() failure,
+ * pcim_iomap_regions() already does it for us.
+ */
+ ret = dwc_pwm_init_one(dev, pcim_iomap_table(pci)[0], i * info->size);
+ if (ret)
+ return ret;
+ }
pm_runtime_put(dev);
pm_runtime_allow(dev);
@@ -73,14 +88,14 @@ static void dwc_pwm_remove(struct pci_dev *pci)
static int dwc_pwm_suspend(struct device *dev)
{
- struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
- struct dwc_pwm *dwc = pci_get_drvdata(pdev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct dwc_pwm *dwc = to_dwc_pwm(chip);
int i;
for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
- if (dwc->chip.pwms[i].state.enabled) {
+ if (chip->pwms[i].state.enabled) {
dev_err(dev, "PWM %u in use by consumer (%s)\n",
- i, dwc->chip.pwms[i].label);
+ i, chip->pwms[i].label);
return -EBUSY;
}
dwc->ctx[i].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(i));
@@ -93,8 +108,8 @@ static int dwc_pwm_suspend(struct device *dev)
static int dwc_pwm_resume(struct device *dev)
{
- struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
- struct dwc_pwm *dwc = pci_get_drvdata(pdev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct dwc_pwm *dwc = to_dwc_pwm(chip);
int i;
for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
@@ -109,7 +124,7 @@ static int dwc_pwm_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(dwc_pwm_pm_ops, dwc_pwm_suspend, dwc_pwm_resume);
static const struct pci_device_id dwc_pwm_id_table[] = {
- { PCI_VDEVICE(INTEL, 0x4bb7) }, /* Elkhart Lake */
+ { PCI_VDEVICE(INTEL, 0x4bb7), (kernel_ulong_t)&ehl_pwm_info },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, dwc_pwm_id_table);
@@ -120,7 +135,7 @@ static struct pci_driver dwc_pwm_driver = {
.remove = dwc_pwm_remove,
.id_table = dwc_pwm_id_table,
.driver = {
- .pm = pm_ptr(&dwc_pwm_pm_ops),
+ .pm = pm_sleep_ptr(&dwc_pwm_pm_ops),
},
};
diff --git a/drivers/pwm/pwm-dwc.h b/drivers/pwm/pwm-dwc.h
index 64795247c54c..a8b074841ae8 100644
--- a/drivers/pwm/pwm-dwc.h
+++ b/drivers/pwm/pwm-dwc.h
@@ -33,6 +33,11 @@ MODULE_IMPORT_NS(dwc_pwm);
#define DWC_TIM_CTRL_INT_MASK BIT(2)
#define DWC_TIM_CTRL_PWM BIT(3)
+struct dwc_pwm_info {
+ unsigned int nr;
+ unsigned int size;
+};
+
struct dwc_pwm_ctx {
u32 cnt;
u32 cnt2;
@@ -40,12 +45,15 @@ struct dwc_pwm_ctx {
};
struct dwc_pwm {
- struct pwm_chip chip;
void __iomem *base;
unsigned int clk_ns;
struct dwc_pwm_ctx ctx[DWC_TIMERS_TOTAL];
};
-#define to_dwc_pwm(p) (container_of((p), struct dwc_pwm, chip))
+
+static inline struct dwc_pwm *to_dwc_pwm(struct pwm_chip *chip)
+{
+ return pwmchip_get_drvdata(chip);
+}
static inline u32 dwc_pwm_readl(struct dwc_pwm *dwc, u32 offset)
{
@@ -57,4 +65,4 @@ static inline void dwc_pwm_writel(struct dwc_pwm *dwc, u32 value, u32 offset)
writel(value, dwc->base + offset);
}
-extern struct dwc_pwm *dwc_pwm_alloc(struct device *dev);
+extern struct pwm_chip *dwc_pwm_alloc(struct device *dev);
diff --git a/drivers/pwm/pwm-ep93xx.c b/drivers/pwm/pwm-ep93xx.c
index 51e072572a87..666f2954133c 100644
--- a/drivers/pwm/pwm-ep93xx.c
+++ b/drivers/pwm/pwm-ep93xx.c
@@ -36,24 +36,23 @@
struct ep93xx_pwm {
void __iomem *base;
struct clk *clk;
- struct pwm_chip chip;
};
static inline struct ep93xx_pwm *to_ep93xx_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct ep93xx_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static int ep93xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{
- struct platform_device *pdev = to_platform_device(chip->dev);
+ struct platform_device *pdev = to_platform_device(pwmchip_parent(chip));
return ep93xx_pwm_acquire_gpio(pdev);
}
static void ep93xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
{
- struct platform_device *pdev = to_platform_device(chip->dev);
+ struct platform_device *pdev = to_platform_device(pwmchip_parent(chip));
ep93xx_pwm_release_gpio(pdev);
}
@@ -163,12 +162,14 @@ static const struct pwm_ops ep93xx_pwm_ops = {
static int ep93xx_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct ep93xx_pwm *ep93xx_pwm;
int ret;
- ep93xx_pwm = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_pwm), GFP_KERNEL);
- if (!ep93xx_pwm)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*ep93xx_pwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ ep93xx_pwm = to_ep93xx_pwm(chip);
ep93xx_pwm->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ep93xx_pwm->base))
@@ -178,11 +179,9 @@ static int ep93xx_pwm_probe(struct platform_device *pdev)
if (IS_ERR(ep93xx_pwm->clk))
return PTR_ERR(ep93xx_pwm->clk);
- ep93xx_pwm->chip.dev = &pdev->dev;
- ep93xx_pwm->chip.ops = &ep93xx_pwm_ops;
- ep93xx_pwm->chip.npwm = 1;
+ chip->ops = &ep93xx_pwm_ops;
- ret = devm_pwmchip_add(&pdev->dev, &ep93xx_pwm->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
return ret;
diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c
index d1b6d1aa4773..2510c10ca473 100644
--- a/drivers/pwm/pwm-fsl-ftm.c
+++ b/drivers/pwm/pwm-fsl-ftm.c
@@ -40,7 +40,6 @@ struct fsl_pwm_periodcfg {
};
struct fsl_pwm_chip {
- struct pwm_chip chip;
struct mutex lock;
struct regmap *regmap;
@@ -55,7 +54,7 @@ struct fsl_pwm_chip {
static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct fsl_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static void ftm_clear_write_protection(struct fsl_pwm_chip *fpc)
@@ -221,10 +220,11 @@ static bool fsl_pwm_is_other_pwm_enabled(struct fsl_pwm_chip *fpc,
return false;
}
-static int fsl_pwm_apply_config(struct fsl_pwm_chip *fpc,
+static int fsl_pwm_apply_config(struct pwm_chip *chip,
struct pwm_device *pwm,
const struct pwm_state *newstate)
{
+ struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
unsigned int duty;
u32 reg_polarity;
@@ -232,7 +232,7 @@ static int fsl_pwm_apply_config(struct fsl_pwm_chip *fpc,
bool do_write_period = false;
if (!fsl_pwm_calculate_period(fpc, newstate->period, &periodcfg)) {
- dev_err(fpc->chip.dev, "failed to calculate new period\n");
+ dev_err(pwmchip_parent(chip), "failed to calculate new period\n");
return -EINVAL;
}
@@ -246,7 +246,7 @@ static int fsl_pwm_apply_config(struct fsl_pwm_chip *fpc,
*/
else if (!fsl_pwm_periodcfg_are_equal(&fpc->period, &periodcfg)) {
if (fsl_pwm_is_other_pwm_enabled(fpc, pwm)) {
- dev_err(fpc->chip.dev,
+ dev_err(pwmchip_parent(chip),
"Cannot change period for PWM %u, disable other PWMs first\n",
pwm->hwpwm);
return -EBUSY;
@@ -322,7 +322,7 @@ static int fsl_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
goto end_mutex;
}
- ret = fsl_pwm_apply_config(fpc, pwm, newstate);
+ ret = fsl_pwm_apply_config(chip, pwm, newstate);
if (ret)
goto end_mutex;
@@ -392,18 +392,19 @@ static const struct regmap_config fsl_pwm_regmap_config = {
static int fsl_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct fsl_pwm_chip *fpc;
void __iomem *base;
int ret;
- fpc = devm_kzalloc(&pdev->dev, sizeof(*fpc), GFP_KERNEL);
- if (!fpc)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 8, sizeof(*fpc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ fpc = to_fsl_chip(chip);
mutex_init(&fpc->lock);
fpc->soc = of_device_get_match_data(&pdev->dev);
- fpc->chip.dev = &pdev->dev;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
@@ -422,16 +423,16 @@ static int fsl_pwm_probe(struct platform_device *pdev)
return PTR_ERR(fpc->clk[FSL_PWM_CLK_SYS]);
}
- fpc->clk[FSL_PWM_CLK_FIX] = devm_clk_get(fpc->chip.dev, "ftm_fix");
+ fpc->clk[FSL_PWM_CLK_FIX] = devm_clk_get(&pdev->dev, "ftm_fix");
if (IS_ERR(fpc->clk[FSL_PWM_CLK_FIX]))
return PTR_ERR(fpc->clk[FSL_PWM_CLK_FIX]);
- fpc->clk[FSL_PWM_CLK_EXT] = devm_clk_get(fpc->chip.dev, "ftm_ext");
+ fpc->clk[FSL_PWM_CLK_EXT] = devm_clk_get(&pdev->dev, "ftm_ext");
if (IS_ERR(fpc->clk[FSL_PWM_CLK_EXT]))
return PTR_ERR(fpc->clk[FSL_PWM_CLK_EXT]);
fpc->clk[FSL_PWM_CLK_CNTEN] =
- devm_clk_get(fpc->chip.dev, "ftm_cnt_clk_en");
+ devm_clk_get(&pdev->dev, "ftm_cnt_clk_en");
if (IS_ERR(fpc->clk[FSL_PWM_CLK_CNTEN]))
return PTR_ERR(fpc->clk[FSL_PWM_CLK_CNTEN]);
@@ -443,17 +444,15 @@ static int fsl_pwm_probe(struct platform_device *pdev)
if (IS_ERR(fpc->ipg_clk))
fpc->ipg_clk = fpc->clk[FSL_PWM_CLK_SYS];
+ chip->ops = &fsl_pwm_ops;
- fpc->chip.ops = &fsl_pwm_ops;
- fpc->chip.npwm = 8;
-
- ret = devm_pwmchip_add(&pdev->dev, &fpc->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
return ret;
}
- platform_set_drvdata(pdev, fpc);
+ platform_set_drvdata(pdev, chip);
return fsl_pwm_init(fpc);
}
@@ -461,14 +460,15 @@ static int fsl_pwm_probe(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int fsl_pwm_suspend(struct device *dev)
{
- struct fsl_pwm_chip *fpc = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
int i;
regcache_cache_only(fpc->regmap, true);
regcache_mark_dirty(fpc->regmap);
- for (i = 0; i < fpc->chip.npwm; i++) {
- struct pwm_device *pwm = &fpc->chip.pwms[i];
+ for (i = 0; i < chip->npwm; i++) {
+ struct pwm_device *pwm = &chip->pwms[i];
if (!test_bit(PWMF_REQUESTED, &pwm->flags))
continue;
@@ -487,11 +487,12 @@ static int fsl_pwm_suspend(struct device *dev)
static int fsl_pwm_resume(struct device *dev)
{
- struct fsl_pwm_chip *fpc = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
int i;
- for (i = 0; i < fpc->chip.npwm; i++) {
- struct pwm_device *pwm = &fpc->chip.pwms[i];
+ for (i = 0; i < chip->npwm; i++) {
+ struct pwm_device *pwm = &chip->pwms[i];
if (!test_bit(PWMF_REQUESTED, &pwm->flags))
continue;
diff --git a/drivers/pwm/pwm-hibvt.c b/drivers/pwm/pwm-hibvt.c
index c435776e2f78..2eb0b13d4e10 100644
--- a/drivers/pwm/pwm-hibvt.c
+++ b/drivers/pwm/pwm-hibvt.c
@@ -33,7 +33,6 @@
#define PWM_DUTY_MASK GENMASK(31, 0)
struct hibvt_pwm_chip {
- struct pwm_chip chip;
struct clk *clk;
void __iomem *base;
struct reset_control *rstc;
@@ -65,7 +64,7 @@ static const struct hibvt_pwm_soc hi3559v100_soc_info = {
static inline struct hibvt_pwm_chip *to_hibvt_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct hibvt_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static void hibvt_pwm_set_bits(void __iomem *base, u32 offset,
@@ -191,72 +190,71 @@ static int hibvt_pwm_probe(struct platform_device *pdev)
{
const struct hibvt_pwm_soc *soc =
of_device_get_match_data(&pdev->dev);
- struct hibvt_pwm_chip *pwm_chip;
+ struct pwm_chip *chip;
+ struct hibvt_pwm_chip *hi_pwm_chip;
int ret, i;
- pwm_chip = devm_kzalloc(&pdev->dev, sizeof(*pwm_chip), GFP_KERNEL);
- if (pwm_chip == NULL)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, soc->num_pwms, sizeof(*hi_pwm_chip));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ hi_pwm_chip = to_hibvt_pwm_chip(chip);
- pwm_chip->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(pwm_chip->clk)) {
+ hi_pwm_chip->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(hi_pwm_chip->clk)) {
dev_err(&pdev->dev, "getting clock failed with %ld\n",
- PTR_ERR(pwm_chip->clk));
- return PTR_ERR(pwm_chip->clk);
+ PTR_ERR(hi_pwm_chip->clk));
+ return PTR_ERR(hi_pwm_chip->clk);
}
- pwm_chip->chip.ops = &hibvt_pwm_ops;
- pwm_chip->chip.dev = &pdev->dev;
- pwm_chip->chip.npwm = soc->num_pwms;
- pwm_chip->soc = soc;
+ chip->ops = &hibvt_pwm_ops;
+ hi_pwm_chip->soc = soc;
- pwm_chip->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(pwm_chip->base))
- return PTR_ERR(pwm_chip->base);
+ hi_pwm_chip->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(hi_pwm_chip->base))
+ return PTR_ERR(hi_pwm_chip->base);
- ret = clk_prepare_enable(pwm_chip->clk);
+ ret = clk_prepare_enable(hi_pwm_chip->clk);
if (ret < 0)
return ret;
- pwm_chip->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
- if (IS_ERR(pwm_chip->rstc)) {
- clk_disable_unprepare(pwm_chip->clk);
- return PTR_ERR(pwm_chip->rstc);
+ hi_pwm_chip->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(hi_pwm_chip->rstc)) {
+ clk_disable_unprepare(hi_pwm_chip->clk);
+ return PTR_ERR(hi_pwm_chip->rstc);
}
- reset_control_assert(pwm_chip->rstc);
+ reset_control_assert(hi_pwm_chip->rstc);
msleep(30);
- reset_control_deassert(pwm_chip->rstc);
+ reset_control_deassert(hi_pwm_chip->rstc);
- ret = pwmchip_add(&pwm_chip->chip);
+ ret = pwmchip_add(chip);
if (ret < 0) {
- clk_disable_unprepare(pwm_chip->clk);
+ clk_disable_unprepare(hi_pwm_chip->clk);
return ret;
}
- for (i = 0; i < pwm_chip->chip.npwm; i++) {
- hibvt_pwm_set_bits(pwm_chip->base, PWM_CTRL_ADDR(i),
+ for (i = 0; i < chip->npwm; i++) {
+ hibvt_pwm_set_bits(hi_pwm_chip->base, PWM_CTRL_ADDR(i),
PWM_KEEP_MASK, (0x1 << PWM_KEEP_SHIFT));
}
- platform_set_drvdata(pdev, pwm_chip);
+ platform_set_drvdata(pdev, chip);
return 0;
}
static void hibvt_pwm_remove(struct platform_device *pdev)
{
- struct hibvt_pwm_chip *pwm_chip;
-
- pwm_chip = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
+ struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip);
- pwmchip_remove(&pwm_chip->chip);
+ pwmchip_remove(chip);
- reset_control_assert(pwm_chip->rstc);
+ reset_control_assert(hi_pwm_chip->rstc);
msleep(30);
- reset_control_deassert(pwm_chip->rstc);
+ reset_control_deassert(hi_pwm_chip->rstc);
- clk_disable_unprepare(pwm_chip->clk);
+ clk_disable_unprepare(hi_pwm_chip->clk);
}
static const struct of_device_id hibvt_pwm_of_match[] = {
diff --git a/drivers/pwm/pwm-img.c b/drivers/pwm/pwm-img.c
index 5965ac35b32e..d79a96679a26 100644
--- a/drivers/pwm/pwm-img.c
+++ b/drivers/pwm/pwm-img.c
@@ -59,8 +59,6 @@ struct img_pwm_soc_data {
};
struct img_pwm_chip {
- struct device *dev;
- struct pwm_chip chip;
struct clk *pwm_clk;
struct clk *sys_clk;
void __iomem *base;
@@ -74,7 +72,7 @@ struct img_pwm_chip {
static inline struct img_pwm_chip *to_img_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct img_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static inline void img_pwm_writel(struct img_pwm_chip *imgchip,
@@ -99,7 +97,7 @@ static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
if (period_ns < imgchip->min_period_ns ||
period_ns > imgchip->max_period_ns) {
- dev_err(chip->dev, "configured period not in range\n");
+ dev_err(pwmchip_parent(chip), "configured period not in range\n");
return -ERANGE;
}
@@ -120,14 +118,14 @@ static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
div = PWM_CTRL_CFG_SUB_DIV0_DIV1;
timebase = DIV_ROUND_UP(mul, 512);
} else {
- dev_err(chip->dev,
+ dev_err(pwmchip_parent(chip),
"failed to configure timebase steps/divider value\n");
return -EINVAL;
}
duty = DIV_ROUND_UP(timebase * duty_ns, period_ns);
- ret = pm_runtime_resume_and_get(chip->dev);
+ ret = pm_runtime_resume_and_get(pwmchip_parent(chip));
if (ret < 0)
return ret;
@@ -141,8 +139,8 @@ static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
(timebase << PWM_CH_CFG_TMBASE_SHIFT);
img_pwm_writel(imgchip, PWM_CH_CFG(pwm->hwpwm), val);
- pm_runtime_mark_last_busy(chip->dev);
- pm_runtime_put_autosuspend(chip->dev);
+ pm_runtime_mark_last_busy(pwmchip_parent(chip));
+ pm_runtime_put_autosuspend(pwmchip_parent(chip));
return 0;
}
@@ -153,7 +151,7 @@ static int img_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);
int ret;
- ret = pm_runtime_resume_and_get(chip->dev);
+ ret = pm_runtime_resume_and_get(pwmchip_parent(chip));
if (ret < 0)
return ret;
@@ -177,8 +175,8 @@ static void img_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
val &= ~BIT(pwm->hwpwm);
img_pwm_writel(imgchip, PWM_CTRL_CFG, val);
- pm_runtime_mark_last_busy(chip->dev);
- pm_runtime_put_autosuspend(chip->dev);
+ pm_runtime_mark_last_busy(pwmchip_parent(chip));
+ pm_runtime_put_autosuspend(pwmchip_parent(chip));
}
static int img_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -225,7 +223,8 @@ MODULE_DEVICE_TABLE(of, img_pwm_of_match);
static int img_pwm_runtime_suspend(struct device *dev)
{
- struct img_pwm_chip *imgchip = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);
clk_disable_unprepare(imgchip->pwm_clk);
clk_disable_unprepare(imgchip->sys_clk);
@@ -235,7 +234,8 @@ static int img_pwm_runtime_suspend(struct device *dev)
static int img_pwm_runtime_resume(struct device *dev)
{
- struct img_pwm_chip *imgchip = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);
int ret;
ret = clk_prepare_enable(imgchip->sys_clk);
@@ -259,13 +259,13 @@ static int img_pwm_probe(struct platform_device *pdev)
int ret;
u64 val;
unsigned long clk_rate;
+ struct pwm_chip *chip;
struct img_pwm_chip *imgchip;
- imgchip = devm_kzalloc(&pdev->dev, sizeof(*imgchip), GFP_KERNEL);
- if (!imgchip)
- return -ENOMEM;
-
- imgchip->dev = &pdev->dev;
+ chip = devm_pwmchip_alloc(&pdev->dev, IMG_PWM_NPWM, sizeof(*imgchip));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ imgchip = to_img_pwm_chip(chip);
imgchip->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(imgchip->base))
@@ -290,7 +290,7 @@ static int img_pwm_probe(struct platform_device *pdev)
return PTR_ERR(imgchip->pwm_clk);
}
- platform_set_drvdata(pdev, imgchip);
+ platform_set_drvdata(pdev, chip);
pm_runtime_set_autosuspend_delay(&pdev->dev, IMG_PWM_PM_TIMEOUT);
pm_runtime_use_autosuspend(&pdev->dev);
@@ -317,11 +317,9 @@ static int img_pwm_probe(struct platform_device *pdev)
do_div(val, clk_rate);
imgchip->min_period_ns = val;
- imgchip->chip.dev = &pdev->dev;
- imgchip->chip.ops = &img_pwm_ops;
- imgchip->chip.npwm = IMG_PWM_NPWM;
+ chip->ops = &img_pwm_ops;
- ret = pwmchip_add(&imgchip->chip);
+ ret = pwmchip_add(chip);
if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret);
goto err_suspend;
@@ -340,19 +338,20 @@ err_pm_disable:
static void img_pwm_remove(struct platform_device *pdev)
{
- struct img_pwm_chip *imgchip = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
img_pwm_runtime_suspend(&pdev->dev);
- pwmchip_remove(&imgchip->chip);
+ pwmchip_remove(chip);
}
#ifdef CONFIG_PM_SLEEP
static int img_pwm_suspend(struct device *dev)
{
- struct img_pwm_chip *imgchip = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);
int i, ret;
if (pm_runtime_status_suspended(dev)) {
@@ -361,7 +360,7 @@ static int img_pwm_suspend(struct device *dev)
return ret;
}
- for (i = 0; i < imgchip->chip.npwm; i++)
+ for (i = 0; i < chip->npwm; i++)
imgchip->suspend_ch_cfg[i] = img_pwm_readl(imgchip,
PWM_CH_CFG(i));
@@ -374,7 +373,8 @@ static int img_pwm_suspend(struct device *dev)
static int img_pwm_resume(struct device *dev)
{
- struct img_pwm_chip *imgchip = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);
int ret;
int i;
@@ -382,13 +382,13 @@ static int img_pwm_resume(struct device *dev)
if (ret)
return ret;
- for (i = 0; i < imgchip->chip.npwm; i++)
+ for (i = 0; i < chip->npwm; i++)
img_pwm_writel(imgchip, PWM_CH_CFG(i),
imgchip->suspend_ch_cfg[i]);
img_pwm_writel(imgchip, PWM_CTRL_CFG, imgchip->suspend_ctrl_cfg);
- for (i = 0; i < imgchip->chip.npwm; i++)
+ for (i = 0; i < chip->npwm; i++)
if (imgchip->suspend_ctrl_cfg & BIT(i))
regmap_clear_bits(imgchip->periph_regs,
PERIP_PWM_PDM_CONTROL,
diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c
index 9fc290e647e1..c50ddbac43c8 100644
--- a/drivers/pwm/pwm-imx-tpm.c
+++ b/drivers/pwm/pwm-imx-tpm.c
@@ -57,7 +57,6 @@
#define PWM_IMX_TPM_MOD_MOD GENMASK(PWM_IMX_TPM_MOD_WIDTH - 1, 0)
struct imx_tpm_pwm_chip {
- struct pwm_chip chip;
struct clk *clk;
void __iomem *base;
struct mutex lock;
@@ -75,7 +74,7 @@ struct imx_tpm_pwm_param {
static inline struct imx_tpm_pwm_chip *
to_imx_tpm_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct imx_tpm_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
/*
@@ -336,35 +335,42 @@ static const struct pwm_ops imx_tpm_pwm_ops = {
static int pwm_imx_tpm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct imx_tpm_pwm_chip *tpm;
+ struct clk *clk;
+ void __iomem *base;
int ret;
+ unsigned int npwm;
u32 val;
- tpm = devm_kzalloc(&pdev->dev, sizeof(*tpm), GFP_KERNEL);
- if (!tpm)
- return -ENOMEM;
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
- platform_set_drvdata(pdev, tpm);
+ clk = devm_clk_get_enabled(&pdev->dev, NULL);
+ if (IS_ERR(clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(clk),
+ "failed to get PWM clock\n");
- tpm->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(tpm->base))
- return PTR_ERR(tpm->base);
+ /* get number of channels */
+ val = readl(base + PWM_IMX_TPM_PARAM);
+ npwm = FIELD_GET(PWM_IMX_TPM_PARAM_CHAN, val);
- tpm->clk = devm_clk_get_enabled(&pdev->dev, NULL);
- if (IS_ERR(tpm->clk))
- return dev_err_probe(&pdev->dev, PTR_ERR(tpm->clk),
- "failed to get PWM clock\n");
+ chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*tpm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ tpm = to_imx_tpm_pwm_chip(chip);
+
+ platform_set_drvdata(pdev, tpm);
- tpm->chip.dev = &pdev->dev;
- tpm->chip.ops = &imx_tpm_pwm_ops;
+ tpm->base = base;
+ tpm->clk = clk;
- /* get number of channels */
- val = readl(tpm->base + PWM_IMX_TPM_PARAM);
- tpm->chip.npwm = FIELD_GET(PWM_IMX_TPM_PARAM_CHAN, val);
+ chip->ops = &imx_tpm_pwm_ops;
mutex_init(&tpm->lock);
- ret = devm_pwmchip_add(&pdev->dev, &tpm->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret)
return dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n");
diff --git a/drivers/pwm/pwm-imx1.c b/drivers/pwm/pwm-imx1.c
index d175d895f22a..1d2aae2d278f 100644
--- a/drivers/pwm/pwm-imx1.c
+++ b/drivers/pwm/pwm-imx1.c
@@ -28,10 +28,12 @@ struct pwm_imx1_chip {
struct clk *clk_ipg;
struct clk *clk_per;
void __iomem *mmio_base;
- struct pwm_chip chip;
};
-#define to_pwm_imx1_chip(chip) container_of(chip, struct pwm_imx1_chip, chip)
+static inline struct pwm_imx1_chip *to_pwm_imx1_chip(struct pwm_chip *chip)
+{
+ return pwmchip_get_drvdata(chip);
+}
static int pwm_imx1_clk_prepare_enable(struct pwm_chip *chip)
{
@@ -156,11 +158,13 @@ MODULE_DEVICE_TABLE(of, pwm_imx1_dt_ids);
static int pwm_imx1_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct pwm_imx1_chip *imx;
- imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
- if (!imx)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*imx));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ imx = to_pwm_imx1_chip(chip);
imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(imx->clk_ipg))
@@ -172,15 +176,13 @@ static int pwm_imx1_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(imx->clk_per),
"failed to get peripheral clock\n");
- imx->chip.ops = &pwm_imx1_ops;
- imx->chip.dev = &pdev->dev;
- imx->chip.npwm = 1;
+ chip->ops = &pwm_imx1_ops;
imx->mmio_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(imx->mmio_base))
return PTR_ERR(imx->mmio_base);
- return devm_pwmchip_add(&pdev->dev, &imx->chip);
+ return devm_pwmchip_add(&pdev->dev, chip);
}
static struct platform_driver pwm_imx1_driver = {
diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c
index 7d9bc43f12b0..e1412116ef65 100644
--- a/drivers/pwm/pwm-imx27.c
+++ b/drivers/pwm/pwm-imx27.c
@@ -83,7 +83,6 @@ struct pwm_imx27_chip {
struct clk *clk_ipg;
struct clk *clk_per;
void __iomem *mmio_base;
- struct pwm_chip chip;
/*
* The driver cannot read the current duty cycle from the hardware if
@@ -93,7 +92,10 @@ struct pwm_imx27_chip {
unsigned int duty_cycle;
};
-#define to_pwm_imx27_chip(chip) container_of(chip, struct pwm_imx27_chip, chip)
+static inline struct pwm_imx27_chip *to_pwm_imx27_chip(struct pwm_chip *chip)
+{
+ return pwmchip_get_drvdata(chip);
+}
static int pwm_imx27_clk_prepare_enable(struct pwm_imx27_chip *imx)
{
@@ -145,7 +147,7 @@ static int pwm_imx27_get_state(struct pwm_chip *chip,
state->polarity = PWM_POLARITY_INVERSED;
break;
default:
- dev_warn(chip->dev, "can't set polarity, output disconnected");
+ dev_warn(pwmchip_parent(chip), "can't set polarity, output disconnected");
}
prescaler = MX3_PWMCR_PRESCALER_GET(val);
@@ -177,7 +179,7 @@ static int pwm_imx27_get_state(struct pwm_chip *chip,
static void pwm_imx27_sw_reset(struct pwm_chip *chip)
{
struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
- struct device *dev = chip->dev;
+ struct device *dev = pwmchip_parent(chip);
int wait_count = 0;
u32 cr;
@@ -196,7 +198,7 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
struct pwm_device *pwm)
{
struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
- struct device *dev = chip->dev;
+ struct device *dev = pwmchip_parent(chip);
unsigned int period_ms;
int fifoav;
u32 sr;
@@ -204,8 +206,8 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
sr = readl(imx->mmio_base + MX3_PWMSR);
fifoav = FIELD_GET(MX3_PWMSR_FIFOAV, sr);
if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) {
- period_ms = DIV_ROUND_UP_ULL(pwm_get_period(pwm),
- NSEC_PER_MSEC);
+ period_ms = DIV_ROUND_UP_ULL(pwm->state.period,
+ NSEC_PER_MSEC);
msleep(period_ms);
sr = readl(imx->mmio_base + MX3_PWMSR);
@@ -219,14 +221,11 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
{
unsigned long period_cycles, duty_cycles, prescale;
struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
- struct pwm_state cstate;
unsigned long long c;
unsigned long long clkrate;
int ret;
u32 cr;
- pwm_get_state(pwm, &cstate);
-
clkrate = clk_get_rate(imx->clk_per);
c = clkrate * state->period;
@@ -254,7 +253,7 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
* Wait for a free FIFO slot if the PWM is already enabled, and flush
* the FIFO if the PWM was disabled and is about to be enabled.
*/
- if (cstate.enabled) {
+ if (pwm->state.enabled) {
pwm_imx27_wait_fifo_slot(chip, pwm);
} else {
ret = pwm_imx27_clk_prepare_enable(imx);
@@ -306,13 +305,15 @@ MODULE_DEVICE_TABLE(of, pwm_imx27_dt_ids);
static int pwm_imx27_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct pwm_imx27_chip *imx;
int ret;
u32 pwmcr;
- imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
- if (imx == NULL)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*imx));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ imx = to_pwm_imx27_chip(chip);
imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(imx->clk_ipg))
@@ -324,9 +325,7 @@ static int pwm_imx27_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(imx->clk_per),
"failed to get peripheral clock\n");
- imx->chip.ops = &pwm_imx27_ops;
- imx->chip.dev = &pdev->dev;
- imx->chip.npwm = 1;
+ chip->ops = &pwm_imx27_ops;
imx->mmio_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(imx->mmio_base))
@@ -341,7 +340,7 @@ static int pwm_imx27_probe(struct platform_device *pdev)
if (!(pwmcr & MX3_PWMCR_EN))
pwm_imx27_clk_disable_unprepare(imx);
- return devm_pwmchip_add(&pdev->dev, &imx->chip);
+ return devm_pwmchip_add(&pdev->dev, chip);
}
static struct platform_driver imx_pwm_driver = {
diff --git a/drivers/pwm/pwm-intel-lgm.c b/drivers/pwm/pwm-intel-lgm.c
index 54ecae7f937e..f9cc7c17c8f0 100644
--- a/drivers/pwm/pwm-intel-lgm.c
+++ b/drivers/pwm/pwm-intel-lgm.c
@@ -42,14 +42,13 @@
#define LGM_PWM_PERIOD_2WIRE_NS (40 * NSEC_PER_MSEC)
struct lgm_pwm_chip {
- struct pwm_chip chip;
struct regmap *regmap;
u32 period;
};
static inline struct lgm_pwm_chip *to_lgm_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct lgm_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static int lgm_pwm_enable(struct pwm_chip *chip, bool enable)
@@ -168,14 +167,16 @@ static int lgm_pwm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct reset_control *rst;
+ struct pwm_chip *chip;
struct lgm_pwm_chip *pc;
void __iomem *io_base;
struct clk *clk;
int ret;
- pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
- if (!pc)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(dev, 1, sizeof(*pc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pc = to_lgm_pwm_chip(chip);
io_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(io_base))
@@ -203,13 +204,11 @@ static int lgm_pwm_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "cannot deassert reset control\n");
- pc->chip.dev = dev;
- pc->chip.ops = &lgm_pwm_ops;
- pc->chip.npwm = 1;
+ chip->ops = &lgm_pwm_ops;
lgm_pwm_init(pc);
- ret = devm_pwmchip_add(dev, &pc->chip);
+ ret = devm_pwmchip_add(dev, chip);
if (ret < 0)
return dev_err_probe(dev, ret, "failed to add PWM chip\n");
diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c
index 378ab036edfe..13e5e138c8e9 100644
--- a/drivers/pwm/pwm-iqs620a.c
+++ b/drivers/pwm/pwm-iqs620a.c
@@ -34,12 +34,17 @@
struct iqs620_pwm_private {
struct iqs62x_core *iqs62x;
- struct pwm_chip chip;
+ struct device *dev;
struct notifier_block notifier;
struct mutex lock;
unsigned int duty_scale;
};
+static inline struct iqs620_pwm_private *iqs620_pwm_from_chip(struct pwm_chip *chip)
+{
+ return pwmchip_get_drvdata(chip);
+}
+
static int iqs620_pwm_init(struct iqs620_pwm_private *iqs620_pwm,
unsigned int duty_scale)
{
@@ -73,7 +78,7 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (state->period < IQS620_PWM_PERIOD_NS)
return -EINVAL;
- iqs620_pwm = container_of(chip, struct iqs620_pwm_private, chip);
+ iqs620_pwm = iqs620_pwm_from_chip(chip);
/*
* The duty cycle generated by the device is calculated as follows:
@@ -109,7 +114,7 @@ static int iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
{
struct iqs620_pwm_private *iqs620_pwm;
- iqs620_pwm = container_of(chip, struct iqs620_pwm_private, chip);
+ iqs620_pwm = iqs620_pwm_from_chip(chip);
mutex_lock(&iqs620_pwm->lock);
@@ -155,7 +160,7 @@ static int iqs620_pwm_notifier(struct notifier_block *notifier,
mutex_unlock(&iqs620_pwm->lock);
if (ret) {
- dev_err(iqs620_pwm->chip.dev,
+ dev_err(iqs620_pwm->dev,
"Failed to re-initialize device: %d\n", ret);
return NOTIFY_BAD;
}
@@ -176,21 +181,24 @@ static void iqs620_pwm_notifier_unregister(void *context)
ret = blocking_notifier_chain_unregister(&iqs620_pwm->iqs62x->nh,
&iqs620_pwm->notifier);
if (ret)
- dev_err(iqs620_pwm->chip.dev,
+ dev_err(iqs620_pwm->dev,
"Failed to unregister notifier: %d\n", ret);
}
static int iqs620_pwm_probe(struct platform_device *pdev)
{
struct iqs62x_core *iqs62x = dev_get_drvdata(pdev->dev.parent);
+ struct pwm_chip *chip;
struct iqs620_pwm_private *iqs620_pwm;
unsigned int val;
int ret;
- iqs620_pwm = devm_kzalloc(&pdev->dev, sizeof(*iqs620_pwm), GFP_KERNEL);
- if (!iqs620_pwm)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*iqs620_pwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ iqs620_pwm = iqs620_pwm_from_chip(chip);
+ iqs620_pwm->dev = &pdev->dev;
iqs620_pwm->iqs62x = iqs62x;
ret = regmap_read(iqs62x->regmap, IQS620_PWR_SETTINGS, &val);
@@ -205,9 +213,7 @@ static int iqs620_pwm_probe(struct platform_device *pdev)
iqs620_pwm->duty_scale = val + 1;
}
- iqs620_pwm->chip.dev = &pdev->dev;
- iqs620_pwm->chip.ops = &iqs620_pwm_ops;
- iqs620_pwm->chip.npwm = 1;
+ chip->ops = &iqs620_pwm_ops;
mutex_init(&iqs620_pwm->lock);
@@ -225,7 +231,7 @@ static int iqs620_pwm_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = devm_pwmchip_add(&pdev->dev, &iqs620_pwm->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret)
dev_err(&pdev->dev, "Failed to add device: %d\n", ret);
diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
index 3933418e551b..da4bf543d357 100644
--- a/drivers/pwm/pwm-jz4740.c
+++ b/drivers/pwm/pwm-jz4740.c
@@ -25,23 +25,21 @@ struct soc_info {
};
struct jz4740_pwm_chip {
- struct pwm_chip chip;
struct regmap *map;
struct clk *clk[];
};
static inline struct jz4740_pwm_chip *to_jz4740(struct pwm_chip *chip)
{
- return container_of(chip, struct jz4740_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
-static bool jz4740_pwm_can_use_chn(struct jz4740_pwm_chip *jz,
- unsigned int channel)
+static bool jz4740_pwm_can_use_chn(struct pwm_chip *chip, unsigned int channel)
{
/* Enable all TCU channels for PWM use by default except channels 0/1 */
- u32 pwm_channels_mask = GENMASK(jz->chip.npwm - 1, 2);
+ u32 pwm_channels_mask = GENMASK(chip->npwm - 1, 2);
- device_property_read_u32(jz->chip.dev->parent,
+ device_property_read_u32(pwmchip_parent(chip)->parent,
"ingenic,pwm-channels-mask",
&pwm_channels_mask);
@@ -55,14 +53,15 @@ static int jz4740_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
char name[16];
int err;
- if (!jz4740_pwm_can_use_chn(jz, pwm->hwpwm))
+ if (!jz4740_pwm_can_use_chn(chip, pwm->hwpwm))
return -EBUSY;
snprintf(name, sizeof(name), "timer%u", pwm->hwpwm);
- clk = clk_get(chip->dev, name);
+ clk = clk_get(pwmchip_parent(chip), name);
if (IS_ERR(clk)) {
- dev_err(chip->dev, "error %pe: Failed to get clock\n", clk);
+ dev_err(pwmchip_parent(chip),
+ "error %pe: Failed to get clock\n", clk);
return PTR_ERR(clk);
}
@@ -150,7 +149,7 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
*/
rate = clk_round_rate(clk, tmp);
if (rate < 0) {
- dev_err(chip->dev, "Unable to round rate: %ld\n", rate);
+ dev_err(pwmchip_parent(chip), "Unable to round rate: %ld\n", rate);
return rate;
}
@@ -171,7 +170,7 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
err = clk_set_rate(clk, rate);
if (err) {
- dev_err(chip->dev, "Unable to set rate: %d\n", err);
+ dev_err(pwmchip_parent(chip), "Unable to set rate: %d\n", err);
return err;
}
@@ -224,6 +223,7 @@ static const struct pwm_ops jz4740_pwm_ops = {
static int jz4740_pwm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct pwm_chip *chip;
struct jz4740_pwm_chip *jz;
const struct soc_info *info;
@@ -231,10 +231,10 @@ static int jz4740_pwm_probe(struct platform_device *pdev)
if (!info)
return -EINVAL;
- jz = devm_kzalloc(dev, struct_size(jz, clk, info->num_pwms),
- GFP_KERNEL);
- if (!jz)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(dev, info->num_pwms, struct_size(jz, clk, info->num_pwms));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ jz = to_jz4740(chip);
jz->map = device_node_to_regmap(dev->parent->of_node);
if (IS_ERR(jz->map)) {
@@ -242,11 +242,9 @@ static int jz4740_pwm_probe(struct platform_device *pdev)
return PTR_ERR(jz->map);
}
- jz->chip.dev = dev;
- jz->chip.ops = &jz4740_pwm_ops;
- jz->chip.npwm = info->num_pwms;
+ chip->ops = &jz4740_pwm_ops;
- return devm_pwmchip_add(dev, &jz->chip);
+ return devm_pwmchip_add(dev, chip);
}
static const struct soc_info jz4740_soc_info = {
diff --git a/drivers/pwm/pwm-keembay.c b/drivers/pwm/pwm-keembay.c
index ac824ecc3f64..35b641f3f6ed 100644
--- a/drivers/pwm/pwm-keembay.c
+++ b/drivers/pwm/pwm-keembay.c
@@ -36,7 +36,6 @@
#define KMB_PWM_HIGHLOW_OFFSET(ch) (0x20 + 4 * (ch))
struct keembay_pwm {
- struct pwm_chip chip;
struct device *dev;
struct clk *clk;
void __iomem *base;
@@ -44,7 +43,7 @@ struct keembay_pwm {
static inline struct keembay_pwm *to_keembay_pwm_dev(struct pwm_chip *chip)
{
- return container_of(chip, struct keembay_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static void keembay_clk_unprepare(void *data)
@@ -185,12 +184,14 @@ static const struct pwm_ops keembay_pwm_ops = {
static int keembay_pwm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct pwm_chip *chip;
struct keembay_pwm *priv;
int ret;
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(dev, KMB_TOTAL_PWM_CHANNELS, sizeof(*priv));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ priv = to_keembay_pwm_dev(chip);
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk))
@@ -204,11 +205,9 @@ static int keembay_pwm_probe(struct platform_device *pdev)
if (ret)
return ret;
- priv->chip.dev = dev;
- priv->chip.ops = &keembay_pwm_ops;
- priv->chip.npwm = KMB_TOTAL_PWM_CHANNELS;
+ chip->ops = &keembay_pwm_ops;
- ret = devm_pwmchip_add(dev, &priv->chip);
+ ret = devm_pwmchip_add(dev, chip);
if (ret)
return dev_err_probe(dev, ret, "Failed to add PWM chip\n");
diff --git a/drivers/pwm/pwm-lp3943.c b/drivers/pwm/pwm-lp3943.c
index 32350a357278..61189cea1046 100644
--- a/drivers/pwm/pwm-lp3943.c
+++ b/drivers/pwm/pwm-lp3943.c
@@ -20,7 +20,6 @@
#define LP3943_MAX_PERIOD 1600000
struct lp3943_pwm {
- struct pwm_chip chip;
struct lp3943 *lp3943;
struct lp3943_platform_data *pdata;
struct lp3943_pwm_map pwm_map[LP3943_NUM_PWMS];
@@ -28,7 +27,7 @@ struct lp3943_pwm {
static inline struct lp3943_pwm *to_lp3943_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct lp3943_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static struct lp3943_pwm_map *
@@ -273,12 +272,14 @@ static int lp3943_pwm_parse_dt(struct device *dev,
static int lp3943_pwm_probe(struct platform_device *pdev)
{
struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent);
+ struct pwm_chip *chip;
struct lp3943_pwm *lp3943_pwm;
int ret;
- lp3943_pwm = devm_kzalloc(&pdev->dev, sizeof(*lp3943_pwm), GFP_KERNEL);
- if (!lp3943_pwm)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, LP3943_NUM_PWMS, sizeof(*lp3943_pwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ lp3943_pwm = to_lp3943_pwm(chip);
lp3943_pwm->pdata = lp3943->pdata;
if (!lp3943_pwm->pdata) {
@@ -292,11 +293,9 @@ static int lp3943_pwm_probe(struct platform_device *pdev)
}
lp3943_pwm->lp3943 = lp3943;
- lp3943_pwm->chip.dev = &pdev->dev;
- lp3943_pwm->chip.ops = &lp3943_pwm_ops;
- lp3943_pwm->chip.npwm = LP3943_NUM_PWMS;
+ chip->ops = &lp3943_pwm_ops;
- return devm_pwmchip_add(&pdev->dev, &lp3943_pwm->chip);
+ return devm_pwmchip_add(&pdev->dev, chip);
}
#ifdef CONFIG_OF
diff --git a/drivers/pwm/pwm-lpc18xx-sct.c b/drivers/pwm/pwm-lpc18xx-sct.c
index fe891fa71a1d..04b76d257fd8 100644
--- a/drivers/pwm/pwm-lpc18xx-sct.c
+++ b/drivers/pwm/pwm-lpc18xx-sct.c
@@ -92,8 +92,6 @@ struct lpc18xx_pwm_data {
};
struct lpc18xx_pwm_chip {
- struct device *dev;
- struct pwm_chip chip;
void __iomem *base;
struct clk *pwm_clk;
unsigned long clk_rate;
@@ -110,7 +108,7 @@ struct lpc18xx_pwm_chip {
static inline struct lpc18xx_pwm_chip *
to_lpc18xx_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct lpc18xx_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static inline void lpc18xx_pwm_writel(struct lpc18xx_pwm_chip *lpc18xx_pwm,
@@ -198,7 +196,7 @@ static int lpc18xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
if (period_ns < lpc18xx_pwm->min_period_ns ||
period_ns > lpc18xx_pwm->max_period_ns) {
- dev_err(chip->dev, "period %d not in range\n", period_ns);
+ dev_err(pwmchip_parent(chip), "period %d not in range\n", period_ns);
return -ERANGE;
}
@@ -214,7 +212,7 @@ static int lpc18xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
*/
if (requested_events > 2 && lpc18xx_pwm->period_ns != period_ns &&
lpc18xx_pwm->period_ns) {
- dev_err(chip->dev, "conflicting period requested for PWM %u\n",
+ dev_err(pwmchip_parent(chip), "conflicting period requested for PWM %u\n",
pwm->hwpwm);
mutex_unlock(&lpc18xx_pwm->period_lock);
return -EBUSY;
@@ -289,7 +287,7 @@ static int lpc18xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
LPC18XX_PWM_EVENT_MAX);
if (event >= LPC18XX_PWM_EVENT_MAX) {
- dev_err(lpc18xx_pwm->dev,
+ dev_err(pwmchip_parent(chip),
"maximum number of simultaneous channels reached\n");
return -EBUSY;
}
@@ -349,16 +347,15 @@ MODULE_DEVICE_TABLE(of, lpc18xx_pwm_of_match);
static int lpc18xx_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct lpc18xx_pwm_chip *lpc18xx_pwm;
int ret;
u64 val;
- lpc18xx_pwm = devm_kzalloc(&pdev->dev, sizeof(*lpc18xx_pwm),
- GFP_KERNEL);
- if (!lpc18xx_pwm)
- return -ENOMEM;
-
- lpc18xx_pwm->dev = &pdev->dev;
+ chip = devm_pwmchip_alloc(&pdev->dev, LPC18XX_NUM_PWMS, sizeof(*lpc18xx_pwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
lpc18xx_pwm->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(lpc18xx_pwm->base))
@@ -389,9 +386,7 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev)
lpc18xx_pwm->min_period_ns = DIV_ROUND_UP(NSEC_PER_SEC,
lpc18xx_pwm->clk_rate);
- lpc18xx_pwm->chip.dev = &pdev->dev;
- lpc18xx_pwm->chip.ops = &lpc18xx_pwm_ops;
- lpc18xx_pwm->chip.npwm = LPC18XX_NUM_PWMS;
+ chip->ops = &lpc18xx_pwm_ops;
/* SCT counter must be in unify (32 bit) mode */
lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG,
@@ -423,21 +418,22 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev)
val |= LPC18XX_PWM_PRE(0);
lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL, val);
- ret = pwmchip_add(&lpc18xx_pwm->chip);
+ ret = pwmchip_add(chip);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "pwmchip_add failed\n");
- platform_set_drvdata(pdev, lpc18xx_pwm);
+ platform_set_drvdata(pdev, chip);
return 0;
}
static void lpc18xx_pwm_remove(struct platform_device *pdev)
{
- struct lpc18xx_pwm_chip *lpc18xx_pwm = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
+ struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
u32 val;
- pwmchip_remove(&lpc18xx_pwm->chip);
+ pwmchip_remove(chip);
val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL);
lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL,
diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c
index 1d9f3e7a2434..c748537e57d1 100644
--- a/drivers/pwm/pwm-lpc32xx.c
+++ b/drivers/pwm/pwm-lpc32xx.c
@@ -15,7 +15,6 @@
#include <linux/slab.h>
struct lpc32xx_pwm_chip {
- struct pwm_chip chip;
struct clk *clk;
void __iomem *base;
};
@@ -23,8 +22,10 @@ struct lpc32xx_pwm_chip {
#define PWM_ENABLE BIT(31)
#define PWM_PIN_LEVEL BIT(30)
-#define to_lpc32xx_pwm_chip(_chip) \
- container_of(_chip, struct lpc32xx_pwm_chip, chip)
+static inline struct lpc32xx_pwm_chip *to_lpc32xx_pwm_chip(struct pwm_chip *chip)
+{
+ return pwmchip_get_drvdata(chip);
+}
static int lpc32xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns)
@@ -119,13 +120,15 @@ static const struct pwm_ops lpc32xx_pwm_ops = {
static int lpc32xx_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct lpc32xx_pwm_chip *lpc32xx;
int ret;
u32 val;
- lpc32xx = devm_kzalloc(&pdev->dev, sizeof(*lpc32xx), GFP_KERNEL);
- if (!lpc32xx)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*lpc32xx));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ lpc32xx = to_lpc32xx_pwm_chip(chip);
lpc32xx->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(lpc32xx->base))
@@ -135,16 +138,14 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
if (IS_ERR(lpc32xx->clk))
return PTR_ERR(lpc32xx->clk);
- lpc32xx->chip.dev = &pdev->dev;
- lpc32xx->chip.ops = &lpc32xx_pwm_ops;
- lpc32xx->chip.npwm = 1;
+ chip->ops = &lpc32xx_pwm_ops;
/* If PWM is disabled, configure the output to the default value */
val = readl(lpc32xx->base);
val &= ~PWM_PIN_LEVEL;
writel(val, lpc32xx->base);
- ret = devm_pwmchip_add(&pdev->dev, &lpc32xx->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add PWM chip, error %d\n", ret);
return ret;
diff --git a/drivers/pwm/pwm-lpss-pci.c b/drivers/pwm/pwm-lpss-pci.c
index b4134bee2863..25045c229520 100644
--- a/drivers/pwm/pwm-lpss-pci.c
+++ b/drivers/pwm/pwm-lpss-pci.c
@@ -18,7 +18,7 @@ static int pwm_lpss_probe_pci(struct pci_dev *pdev,
const struct pci_device_id *id)
{
const struct pwm_lpss_boardinfo *info;
- struct pwm_lpss_chip *lpwm;
+ struct pwm_chip *chip;
int err;
err = pcim_enable_device(pdev);
@@ -30,11 +30,9 @@ static int pwm_lpss_probe_pci(struct pci_dev *pdev,
return err;
info = (struct pwm_lpss_boardinfo *)id->driver_data;
- lpwm = devm_pwm_lpss_probe(&pdev->dev, pcim_iomap_table(pdev)[0], info);
- if (IS_ERR(lpwm))
- return PTR_ERR(lpwm);
-
- pci_set_drvdata(pdev, lpwm);
+ chip = devm_pwm_lpss_probe(&pdev->dev, pcim_iomap_table(pdev)[0], info);
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
pm_runtime_put(&pdev->dev);
pm_runtime_allow(&pdev->dev);
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
index 319809aac2c4..dbc9f5b17bdc 100644
--- a/drivers/pwm/pwm-lpss-platform.c
+++ b/drivers/pwm/pwm-lpss-platform.c
@@ -20,7 +20,7 @@
static int pwm_lpss_probe_platform(struct platform_device *pdev)
{
const struct pwm_lpss_boardinfo *info;
- struct pwm_lpss_chip *lpwm;
+ struct pwm_chip *chip;
void __iomem *base;
info = device_get_match_data(&pdev->dev);
@@ -31,11 +31,9 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
- lpwm = devm_pwm_lpss_probe(&pdev->dev, base, info);
- if (IS_ERR(lpwm))
- return PTR_ERR(lpwm);
-
- platform_set_drvdata(pdev, lpwm);
+ chip = devm_pwm_lpss_probe(&pdev->dev, base, info);
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
/*
* On Cherry Trail devices the GFX0._PS0 AML checks if the controller
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
index a6ea3ce7e019..867e2bc8c601 100644
--- a/drivers/pwm/pwm-lpss.c
+++ b/drivers/pwm/pwm-lpss.c
@@ -68,7 +68,7 @@ EXPORT_SYMBOL_GPL(pwm_lpss_tng_info);
static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip)
{
- return container_of(chip, struct pwm_lpss_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static inline u32 pwm_lpss_read(const struct pwm_device *pwm)
@@ -106,7 +106,7 @@ static int pwm_lpss_wait_for_update(struct pwm_device *pwm)
*/
err = readl_poll_timeout(addr, val, !(val & PWM_SW_UPDATE), 40, ms);
if (err)
- dev_err(pwm->chip->dev, "PWM_SW_UPDATE was not cleared\n");
+ dev_err(pwmchip_parent(pwm->chip), "PWM_SW_UPDATE was not cleared\n");
return err;
}
@@ -114,7 +114,7 @@ static int pwm_lpss_wait_for_update(struct pwm_device *pwm)
static inline int pwm_lpss_is_updating(struct pwm_device *pwm)
{
if (pwm_lpss_read(pwm) & PWM_SW_UPDATE) {
- dev_err(pwm->chip->dev, "PWM_SW_UPDATE is still set, skipping update\n");
+ dev_err(pwmchip_parent(pwm->chip), "PWM_SW_UPDATE is still set, skipping update\n");
return -EBUSY;
}
@@ -190,16 +190,16 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (state->enabled) {
if (!pwm_is_enabled(pwm)) {
- pm_runtime_get_sync(chip->dev);
+ pm_runtime_get_sync(pwmchip_parent(chip));
ret = pwm_lpss_prepare_enable(lpwm, pwm, state);
if (ret)
- pm_runtime_put(chip->dev);
+ pm_runtime_put(pwmchip_parent(chip));
} else {
ret = pwm_lpss_prepare_enable(lpwm, pwm, state);
}
} else if (pwm_is_enabled(pwm)) {
pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE);
- pm_runtime_put(chip->dev);
+ pm_runtime_put(pwmchip_parent(chip));
}
return ret;
@@ -213,7 +213,7 @@ static int pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
unsigned long long base_unit, freq, on_time_div;
u32 ctrl;
- pm_runtime_get_sync(chip->dev);
+ pm_runtime_get_sync(pwmchip_parent(chip));
base_unit_range = BIT(lpwm->info->base_unit_bits);
@@ -235,7 +235,7 @@ static int pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->polarity = PWM_POLARITY_NORMAL;
state->enabled = !!(ctrl & PWM_ENABLE);
- pm_runtime_put(chip->dev);
+ pm_runtime_put(pwmchip_parent(chip));
return 0;
}
@@ -245,10 +245,11 @@ static const struct pwm_ops pwm_lpss_ops = {
.get_state = pwm_lpss_get_state,
};
-struct pwm_lpss_chip *devm_pwm_lpss_probe(struct device *dev, void __iomem *base,
- const struct pwm_lpss_boardinfo *info)
+struct pwm_chip *devm_pwm_lpss_probe(struct device *dev, void __iomem *base,
+ const struct pwm_lpss_boardinfo *info)
{
struct pwm_lpss_chip *lpwm;
+ struct pwm_chip *chip;
unsigned long c;
int i, ret;
u32 ctrl;
@@ -256,9 +257,10 @@ struct pwm_lpss_chip *devm_pwm_lpss_probe(struct device *dev, void __iomem *base
if (WARN_ON(info->npwm > LPSS_MAX_PWMS))
return ERR_PTR(-ENODEV);
- lpwm = devm_kzalloc(dev, sizeof(*lpwm), GFP_KERNEL);
- if (!lpwm)
- return ERR_PTR(-ENOMEM);
+ chip = devm_pwmchip_alloc(dev, info->npwm, sizeof(*lpwm));
+ if (IS_ERR(chip))
+ return chip;
+ lpwm = to_lpwm(chip);
lpwm->regs = base;
lpwm->info = info;
@@ -267,23 +269,21 @@ struct pwm_lpss_chip *devm_pwm_lpss_probe(struct device *dev, void __iomem *base
if (!c)
return ERR_PTR(-EINVAL);
- lpwm->chip.dev = dev;
- lpwm->chip.ops = &pwm_lpss_ops;
- lpwm->chip.npwm = info->npwm;
+ chip->ops = &pwm_lpss_ops;
- ret = devm_pwmchip_add(dev, &lpwm->chip);
+ ret = devm_pwmchip_add(dev, chip);
if (ret) {
dev_err(dev, "failed to add PWM chip: %d\n", ret);
return ERR_PTR(ret);
}
for (i = 0; i < lpwm->info->npwm; i++) {
- ctrl = pwm_lpss_read(&lpwm->chip.pwms[i]);
+ ctrl = pwm_lpss_read(&chip->pwms[i]);
if (ctrl & PWM_ENABLE)
pm_runtime_get(dev);
}
- return lpwm;
+ return chip;
}
EXPORT_SYMBOL_GPL(devm_pwm_lpss_probe);
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
index bf841250385f..b5267ab5193b 100644
--- a/drivers/pwm/pwm-lpss.h
+++ b/drivers/pwm/pwm-lpss.h
@@ -18,7 +18,6 @@
#define LPSS_MAX_PWMS 4
struct pwm_lpss_chip {
- struct pwm_chip chip;
void __iomem *regs;
const struct pwm_lpss_boardinfo *info;
};
diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
index 17d290f847af..19a87873ad60 100644
--- a/drivers/pwm/pwm-mediatek.c
+++ b/drivers/pwm/pwm-mediatek.c
@@ -42,16 +42,13 @@ struct pwm_mediatek_of_data {
/**
* struct pwm_mediatek_chip - struct representing PWM chip
- * @chip: linux PWM chip representation
* @regs: base address of PWM chip
* @clk_top: the top clock generator
* @clk_main: the clock used by PWM core
* @clk_pwms: the clock used by each PWM channel
- * @clk_freq: the fix clock frequency of legacy MIPS SoC
* @soc: pointer to chip's platform data
*/
struct pwm_mediatek_chip {
- struct pwm_chip chip;
void __iomem *regs;
struct clk *clk_top;
struct clk *clk_main;
@@ -70,7 +67,7 @@ static const unsigned int mtk_pwm_reg_offset_v2[] = {
static inline struct pwm_mediatek_chip *
to_pwm_mediatek_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct pwm_mediatek_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static int pwm_mediatek_clk_enable(struct pwm_chip *chip,
@@ -150,7 +147,7 @@ static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm,
if (clkdiv > PWM_CLK_DIV_MAX) {
pwm_mediatek_clk_disable(chip, pwm);
- dev_err(chip->dev, "period of %d ns not supported\n", period_ns);
+ dev_err(pwmchip_parent(chip), "period of %d ns not supported\n", period_ns);
return -EINVAL;
}
@@ -233,21 +230,26 @@ static const struct pwm_ops pwm_mediatek_ops = {
static int pwm_mediatek_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct pwm_mediatek_chip *pc;
+ const struct pwm_mediatek_of_data *soc;
unsigned int i;
int ret;
- pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
- if (!pc)
- return -ENOMEM;
+ soc = of_device_get_match_data(&pdev->dev);
+
+ chip = devm_pwmchip_alloc(&pdev->dev, soc->num_pwms, sizeof(*pc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pc = to_pwm_mediatek_chip(chip);
- pc->soc = of_device_get_match_data(&pdev->dev);
+ pc->soc = soc;
pc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pc->regs))
return PTR_ERR(pc->regs);
- pc->clk_pwms = devm_kmalloc_array(&pdev->dev, pc->soc->num_pwms,
+ pc->clk_pwms = devm_kmalloc_array(&pdev->dev, soc->num_pwms,
sizeof(*pc->clk_pwms), GFP_KERNEL);
if (!pc->clk_pwms)
return -ENOMEM;
@@ -262,7 +264,7 @@ static int pwm_mediatek_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_main),
"Failed to get main clock\n");
- for (i = 0; i < pc->soc->num_pwms; i++) {
+ for (i = 0; i < soc->num_pwms; i++) {
char name[8];
snprintf(name, sizeof(name), "pwm%d", i + 1);
@@ -273,11 +275,9 @@ static int pwm_mediatek_probe(struct platform_device *pdev)
"Failed to get %s clock\n", name);
}
- pc->chip.dev = &pdev->dev;
- pc->chip.ops = &pwm_mediatek_ops;
- pc->chip.npwm = pc->soc->num_pwms;
+ chip->ops = &pwm_mediatek_ops;
- ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n");
@@ -340,6 +340,13 @@ static const struct pwm_mediatek_of_data mt7986_pwm_data = {
.reg_offset = mtk_pwm_reg_offset_v1,
};
+static const struct pwm_mediatek_of_data mt7988_pwm_data = {
+ .num_pwms = 8,
+ .pwm45_fixup = false,
+ .has_ck_26m_sel = false,
+ .reg_offset = mtk_pwm_reg_offset_v2,
+};
+
static const struct pwm_mediatek_of_data mt8183_pwm_data = {
.num_pwms = 4,
.pwm45_fixup = false,
@@ -370,6 +377,7 @@ static const struct of_device_id pwm_mediatek_of_match[] = {
{ .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data },
{ .compatible = "mediatek,mt7981-pwm", .data = &mt7981_pwm_data },
{ .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data },
+ { .compatible = "mediatek,mt7988-pwm", .data = &mt7988_pwm_data },
{ .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data },
{ .compatible = "mediatek,mt8365-pwm", .data = &mt8365_pwm_data },
{ .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data },
diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
index 2971bbf3b5e7..a02fdbc61256 100644
--- a/drivers/pwm/pwm-meson.c
+++ b/drivers/pwm/pwm-meson.c
@@ -60,7 +60,7 @@
#define MISC_A_EN BIT(0)
#define MESON_NUM_PWMS 2
-#define MESON_MAX_MUX_PARENTS 4
+#define MESON_NUM_MUX_PARENTS 4
static struct meson_pwm_channel_data {
u8 reg_offset;
@@ -97,12 +97,10 @@ struct meson_pwm_channel {
};
struct meson_pwm_data {
- const char * const *parent_names;
- unsigned int num_parents;
+ const char *const parent_names[MESON_NUM_MUX_PARENTS];
};
struct meson_pwm {
- struct pwm_chip chip;
const struct meson_pwm_data *data;
struct meson_pwm_channel channels[MESON_NUM_PWMS];
void __iomem *base;
@@ -115,14 +113,14 @@ struct meson_pwm {
static inline struct meson_pwm *to_meson_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct meson_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct meson_pwm *meson = to_meson_pwm(chip);
struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
- struct device *dev = chip->dev;
+ struct device *dev = pwmchip_parent(chip);
int err;
err = clk_prepare_enable(channel->clk);
@@ -143,9 +141,10 @@ static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
clk_disable_unprepare(channel->clk);
}
-static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
+static int meson_pwm_calc(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
+ struct meson_pwm *meson = to_meson_pwm(chip);
struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
unsigned int cnt, duty_cnt;
unsigned long fin_freq;
@@ -169,19 +168,19 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
fin_freq = clk_round_rate(channel->clk, freq);
if (fin_freq == 0) {
- dev_err(meson->chip.dev, "invalid source clock frequency\n");
+ dev_err(pwmchip_parent(chip), "invalid source clock frequency\n");
return -EINVAL;
}
- dev_dbg(meson->chip.dev, "fin_freq: %lu Hz\n", fin_freq);
+ dev_dbg(pwmchip_parent(chip), "fin_freq: %lu Hz\n", fin_freq);
cnt = div_u64(fin_freq * period, NSEC_PER_SEC);
if (cnt > 0xffff) {
- dev_err(meson->chip.dev, "unable to get period cnt\n");
+ dev_err(pwmchip_parent(chip), "unable to get period cnt\n");
return -EINVAL;
}
- dev_dbg(meson->chip.dev, "period=%llu cnt=%u\n", period, cnt);
+ dev_dbg(pwmchip_parent(chip), "period=%llu cnt=%u\n", period, cnt);
if (duty == period) {
channel->hi = cnt;
@@ -192,7 +191,7 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
} else {
duty_cnt = div_u64(fin_freq * duty, NSEC_PER_SEC);
- dev_dbg(meson->chip.dev, "duty=%llu duty_cnt=%u\n", duty, duty_cnt);
+ dev_dbg(pwmchip_parent(chip), "duty=%llu duty_cnt=%u\n", duty, duty_cnt);
channel->hi = duty_cnt;
channel->lo = cnt - duty_cnt;
@@ -203,8 +202,9 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
return 0;
}
-static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm)
+static void meson_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
{
+ struct meson_pwm *meson = to_meson_pwm(chip);
struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
struct meson_pwm_channel_data *channel_data;
unsigned long flags;
@@ -215,7 +215,7 @@ static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm)
err = clk_set_rate(channel->clk, channel->rate);
if (err)
- dev_err(meson->chip.dev, "setting clock rate failed\n");
+ dev_err(pwmchip_parent(chip), "setting clock rate failed\n");
spin_lock_irqsave(&meson->lock, flags);
@@ -230,8 +230,9 @@ static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm)
spin_unlock_irqrestore(&meson->lock, flags);
}
-static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm)
+static void meson_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
{
+ struct meson_pwm *meson = to_meson_pwm(chip);
unsigned long flags;
u32 value;
@@ -269,16 +270,16 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
channel->hi = ~0;
channel->lo = 0;
- meson_pwm_enable(meson, pwm);
+ meson_pwm_enable(chip, pwm);
} else {
- meson_pwm_disable(meson, pwm);
+ meson_pwm_disable(chip, pwm);
}
} else {
- err = meson_pwm_calc(meson, pwm, state);
+ err = meson_pwm_calc(chip, pwm, state);
if (err < 0)
return err;
- meson_pwm_enable(meson, pwm);
+ meson_pwm_enable(chip, pwm);
}
return 0;
@@ -337,62 +338,32 @@ static const struct pwm_ops meson_pwm_ops = {
.get_state = meson_pwm_get_state,
};
-static const char * const pwm_meson8b_parent_names[] = {
- "xtal", NULL, "fclk_div4", "fclk_div3"
-};
-
static const struct meson_pwm_data pwm_meson8b_data = {
- .parent_names = pwm_meson8b_parent_names,
- .num_parents = ARRAY_SIZE(pwm_meson8b_parent_names),
+ .parent_names = { "xtal", NULL, "fclk_div4", "fclk_div3" },
};
/*
* Only the 2 first inputs of the GXBB AO PWMs are valid
* The last 2 are grounded
*/
-static const char * const pwm_gxbb_ao_parent_names[] = {
- "xtal", "clk81"
-};
-
static const struct meson_pwm_data pwm_gxbb_ao_data = {
- .parent_names = pwm_gxbb_ao_parent_names,
- .num_parents = ARRAY_SIZE(pwm_gxbb_ao_parent_names),
-};
-
-static const char * const pwm_axg_ee_parent_names[] = {
- "xtal", "fclk_div5", "fclk_div4", "fclk_div3"
+ .parent_names = { "xtal", "clk81", NULL, NULL },
};
static const struct meson_pwm_data pwm_axg_ee_data = {
- .parent_names = pwm_axg_ee_parent_names,
- .num_parents = ARRAY_SIZE(pwm_axg_ee_parent_names),
-};
-
-static const char * const pwm_axg_ao_parent_names[] = {
- "xtal", "axg_ao_clk81", "fclk_div4", "fclk_div5"
+ .parent_names = { "xtal", "fclk_div5", "fclk_div4", "fclk_div3" },
};
static const struct meson_pwm_data pwm_axg_ao_data = {
- .parent_names = pwm_axg_ao_parent_names,
- .num_parents = ARRAY_SIZE(pwm_axg_ao_parent_names),
-};
-
-static const char * const pwm_g12a_ao_ab_parent_names[] = {
- "xtal", "g12a_ao_clk81", "fclk_div4", "fclk_div5"
+ .parent_names = { "xtal", "axg_ao_clk81", "fclk_div4", "fclk_div5" },
};
static const struct meson_pwm_data pwm_g12a_ao_ab_data = {
- .parent_names = pwm_g12a_ao_ab_parent_names,
- .num_parents = ARRAY_SIZE(pwm_g12a_ao_ab_parent_names),
-};
-
-static const char * const pwm_g12a_ao_cd_parent_names[] = {
- "xtal", "g12a_ao_clk81",
+ .parent_names = { "xtal", "g12a_ao_clk81", "fclk_div4", "fclk_div5" },
};
static const struct meson_pwm_data pwm_g12a_ao_cd_data = {
- .parent_names = pwm_g12a_ao_cd_parent_names,
- .num_parents = ARRAY_SIZE(pwm_g12a_ao_cd_parent_names),
+ .parent_names = { "xtal", "g12a_ao_clk81", NULL, NULL },
};
static const struct of_device_id meson_pwm_matches[] = {
@@ -432,20 +403,21 @@ static const struct of_device_id meson_pwm_matches[] = {
};
MODULE_DEVICE_TABLE(of, meson_pwm_matches);
-static int meson_pwm_init_channels(struct meson_pwm *meson)
+static int meson_pwm_init_channels(struct pwm_chip *chip)
{
- struct clk_parent_data mux_parent_data[MESON_MAX_MUX_PARENTS] = {};
- struct device *dev = meson->chip.dev;
+ struct meson_pwm *meson = to_meson_pwm(chip);
+ struct clk_parent_data mux_parent_data[MESON_NUM_MUX_PARENTS] = {};
+ struct device *dev = pwmchip_parent(chip);
unsigned int i;
char name[255];
int err;
- for (i = 0; i < meson->data->num_parents; i++) {
+ for (i = 0; i < MESON_NUM_MUX_PARENTS; i++) {
mux_parent_data[i].index = -1;
mux_parent_data[i].name = meson->data->parent_names[i];
}
- for (i = 0; i < meson->chip.npwm; i++) {
+ for (i = 0; i < chip->npwm; i++) {
struct meson_pwm_channel *channel = &meson->channels[i];
struct clk_parent_data div_parent = {}, gate_parent = {};
struct clk_init_data init = {};
@@ -456,7 +428,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson)
init.ops = &clk_mux_ops;
init.flags = 0;
init.parent_data = mux_parent_data;
- init.num_parents = meson->data->num_parents;
+ init.num_parents = MESON_NUM_MUX_PARENTS;
channel->mux.reg = meson->base + REG_MISC_AB;
channel->mux.shift =
@@ -525,29 +497,29 @@ static int meson_pwm_init_channels(struct meson_pwm *meson)
static int meson_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct meson_pwm *meson;
int err;
- meson = devm_kzalloc(&pdev->dev, sizeof(*meson), GFP_KERNEL);
- if (!meson)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, MESON_NUM_PWMS, sizeof(*meson));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ meson = to_meson_pwm(chip);
meson->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(meson->base))
return PTR_ERR(meson->base);
spin_lock_init(&meson->lock);
- meson->chip.dev = &pdev->dev;
- meson->chip.ops = &meson_pwm_ops;
- meson->chip.npwm = MESON_NUM_PWMS;
+ chip->ops = &meson_pwm_ops;
meson->data = of_device_get_match_data(&pdev->dev);
- err = meson_pwm_init_channels(meson);
+ err = meson_pwm_init_channels(chip);
if (err < 0)
return err;
- err = devm_pwmchip_add(&pdev->dev, &meson->chip);
+ err = devm_pwmchip_add(&pdev->dev, chip);
if (err < 0)
return dev_err_probe(&pdev->dev, err,
"failed to register PWM chip\n");
diff --git a/drivers/pwm/pwm-microchip-core.c b/drivers/pwm/pwm-microchip-core.c
index c0c53968f3e9..c1f2287b8e97 100644
--- a/drivers/pwm/pwm-microchip-core.c
+++ b/drivers/pwm/pwm-microchip-core.c
@@ -54,7 +54,6 @@
#define MCHPCOREPWM_TIMEOUT_MS 100u
struct mchp_core_pwm_chip {
- struct pwm_chip chip;
struct clk *clk;
void __iomem *base;
struct mutex lock; /* protects the shared period */
@@ -65,7 +64,7 @@ struct mchp_core_pwm_chip {
static inline struct mchp_core_pwm_chip *to_mchp_core_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct mchp_core_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static void mchp_core_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -447,13 +446,15 @@ MODULE_DEVICE_TABLE(of, mchp_core_of_match);
static int mchp_core_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct mchp_core_pwm_chip *mchp_core_pwm;
struct resource *regs;
int ret;
- mchp_core_pwm = devm_kzalloc(&pdev->dev, sizeof(*mchp_core_pwm), GFP_KERNEL);
- if (!mchp_core_pwm)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 16, sizeof(*mchp_core_pwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ mchp_core_pwm = to_mchp_core_pwm(chip);
mchp_core_pwm->base = devm_platform_get_and_ioremap_resource(pdev, 0, &regs);
if (IS_ERR(mchp_core_pwm->base))
@@ -470,9 +471,7 @@ static int mchp_core_pwm_probe(struct platform_device *pdev)
mutex_init(&mchp_core_pwm->lock);
- mchp_core_pwm->chip.dev = &pdev->dev;
- mchp_core_pwm->chip.ops = &mchp_core_pwm_ops;
- mchp_core_pwm->chip.npwm = 16;
+ chip->ops = &mchp_core_pwm_ops;
mchp_core_pwm->channel_enabled = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_EN(0));
mchp_core_pwm->channel_enabled |=
@@ -485,7 +484,7 @@ static int mchp_core_pwm_probe(struct platform_device *pdev)
writel_relaxed(1U, mchp_core_pwm->base + MCHPCOREPWM_SYNC_UPD);
mchp_core_pwm->update_timestamp = ktime_get();
- ret = devm_pwmchip_add(&pdev->dev, &mchp_core_pwm->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret)
return dev_err_probe(&pdev->dev, ret, "Failed to add pwmchip\n");
diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c
index a72f7be36996..bafd6b6195f6 100644
--- a/drivers/pwm/pwm-mtk-disp.c
+++ b/drivers/pwm/pwm-mtk-disp.c
@@ -42,7 +42,6 @@ struct mtk_pwm_data {
};
struct mtk_disp_pwm {
- struct pwm_chip chip;
const struct mtk_pwm_data *data;
struct clk *clk_main;
struct clk *clk_mm;
@@ -52,7 +51,7 @@ struct mtk_disp_pwm {
static inline struct mtk_disp_pwm *to_mtk_disp_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct mtk_disp_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static void mtk_disp_pwm_update_bits(struct mtk_disp_pwm *mdp, u32 offset,
@@ -91,14 +90,14 @@ static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (!mdp->enabled) {
err = clk_prepare_enable(mdp->clk_main);
if (err < 0) {
- dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n",
+ dev_err(pwmchip_parent(chip), "Can't enable mdp->clk_main: %pe\n",
ERR_PTR(err));
return err;
}
err = clk_prepare_enable(mdp->clk_mm);
if (err < 0) {
- dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n",
+ dev_err(pwmchip_parent(chip), "Can't enable mdp->clk_mm: %pe\n",
ERR_PTR(err));
clk_disable_unprepare(mdp->clk_main);
return err;
@@ -181,13 +180,13 @@ static int mtk_disp_pwm_get_state(struct pwm_chip *chip,
err = clk_prepare_enable(mdp->clk_main);
if (err < 0) {
- dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err));
+ dev_err(pwmchip_parent(chip), "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err));
return err;
}
err = clk_prepare_enable(mdp->clk_mm);
if (err < 0) {
- dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err));
+ dev_err(pwmchip_parent(chip), "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err));
clk_disable_unprepare(mdp->clk_main);
return err;
}
@@ -231,12 +230,14 @@ static const struct pwm_ops mtk_disp_pwm_ops = {
static int mtk_disp_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct mtk_disp_pwm *mdp;
int ret;
- mdp = devm_kzalloc(&pdev->dev, sizeof(*mdp), GFP_KERNEL);
- if (!mdp)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*mdp));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ mdp = to_mtk_disp_pwm(chip);
mdp->data = of_device_get_match_data(&pdev->dev);
@@ -254,11 +255,9 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(mdp->clk_mm),
"Failed to get mm clock\n");
- mdp->chip.dev = &pdev->dev;
- mdp->chip.ops = &mtk_disp_pwm_ops;
- mdp->chip.npwm = 1;
+ chip->ops = &mtk_disp_pwm_ops;
- ret = devm_pwmchip_add(&pdev->dev, &mdp->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n");
diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
index 1b5e787d78f1..8cad214b1c29 100644
--- a/drivers/pwm/pwm-mxs.c
+++ b/drivers/pwm/pwm-mxs.c
@@ -37,12 +37,14 @@ static const u8 cdiv_shift[PERIOD_CDIV_MAX] = {
};
struct mxs_pwm_chip {
- struct pwm_chip chip;
struct clk *clk;
void __iomem *base;
};
-#define to_mxs_pwm_chip(_chip) container_of(_chip, struct mxs_pwm_chip, chip)
+static inline struct mxs_pwm_chip *to_mxs_pwm_chip(struct pwm_chip *chip)
+{
+ return pwmchip_get_drvdata(chip);
+}
static int mxs_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
@@ -120,12 +122,21 @@ static const struct pwm_ops mxs_pwm_ops = {
static int mxs_pwm_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
+ struct pwm_chip *chip;
struct mxs_pwm_chip *mxs;
+ u32 npwm;
int ret;
- mxs = devm_kzalloc(&pdev->dev, sizeof(*mxs), GFP_KERNEL);
- if (!mxs)
- return -ENOMEM;
+ ret = of_property_read_u32(np, "fsl,pwm-number", &npwm);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to get pwm number: %d\n", ret);
+ return ret;
+ }
+
+ chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*mxs));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ mxs = to_mxs_pwm_chip(chip);
mxs->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mxs->base))
@@ -135,21 +146,14 @@ static int mxs_pwm_probe(struct platform_device *pdev)
if (IS_ERR(mxs->clk))
return PTR_ERR(mxs->clk);
- mxs->chip.dev = &pdev->dev;
- mxs->chip.ops = &mxs_pwm_ops;
-
- ret = of_property_read_u32(np, "fsl,pwm-number", &mxs->chip.npwm);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to get pwm number: %d\n", ret);
- return ret;
- }
+ chip->ops = &mxs_pwm_ops;
/* FIXME: Only do this if the PWM isn't already running */
ret = stmp_reset_block(mxs->base);
if (ret)
return dev_err_probe(&pdev->dev, ret, "failed to reset PWM\n");
- ret = devm_pwmchip_add(&pdev->dev, &mxs->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add pwm chip %d\n", ret);
return ret;
diff --git a/drivers/pwm/pwm-ntxec.c b/drivers/pwm/pwm-ntxec.c
index 78606039eda2..28d1c2e5a98f 100644
--- a/drivers/pwm/pwm-ntxec.c
+++ b/drivers/pwm/pwm-ntxec.c
@@ -25,12 +25,11 @@
struct ntxec_pwm {
struct ntxec *ec;
- struct pwm_chip chip;
};
static struct ntxec_pwm *ntxec_pwm_from_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct ntxec_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
#define NTXEC_REG_AUTO_OFF_HI 0xa1
@@ -141,16 +140,13 @@ static int ntxec_pwm_probe(struct platform_device *pdev)
device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*priv));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ priv = ntxec_pwm_from_chip(chip);
priv->ec = ec;
-
- chip = &priv->chip;
- chip->dev = &pdev->dev;
chip->ops = &ntxec_pwm_ops;
- chip->npwm = 1;
return devm_pwmchip_add(&pdev->dev, chip);
}
diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
index 496bd73d29fe..cd51c4a938f5 100644
--- a/drivers/pwm/pwm-omap-dmtimer.c
+++ b/drivers/pwm/pwm-omap-dmtimer.c
@@ -53,13 +53,11 @@
/**
* struct pwm_omap_dmtimer_chip - Structure representing a pwm chip
* corresponding to omap dmtimer.
- * @chip: PWM chip structure representing PWM controller
* @dm_timer: Pointer to omap dm timer.
* @pdata: Pointer to omap dm timer ops.
* @dm_timer_pdev: Pointer to omap dm timer platform device
*/
struct pwm_omap_dmtimer_chip {
- struct pwm_chip chip;
/* Mutex to protect pwm apply state */
struct omap_dm_timer *dm_timer;
const struct omap_dm_timer_ops *pdata;
@@ -69,7 +67,7 @@ struct pwm_omap_dmtimer_chip {
static inline struct pwm_omap_dmtimer_chip *
to_pwm_omap_dmtimer_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct pwm_omap_dmtimer_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
/**
@@ -155,7 +153,7 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
unsigned long clk_rate;
struct clk *fclk;
- dev_dbg(chip->dev, "requested duty cycle: %d ns, period: %d ns\n",
+ dev_dbg(pwmchip_parent(chip), "requested duty cycle: %d ns, period: %d ns\n",
duty_ns, period_ns);
if (duty_ns == pwm_get_duty_cycle(pwm) &&
@@ -164,17 +162,17 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
fclk = omap->pdata->get_fclk(omap->dm_timer);
if (!fclk) {
- dev_err(chip->dev, "invalid pmtimer fclk\n");
+ dev_err(pwmchip_parent(chip), "invalid pmtimer fclk\n");
return -EINVAL;
}
clk_rate = clk_get_rate(fclk);
if (!clk_rate) {
- dev_err(chip->dev, "invalid pmtimer fclk rate\n");
+ dev_err(pwmchip_parent(chip), "invalid pmtimer fclk rate\n");
return -EINVAL;
}
- dev_dbg(chip->dev, "clk rate: %luHz\n", clk_rate);
+ dev_dbg(pwmchip_parent(chip), "clk rate: %luHz\n", clk_rate);
/*
* Calculate the appropriate load and match values based on the
@@ -196,27 +194,27 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
duty_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, duty_ns);
if (period_cycles < 2) {
- dev_info(chip->dev,
+ dev_info(pwmchip_parent(chip),
"period %d ns too short for clock rate %lu Hz\n",
period_ns, clk_rate);
return -EINVAL;
}
if (duty_cycles < 1) {
- dev_dbg(chip->dev,
+ dev_dbg(pwmchip_parent(chip),
"duty cycle %d ns is too short for clock rate %lu Hz\n",
duty_ns, clk_rate);
- dev_dbg(chip->dev, "using minimum of 1 clock cycle\n");
+ dev_dbg(pwmchip_parent(chip), "using minimum of 1 clock cycle\n");
duty_cycles = 1;
} else if (duty_cycles >= period_cycles) {
- dev_dbg(chip->dev,
+ dev_dbg(pwmchip_parent(chip),
"duty cycle %d ns is too long for period %d ns at clock rate %lu Hz\n",
duty_ns, period_ns, clk_rate);
- dev_dbg(chip->dev, "using maximum of 1 clock cycle less than period\n");
+ dev_dbg(pwmchip_parent(chip), "using maximum of 1 clock cycle less than period\n");
duty_cycles = period_cycles - 1;
}
- dev_dbg(chip->dev, "effective duty cycle: %lld ns, period: %lld ns\n",
+ dev_dbg(pwmchip_parent(chip), "effective duty cycle: %lld ns, period: %lld ns\n",
DIV_ROUND_CLOSEST_ULL((u64)NSEC_PER_SEC * duty_cycles,
clk_rate),
DIV_ROUND_CLOSEST_ULL((u64)NSEC_PER_SEC * period_cycles,
@@ -228,7 +226,7 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
omap->pdata->set_load(omap->dm_timer, load_value);
omap->pdata->set_match(omap->dm_timer, true, match_value);
- dev_dbg(chip->dev, "load value: %#08x (%d), match value: %#08x (%d)\n",
+ dev_dbg(pwmchip_parent(chip), "load value: %#08x (%d), match value: %#08x (%d)\n",
load_value, load_value, match_value, match_value);
return 0;
@@ -311,6 +309,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
struct dmtimer_platform_data *timer_pdata;
const struct omap_dm_timer_ops *pdata;
struct platform_device *timer_pdev;
+ struct pwm_chip *chip;
struct pwm_omap_dmtimer_chip *omap;
struct omap_dm_timer *dm_timer;
struct device_node *timer;
@@ -368,11 +367,12 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
goto err_request_timer;
}
- omap = devm_kzalloc(&pdev->dev, sizeof(*omap), GFP_KERNEL);
- if (!omap) {
- ret = -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*omap));
+ if (IS_ERR(chip)) {
+ ret = PTR_ERR(chip);
goto err_alloc_omap;
}
+ omap = to_pwm_omap_dmtimer_chip(chip);
omap->pdata = pdata;
omap->dm_timer = dm_timer;
@@ -392,11 +392,9 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
if (!of_property_read_u32(pdev->dev.of_node, "ti,clock-source", &v))
omap->pdata->set_source(omap->dm_timer, v);
- omap->chip.dev = &pdev->dev;
- omap->chip.ops = &pwm_omap_dmtimer_ops;
- omap->chip.npwm = 1;
+ chip->ops = &pwm_omap_dmtimer_ops;
- ret = pwmchip_add(&omap->chip);
+ ret = pwmchip_add(chip);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register PWM\n");
goto err_pwmchip_add;
@@ -404,7 +402,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
of_node_put(timer);
- platform_set_drvdata(pdev, omap);
+ platform_set_drvdata(pdev, chip);
return 0;
@@ -432,9 +430,10 @@ err_find_timer_pdev:
static void pwm_omap_dmtimer_remove(struct platform_device *pdev)
{
- struct pwm_omap_dmtimer_chip *omap = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
+ struct pwm_omap_dmtimer_chip *omap = to_pwm_omap_dmtimer_chip(chip);
- pwmchip_remove(&omap->chip);
+ pwmchip_remove(chip);
if (pm_runtime_active(&omap->dm_timer_pdev->dev))
omap->pdata->stop(omap->dm_timer);
diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c
index e79b1de8c4d8..c5da2a6ed846 100644
--- a/drivers/pwm/pwm-pca9685.c
+++ b/drivers/pwm/pwm-pca9685.c
@@ -76,7 +76,6 @@
#define REG_OFF_L(C) ((C) >= PCA9685_MAXCHAN ? PCA9685_ALL_LED_OFF_L : LED_N_OFF_L((C)))
struct pca9685 {
- struct pwm_chip chip;
struct regmap *regmap;
struct mutex lock;
DECLARE_BITMAP(pwms_enabled, PCA9685_MAXCHAN + 1);
@@ -88,7 +87,7 @@ struct pca9685 {
static inline struct pca9685 *to_pca(struct pwm_chip *chip)
{
- return container_of(chip, struct pca9685, chip);
+ return pwmchip_get_drvdata(chip);
}
/* This function is supposed to be called with the lock mutex held */
@@ -107,9 +106,10 @@ static bool pca9685_prescaler_can_change(struct pca9685 *pca, int channel)
return test_bit(channel, pca->pwms_enabled);
}
-static int pca9685_read_reg(struct pca9685 *pca, unsigned int reg, unsigned int *val)
+static int pca9685_read_reg(struct pwm_chip *chip, unsigned int reg, unsigned int *val)
{
- struct device *dev = pca->chip.dev;
+ struct pca9685 *pca = to_pca(chip);
+ struct device *dev = pwmchip_parent(chip);
int err;
err = regmap_read(pca->regmap, reg, val);
@@ -119,9 +119,10 @@ static int pca9685_read_reg(struct pca9685 *pca, unsigned int reg, unsigned int
return err;
}
-static int pca9685_write_reg(struct pca9685 *pca, unsigned int reg, unsigned int val)
+static int pca9685_write_reg(struct pwm_chip *chip, unsigned int reg, unsigned int val)
{
- struct device *dev = pca->chip.dev;
+ struct pca9685 *pca = to_pca(chip);
+ struct device *dev = pwmchip_parent(chip);
int err;
err = regmap_write(pca->regmap, reg, val);
@@ -132,19 +133,19 @@ static int pca9685_write_reg(struct pca9685 *pca, unsigned int reg, unsigned int
}
/* 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)
+static void pca9685_pwm_set_duty(struct pwm_chip *chip, int channel, unsigned int duty)
{
- struct pwm_device *pwm = &pca->chip.pwms[channel];
+ struct pwm_device *pwm = &chip->pwms[channel];
unsigned int on, off;
if (duty == 0) {
/* Set the full OFF bit, which has the highest precedence */
- pca9685_write_reg(pca, REG_OFF_H(channel), LED_FULL);
+ pca9685_write_reg(chip, REG_OFF_H(channel), LED_FULL);
return;
} else if (duty >= PCA9685_COUNTER_RANGE) {
/* Set the full ON bit and clear the full OFF bit */
- pca9685_write_reg(pca, REG_ON_H(channel), LED_FULL);
- pca9685_write_reg(pca, REG_OFF_H(channel), 0);
+ pca9685_write_reg(chip, REG_ON_H(channel), LED_FULL);
+ pca9685_write_reg(chip, REG_OFF_H(channel), 0);
return;
}
@@ -164,16 +165,16 @@ static void pca9685_pwm_set_duty(struct pca9685 *pca, int channel, unsigned int
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);
+ pca9685_write_reg(chip, REG_ON_L(channel), on & 0xff);
+ pca9685_write_reg(chip, 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);
+ pca9685_write_reg(chip, REG_OFF_L(channel), off & 0xff);
+ pca9685_write_reg(chip, REG_OFF_H(channel), (off >> 8) & 0xf);
}
-static unsigned int pca9685_pwm_get_duty(struct pca9685 *pca, int channel)
+static unsigned int pca9685_pwm_get_duty(struct pwm_chip *chip, int channel)
{
- struct pwm_device *pwm = &pca->chip.pwms[channel];
+ struct pwm_device *pwm = &chip->pwms[channel];
unsigned int off = 0, on = 0, val = 0;
if (WARN_ON(channel >= PCA9685_MAXCHAN)) {
@@ -181,25 +182,25 @@ static unsigned int pca9685_pwm_get_duty(struct pca9685 *pca, int channel)
return 0;
}
- pca9685_read_reg(pca, LED_N_OFF_H(channel), &off);
+ pca9685_read_reg(chip, LED_N_OFF_H(channel), &off);
if (off & LED_FULL) {
/* Full OFF bit is set */
return 0;
}
- pca9685_read_reg(pca, LED_N_ON_H(channel), &on);
+ pca9685_read_reg(chip, LED_N_ON_H(channel), &on);
if (on & LED_FULL) {
/* Full ON bit is set */
return PCA9685_COUNTER_RANGE;
}
- pca9685_read_reg(pca, LED_N_OFF_L(channel), &val);
+ pca9685_read_reg(chip, 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)) {
+ if (pca9685_read_reg(chip, LED_N_ON_L(channel), &val)) {
/* Reset val to 0 in case reading LED_N_ON_L failed */
val = 0;
}
@@ -247,35 +248,37 @@ static void pca9685_pwm_clear_inuse(struct pca9685 *pca, int pwm_idx)
static int pca9685_pwm_gpio_request(struct gpio_chip *gpio, unsigned int offset)
{
- struct pca9685 *pca = gpiochip_get_data(gpio);
+ struct pwm_chip *chip = gpiochip_get_data(gpio);
+ struct pca9685 *pca = to_pca(chip);
if (pca9685_pwm_test_and_set_inuse(pca, offset))
return -EBUSY;
- pm_runtime_get_sync(pca->chip.dev);
+ pm_runtime_get_sync(pwmchip_parent(chip));
return 0;
}
static int pca9685_pwm_gpio_get(struct gpio_chip *gpio, unsigned int offset)
{
- struct pca9685 *pca = gpiochip_get_data(gpio);
+ struct pwm_chip *chip = gpiochip_get_data(gpio);
- return pca9685_pwm_get_duty(pca, offset) != 0;
+ return pca9685_pwm_get_duty(chip, offset) != 0;
}
static void pca9685_pwm_gpio_set(struct gpio_chip *gpio, unsigned int offset,
int value)
{
- struct pca9685 *pca = gpiochip_get_data(gpio);
+ struct pwm_chip *chip = gpiochip_get_data(gpio);
- pca9685_pwm_set_duty(pca, offset, value ? PCA9685_COUNTER_RANGE : 0);
+ pca9685_pwm_set_duty(chip, offset, value ? PCA9685_COUNTER_RANGE : 0);
}
static void pca9685_pwm_gpio_free(struct gpio_chip *gpio, unsigned int offset)
{
- struct pca9685 *pca = gpiochip_get_data(gpio);
+ struct pwm_chip *chip = gpiochip_get_data(gpio);
+ struct pca9685 *pca = to_pca(chip);
- pca9685_pwm_set_duty(pca, offset, 0);
- pm_runtime_put(pca->chip.dev);
+ pca9685_pwm_set_duty(chip, offset, 0);
+ pm_runtime_put(pwmchip_parent(chip));
pca9685_pwm_clear_inuse(pca, offset);
}
@@ -306,9 +309,10 @@ static int pca9685_pwm_gpio_direction_output(struct gpio_chip *gpio,
* expose a GPIO chip here which can exclusively take over the underlying
* PWM channel.
*/
-static int pca9685_pwm_gpio_probe(struct pca9685 *pca)
+static int pca9685_pwm_gpio_probe(struct pwm_chip *chip)
{
- struct device *dev = pca->chip.dev;
+ struct pca9685 *pca = to_pca(chip);
+ struct device *dev = pwmchip_parent(chip);
pca->gpio.label = dev_name(dev);
pca->gpio.parent = dev;
@@ -323,7 +327,7 @@ static int pca9685_pwm_gpio_probe(struct pca9685 *pca)
pca->gpio.ngpio = PCA9685_MAXCHAN;
pca->gpio.can_sleep = true;
- return devm_gpiochip_add_data(dev, &pca->gpio, pca);
+ return devm_gpiochip_add_data(dev, &pca->gpio, chip);
}
#else
static inline bool pca9685_pwm_test_and_set_inuse(struct pca9685 *pca,
@@ -337,15 +341,16 @@ pca9685_pwm_clear_inuse(struct pca9685 *pca, int pwm_idx)
{
}
-static inline int pca9685_pwm_gpio_probe(struct pca9685 *pca)
+static inline int pca9685_pwm_gpio_probe(struct pwm_chip *chip)
{
return 0;
}
#endif
-static void pca9685_set_sleep_mode(struct pca9685 *pca, bool enable)
+static void pca9685_set_sleep_mode(struct pwm_chip *chip, bool enable)
{
- struct device *dev = pca->chip.dev;
+ struct device *dev = pwmchip_parent(chip);
+ struct pca9685 *pca = to_pca(chip);
int err = regmap_update_bits(pca->regmap, PCA9685_MODE1,
MODE1_SLEEP, enable ? MODE1_SLEEP : 0);
if (err) {
@@ -373,19 +378,19 @@ static int __pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
prescale = DIV_ROUND_CLOSEST_ULL(PCA9685_OSC_CLOCK_MHZ * state->period,
PCA9685_COUNTER_RANGE * 1000) - 1;
if (prescale < PCA9685_PRESCALE_MIN || prescale > PCA9685_PRESCALE_MAX) {
- dev_err(chip->dev, "pwm not changed: period out of bounds!\n");
+ dev_err(pwmchip_parent(chip), "pwm not changed: period out of bounds!\n");
return -EINVAL;
}
if (!state->enabled) {
- pca9685_pwm_set_duty(pca, pwm->hwpwm, 0);
+ pca9685_pwm_set_duty(chip, pwm->hwpwm, 0);
return 0;
}
- pca9685_read_reg(pca, PCA9685_PRESCALE, &val);
+ pca9685_read_reg(chip, PCA9685_PRESCALE, &val);
if (prescale != val) {
if (!pca9685_prescaler_can_change(pca, pwm->hwpwm)) {
- dev_err(chip->dev,
+ dev_err(pwmchip_parent(chip),
"pwm not changed: periods of enabled pwms must match!\n");
return -EBUSY;
}
@@ -397,18 +402,18 @@ static int __pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
* state is guaranteed active here.
*/
/* Put chip into sleep mode */
- pca9685_set_sleep_mode(pca, true);
+ pca9685_set_sleep_mode(chip, true);
/* Change the chip-wide output frequency */
- pca9685_write_reg(pca, PCA9685_PRESCALE, prescale);
+ pca9685_write_reg(chip, PCA9685_PRESCALE, prescale);
/* Wake the chip up */
- pca9685_set_sleep_mode(pca, false);
+ pca9685_set_sleep_mode(chip, false);
}
duty = PCA9685_COUNTER_RANGE * state->duty_cycle;
duty = DIV_ROUND_UP_ULL(duty, state->period);
- pca9685_pwm_set_duty(pca, pwm->hwpwm, duty);
+ pca9685_pwm_set_duty(chip, pwm->hwpwm, duty);
return 0;
}
@@ -434,12 +439,11 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
static int pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
{
- struct pca9685 *pca = to_pca(chip);
unsigned long long duty;
unsigned int val = 0;
/* Calculate (chip-wide) period from prescale value */
- pca9685_read_reg(pca, PCA9685_PRESCALE, &val);
+ pca9685_read_reg(chip, PCA9685_PRESCALE, &val);
/*
* PCA9685_OSC_CLOCK_MHZ is 25, i.e. an integer divider of 1000.
* The following calculation is therefore only a multiplication
@@ -462,7 +466,7 @@ static int pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
}
state->enabled = true;
- duty = pca9685_pwm_get_duty(pca, pwm->hwpwm);
+ duty = pca9685_pwm_get_duty(chip, pwm->hwpwm);
state->duty_cycle = DIV_ROUND_DOWN_ULL(duty * state->period, PCA9685_COUNTER_RANGE);
return 0;
@@ -482,7 +486,7 @@ static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
mutex_unlock(&pca->lock);
}
- pm_runtime_get_sync(chip->dev);
+ pm_runtime_get_sync(pwmchip_parent(chip));
return 0;
}
@@ -492,11 +496,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);
+ pca9685_pwm_set_duty(chip, pwm->hwpwm, 0);
clear_bit(pwm->hwpwm, pca->pwms_enabled);
mutex_unlock(&pca->lock);
- pm_runtime_put(chip->dev);
+ pm_runtime_put(pwmchip_parent(chip));
pca9685_pwm_clear_inuse(pca, pwm->hwpwm);
}
@@ -516,13 +520,16 @@ static const struct regmap_config pca9685_regmap_i2c_config = {
static int pca9685_pwm_probe(struct i2c_client *client)
{
+ struct pwm_chip *chip;
struct pca9685 *pca;
unsigned int reg;
int ret;
- pca = devm_kzalloc(&client->dev, sizeof(*pca), GFP_KERNEL);
- if (!pca)
- return -ENOMEM;
+ /* Add an extra channel for ALL_LED */
+ chip = devm_pwmchip_alloc(&client->dev, PCA9685_MAXCHAN + 1, sizeof(*pca));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pca = to_pca(chip);
pca->regmap = devm_regmap_init_i2c(client, &pca9685_regmap_i2c_config);
if (IS_ERR(pca->regmap)) {
@@ -532,11 +539,11 @@ static int pca9685_pwm_probe(struct i2c_client *client)
return ret;
}
- i2c_set_clientdata(client, pca);
+ i2c_set_clientdata(client, chip);
mutex_init(&pca->lock);
- ret = pca9685_read_reg(pca, PCA9685_MODE2, &reg);
+ ret = pca9685_read_reg(chip, PCA9685_MODE2, &reg);
if (ret)
return ret;
@@ -550,34 +557,30 @@ static int pca9685_pwm_probe(struct i2c_client *client)
else
reg |= MODE2_OUTDRV;
- ret = pca9685_write_reg(pca, PCA9685_MODE2, reg);
+ ret = pca9685_write_reg(chip, PCA9685_MODE2, reg);
if (ret)
return ret;
/* Disable all LED ALLCALL and SUBx addresses to avoid bus collisions */
- pca9685_read_reg(pca, PCA9685_MODE1, &reg);
+ pca9685_read_reg(chip, PCA9685_MODE1, &reg);
reg &= ~(MODE1_ALLCALL | MODE1_SUB1 | MODE1_SUB2 | MODE1_SUB3);
- pca9685_write_reg(pca, PCA9685_MODE1, reg);
+ pca9685_write_reg(chip, PCA9685_MODE1, reg);
/* Reset OFF/ON registers to POR default */
- pca9685_write_reg(pca, PCA9685_ALL_LED_OFF_L, 0);
- 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, LED_FULL);
-
- pca->chip.ops = &pca9685_pwm_ops;
- /* Add an extra channel for ALL_LED */
- pca->chip.npwm = PCA9685_MAXCHAN + 1;
+ pca9685_write_reg(chip, PCA9685_ALL_LED_OFF_L, 0);
+ pca9685_write_reg(chip, PCA9685_ALL_LED_OFF_H, LED_FULL);
+ pca9685_write_reg(chip, PCA9685_ALL_LED_ON_L, 0);
+ pca9685_write_reg(chip, PCA9685_ALL_LED_ON_H, LED_FULL);
- pca->chip.dev = &client->dev;
+ chip->ops = &pca9685_pwm_ops;
- ret = pwmchip_add(&pca->chip);
+ ret = pwmchip_add(chip);
if (ret < 0)
return ret;
- ret = pca9685_pwm_gpio_probe(pca);
+ ret = pca9685_pwm_gpio_probe(chip);
if (ret < 0) {
- pwmchip_remove(&pca->chip);
+ pwmchip_remove(chip);
return ret;
}
@@ -588,11 +591,11 @@ static int pca9685_pwm_probe(struct i2c_client *client)
* Although the chip comes out of power-up in the sleep state,
* we force it to sleep in case it was woken up before
*/
- pca9685_set_sleep_mode(pca, true);
+ pca9685_set_sleep_mode(chip, true);
pm_runtime_set_suspended(&client->dev);
} else {
/* Wake the chip up if runtime PM is disabled */
- pca9685_set_sleep_mode(pca, false);
+ pca9685_set_sleep_mode(chip, false);
}
return 0;
@@ -600,13 +603,13 @@ static int pca9685_pwm_probe(struct i2c_client *client)
static void pca9685_pwm_remove(struct i2c_client *client)
{
- struct pca9685 *pca = i2c_get_clientdata(client);
+ struct pwm_chip *chip = i2c_get_clientdata(client);
- pwmchip_remove(&pca->chip);
+ pwmchip_remove(chip);
if (!pm_runtime_enabled(&client->dev)) {
/* Put chip in sleep state if runtime PM is disabled */
- pca9685_set_sleep_mode(pca, true);
+ pca9685_set_sleep_mode(chip, true);
}
pm_runtime_disable(&client->dev);
@@ -615,18 +618,18 @@ static void pca9685_pwm_remove(struct i2c_client *client)
static int __maybe_unused pca9685_pwm_runtime_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
- struct pca9685 *pca = i2c_get_clientdata(client);
+ struct pwm_chip *chip = i2c_get_clientdata(client);
- pca9685_set_sleep_mode(pca, true);
+ pca9685_set_sleep_mode(chip, true);
return 0;
}
static int __maybe_unused pca9685_pwm_runtime_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
- struct pca9685 *pca = i2c_get_clientdata(client);
+ struct pwm_chip *chip = i2c_get_clientdata(client);
- pca9685_set_sleep_mode(pca, false);
+ pca9685_set_sleep_mode(chip, false);
return 0;
}
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index 76685f926c75..bb7bb48b2e6d 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -49,7 +49,6 @@ MODULE_DEVICE_TABLE(platform, pwm_id_table);
#define PWMDCR_FD (1 << 10)
struct pxa_pwm_chip {
- struct pwm_chip chip;
struct device *dev;
struct clk *clk;
@@ -58,7 +57,7 @@ struct pxa_pwm_chip {
static inline struct pxa_pwm_chip *to_pxa_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct pxa_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
/*
@@ -159,6 +158,7 @@ MODULE_DEVICE_TABLE(of, pwm_of_match);
static int pwm_probe(struct platform_device *pdev)
{
const struct platform_device_id *id = platform_get_device_id(pdev);
+ struct pwm_chip *chip;
struct pxa_pwm_chip *pc;
int ret = 0;
@@ -168,28 +168,27 @@ static int pwm_probe(struct platform_device *pdev)
if (id == NULL)
return -EINVAL;
- pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
- if (pc == NULL)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev,
+ (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1,
+ sizeof(*pc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pc = to_pxa_pwm_chip(chip);
pc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pc->clk))
return PTR_ERR(pc->clk);
- pc->chip.dev = &pdev->dev;
- pc->chip.ops = &pxa_pwm_ops;
- pc->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1;
+ chip->ops = &pxa_pwm_ops;
- if (IS_ENABLED(CONFIG_OF)) {
- pc->chip.of_xlate = of_pwm_single_xlate;
- pc->chip.of_pwm_n_cells = 1;
- }
+ if (IS_ENABLED(CONFIG_OF))
+ chip->of_xlate = of_pwm_single_xlate;
pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pc->mmio_base))
return PTR_ERR(pc->mmio_base);
- ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
return ret;
diff --git a/drivers/pwm/pwm-raspberrypi-poe.c b/drivers/pwm/pwm-raspberrypi-poe.c
index 1ad814fdec6b..8921e7ea2cea 100644
--- a/drivers/pwm/pwm-raspberrypi-poe.c
+++ b/drivers/pwm/pwm-raspberrypi-poe.c
@@ -27,7 +27,6 @@
struct raspberrypi_pwm {
struct rpi_firmware *firmware;
- struct pwm_chip chip;
unsigned int duty_cycle;
};
@@ -40,7 +39,7 @@ struct raspberrypi_pwm_prop {
static inline
struct raspberrypi_pwm *raspberrypi_pwm_from_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct raspberrypi_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static int raspberrypi_pwm_set_property(struct rpi_firmware *firmware,
@@ -122,7 +121,7 @@ static int raspberrypi_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
ret = raspberrypi_pwm_set_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG,
duty_cycle);
if (ret) {
- dev_err(chip->dev, "Failed to set duty cycle: %pe\n",
+ dev_err(pwmchip_parent(chip), "Failed to set duty cycle: %pe\n",
ERR_PTR(ret));
return ret;
}
@@ -142,6 +141,7 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev)
struct device_node *firmware_node;
struct device *dev = &pdev->dev;
struct rpi_firmware *firmware;
+ struct pwm_chip *chip;
struct raspberrypi_pwm *rpipwm;
int ret;
@@ -157,14 +157,14 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev)
return dev_err_probe(dev, -EPROBE_DEFER,
"Failed to get firmware handle\n");
- rpipwm = devm_kzalloc(&pdev->dev, sizeof(*rpipwm), GFP_KERNEL);
- if (!rpipwm)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, RASPBERRYPI_FIRMWARE_PWM_NUM,
+ sizeof(*rpipwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ rpipwm = raspberrypi_pwm_from_chip(chip);
rpipwm->firmware = firmware;
- rpipwm->chip.dev = dev;
- rpipwm->chip.ops = &raspberrypi_pwm_ops;
- rpipwm->chip.npwm = RASPBERRYPI_FIRMWARE_PWM_NUM;
+ chip->ops = &raspberrypi_pwm_ops;
ret = raspberrypi_pwm_get_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG,
&rpipwm->duty_cycle);
@@ -173,7 +173,7 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev)
return ret;
}
- return devm_pwmchip_add(dev, &rpipwm->chip);
+ return devm_pwmchip_add(dev, chip);
}
static const struct of_device_id raspberrypi_pwm_of_match[] = {
diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
index 13269f55fccf..4cfecd88ede0 100644
--- a/drivers/pwm/pwm-rcar.c
+++ b/drivers/pwm/pwm-rcar.c
@@ -38,14 +38,13 @@
#define RCAR_PWMCNT_PH0_SHIFT 0
struct rcar_pwm_chip {
- struct pwm_chip chip;
void __iomem *base;
struct clk *clk;
};
static inline struct rcar_pwm_chip *to_rcar_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct rcar_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static void rcar_pwm_write(struct rcar_pwm_chip *rp, u32 data,
@@ -132,12 +131,12 @@ static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, int duty_ns,
static int rcar_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{
- return pm_runtime_get_sync(chip->dev);
+ return pm_runtime_get_sync(pwmchip_parent(chip));
}
static void rcar_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
{
- pm_runtime_put(chip->dev);
+ pm_runtime_put(pwmchip_parent(chip));
}
static int rcar_pwm_enable(struct rcar_pwm_chip *rp)
@@ -202,12 +201,14 @@ static const struct pwm_ops rcar_pwm_ops = {
static int rcar_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct rcar_pwm_chip *rcar_pwm;
int ret;
- rcar_pwm = devm_kzalloc(&pdev->dev, sizeof(*rcar_pwm), GFP_KERNEL);
- if (rcar_pwm == NULL)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*rcar_pwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ rcar_pwm = to_rcar_pwm_chip(chip);
rcar_pwm->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rcar_pwm->base))
@@ -219,15 +220,13 @@ static int rcar_pwm_probe(struct platform_device *pdev)
return PTR_ERR(rcar_pwm->clk);
}
- platform_set_drvdata(pdev, rcar_pwm);
+ chip->ops = &rcar_pwm_ops;
- rcar_pwm->chip.dev = &pdev->dev;
- rcar_pwm->chip.ops = &rcar_pwm_ops;
- rcar_pwm->chip.npwm = 1;
+ platform_set_drvdata(pdev, chip);
pm_runtime_enable(&pdev->dev);
- ret = pwmchip_add(&rcar_pwm->chip);
+ ret = pwmchip_add(chip);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register PWM chip: %d\n", ret);
pm_runtime_disable(&pdev->dev);
@@ -239,9 +238,9 @@ static int rcar_pwm_probe(struct platform_device *pdev)
static void rcar_pwm_remove(struct platform_device *pdev)
{
- struct rcar_pwm_chip *rcar_pwm = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
- pwmchip_remove(&rcar_pwm->chip);
+ pwmchip_remove(chip);
pm_runtime_disable(&pdev->dev);
}
diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c
index 28265fdfc92a..2196080b4177 100644
--- a/drivers/pwm/pwm-renesas-tpu.c
+++ b/drivers/pwm/pwm-renesas-tpu.c
@@ -79,7 +79,6 @@ struct tpu_pwm_device {
struct tpu_device {
struct platform_device *pdev;
- struct pwm_chip chip;
spinlock_t lock;
void __iomem *base;
@@ -87,7 +86,10 @@ struct tpu_device {
struct tpu_pwm_device tpd[TPU_CHANNEL_MAX];
};
-#define to_tpu_device(c) container_of(c, struct tpu_device, chip)
+static inline struct tpu_device *to_tpu_device(struct pwm_chip *chip)
+{
+ return pwmchip_get_drvdata(chip);
+}
static void tpu_pwm_write(struct tpu_pwm_device *tpd, int reg_nr, u16 value)
{
@@ -438,12 +440,14 @@ static const struct pwm_ops tpu_pwm_ops = {
static int tpu_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct tpu_device *tpu;
int ret;
- tpu = devm_kzalloc(&pdev->dev, sizeof(*tpu), GFP_KERNEL);
- if (tpu == NULL)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, TPU_CHANNEL_MAX, sizeof(*tpu));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ tpu = to_tpu_device(chip);
spin_lock_init(&tpu->lock);
tpu->pdev = pdev;
@@ -460,15 +464,13 @@ static int tpu_probe(struct platform_device *pdev)
/* Initialize and register the device. */
platform_set_drvdata(pdev, tpu);
- tpu->chip.dev = &pdev->dev;
- tpu->chip.ops = &tpu_pwm_ops;
- tpu->chip.npwm = TPU_CHANNEL_MAX;
+ chip->ops = &tpu_pwm_ops;
ret = devm_pm_runtime_enable(&pdev->dev);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "Failed to enable runtime PM\n");
- ret = devm_pwmchip_add(&pdev->dev, &tpu->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "Failed to register PWM chip\n");
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
index a7c647e37837..0fa7575dbb54 100644
--- a/drivers/pwm/pwm-rockchip.c
+++ b/drivers/pwm/pwm-rockchip.c
@@ -30,7 +30,6 @@
#define PWM_LP_DISABLE (0 << 8)
struct rockchip_pwm_chip {
- struct pwm_chip chip;
struct clk *clk;
struct clk *pclk;
const struct rockchip_pwm_data *data;
@@ -54,7 +53,7 @@ struct rockchip_pwm_data {
static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct rockchip_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static int rockchip_pwm_get_state(struct pwm_chip *chip,
@@ -296,14 +295,16 @@ MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids);
static int rockchip_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct rockchip_pwm_chip *pc;
u32 enable_conf, ctrl;
bool enabled;
int ret, count;
- pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
- if (!pc)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*pc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pc = to_rockchip_pwm_chip(chip);
pc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pc->base))
@@ -337,18 +338,16 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
goto err_clk;
}
- platform_set_drvdata(pdev, pc);
+ platform_set_drvdata(pdev, chip);
pc->data = device_get_match_data(&pdev->dev);
- pc->chip.dev = &pdev->dev;
- pc->chip.ops = &rockchip_pwm_ops;
- pc->chip.npwm = 1;
+ chip->ops = &rockchip_pwm_ops;
enable_conf = pc->data->enable_conf;
ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl);
enabled = (ctrl & enable_conf) == enable_conf;
- ret = pwmchip_add(&pc->chip);
+ ret = pwmchip_add(chip);
if (ret < 0) {
dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n");
goto err_pclk;
@@ -372,9 +371,10 @@ err_clk:
static void rockchip_pwm_remove(struct platform_device *pdev)
{
- struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
+ struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
- pwmchip_remove(&pc->chip);
+ pwmchip_remove(chip);
clk_unprepare(pc->pclk);
clk_unprepare(pc->clk);
diff --git a/drivers/pwm/pwm-rz-mtu3.c b/drivers/pwm/pwm-rz-mtu3.c
index bdda315b3bd3..ab39bd37edaf 100644
--- a/drivers/pwm/pwm-rz-mtu3.c
+++ b/drivers/pwm/pwm-rz-mtu3.c
@@ -61,7 +61,6 @@ struct rz_mtu3_pwm_channel {
/**
* struct rz_mtu3_pwm_chip - MTU3 pwm private data
*
- * @chip: MTU3 pwm chip data
* @clk: MTU3 module clock
* @lock: Lock to prevent concurrent access for usage count
* @rate: MTU3 clock rate
@@ -72,7 +71,6 @@ struct rz_mtu3_pwm_channel {
*/
struct rz_mtu3_pwm_chip {
- struct pwm_chip chip;
struct clk *clk;
struct mutex lock;
unsigned long rate;
@@ -92,7 +90,7 @@ static const struct rz_mtu3_channel_io_map channel_map[] = {
static inline struct rz_mtu3_pwm_chip *to_rz_mtu3_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct rz_mtu3_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static void rz_mtu3_pwm_read_tgr_registers(struct rz_mtu3_pwm_channel *priv,
@@ -211,15 +209,15 @@ static void rz_mtu3_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
mutex_unlock(&rz_mtu3_pwm->lock);
}
-static int rz_mtu3_pwm_enable(struct rz_mtu3_pwm_chip *rz_mtu3_pwm,
- struct pwm_device *pwm)
+static int rz_mtu3_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
{
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip);
struct rz_mtu3_pwm_channel *priv;
u32 ch;
u8 val;
int rc;
- rc = pm_runtime_resume_and_get(rz_mtu3_pwm->chip.dev);
+ rc = pm_runtime_resume_and_get(pwmchip_parent(chip));
if (rc)
return rc;
@@ -243,9 +241,9 @@ static int rz_mtu3_pwm_enable(struct rz_mtu3_pwm_chip *rz_mtu3_pwm,
return 0;
}
-static void rz_mtu3_pwm_disable(struct rz_mtu3_pwm_chip *rz_mtu3_pwm,
- struct pwm_device *pwm)
+static void rz_mtu3_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
{
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip);
struct rz_mtu3_pwm_channel *priv;
u32 ch;
@@ -265,7 +263,7 @@ static void rz_mtu3_pwm_disable(struct rz_mtu3_pwm_chip *rz_mtu3_pwm,
mutex_unlock(&rz_mtu3_pwm->lock);
- pm_runtime_put_sync(rz_mtu3_pwm->chip.dev);
+ pm_runtime_put_sync(pwmchip_parent(chip));
}
static int rz_mtu3_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -274,7 +272,7 @@ static int rz_mtu3_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip);
int rc;
- rc = pm_runtime_resume_and_get(chip->dev);
+ rc = pm_runtime_resume_and_get(pwmchip_parent(chip));
if (rc)
return rc;
@@ -307,7 +305,7 @@ static int rz_mtu3_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
}
state->polarity = PWM_POLARITY_NORMAL;
- pm_runtime_put(chip->dev);
+ pm_runtime_put(pwmchip_parent(chip));
return 0;
}
@@ -362,7 +360,7 @@ static int rz_mtu3_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
if (!pwm->state.enabled) {
int rc;
- rc = pm_runtime_resume_and_get(chip->dev);
+ rc = pm_runtime_resume_and_get(pwmchip_parent(chip));
if (rc)
return rc;
}
@@ -399,7 +397,7 @@ static int rz_mtu3_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
/* If the PWM is not enabled, turn the clock off again to save power. */
if (!pwm->state.enabled)
- pm_runtime_put(chip->dev);
+ pm_runtime_put(pwmchip_parent(chip));
return 0;
}
@@ -416,7 +414,7 @@ static int rz_mtu3_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (!state->enabled) {
if (enabled)
- rz_mtu3_pwm_disable(rz_mtu3_pwm, pwm);
+ rz_mtu3_pwm_disable(chip, pwm);
return 0;
}
@@ -428,7 +426,7 @@ static int rz_mtu3_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
if (!enabled)
- ret = rz_mtu3_pwm_enable(rz_mtu3_pwm, pwm);
+ ret = rz_mtu3_pwm_enable(chip, pwm);
return ret;
}
@@ -442,7 +440,8 @@ static const struct pwm_ops rz_mtu3_pwm_ops = {
static int rz_mtu3_pwm_pm_runtime_suspend(struct device *dev)
{
- struct rz_mtu3_pwm_chip *rz_mtu3_pwm = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip);
clk_disable_unprepare(rz_mtu3_pwm->clk);
@@ -451,7 +450,8 @@ static int rz_mtu3_pwm_pm_runtime_suspend(struct device *dev)
static int rz_mtu3_pwm_pm_runtime_resume(struct device *dev)
{
- struct rz_mtu3_pwm_chip *rz_mtu3_pwm = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip);
return clk_prepare_enable(rz_mtu3_pwm->clk);
}
@@ -462,24 +462,28 @@ static DEFINE_RUNTIME_DEV_PM_OPS(rz_mtu3_pwm_pm_ops,
static void rz_mtu3_pwm_pm_disable(void *data)
{
- struct rz_mtu3_pwm_chip *rz_mtu3_pwm = data;
+ struct pwm_chip *chip = data;
+ struct rz_mtu3_pwm_chip *rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip);
clk_rate_exclusive_put(rz_mtu3_pwm->clk);
- pm_runtime_disable(rz_mtu3_pwm->chip.dev);
- pm_runtime_set_suspended(rz_mtu3_pwm->chip.dev);
+ pm_runtime_disable(pwmchip_parent(chip));
+ pm_runtime_set_suspended(pwmchip_parent(chip));
}
static int rz_mtu3_pwm_probe(struct platform_device *pdev)
{
struct rz_mtu3 *parent_ddata = dev_get_drvdata(pdev->dev.parent);
struct rz_mtu3_pwm_chip *rz_mtu3_pwm;
+ struct pwm_chip *chip;
struct device *dev = &pdev->dev;
unsigned int i, j = 0;
int ret;
- rz_mtu3_pwm = devm_kzalloc(&pdev->dev, sizeof(*rz_mtu3_pwm), GFP_KERNEL);
- if (!rz_mtu3_pwm)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, RZ_MTU3_MAX_PWM_CHANNELS,
+ sizeof(*rz_mtu3_pwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ rz_mtu3_pwm = to_rz_mtu3_pwm_chip(chip);
rz_mtu3_pwm->clk = parent_ddata->clk;
@@ -494,7 +498,7 @@ static int rz_mtu3_pwm_probe(struct platform_device *pdev)
}
mutex_init(&rz_mtu3_pwm->lock);
- platform_set_drvdata(pdev, rz_mtu3_pwm);
+ platform_set_drvdata(pdev, chip);
ret = clk_prepare_enable(rz_mtu3_pwm->clk);
if (ret)
return dev_err_probe(dev, ret, "Clock enable failed\n");
@@ -514,15 +518,13 @@ static int rz_mtu3_pwm_probe(struct platform_device *pdev)
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
- rz_mtu3_pwm->chip.dev = &pdev->dev;
ret = devm_add_action_or_reset(&pdev->dev, rz_mtu3_pwm_pm_disable,
- rz_mtu3_pwm);
+ chip);
if (ret < 0)
return ret;
- rz_mtu3_pwm->chip.ops = &rz_mtu3_pwm_ops;
- rz_mtu3_pwm->chip.npwm = RZ_MTU3_MAX_PWM_CHANNELS;
- ret = devm_pwmchip_add(&pdev->dev, &rz_mtu3_pwm->chip);
+ chip->ops = &rz_mtu3_pwm_ops;
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret)
return dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n");
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index 6e77302f7368..efb60c9f0cb3 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -69,7 +69,6 @@ struct samsung_pwm_channel {
/**
* struct samsung_pwm_chip - private data of PWM chip
- * @chip: generic PWM chip
* @variant: local copy of hardware variant data
* @inverter_mask: inverter status for all channels - one bit per channel
* @disabled_mask: disabled status for all channels - one bit per channel
@@ -80,7 +79,6 @@ struct samsung_pwm_channel {
* @channel: per channel driver data
*/
struct samsung_pwm_chip {
- struct pwm_chip chip;
struct samsung_pwm_variant variant;
u8 inverter_mask;
u8 disabled_mask;
@@ -110,7 +108,7 @@ static DEFINE_SPINLOCK(samsung_pwm_lock);
static inline
struct samsung_pwm_chip *to_samsung_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct samsung_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static inline unsigned int to_tcon_channel(unsigned int channel)
@@ -181,9 +179,10 @@ static unsigned long pwm_samsung_get_tin_rate(struct samsung_pwm_chip *our_chip,
return rate / (reg + 1);
}
-static unsigned long pwm_samsung_calc_tin(struct samsung_pwm_chip *our_chip,
+static unsigned long pwm_samsung_calc_tin(struct pwm_chip *chip,
unsigned int chan, unsigned long freq)
{
+ struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip);
struct samsung_pwm_variant *variant = &our_chip->variant;
unsigned long rate;
struct clk *clk;
@@ -197,12 +196,12 @@ static unsigned long pwm_samsung_calc_tin(struct samsung_pwm_chip *our_chip,
return rate;
}
- dev_warn(our_chip->chip.dev,
+ dev_warn(pwmchip_parent(chip),
"tclk of PWM %d is inoperational, using tdiv\n", chan);
}
rate = pwm_samsung_get_tin_rate(our_chip, chan);
- dev_dbg(our_chip->chip.dev, "tin parent at %lu\n", rate);
+ dev_dbg(pwmchip_parent(chip), "tin parent at %lu\n", rate);
/*
* Compare minimum PWM frequency that can be achieved with possible
@@ -232,7 +231,7 @@ static int pwm_samsung_request(struct pwm_chip *chip, struct pwm_device *pwm)
struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip);
if (!(our_chip->variant.output_mask & BIT(pwm->hwpwm))) {
- dev_warn(chip->dev,
+ dev_warn(pwmchip_parent(chip),
"tried to request PWM channel %d without output\n",
pwm->hwpwm);
return -EINVAL;
@@ -326,12 +325,12 @@ static int __pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
period = NSEC_PER_SEC / period_ns;
- dev_dbg(our_chip->chip.dev, "duty_ns=%d, period_ns=%d (%u)\n",
+ dev_dbg(pwmchip_parent(chip), "duty_ns=%d, period_ns=%d (%u)\n",
duty_ns, period_ns, period);
- tin_rate = pwm_samsung_calc_tin(our_chip, pwm->hwpwm, period);
+ tin_rate = pwm_samsung_calc_tin(chip, pwm->hwpwm, period);
- dev_dbg(our_chip->chip.dev, "tin_rate=%lu\n", tin_rate);
+ dev_dbg(pwmchip_parent(chip), "tin_rate=%lu\n", tin_rate);
tin_ns = NSEC_PER_SEC / tin_rate;
tcnt = period_ns / tin_ns;
@@ -355,8 +354,7 @@ static int __pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
/* -1UL will give 100% duty. */
--tcmp;
- dev_dbg(our_chip->chip.dev,
- "tin_ns=%u, tcmp=%u/%u\n", tin_ns, tcmp, tcnt);
+ dev_dbg(pwmchip_parent(chip), "tin_ns=%u, tcmp=%u/%u\n", tin_ns, tcmp, tcnt);
/* Update PWM registers. */
writel(tcnt, our_chip->base + REG_TCNTB(pwm->hwpwm));
@@ -368,7 +366,7 @@ static int __pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
* shortly afer this update (before it autoreloaded the new values).
*/
if (oldtcmp == (u32) -1) {
- dev_dbg(our_chip->chip.dev, "Forcing manual update");
+ dev_dbg(pwmchip_parent(chip), "Forcing manual update");
pwm_samsung_manual_update(our_chip, pwm);
}
@@ -507,9 +505,10 @@ static const struct of_device_id samsung_pwm_matches[] = {
};
MODULE_DEVICE_TABLE(of, samsung_pwm_matches);
-static int pwm_samsung_parse_dt(struct samsung_pwm_chip *our_chip)
+static int pwm_samsung_parse_dt(struct pwm_chip *chip)
{
- struct device_node *np = our_chip->chip.dev->of_node;
+ struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip);
+ struct device_node *np = pwmchip_parent(chip)->of_node;
const struct of_device_id *match;
struct property *prop;
const __be32 *cur;
@@ -523,7 +522,7 @@ static int pwm_samsung_parse_dt(struct samsung_pwm_chip *our_chip)
of_property_for_each_u32(np, "samsung,pwm-outputs", prop, cur, val) {
if (val >= SAMSUNG_PWM_NUM) {
- dev_err(our_chip->chip.dev,
+ dev_err(pwmchip_parent(chip),
"%s: invalid channel index in samsung,pwm-outputs property\n",
__func__);
continue;
@@ -534,7 +533,7 @@ static int pwm_samsung_parse_dt(struct samsung_pwm_chip *our_chip)
return 0;
}
#else
-static int pwm_samsung_parse_dt(struct samsung_pwm_chip *our_chip)
+static int pwm_samsung_parse_dt(struct pwm_chip *chip)
{
return -ENODEV;
}
@@ -544,27 +543,26 @@ static int pwm_samsung_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct samsung_pwm_chip *our_chip;
+ struct pwm_chip *chip;
unsigned int chan;
int ret;
- our_chip = devm_kzalloc(&pdev->dev, sizeof(*our_chip), GFP_KERNEL);
- if (our_chip == NULL)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, SAMSUNG_PWM_NUM, sizeof(*our_chip));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ our_chip = to_samsung_pwm_chip(chip);
- our_chip->chip.dev = &pdev->dev;
- our_chip->chip.ops = &pwm_samsung_ops;
- our_chip->chip.npwm = SAMSUNG_PWM_NUM;
+ chip->ops = &pwm_samsung_ops;
our_chip->inverter_mask = BIT(SAMSUNG_PWM_NUM) - 1;
if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
- ret = pwm_samsung_parse_dt(our_chip);
+ ret = pwm_samsung_parse_dt(chip);
if (ret)
return ret;
} else {
- if (!pdev->dev.platform_data) {
- dev_err(&pdev->dev, "no platform data specified\n");
- return -EINVAL;
- }
+ if (!pdev->dev.platform_data)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "no platform data specified\n");
memcpy(&our_chip->variant, pdev->dev.platform_data,
sizeof(our_chip->variant));
@@ -574,17 +572,10 @@ static int pwm_samsung_probe(struct platform_device *pdev)
if (IS_ERR(our_chip->base))
return PTR_ERR(our_chip->base);
- our_chip->base_clk = devm_clk_get(&pdev->dev, "timers");
- if (IS_ERR(our_chip->base_clk)) {
- dev_err(dev, "failed to get timer base clk\n");
- return PTR_ERR(our_chip->base_clk);
- }
-
- ret = clk_prepare_enable(our_chip->base_clk);
- if (ret < 0) {
- dev_err(dev, "failed to enable base clock\n");
- return ret;
- }
+ our_chip->base_clk = devm_clk_get_enabled(&pdev->dev, "timers");
+ if (IS_ERR(our_chip->base_clk))
+ return dev_err_probe(dev, PTR_ERR(our_chip->base_clk),
+ "failed to get timer base clk\n");
for (chan = 0; chan < SAMSUNG_PWM_NUM; ++chan)
if (our_chip->variant.output_mask & BIT(chan))
@@ -594,14 +585,11 @@ static int pwm_samsung_probe(struct platform_device *pdev)
our_chip->tclk0 = devm_clk_get(&pdev->dev, "pwm-tclk0");
our_chip->tclk1 = devm_clk_get(&pdev->dev, "pwm-tclk1");
- platform_set_drvdata(pdev, our_chip);
+ platform_set_drvdata(pdev, chip);
- ret = pwmchip_add(&our_chip->chip);
- if (ret < 0) {
- dev_err(dev, "failed to register PWM chip\n");
- clk_disable_unprepare(our_chip->base_clk);
- return ret;
- }
+ ret = devm_pwmchip_add(&pdev->dev, chip);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to register PWM chip\n");
dev_dbg(dev, "base_clk at %lu, tclk0 at %lu, tclk1 at %lu\n",
clk_get_rate(our_chip->base_clk),
@@ -611,19 +599,10 @@ static int pwm_samsung_probe(struct platform_device *pdev)
return 0;
}
-static void pwm_samsung_remove(struct platform_device *pdev)
-{
- struct samsung_pwm_chip *our_chip = platform_get_drvdata(pdev);
-
- pwmchip_remove(&our_chip->chip);
-
- clk_disable_unprepare(our_chip->base_clk);
-}
-
static int pwm_samsung_resume(struct device *dev)
{
- struct samsung_pwm_chip *our_chip = dev_get_drvdata(dev);
- struct pwm_chip *chip = &our_chip->chip;
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip);
unsigned int i;
for (i = 0; i < SAMSUNG_PWM_NUM; i++) {
@@ -662,7 +641,6 @@ static struct platform_driver pwm_samsung_driver = {
.of_match_table = of_match_ptr(samsung_pwm_matches),
},
.probe = pwm_samsung_probe,
- .remove_new = pwm_samsung_remove,
};
module_platform_driver(pwm_samsung_driver);
diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c
index 089e50bdbbf0..ed7957cc51fd 100644
--- a/drivers/pwm/pwm-sifive.c
+++ b/drivers/pwm/pwm-sifive.c
@@ -41,7 +41,7 @@
#define PWM_SIFIVE_DEFAULT_PERIOD 10000000
struct pwm_sifive_ddata {
- struct pwm_chip chip;
+ struct device *parent;
struct mutex lock; /* lock to protect user_count and approx_period */
struct notifier_block notifier;
struct clk *clk;
@@ -54,7 +54,7 @@ struct pwm_sifive_ddata {
static inline
struct pwm_sifive_ddata *pwm_sifive_chip_to_ddata(struct pwm_chip *chip)
{
- return container_of(chip, struct pwm_sifive_ddata, chip);
+ return pwmchip_get_drvdata(chip);
}
static int pwm_sifive_request(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -102,7 +102,7 @@ static void pwm_sifive_update_clock(struct pwm_sifive_ddata *ddata,
/* As scale <= 15 the shift operation cannot overflow. */
num = (unsigned long long)NSEC_PER_SEC << (PWM_SIFIVE_CMPWIDTH + scale);
ddata->real_period = div64_ul(num, rate);
- dev_dbg(ddata->chip.dev,
+ dev_dbg(ddata->parent,
"New real_period = %u ns\n", ddata->real_period);
}
@@ -185,7 +185,7 @@ static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (!enabled) {
ret = clk_enable(ddata->clk);
if (ret) {
- dev_err(ddata->chip.dev, "Enable clk failed\n");
+ dev_err(pwmchip_parent(chip), "Enable clk failed\n");
return ret;
}
}
@@ -230,15 +230,14 @@ static int pwm_sifive_probe(struct platform_device *pdev)
u32 val;
unsigned int enabled_pwms = 0, enabled_clks = 1;
- ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
- if (!ddata)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(dev, 4, sizeof(*ddata));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ ddata = pwm_sifive_chip_to_ddata(chip);
+ ddata->parent = dev;
mutex_init(&ddata->lock);
- chip = &ddata->chip;
- chip->dev = dev;
chip->ops = &pwm_sifive_ops;
- chip->npwm = 4;
ddata->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ddata->regs))
@@ -296,7 +295,7 @@ static int pwm_sifive_probe(struct platform_device *pdev)
goto unregister_clk;
}
- platform_set_drvdata(pdev, ddata);
+ platform_set_drvdata(pdev, chip);
dev_dbg(dev, "SiFive PWM chip registered %d PWMs\n", chip->npwm);
return 0;
@@ -314,15 +313,16 @@ disable_clk:
static void pwm_sifive_remove(struct platform_device *dev)
{
- struct pwm_sifive_ddata *ddata = platform_get_drvdata(dev);
+ struct pwm_chip *chip = platform_get_drvdata(dev);
+ struct pwm_sifive_ddata *ddata = pwm_sifive_chip_to_ddata(chip);
struct pwm_device *pwm;
int ch;
- pwmchip_remove(&ddata->chip);
+ pwmchip_remove(chip);
clk_notifier_unregister(ddata->clk, &ddata->notifier);
- for (ch = 0; ch < ddata->chip.npwm; ch++) {
- pwm = &ddata->chip.pwms[ch];
+ for (ch = 0; ch < chip->npwm; ch++) {
+ pwm = &chip->pwms[ch];
if (pwm->state.enabled)
clk_disable(ddata->clk);
}
diff --git a/drivers/pwm/pwm-sl28cpld.c b/drivers/pwm/pwm-sl28cpld.c
index 88b01ff9e460..934378d6a002 100644
--- a/drivers/pwm/pwm-sl28cpld.c
+++ b/drivers/pwm/pwm-sl28cpld.c
@@ -81,14 +81,13 @@
regmap_write((priv)->regmap, (priv)->offset + (reg), (val))
struct sl28cpld_pwm {
- struct pwm_chip chip;
struct regmap *regmap;
u32 offset;
};
static inline struct sl28cpld_pwm *sl28cpld_pwm_from_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct sl28cpld_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static int sl28cpld_pwm_get_state(struct pwm_chip *chip,
@@ -213,9 +212,10 @@ static int sl28cpld_pwm_probe(struct platform_device *pdev)
return -ENODEV;
}
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*priv));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ priv = sl28cpld_pwm_from_chip(chip);
priv->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!priv->regmap) {
@@ -231,10 +231,7 @@ static int sl28cpld_pwm_probe(struct platform_device *pdev)
}
/* Initialize the pwm_chip structure */
- chip = &priv->chip;
- chip->dev = &pdev->dev;
chip->ops = &sl28cpld_pwm_ops;
- chip->npwm = 1;
ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret) {
diff --git a/drivers/pwm/pwm-spear.c b/drivers/pwm/pwm-spear.c
index ff991319feef..6c6f3b38c835 100644
--- a/drivers/pwm/pwm-spear.c
+++ b/drivers/pwm/pwm-spear.c
@@ -48,17 +48,15 @@
*
* @mmio_base: base address of pwm chip
* @clk: pointer to clk structure of pwm chip
- * @chip: linux pwm chip representation
*/
struct spear_pwm_chip {
void __iomem *mmio_base;
struct clk *clk;
- struct pwm_chip chip;
};
static inline struct spear_pwm_chip *to_spear_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct spear_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static inline u32 spear_pwm_readl(struct spear_pwm_chip *chip, unsigned int num,
@@ -194,13 +192,15 @@ static const struct pwm_ops spear_pwm_ops = {
static int spear_pwm_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
+ struct pwm_chip *chip;
struct spear_pwm_chip *pc;
int ret;
u32 val;
- pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
- if (!pc)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, NUM_PWM, sizeof(*pc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pc = to_spear_pwm_chip(chip);
pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pc->mmio_base))
@@ -211,9 +211,7 @@ static int spear_pwm_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk),
"Failed to get clock\n");
- pc->chip.dev = &pdev->dev;
- pc->chip.ops = &spear_pwm_ops;
- pc->chip.npwm = NUM_PWM;
+ chip->ops = &spear_pwm_ops;
if (of_device_is_compatible(np, "st,spear1340-pwm")) {
ret = clk_enable(pc->clk);
@@ -232,7 +230,7 @@ static int spear_pwm_probe(struct platform_device *pdev)
clk_disable(pc->clk);
}
- ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n");
diff --git a/drivers/pwm/pwm-sprd.c b/drivers/pwm/pwm-sprd.c
index 77939e161006..4c76ca5e4cdd 100644
--- a/drivers/pwm/pwm-sprd.c
+++ b/drivers/pwm/pwm-sprd.c
@@ -34,15 +34,12 @@ struct sprd_pwm_chn {
struct sprd_pwm_chip {
void __iomem *base;
- struct device *dev;
- struct pwm_chip chip;
- int num_pwms;
struct sprd_pwm_chn chn[SPRD_PWM_CHN_NUM];
};
static inline struct sprd_pwm_chip* sprd_pwm_from_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct sprd_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
/*
@@ -86,7 +83,7 @@ static int sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
*/
ret = clk_bulk_prepare_enable(SPRD_PWM_CHN_CLKS_NUM, chn->clks);
if (ret) {
- dev_err(spc->dev, "failed to enable pwm%u clocks\n",
+ dev_err(pwmchip_parent(chip), "failed to enable pwm%u clocks\n",
pwm->hwpwm);
return ret;
}
@@ -183,7 +180,7 @@ static int sprd_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
ret = clk_bulk_prepare_enable(SPRD_PWM_CHN_CLKS_NUM,
chn->clks);
if (ret) {
- dev_err(spc->dev,
+ dev_err(pwmchip_parent(chip),
"failed to enable pwm%u clocks\n",
pwm->hwpwm);
return ret;
@@ -215,65 +212,64 @@ static const struct pwm_ops sprd_pwm_ops = {
.get_state = sprd_pwm_get_state,
};
-static int sprd_pwm_clk_init(struct sprd_pwm_chip *spc)
+static int sprd_pwm_clk_init(struct device *dev,
+ struct sprd_pwm_chn chn[SPRD_PWM_CHN_NUM])
{
struct clk *clk_pwm;
int ret, i;
for (i = 0; i < SPRD_PWM_CHN_NUM; i++) {
- struct sprd_pwm_chn *chn = &spc->chn[i];
int j;
for (j = 0; j < SPRD_PWM_CHN_CLKS_NUM; ++j)
- chn->clks[j].id =
+ chn[i].clks[j].id =
sprd_pwm_clks[i * SPRD_PWM_CHN_CLKS_NUM + j];
- ret = devm_clk_bulk_get(spc->dev, SPRD_PWM_CHN_CLKS_NUM,
- chn->clks);
+ ret = devm_clk_bulk_get(dev, SPRD_PWM_CHN_CLKS_NUM,
+ chn[i].clks);
if (ret) {
if (ret == -ENOENT)
break;
- return dev_err_probe(spc->dev, ret,
+ return dev_err_probe(dev, ret,
"failed to get channel clocks\n");
}
- clk_pwm = chn->clks[SPRD_PWM_CHN_OUTPUT_CLK].clk;
- chn->clk_rate = clk_get_rate(clk_pwm);
+ clk_pwm = chn[i].clks[SPRD_PWM_CHN_OUTPUT_CLK].clk;
+ chn[i].clk_rate = clk_get_rate(clk_pwm);
}
if (!i)
- return dev_err_probe(spc->dev, -ENODEV, "no available PWM channels\n");
+ return dev_err_probe(dev, -ENODEV, "no available PWM channels\n");
- spc->num_pwms = i;
-
- return 0;
+ return i;
}
static int sprd_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct sprd_pwm_chip *spc;
- int ret;
+ struct sprd_pwm_chn chn[SPRD_PWM_CHN_NUM];
+ int ret, npwm;
- spc = devm_kzalloc(&pdev->dev, sizeof(*spc), GFP_KERNEL);
- if (!spc)
- return -ENOMEM;
+ npwm = sprd_pwm_clk_init(&pdev->dev, chn);
+ if (npwm < 0)
+ return npwm;
+
+ chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*spc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ spc = sprd_pwm_from_chip(chip);
spc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(spc->base))
return PTR_ERR(spc->base);
- spc->dev = &pdev->dev;
-
- ret = sprd_pwm_clk_init(spc);
- if (ret)
- return ret;
+ memcpy(spc->chn, chn, sizeof(chn));
- spc->chip.dev = &pdev->dev;
- spc->chip.ops = &sprd_pwm_ops;
- spc->chip.npwm = spc->num_pwms;
+ chip->ops = &sprd_pwm_ops;
- ret = devm_pwmchip_add(&pdev->dev, &spc->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret)
dev_err(&pdev->dev, "failed to add PWM chip\n");
diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c
index 6cf55cf34d39..39d80da0e14a 100644
--- a/drivers/pwm/pwm-sti.c
+++ b/drivers/pwm/pwm-sti.c
@@ -94,7 +94,6 @@ struct sti_pwm_chip {
struct regmap_field *pwm_cpt_en;
struct regmap_field *pwm_cpt_int_en;
struct regmap_field *pwm_cpt_int_stat;
- struct pwm_chip chip;
struct pwm_device *cur;
unsigned long configured;
unsigned int en_count;
@@ -114,7 +113,7 @@ static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = {
static inline struct sti_pwm_chip *to_sti_pwmchip(struct pwm_chip *chip)
{
- return container_of(chip, struct sti_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
/*
@@ -395,8 +394,17 @@ out:
static int sti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
+ struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
+ struct sti_pwm_compat_data *cdata = pc->cdata;
+ struct device *dev = pc->dev;
int err;
+ if (pwm->hwpwm >= cdata->pwm_num_devs) {
+ dev_err(dev, "device %u is not valid for pwm mode\n",
+ pwm->hwpwm);
+ return -EINVAL;
+ }
+
if (state->polarity != PWM_POLARITY_NORMAL)
return -EINVAL;
@@ -498,23 +506,7 @@ static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)
{
struct device *dev = pc->dev;
const struct reg_field *reg_fields;
- struct device_node *np = dev->of_node;
struct sti_pwm_compat_data *cdata = pc->cdata;
- u32 num_devs;
- int ret;
-
- ret = of_property_read_u32(np, "st,pwm-num-chan", &num_devs);
- if (!ret)
- cdata->pwm_num_devs = num_devs;
-
- ret = of_property_read_u32(np, "st,capture-num-chan", &num_devs);
- if (!ret)
- cdata->cpt_num_devs = num_devs;
-
- if (!cdata->pwm_num_devs && !cdata->cpt_num_devs) {
- dev_err(dev, "No channels configured\n");
- return -EINVAL;
- }
reg_fields = cdata->reg_fields;
@@ -560,14 +552,33 @@ static const struct regmap_config sti_pwm_regmap_config = {
static int sti_pwm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ u32 num_devs;
+ unsigned int pwm_num_devs = 0;
+ unsigned int cpt_num_devs = 0;
struct sti_pwm_compat_data *cdata;
+ struct pwm_chip *chip;
struct sti_pwm_chip *pc;
unsigned int i;
int irq, ret;
- pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
- if (!pc)
- return -ENOMEM;
+ ret = of_property_read_u32(np, "st,pwm-num-chan", &num_devs);
+ if (!ret)
+ pwm_num_devs = num_devs;
+
+ ret = of_property_read_u32(np, "st,capture-num-chan", &num_devs);
+ if (!ret)
+ cpt_num_devs = num_devs;
+
+ if (!pwm_num_devs && !cpt_num_devs) {
+ dev_err(dev, "No channels configured\n");
+ return -EINVAL;
+ }
+
+ chip = devm_pwmchip_alloc(dev, max(pwm_num_devs, cpt_num_devs), sizeof(*pc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pc = to_sti_pwmchip(chip);
cdata = devm_kzalloc(dev, sizeof(*cdata), GFP_KERNEL);
if (!cdata)
@@ -600,8 +611,8 @@ static int sti_pwm_probe(struct platform_device *pdev)
cdata->reg_fields = sti_pwm_regfields;
cdata->max_prescale = 0xff;
cdata->max_pwm_cnt = 255;
- cdata->pwm_num_devs = 0;
- cdata->cpt_num_devs = 0;
+ cdata->pwm_num_devs = pwm_num_devs;
+ cdata->cpt_num_devs = cpt_num_devs;
pc->cdata = cdata;
pc->dev = dev;
@@ -644,9 +655,7 @@ static int sti_pwm_probe(struct platform_device *pdev)
return -ENOMEM;
}
- pc->chip.dev = dev;
- pc->chip.ops = &sti_pwm_ops;
- pc->chip.npwm = pc->cdata->pwm_num_devs;
+ chip->ops = &sti_pwm_ops;
for (i = 0; i < cdata->cpt_num_devs; i++) {
struct sti_cpt_ddata *ddata = &cdata->ddata[i];
@@ -655,23 +664,24 @@ static int sti_pwm_probe(struct platform_device *pdev)
mutex_init(&ddata->lock);
}
- ret = pwmchip_add(&pc->chip);
+ ret = pwmchip_add(chip);
if (ret < 0) {
clk_unprepare(pc->pwm_clk);
clk_unprepare(pc->cpt_clk);
return ret;
}
- platform_set_drvdata(pdev, pc);
+ platform_set_drvdata(pdev, chip);
return 0;
}
static void sti_pwm_remove(struct platform_device *pdev)
{
- struct sti_pwm_chip *pc = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
+ struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
- pwmchip_remove(&pc->chip);
+ pwmchip_remove(chip);
clk_unprepare(pc->pwm_clk);
clk_unprepare(pc->cpt_clk);
diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c
index 439068f3eca1..989731256f50 100644
--- a/drivers/pwm/pwm-stm32-lp.c
+++ b/drivers/pwm/pwm-stm32-lp.c
@@ -18,14 +18,13 @@
#include <linux/pwm.h>
struct stm32_pwm_lp {
- struct pwm_chip chip;
struct clk *clk;
struct regmap *regmap;
};
static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)
{
- return container_of(chip, struct stm32_pwm_lp, chip);
+ return pwmchip_get_drvdata(chip);
}
/* STM32 Low-Power Timer is preceded by a configurable power-of-2 prescaler */
@@ -61,7 +60,7 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
do_div(div, NSEC_PER_SEC);
if (!div) {
/* Clock is too slow to achieve requested period. */
- dev_dbg(priv->chip.dev, "Can't reach %llu ns\n", state->period);
+ dev_dbg(pwmchip_parent(chip), "Can't reach %llu ns\n", state->period);
return -EINVAL;
}
@@ -69,7 +68,7 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
while (div > STM32_LPTIM_MAX_ARR) {
presc++;
if ((1 << presc) > STM32_LPTIM_MAX_PRESCALER) {
- dev_err(priv->chip.dev, "max prescaler exceeded\n");
+ dev_err(pwmchip_parent(chip), "max prescaler exceeded\n");
return -EINVAL;
}
div = prd >> presc;
@@ -130,7 +129,7 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
(val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK,
100, 1000);
if (ret) {
- dev_err(priv->chip.dev, "ARR/CMP registers write issue\n");
+ dev_err(pwmchip_parent(chip), "ARR/CMP registers write issue\n");
goto err;
}
ret = regmap_write(priv->regmap, STM32_LPTIM_ICR,
@@ -197,36 +196,36 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
{
struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent);
struct stm32_pwm_lp *priv;
+ struct pwm_chip *chip;
int ret;
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*priv));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ priv = to_stm32_pwm_lp(chip);
priv->regmap = ddata->regmap;
priv->clk = ddata->clk;
- priv->chip.dev = &pdev->dev;
- priv->chip.ops = &stm32_pwm_lp_ops;
- priv->chip.npwm = 1;
+ chip->ops = &stm32_pwm_lp_ops;
- ret = devm_pwmchip_add(&pdev->dev, &priv->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
return ret;
- platform_set_drvdata(pdev, priv);
+ platform_set_drvdata(pdev, chip);
return 0;
}
static int stm32_pwm_lp_suspend(struct device *dev)
{
- struct stm32_pwm_lp *priv = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
struct pwm_state state;
- pwm_get_state(&priv->chip.pwms[0], &state);
+ pwm_get_state(&chip->pwms[0], &state);
if (state.enabled) {
dev_err(dev, "The consumer didn't stop us (%s)\n",
- priv->chip.pwms[0].label);
+ chip->pwms[0].label);
return -EBUSY;
}
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index 5f10cba492ec..0c028d17c075 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -27,7 +27,6 @@ struct stm32_breakinput {
};
struct stm32_pwm {
- struct pwm_chip chip;
struct mutex lock; /* protect pwm config/enable */
struct clk *clk;
struct regmap *regmap;
@@ -40,7 +39,7 @@ struct stm32_pwm {
static inline struct stm32_pwm *to_stm32_pwm_dev(struct pwm_chip *chip)
{
- return container_of(chip, struct stm32_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static u32 active_channels(struct stm32_pwm *dev)
@@ -90,11 +89,12 @@ static u32 active_channels(struct stm32_pwm *dev)
* - Period = t2 - t0
* - Duty cycle = t1 - t0
*/
-static int stm32_pwm_raw_capture(struct stm32_pwm *priv, struct pwm_device *pwm,
+static int stm32_pwm_raw_capture(struct pwm_chip *chip, struct pwm_device *pwm,
unsigned long tmo_ms, u32 *raw_prd,
u32 *raw_dty)
{
- struct device *parent = priv->chip.dev->parent;
+ struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
+ struct device *parent = pwmchip_parent(chip)->parent;
enum stm32_timers_dmas dma_id;
u32 ccen, ccr;
int ret;
@@ -170,7 +170,7 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
ret = clk_enable(priv->clk);
if (ret) {
- dev_err(priv->chip.dev, "failed to enable counter clock\n");
+ dev_err(pwmchip_parent(chip), "failed to enable counter clock\n");
goto unlock;
}
@@ -208,7 +208,7 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
TIM_CCER_CC12P : TIM_CCER_CC34P, pwm->hwpwm < 2 ?
TIM_CCER_CC2P : TIM_CCER_CC4P);
- ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd, &raw_dty);
+ ret = stm32_pwm_raw_capture(chip, pwm, tmo_ms, &raw_prd, &raw_dty);
if (ret)
goto stop;
@@ -229,7 +229,7 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
/* 2nd measure with new scale */
psc /= scale;
regmap_write(priv->regmap, TIM_PSC, psc);
- ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd,
+ ret = stm32_pwm_raw_capture(chip, pwm, tmo_ms, &raw_prd,
&raw_dty);
if (ret)
goto stop;
@@ -257,7 +257,7 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
FIELD_PREP(TIM_CCMR_IC1PSC, icpsc) |
FIELD_PREP(TIM_CCMR_IC2PSC, icpsc));
- ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd, &raw_dty);
+ ret = stm32_pwm_raw_capture(chip, pwm, tmo_ms, &raw_prd, &raw_dty);
if (ret)
goto stop;
@@ -605,7 +605,7 @@ static void stm32_pwm_detect_complementary(struct stm32_pwm *priv)
priv->have_complementary_output = (ccer != 0);
}
-static unsigned int stm32_pwm_detect_channels(struct stm32_pwm *priv,
+static unsigned int stm32_pwm_detect_channels(struct regmap *regmap,
unsigned int *num_enabled)
{
u32 ccer, ccer_backup;
@@ -614,10 +614,10 @@ static unsigned int stm32_pwm_detect_channels(struct stm32_pwm *priv,
* If channels enable bits don't exist writing 1 will have no
* effect so we can detect and count them.
*/
- regmap_read(priv->regmap, TIM_CCER, &ccer_backup);
- regmap_set_bits(priv->regmap, TIM_CCER, TIM_CCER_CCXE);
- regmap_read(priv->regmap, TIM_CCER, &ccer);
- regmap_write(priv->regmap, TIM_CCER, ccer_backup);
+ regmap_read(regmap, TIM_CCER, &ccer_backup);
+ regmap_set_bits(regmap, TIM_CCER, TIM_CCER_CCXE);
+ regmap_read(regmap, TIM_CCER, &ccer);
+ regmap_write(regmap, TIM_CCER, ccer_backup);
*num_enabled = hweight32(ccer_backup & TIM_CCER_CCXE);
@@ -629,14 +629,18 @@ static int stm32_pwm_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct stm32_timers *ddata = dev_get_drvdata(pdev->dev.parent);
+ struct pwm_chip *chip;
struct stm32_pwm *priv;
- unsigned int num_enabled;
+ unsigned int npwm, num_enabled;
unsigned int i;
int ret;
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ npwm = stm32_pwm_detect_channels(ddata->regmap, &num_enabled);
+
+ chip = devm_pwmchip_alloc(dev, npwm, sizeof(*priv));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ priv = to_stm32_pwm_dev(chip);
mutex_init(&priv->lock);
priv->regmap = ddata->regmap;
@@ -652,37 +656,36 @@ static int stm32_pwm_probe(struct platform_device *pdev)
stm32_pwm_detect_complementary(priv);
- priv->chip.dev = dev;
- priv->chip.ops = &stm32pwm_ops;
- priv->chip.npwm = stm32_pwm_detect_channels(priv, &num_enabled);
+ chip->ops = &stm32pwm_ops;
/* Initialize clock refcount to number of enabled PWM channels. */
for (i = 0; i < num_enabled; i++)
clk_enable(priv->clk);
- ret = devm_pwmchip_add(dev, &priv->chip);
+ ret = devm_pwmchip_add(dev, chip);
if (ret < 0)
return ret;
- platform_set_drvdata(pdev, priv);
+ platform_set_drvdata(pdev, chip);
return 0;
}
static int stm32_pwm_suspend(struct device *dev)
{
- struct stm32_pwm *priv = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
unsigned int i;
u32 ccer, mask;
/* Look for active channels */
ccer = active_channels(priv);
- for (i = 0; i < priv->chip.npwm; i++) {
+ for (i = 0; i < chip->npwm; i++) {
mask = TIM_CCER_CC1E << (i * 4);
if (ccer & mask) {
dev_err(dev, "PWM %u still in use by consumer %s\n",
- i, priv->chip.pwms[i].label);
+ i, chip->pwms[i].label);
return -EBUSY;
}
}
@@ -692,7 +695,8 @@ static int stm32_pwm_suspend(struct device *dev)
static int stm32_pwm_resume(struct device *dev)
{
- struct stm32_pwm *priv = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
int ret;
ret = pinctrl_pm_select_default_state(dev);
diff --git a/drivers/pwm/pwm-stmpe.c b/drivers/pwm/pwm-stmpe.c
index 19c0c0f39675..bb91062d5f1d 100644
--- a/drivers/pwm/pwm-stmpe.c
+++ b/drivers/pwm/pwm-stmpe.c
@@ -27,13 +27,12 @@
struct stmpe_pwm {
struct stmpe *stmpe;
- struct pwm_chip chip;
u8 last_duty;
};
static inline struct stmpe_pwm *to_stmpe_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct stmpe_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static int stmpe_24xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -44,7 +43,7 @@ static int stmpe_24xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
ret = stmpe_reg_read(stmpe_pwm->stmpe, STMPE24XX_PWMCS);
if (ret < 0) {
- dev_dbg(chip->dev, "error reading PWM#%u control\n",
+ dev_dbg(pwmchip_parent(chip), "error reading PWM#%u control\n",
pwm->hwpwm);
return ret;
}
@@ -53,7 +52,7 @@ static int stmpe_24xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
ret = stmpe_reg_write(stmpe_pwm->stmpe, STMPE24XX_PWMCS, value);
if (ret) {
- dev_dbg(chip->dev, "error writing PWM#%u control\n",
+ dev_dbg(pwmchip_parent(chip), "error writing PWM#%u control\n",
pwm->hwpwm);
return ret;
}
@@ -70,7 +69,7 @@ static int stmpe_24xx_pwm_disable(struct pwm_chip *chip,
ret = stmpe_reg_read(stmpe_pwm->stmpe, STMPE24XX_PWMCS);
if (ret < 0) {
- dev_dbg(chip->dev, "error reading PWM#%u control\n",
+ dev_dbg(pwmchip_parent(chip), "error reading PWM#%u control\n",
pwm->hwpwm);
return ret;
}
@@ -79,7 +78,7 @@ static int stmpe_24xx_pwm_disable(struct pwm_chip *chip,
ret = stmpe_reg_write(stmpe_pwm->stmpe, STMPE24XX_PWMCS, value);
if (ret)
- dev_dbg(chip->dev, "error writing PWM#%u control\n",
+ dev_dbg(pwmchip_parent(chip), "error writing PWM#%u control\n",
pwm->hwpwm);
return ret;
}
@@ -125,7 +124,7 @@ static int stmpe_24xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
ret = stmpe_set_altfunc(stmpe_pwm->stmpe, BIT(pin),
STMPE_BLOCK_PWM);
if (ret) {
- dev_err(chip->dev, "unable to connect PWM#%u to pin\n",
+ dev_err(pwmchip_parent(chip), "unable to connect PWM#%u to pin\n",
pwm->hwpwm);
return ret;
}
@@ -150,7 +149,7 @@ static int stmpe_24xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
return -ENODEV;
}
- dev_dbg(chip->dev, "PWM#%u: config duty %d ns, period %d ns\n",
+ dev_dbg(pwmchip_parent(chip), "PWM#%u: config duty %d ns, period %d ns\n",
pwm->hwpwm, duty_ns, period_ns);
if (duty_ns == 0) {
@@ -216,7 +215,7 @@ static int stmpe_24xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
program[1] = BRANCH;
}
- dev_dbg(chip->dev,
+ dev_dbg(pwmchip_parent(chip),
"PWM#%u: value = %02x, last_duty = %02x, program=%04x,%04x,%04x\n",
pwm->hwpwm, value, last, program[0], program[1],
program[2]);
@@ -233,7 +232,7 @@ static int stmpe_24xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
ret = stmpe_reg_write(stmpe_pwm->stmpe, offset, value);
if (ret) {
- dev_dbg(chip->dev, "error writing register %02x: %d\n",
+ dev_dbg(pwmchip_parent(chip), "error writing register %02x: %d\n",
offset, ret);
return ret;
}
@@ -242,7 +241,7 @@ static int stmpe_24xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
ret = stmpe_reg_write(stmpe_pwm->stmpe, offset, value);
if (ret) {
- dev_dbg(chip->dev, "error writing register %02x: %d\n",
+ dev_dbg(pwmchip_parent(chip), "error writing register %02x: %d\n",
offset, ret);
return ret;
}
@@ -255,7 +254,7 @@ static int stmpe_24xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
/* Sleep for 200ms so we're sure it will take effect */
msleep(200);
- dev_dbg(chip->dev, "programmed PWM#%u, %u bytes\n", pwm->hwpwm, i);
+ dev_dbg(pwmchip_parent(chip), "programmed PWM#%u, %u bytes\n", pwm->hwpwm, i);
return 0;
}
@@ -292,33 +291,36 @@ static const struct pwm_ops stmpe_24xx_pwm_ops = {
static int __init stmpe_pwm_probe(struct platform_device *pdev)
{
struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+ struct pwm_chip *chip;
struct stmpe_pwm *stmpe_pwm;
int ret;
- stmpe_pwm = devm_kzalloc(&pdev->dev, sizeof(*stmpe_pwm), GFP_KERNEL);
- if (!stmpe_pwm)
- return -ENOMEM;
+ switch (stmpe->partnum) {
+ case STMPE2401:
+ case STMPE2403:
+ break;
+ case STMPE1601:
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "STMPE1601 not yet supported\n");
+ default:
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "Unknown STMPE PWM\n");
+ }
- stmpe_pwm->stmpe = stmpe;
- stmpe_pwm->chip.dev = &pdev->dev;
+ chip = devm_pwmchip_alloc(&pdev->dev, 3, sizeof(*stmpe_pwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ stmpe_pwm = to_stmpe_pwm(chip);
- if (stmpe->partnum == STMPE2401 || stmpe->partnum == STMPE2403) {
- stmpe_pwm->chip.ops = &stmpe_24xx_pwm_ops;
- stmpe_pwm->chip.npwm = 3;
- } else {
- if (stmpe->partnum == STMPE1601)
- dev_err(&pdev->dev, "STMPE1601 not yet supported\n");
- else
- dev_err(&pdev->dev, "Unknown STMPE PWM\n");
+ stmpe_pwm->stmpe = stmpe;
- return -ENODEV;
- }
+ chip->ops = &stmpe_24xx_pwm_ops;
ret = stmpe_enable(stmpe, STMPE_BLOCK_PWM);
if (ret)
return ret;
- ret = pwmchip_add(&stmpe_pwm->chip);
+ ret = pwmchip_add(chip);
if (ret) {
stmpe_disable(stmpe, STMPE_BLOCK_PWM);
return ret;
diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index 1a439025540d..5c29590d1821 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -81,7 +81,6 @@ struct sun4i_pwm_data {
};
struct sun4i_pwm_chip {
- struct pwm_chip chip;
struct clk *bus_clk;
struct clk *clk;
struct reset_control *rst;
@@ -92,35 +91,35 @@ struct sun4i_pwm_chip {
static inline struct sun4i_pwm_chip *to_sun4i_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct sun4i_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
-static inline u32 sun4i_pwm_readl(struct sun4i_pwm_chip *chip,
+static inline u32 sun4i_pwm_readl(struct sun4i_pwm_chip *sun4ichip,
unsigned long offset)
{
- return readl(chip->base + offset);
+ return readl(sun4ichip->base + offset);
}
-static inline void sun4i_pwm_writel(struct sun4i_pwm_chip *chip,
+static inline void sun4i_pwm_writel(struct sun4i_pwm_chip *sun4ichip,
u32 val, unsigned long offset)
{
- writel(val, chip->base + offset);
+ writel(val, sun4ichip->base + offset);
}
static int sun4i_pwm_get_state(struct pwm_chip *chip,
struct pwm_device *pwm,
struct pwm_state *state)
{
- struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip);
+ struct sun4i_pwm_chip *sun4ichip = to_sun4i_pwm_chip(chip);
u64 clk_rate, tmp;
u32 val;
unsigned int prescaler;
- clk_rate = clk_get_rate(sun4i_pwm->clk);
+ clk_rate = clk_get_rate(sun4ichip->clk);
if (!clk_rate)
return -EINVAL;
- val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
+ val = sun4i_pwm_readl(sun4ichip, PWM_CTRL_REG);
/*
* PWM chapter in H6 manual has a diagram which explains that if bypass
@@ -128,7 +127,7 @@ static int sun4i_pwm_get_state(struct pwm_chip *chip,
* proved that also enable bit is ignored in this case.
*/
if ((val & BIT_CH(PWM_BYPASS, pwm->hwpwm)) &&
- sun4i_pwm->data->has_direct_mod_clk_output) {
+ sun4ichip->data->has_direct_mod_clk_output) {
state->period = DIV_ROUND_UP_ULL(NSEC_PER_SEC, clk_rate);
state->duty_cycle = DIV_ROUND_UP_ULL(state->period, 2);
state->polarity = PWM_POLARITY_NORMAL;
@@ -137,7 +136,7 @@ static int sun4i_pwm_get_state(struct pwm_chip *chip,
}
if ((PWM_REG_PRESCAL(val, pwm->hwpwm) == PWM_PRESCAL_MASK) &&
- sun4i_pwm->data->has_prescaler_bypass)
+ sun4ichip->data->has_prescaler_bypass)
prescaler = 1;
else
prescaler = prescaler_table[PWM_REG_PRESCAL(val, pwm->hwpwm)];
@@ -156,7 +155,7 @@ static int sun4i_pwm_get_state(struct pwm_chip *chip,
else
state->enabled = false;
- val = sun4i_pwm_readl(sun4i_pwm, PWM_CH_PRD(pwm->hwpwm));
+ val = sun4i_pwm_readl(sun4ichip, PWM_CH_PRD(pwm->hwpwm));
tmp = (u64)prescaler * NSEC_PER_SEC * PWM_REG_DTY(val);
state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
@@ -167,7 +166,7 @@ static int sun4i_pwm_get_state(struct pwm_chip *chip,
return 0;
}
-static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm,
+static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4ichip,
const struct pwm_state *state,
u32 *dty, u32 *prd, unsigned int *prsclr,
bool *bypass)
@@ -175,9 +174,9 @@ static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm,
u64 clk_rate, div = 0;
unsigned int prescaler = 0;
- clk_rate = clk_get_rate(sun4i_pwm->clk);
+ clk_rate = clk_get_rate(sun4ichip->clk);
- *bypass = sun4i_pwm->data->has_direct_mod_clk_output &&
+ *bypass = sun4ichip->data->has_direct_mod_clk_output &&
state->enabled &&
(state->period * clk_rate >= NSEC_PER_SEC) &&
(state->period * clk_rate < 2 * NSEC_PER_SEC) &&
@@ -187,7 +186,7 @@ static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm,
if (*bypass)
return 0;
- if (sun4i_pwm->data->has_prescaler_bypass) {
+ if (sun4ichip->data->has_prescaler_bypass) {
/* First, test without any prescaler when available */
prescaler = PWM_PRESCAL_MASK;
/*
@@ -233,7 +232,7 @@ static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm,
static int sun4i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
- struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip);
+ struct sun4i_pwm_chip *sun4ichip = to_sun4i_pwm_chip(chip);
struct pwm_state cstate;
u32 ctrl, duty = 0, period = 0, val;
int ret;
@@ -243,31 +242,31 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
pwm_get_state(pwm, &cstate);
if (!cstate.enabled) {
- ret = clk_prepare_enable(sun4i_pwm->clk);
+ ret = clk_prepare_enable(sun4ichip->clk);
if (ret) {
- dev_err(chip->dev, "failed to enable PWM clock\n");
+ dev_err(pwmchip_parent(chip), "failed to enable PWM clock\n");
return ret;
}
}
- ret = sun4i_pwm_calculate(sun4i_pwm, state, &duty, &period, &prescaler,
+ ret = sun4i_pwm_calculate(sun4ichip, state, &duty, &period, &prescaler,
&bypass);
if (ret) {
- dev_err(chip->dev, "period exceeds the maximum value\n");
+ dev_err(pwmchip_parent(chip), "period exceeds the maximum value\n");
if (!cstate.enabled)
- clk_disable_unprepare(sun4i_pwm->clk);
+ clk_disable_unprepare(sun4ichip->clk);
return ret;
}
- spin_lock(&sun4i_pwm->ctrl_lock);
- ctrl = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
+ spin_lock(&sun4ichip->ctrl_lock);
+ ctrl = sun4i_pwm_readl(sun4ichip, PWM_CTRL_REG);
- if (sun4i_pwm->data->has_direct_mod_clk_output) {
+ if (sun4ichip->data->has_direct_mod_clk_output) {
if (bypass) {
ctrl |= BIT_CH(PWM_BYPASS, pwm->hwpwm);
/* We can skip other parameter */
- sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
- spin_unlock(&sun4i_pwm->ctrl_lock);
+ sun4i_pwm_writel(sun4ichip, ctrl, PWM_CTRL_REG);
+ spin_unlock(&sun4ichip->ctrl_lock);
return 0;
}
@@ -277,14 +276,14 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (PWM_REG_PRESCAL(ctrl, pwm->hwpwm) != prescaler) {
/* Prescaler changed, the clock has to be gated */
ctrl &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
- sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
+ sun4i_pwm_writel(sun4ichip, ctrl, PWM_CTRL_REG);
ctrl &= ~BIT_CH(PWM_PRESCAL_MASK, pwm->hwpwm);
ctrl |= BIT_CH(prescaler, pwm->hwpwm);
}
val = (duty & PWM_DTY_MASK) | PWM_PRD(period);
- sun4i_pwm_writel(sun4i_pwm, val, PWM_CH_PRD(pwm->hwpwm));
+ sun4i_pwm_writel(sun4ichip, val, PWM_CH_PRD(pwm->hwpwm));
if (state->polarity != PWM_POLARITY_NORMAL)
ctrl &= ~BIT_CH(PWM_ACT_STATE, pwm->hwpwm);
@@ -296,9 +295,9 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (state->enabled)
ctrl |= BIT_CH(PWM_EN, pwm->hwpwm);
- sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
+ sun4i_pwm_writel(sun4ichip, ctrl, PWM_CTRL_REG);
- spin_unlock(&sun4i_pwm->ctrl_lock);
+ spin_unlock(&sun4ichip->ctrl_lock);
if (state->enabled)
return 0;
@@ -310,14 +309,14 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
else
usleep_range(delay_us, delay_us * 2);
- spin_lock(&sun4i_pwm->ctrl_lock);
- ctrl = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
+ spin_lock(&sun4ichip->ctrl_lock);
+ ctrl = sun4i_pwm_readl(sun4ichip, PWM_CTRL_REG);
ctrl &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
ctrl &= ~BIT_CH(PWM_EN, pwm->hwpwm);
- sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
- spin_unlock(&sun4i_pwm->ctrl_lock);
+ sun4i_pwm_writel(sun4ichip, ctrl, PWM_CTRL_REG);
+ spin_unlock(&sun4ichip->ctrl_lock);
- clk_disable_unprepare(sun4i_pwm->clk);
+ clk_disable_unprepare(sun4ichip->clk);
return 0;
}
@@ -384,17 +383,21 @@ MODULE_DEVICE_TABLE(of, sun4i_pwm_dt_ids);
static int sun4i_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
+ const struct sun4i_pwm_data *data;
struct sun4i_pwm_chip *sun4ichip;
int ret;
- sun4ichip = devm_kzalloc(&pdev->dev, sizeof(*sun4ichip), GFP_KERNEL);
- if (!sun4ichip)
- return -ENOMEM;
-
- sun4ichip->data = of_device_get_match_data(&pdev->dev);
- if (!sun4ichip->data)
+ data = of_device_get_match_data(&pdev->dev);
+ if (!data)
return -ENODEV;
+ chip = devm_pwmchip_alloc(&pdev->dev, data->npwm, sizeof(*sun4ichip));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ sun4ichip = to_sun4i_pwm_chip(chip);
+
+ sun4ichip->data = data;
sun4ichip->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sun4ichip->base))
return PTR_ERR(sun4ichip->base);
@@ -451,19 +454,17 @@ static int sun4i_pwm_probe(struct platform_device *pdev)
goto err_bus;
}
- sun4ichip->chip.dev = &pdev->dev;
- sun4ichip->chip.ops = &sun4i_pwm_ops;
- sun4ichip->chip.npwm = sun4ichip->data->npwm;
+ chip->ops = &sun4i_pwm_ops;
spin_lock_init(&sun4ichip->ctrl_lock);
- ret = pwmchip_add(&sun4ichip->chip);
+ ret = pwmchip_add(chip);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
goto err_pwm_add;
}
- platform_set_drvdata(pdev, sun4ichip);
+ platform_set_drvdata(pdev, chip);
return 0;
@@ -477,9 +478,10 @@ err_bus:
static void sun4i_pwm_remove(struct platform_device *pdev)
{
- struct sun4i_pwm_chip *sun4ichip = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
+ struct sun4i_pwm_chip *sun4ichip = to_sun4i_pwm_chip(chip);
- pwmchip_remove(&sun4ichip->chip);
+ pwmchip_remove(chip);
clk_disable_unprepare(sun4ichip->bus_clk);
reset_control_assert(sun4ichip->rst);
diff --git a/drivers/pwm/pwm-sunplus.c b/drivers/pwm/pwm-sunplus.c
index 773e2f80526e..b342b843247b 100644
--- a/drivers/pwm/pwm-sunplus.c
+++ b/drivers/pwm/pwm-sunplus.c
@@ -43,14 +43,13 @@
#define SP7021_PWM_NUM 4
struct sunplus_pwm {
- struct pwm_chip chip;
void __iomem *base;
struct clk *clk;
};
static inline struct sunplus_pwm *to_sunplus_pwm(struct pwm_chip *chip)
{
- return container_of(chip, struct sunplus_pwm, chip);
+ return pwmchip_get_drvdata(chip);
}
static int sunplus_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -175,12 +174,14 @@ static void sunplus_pwm_clk_release(void *data)
static int sunplus_pwm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct pwm_chip *chip;
struct sunplus_pwm *priv;
int ret;
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(dev, SP7021_PWM_NUM, sizeof(*priv));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ priv = to_sunplus_pwm(chip);
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
@@ -203,11 +204,9 @@ static int sunplus_pwm_probe(struct platform_device *pdev)
return ret;
}
- priv->chip.dev = dev;
- priv->chip.ops = &sunplus_pwm_ops;
- priv->chip.npwm = SP7021_PWM_NUM;
+ chip->ops = &sunplus_pwm_ops;
- ret = devm_pwmchip_add(dev, &priv->chip);
+ ret = devm_pwmchip_add(dev, chip);
if (ret < 0)
return dev_err_probe(dev, ret, "Cannot register sunplus PWM\n");
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index 82ee2f0754f9..a3d69976148f 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -65,9 +65,6 @@ struct tegra_pwm_soc {
};
struct tegra_pwm_chip {
- struct pwm_chip chip;
- struct device *dev;
-
struct clk *clk;
struct reset_control*rst;
@@ -81,7 +78,7 @@ struct tegra_pwm_chip {
static inline struct tegra_pwm_chip *to_tegra_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct tegra_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static inline u32 pwm_readl(struct tegra_pwm_chip *pc, unsigned int offset)
@@ -158,7 +155,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
*/
required_clk_rate *= 2;
- err = dev_pm_opp_set_rate(pc->dev, required_clk_rate);
+ err = dev_pm_opp_set_rate(pwmchip_parent(chip), required_clk_rate);
if (err < 0)
return -EINVAL;
@@ -194,7 +191,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
* before writing the register. Otherwise, keep it enabled.
*/
if (!pwm_is_enabled(pwm)) {
- err = pm_runtime_resume_and_get(pc->dev);
+ err = pm_runtime_resume_and_get(pwmchip_parent(chip));
if (err)
return err;
} else
@@ -206,7 +203,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
* If the PWM is not enabled, turn the clock off again to save power.
*/
if (!pwm_is_enabled(pwm))
- pm_runtime_put(pc->dev);
+ pm_runtime_put(pwmchip_parent(chip));
return 0;
}
@@ -217,7 +214,7 @@ static int tegra_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
int rc = 0;
u32 val;
- rc = pm_runtime_resume_and_get(pc->dev);
+ rc = pm_runtime_resume_and_get(pwmchip_parent(chip));
if (rc)
return rc;
@@ -237,7 +234,7 @@ static void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
val &= ~PWM_ENABLE;
pwm_writel(pc, pwm->hwpwm, val);
- pm_runtime_put_sync(pc->dev);
+ pm_runtime_put_sync(pwmchip_parent(chip));
}
static int tegra_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -272,21 +269,25 @@ static const struct pwm_ops tegra_pwm_ops = {
static int tegra_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct tegra_pwm_chip *pc;
+ const struct tegra_pwm_soc *soc;
int ret;
- pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
- if (!pc)
- return -ENOMEM;
+ soc = of_device_get_match_data(&pdev->dev);
+
+ chip = devm_pwmchip_alloc(&pdev->dev, soc->num_channels, sizeof(*pc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pc = to_tegra_pwm_chip(chip);
- pc->soc = of_device_get_match_data(&pdev->dev);
- pc->dev = &pdev->dev;
+ pc->soc = soc;
pc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pc->regs))
return PTR_ERR(pc->regs);
- platform_set_drvdata(pdev, pc);
+ platform_set_drvdata(pdev, chip);
pc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pc->clk))
@@ -302,7 +303,7 @@ static int tegra_pwm_probe(struct platform_device *pdev)
return ret;
/* Set maximum frequency of the IP */
- ret = dev_pm_opp_set_rate(pc->dev, pc->soc->max_frequency);
+ ret = dev_pm_opp_set_rate(&pdev->dev, pc->soc->max_frequency);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to set max frequency: %d\n", ret);
goto put_pm;
@@ -328,11 +329,9 @@ static int tegra_pwm_probe(struct platform_device *pdev)
reset_control_deassert(pc->rst);
- pc->chip.dev = &pdev->dev;
- pc->chip.ops = &tegra_pwm_ops;
- pc->chip.npwm = pc->soc->num_channels;
+ chip->ops = &tegra_pwm_ops;
- ret = pwmchip_add(&pc->chip);
+ ret = pwmchip_add(chip);
if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
reset_control_assert(pc->rst);
@@ -350,9 +349,10 @@ put_pm:
static void tegra_pwm_remove(struct platform_device *pdev)
{
- struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
+ struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
- pwmchip_remove(&pc->chip);
+ pwmchip_remove(chip);
reset_control_assert(pc->rst);
@@ -361,7 +361,8 @@ static void tegra_pwm_remove(struct platform_device *pdev)
static int __maybe_unused tegra_pwm_runtime_suspend(struct device *dev)
{
- struct tegra_pwm_chip *pc = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
int err;
clk_disable_unprepare(pc->clk);
@@ -377,7 +378,8 @@ static int __maybe_unused tegra_pwm_runtime_suspend(struct device *dev)
static int __maybe_unused tegra_pwm_runtime_resume(struct device *dev)
{
- struct tegra_pwm_chip *pc = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
int err;
err = pinctrl_pm_select_default_state(dev);
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index d974f4414ac9..d6c2b1b1387e 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -32,7 +32,6 @@ struct ecap_context {
};
struct ecap_pwm_chip {
- struct pwm_chip chip;
unsigned int clk_rate;
void __iomem *mmio_base;
struct ecap_context ctx;
@@ -40,7 +39,7 @@ struct ecap_pwm_chip {
static inline struct ecap_pwm_chip *to_ecap_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct ecap_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
/*
@@ -70,7 +69,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
duty_cycles = (u32)c;
}
- pm_runtime_get_sync(pc->chip.dev);
+ pm_runtime_get_sync(pwmchip_parent(chip));
value = readw(pc->mmio_base + ECCTL2);
@@ -100,7 +99,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
writew(value, pc->mmio_base + ECCTL2);
}
- pm_runtime_put_sync(pc->chip.dev);
+ pm_runtime_put_sync(pwmchip_parent(chip));
return 0;
}
@@ -111,7 +110,7 @@ static int ecap_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
u16 value;
- pm_runtime_get_sync(pc->chip.dev);
+ pm_runtime_get_sync(pwmchip_parent(chip));
value = readw(pc->mmio_base + ECCTL2);
@@ -124,7 +123,7 @@ static int ecap_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
writew(value, pc->mmio_base + ECCTL2);
- pm_runtime_put_sync(pc->chip.dev);
+ pm_runtime_put_sync(pwmchip_parent(chip));
return 0;
}
@@ -135,7 +134,7 @@ static int ecap_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
u16 value;
/* Leave clock enabled on enabling PWM */
- pm_runtime_get_sync(pc->chip.dev);
+ pm_runtime_get_sync(pwmchip_parent(chip));
/*
* Enable 'Free run Time stamp counter mode' to start counter
@@ -162,7 +161,7 @@ static void ecap_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
writew(value, pc->mmio_base + ECCTL2);
/* Disable clock on PWM disable */
- pm_runtime_put_sync(pc->chip.dev);
+ pm_runtime_put_sync(pwmchip_parent(chip));
}
static int ecap_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -218,12 +217,14 @@ static int ecap_pwm_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct ecap_pwm_chip *pc;
+ struct pwm_chip *chip;
struct clk *clk;
int ret;
- pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
- if (!pc)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*pc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pc = to_ecap_pwm_chip(chip);
clk = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(clk)) {
@@ -244,21 +245,19 @@ static int ecap_pwm_probe(struct platform_device *pdev)
return -EINVAL;
}
- pc->chip.dev = &pdev->dev;
- pc->chip.ops = &ecap_pwm_ops;
- pc->chip.npwm = 1;
+ chip->ops = &ecap_pwm_ops;
pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pc->mmio_base))
return PTR_ERR(pc->mmio_base);
- ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
return ret;
}
- platform_set_drvdata(pdev, pc);
+ platform_set_drvdata(pdev, chip);
pm_runtime_enable(&pdev->dev);
return 0;
@@ -269,17 +268,21 @@ static void ecap_pwm_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
}
-static void ecap_pwm_save_context(struct ecap_pwm_chip *pc)
+static void ecap_pwm_save_context(struct pwm_chip *chip)
{
- pm_runtime_get_sync(pc->chip.dev);
+ struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
+
+ pm_runtime_get_sync(pwmchip_parent(chip));
pc->ctx.ecctl2 = readw(pc->mmio_base + ECCTL2);
pc->ctx.cap4 = readl(pc->mmio_base + CAP4);
pc->ctx.cap3 = readl(pc->mmio_base + CAP3);
- pm_runtime_put_sync(pc->chip.dev);
+ pm_runtime_put_sync(pwmchip_parent(chip));
}
-static void ecap_pwm_restore_context(struct ecap_pwm_chip *pc)
+static void ecap_pwm_restore_context(struct pwm_chip *chip)
{
+ struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
+
writel(pc->ctx.cap3, pc->mmio_base + CAP3);
writel(pc->ctx.cap4, pc->mmio_base + CAP4);
writew(pc->ctx.ecctl2, pc->mmio_base + ECCTL2);
@@ -287,10 +290,10 @@ static void ecap_pwm_restore_context(struct ecap_pwm_chip *pc)
static int ecap_pwm_suspend(struct device *dev)
{
- struct ecap_pwm_chip *pc = dev_get_drvdata(dev);
- struct pwm_device *pwm = pc->chip.pwms;
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct pwm_device *pwm = chip->pwms;
- ecap_pwm_save_context(pc);
+ ecap_pwm_save_context(chip);
/* Disable explicitly if PWM is running */
if (pwm_is_enabled(pwm))
@@ -301,14 +304,14 @@ static int ecap_pwm_suspend(struct device *dev)
static int ecap_pwm_resume(struct device *dev)
{
- struct ecap_pwm_chip *pc = dev_get_drvdata(dev);
- struct pwm_device *pwm = pc->chip.pwms;
+ struct pwm_chip *chip = dev_get_drvdata(dev);
+ struct pwm_device *pwm = chip->pwms;
/* Enable explicitly if PWM was running */
if (pwm_is_enabled(pwm))
pm_runtime_get_sync(dev);
- ecap_pwm_restore_context(pc);
+ ecap_pwm_restore_context(chip);
return 0;
}
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index af231fa74fa9..e5104725d9b7 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -105,7 +105,6 @@ struct ehrpwm_context {
};
struct ehrpwm_pwm_chip {
- struct pwm_chip chip;
unsigned long clk_rate;
void __iomem *mmio_base;
unsigned long period_cycles[NUM_PWM_CHANNEL];
@@ -116,7 +115,7 @@ struct ehrpwm_pwm_chip {
static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct ehrpwm_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static inline u16 ehrpwm_read(void __iomem *base, unsigned int offset)
@@ -256,7 +255,7 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
if (i == pwm->hwpwm)
continue;
- dev_err(chip->dev,
+ dev_err(pwmchip_parent(chip),
"period value conflicts with channel %u\n",
i);
return -EINVAL;
@@ -268,11 +267,11 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
/* Configure clock prescaler to support Low frequency PWM wave */
if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval,
&tb_divval)) {
- dev_err(chip->dev, "Unsupported values\n");
+ dev_err(pwmchip_parent(chip), "Unsupported values\n");
return -EINVAL;
}
- pm_runtime_get_sync(chip->dev);
+ pm_runtime_get_sync(pwmchip_parent(chip));
/* Update clock prescaler values */
ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CLKDIV_MASK, tb_divval);
@@ -299,7 +298,7 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles);
- pm_runtime_put_sync(chip->dev);
+ pm_runtime_put_sync(pwmchip_parent(chip));
return 0;
}
@@ -323,7 +322,7 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
int ret;
/* Leave clock enabled on enabling PWM */
- pm_runtime_get_sync(chip->dev);
+ pm_runtime_get_sync(pwmchip_parent(chip));
/* Disabling Action Qualifier on PWM output */
if (pwm->hwpwm) {
@@ -346,8 +345,8 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
/* Enable TBCLK */
ret = clk_enable(pc->tbclk);
if (ret) {
- dev_err(chip->dev, "Failed to enable TBCLK for %s: %d\n",
- dev_name(pc->chip.dev), ret);
+ dev_err(pwmchip_parent(chip), "Failed to enable TBCLK for %s: %d\n",
+ dev_name(pwmchip_parent(chip)), ret);
return ret;
}
@@ -385,7 +384,7 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
clk_disable(pc->tbclk);
/* Disable clock on PWM disable */
- pm_runtime_put_sync(chip->dev);
+ pm_runtime_put_sync(pwmchip_parent(chip));
}
static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -393,8 +392,8 @@ static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
if (pwm_is_enabled(pwm)) {
- dev_warn(chip->dev, "Removing PWM device without disabling\n");
- pm_runtime_put_sync(chip->dev);
+ dev_warn(pwmchip_parent(chip), "Removing PWM device without disabling\n");
+ pm_runtime_put_sync(pwmchip_parent(chip));
}
/* set period value to zero on free */
@@ -450,12 +449,14 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct ehrpwm_pwm_chip *pc;
+ struct pwm_chip *chip;
struct clk *clk;
int ret;
- pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
- if (!pc)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, NUM_PWM_CHANNEL, sizeof(*pc));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pc = to_ehrpwm_pwm_chip(chip);
clk = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(clk)) {
@@ -474,9 +475,7 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
return -EINVAL;
}
- pc->chip.dev = &pdev->dev;
- pc->chip.ops = &ehrpwm_pwm_ops;
- pc->chip.npwm = NUM_PWM_CHANNEL;
+ chip->ops = &ehrpwm_pwm_ops;
pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pc->mmio_base))
@@ -493,13 +492,13 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
return ret;
}
- ret = pwmchip_add(&pc->chip);
+ ret = pwmchip_add(chip);
if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
goto err_clk_unprepare;
}
- platform_set_drvdata(pdev, pc);
+ platform_set_drvdata(pdev, chip);
pm_runtime_enable(&pdev->dev);
return 0;
@@ -512,18 +511,21 @@ err_clk_unprepare:
static void ehrpwm_pwm_remove(struct platform_device *pdev)
{
- struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
+ struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
- pwmchip_remove(&pc->chip);
+ pwmchip_remove(chip);
clk_unprepare(pc->tbclk);
pm_runtime_disable(&pdev->dev);
}
-static void ehrpwm_pwm_save_context(struct ehrpwm_pwm_chip *pc)
+static void ehrpwm_pwm_save_context(struct pwm_chip *chip)
{
- pm_runtime_get_sync(pc->chip.dev);
+ struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
+
+ pm_runtime_get_sync(pwmchip_parent(chip));
pc->ctx.tbctl = ehrpwm_read(pc->mmio_base, TBCTL);
pc->ctx.tbprd = ehrpwm_read(pc->mmio_base, TBPRD);
@@ -534,11 +536,13 @@ static void ehrpwm_pwm_save_context(struct ehrpwm_pwm_chip *pc)
pc->ctx.aqsfrc = ehrpwm_read(pc->mmio_base, AQSFRC);
pc->ctx.aqcsfrc = ehrpwm_read(pc->mmio_base, AQCSFRC);
- pm_runtime_put_sync(pc->chip.dev);
+ pm_runtime_put_sync(pwmchip_parent(chip));
}
-static void ehrpwm_pwm_restore_context(struct ehrpwm_pwm_chip *pc)
+static void ehrpwm_pwm_restore_context(struct pwm_chip *chip)
{
+ struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
+
ehrpwm_write(pc->mmio_base, TBPRD, pc->ctx.tbprd);
ehrpwm_write(pc->mmio_base, CMPA, pc->ctx.cmpa);
ehrpwm_write(pc->mmio_base, CMPB, pc->ctx.cmpb);
@@ -551,13 +555,13 @@ static void ehrpwm_pwm_restore_context(struct ehrpwm_pwm_chip *pc)
static int ehrpwm_pwm_suspend(struct device *dev)
{
- struct ehrpwm_pwm_chip *pc = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
unsigned int i;
- ehrpwm_pwm_save_context(pc);
+ ehrpwm_pwm_save_context(chip);
- for (i = 0; i < pc->chip.npwm; i++) {
- struct pwm_device *pwm = &pc->chip.pwms[i];
+ for (i = 0; i < chip->npwm; i++) {
+ struct pwm_device *pwm = &chip->pwms[i];
if (!pwm_is_enabled(pwm))
continue;
@@ -571,11 +575,11 @@ static int ehrpwm_pwm_suspend(struct device *dev)
static int ehrpwm_pwm_resume(struct device *dev)
{
- struct ehrpwm_pwm_chip *pc = dev_get_drvdata(dev);
+ struct pwm_chip *chip = dev_get_drvdata(dev);
unsigned int i;
- for (i = 0; i < pc->chip.npwm; i++) {
- struct pwm_device *pwm = &pc->chip.pwms[i];
+ for (i = 0; i < chip->npwm; i++) {
+ struct pwm_device *pwm = &chip->pwms[i];
if (!pwm_is_enabled(pwm))
continue;
@@ -584,7 +588,7 @@ static int ehrpwm_pwm_resume(struct device *dev)
pm_runtime_get_sync(dev);
}
- ehrpwm_pwm_restore_context(pc);
+ ehrpwm_pwm_restore_context(chip);
return 0;
}
diff --git a/drivers/pwm/pwm-twl-led.c b/drivers/pwm/pwm-twl-led.c
index c670ccb81653..4b10a8dab312 100644
--- a/drivers/pwm/pwm-twl-led.c
+++ b/drivers/pwm/pwm-twl-led.c
@@ -62,13 +62,12 @@
#define TWL6040_LED_MODE_MASK 0x03
struct twl_pwmled_chip {
- struct pwm_chip chip;
struct mutex mutex;
};
static inline struct twl_pwmled_chip *to_twl(struct pwm_chip *chip)
{
- return container_of(chip, struct twl_pwmled_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static int twl4030_pwmled_config(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -100,7 +99,7 @@ static int twl4030_pwmled_config(struct pwm_chip *chip, struct pwm_device *pwm,
ret = twl_i2c_write(TWL4030_MODULE_LED, pwm_config, base, 2);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to configure PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to configure PWM\n", pwm->label);
return ret;
}
@@ -114,7 +113,7 @@ static int twl4030_pwmled_enable(struct pwm_chip *chip, struct pwm_device *pwm)
mutex_lock(&twl->mutex);
ret = twl_i2c_read_u8(TWL4030_MODULE_LED, &val, TWL4030_LEDEN_REG);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to read LEDEN\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to read LEDEN\n", pwm->label);
goto out;
}
@@ -122,7 +121,7 @@ static int twl4030_pwmled_enable(struct pwm_chip *chip, struct pwm_device *pwm)
ret = twl_i2c_write_u8(TWL4030_MODULE_LED, val, TWL4030_LEDEN_REG);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to enable PWM\n", pwm->label);
out:
mutex_unlock(&twl->mutex);
@@ -139,7 +138,7 @@ static void twl4030_pwmled_disable(struct pwm_chip *chip,
mutex_lock(&twl->mutex);
ret = twl_i2c_read_u8(TWL4030_MODULE_LED, &val, TWL4030_LEDEN_REG);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to read LEDEN\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to read LEDEN\n", pwm->label);
goto out;
}
@@ -147,7 +146,7 @@ static void twl4030_pwmled_disable(struct pwm_chip *chip,
ret = twl_i2c_write_u8(TWL4030_MODULE_LED, val, TWL4030_LEDEN_REG);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label);
out:
mutex_unlock(&twl->mutex);
@@ -203,7 +202,7 @@ static int twl6030_pwmled_config(struct pwm_chip *chip, struct pwm_device *pwm,
ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, on_time,
TWL6030_LED_PWM_CTRL1);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to configure PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to configure PWM\n", pwm->label);
return ret;
}
@@ -217,7 +216,7 @@ static int twl6030_pwmled_enable(struct pwm_chip *chip, struct pwm_device *pwm)
mutex_lock(&twl->mutex);
ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n",
+ dev_err(pwmchip_parent(chip), "%s: Failed to read PWM_CTRL2\n",
pwm->label);
goto out;
}
@@ -227,7 +226,7 @@ static int twl6030_pwmled_enable(struct pwm_chip *chip, struct pwm_device *pwm)
ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to enable PWM\n", pwm->label);
out:
mutex_unlock(&twl->mutex);
@@ -244,7 +243,7 @@ static void twl6030_pwmled_disable(struct pwm_chip *chip,
mutex_lock(&twl->mutex);
ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n",
+ dev_err(pwmchip_parent(chip), "%s: Failed to read PWM_CTRL2\n",
pwm->label);
goto out;
}
@@ -254,7 +253,7 @@ static void twl6030_pwmled_disable(struct pwm_chip *chip,
ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label);
out:
mutex_unlock(&twl->mutex);
@@ -295,7 +294,7 @@ static int twl6030_pwmled_request(struct pwm_chip *chip, struct pwm_device *pwm)
mutex_lock(&twl->mutex);
ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n",
+ dev_err(pwmchip_parent(chip), "%s: Failed to read PWM_CTRL2\n",
pwm->label);
goto out;
}
@@ -305,7 +304,7 @@ static int twl6030_pwmled_request(struct pwm_chip *chip, struct pwm_device *pwm)
ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to request PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to request PWM\n", pwm->label);
out:
mutex_unlock(&twl->mutex);
@@ -321,7 +320,7 @@ static void twl6030_pwmled_free(struct pwm_chip *chip, struct pwm_device *pwm)
mutex_lock(&twl->mutex);
ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n",
+ dev_err(pwmchip_parent(chip), "%s: Failed to read PWM_CTRL2\n",
pwm->label);
goto out;
}
@@ -331,7 +330,7 @@ static void twl6030_pwmled_free(struct pwm_chip *chip, struct pwm_device *pwm)
ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to free PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to free PWM\n", pwm->label);
out:
mutex_unlock(&twl->mutex);
@@ -345,25 +344,29 @@ static const struct pwm_ops twl6030_pwmled_ops = {
static int twl_pwmled_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct twl_pwmled_chip *twl;
-
- twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
- if (!twl)
- return -ENOMEM;
+ unsigned int npwm;
+ const struct pwm_ops *ops;
if (twl_class_is_4030()) {
- twl->chip.ops = &twl4030_pwmled_ops;
- twl->chip.npwm = 2;
+ ops = &twl4030_pwmled_ops;
+ npwm = 2;
} else {
- twl->chip.ops = &twl6030_pwmled_ops;
- twl->chip.npwm = 1;
+ ops = &twl6030_pwmled_ops;
+ npwm = 1;
}
- twl->chip.dev = &pdev->dev;
+ chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*twl));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ twl = to_twl(chip);
+
+ chip->ops = ops;
mutex_init(&twl->mutex);
- return devm_pwmchip_add(&pdev->dev, &twl->chip);
+ return devm_pwmchip_add(&pdev->dev, chip);
}
#ifdef CONFIG_OF
diff --git a/drivers/pwm/pwm-twl.c b/drivers/pwm/pwm-twl.c
index 68e02c9a6bf9..8f981ffff4b4 100644
--- a/drivers/pwm/pwm-twl.c
+++ b/drivers/pwm/pwm-twl.c
@@ -46,7 +46,6 @@
#define TWL6030_PWM_TOGGLE(pwm, x) ((x) << (pwm * 3))
struct twl_pwm_chip {
- struct pwm_chip chip;
struct mutex mutex;
u8 twl6030_toggle3;
u8 twl4030_pwm_mux;
@@ -54,7 +53,7 @@ struct twl_pwm_chip {
static inline struct twl_pwm_chip *to_twl(struct pwm_chip *chip)
{
- return container_of(chip, struct twl_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static int twl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -86,7 +85,7 @@ static int twl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
ret = twl_i2c_write(TWL_MODULE_PWM, pwm_config, base, 2);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to configure PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to configure PWM\n", pwm->label);
return ret;
}
@@ -100,7 +99,7 @@ static int twl4030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
mutex_lock(&twl->mutex);
ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_GPBR1_REG);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to read GPBR1\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to read GPBR1\n", pwm->label);
goto out;
}
@@ -108,13 +107,13 @@ static int twl4030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to enable PWM\n", pwm->label);
val |= TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMX_ENABLE);
ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to enable PWM\n", pwm->label);
out:
mutex_unlock(&twl->mutex);
@@ -130,7 +129,7 @@ static void twl4030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
mutex_lock(&twl->mutex);
ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_GPBR1_REG);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to read GPBR1\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to read GPBR1\n", pwm->label);
goto out;
}
@@ -138,13 +137,13 @@ static void twl4030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label);
val &= ~TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMXCLK_ENABLE);
ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label);
out:
mutex_unlock(&twl->mutex);
@@ -167,7 +166,7 @@ static int twl4030_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
mutex_lock(&twl->mutex);
ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_PMBR1_REG);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to read PMBR1\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to read PMBR1\n", pwm->label);
goto out;
}
@@ -181,7 +180,7 @@ static int twl4030_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_PMBR1_REG);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to request PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to request PWM\n", pwm->label);
out:
mutex_unlock(&twl->mutex);
@@ -202,7 +201,7 @@ static void twl4030_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
mutex_lock(&twl->mutex);
ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_PMBR1_REG);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to read PMBR1\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to read PMBR1\n", pwm->label);
goto out;
}
@@ -212,7 +211,7 @@ static void twl4030_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_PMBR1_REG);
if (ret < 0)
- dev_err(chip->dev, "%s: Failed to free PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to free PWM\n", pwm->label);
out:
mutex_unlock(&twl->mutex);
@@ -231,7 +230,7 @@ static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to enable PWM\n", pwm->label);
goto out;
}
@@ -254,7 +253,7 @@ static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label);
goto out;
}
@@ -262,7 +261,7 @@ static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label);
goto out;
}
@@ -270,7 +269,7 @@ static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG);
if (ret < 0) {
- dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
+ dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label);
goto out;
}
@@ -341,23 +340,22 @@ static const struct pwm_ops twl6030_pwm_ops = {
static int twl_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct twl_pwm_chip *twl;
- twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
- if (!twl)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, 2, sizeof(*twl));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ twl = to_twl(chip);
if (twl_class_is_4030())
- twl->chip.ops = &twl4030_pwm_ops;
+ chip->ops = &twl4030_pwm_ops;
else
- twl->chip.ops = &twl6030_pwm_ops;
-
- twl->chip.dev = &pdev->dev;
- twl->chip.npwm = 2;
+ chip->ops = &twl6030_pwm_ops;
mutex_init(&twl->mutex);
- return devm_pwmchip_add(&pdev->dev, &twl->chip);
+ return devm_pwmchip_add(&pdev->dev, chip);
}
#ifdef CONFIG_OF
diff --git a/drivers/pwm/pwm-visconti.c b/drivers/pwm/pwm-visconti.c
index 8d736d558122..9e55380957be 100644
--- a/drivers/pwm/pwm-visconti.c
+++ b/drivers/pwm/pwm-visconti.c
@@ -34,13 +34,12 @@
#define PIPGM_PWMC_POLARITY_MASK GENMASK(5, 5)
struct visconti_pwm_chip {
- struct pwm_chip chip;
void __iomem *base;
};
static inline struct visconti_pwm_chip *visconti_pwm_from_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct visconti_pwm_chip, chip);
+ return pwmchip_get_drvdata(chip);
}
static int visconti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -134,22 +133,22 @@ static const struct pwm_ops visconti_pwm_ops = {
static int visconti_pwm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct pwm_chip *chip;
struct visconti_pwm_chip *priv;
int ret;
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(dev, 4, sizeof(*priv));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ priv = visconti_pwm_from_chip(chip);
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
- priv->chip.dev = dev;
- priv->chip.ops = &visconti_pwm_ops;
- priv->chip.npwm = 4;
+ chip->ops = &visconti_pwm_ops;
- ret = devm_pwmchip_add(&pdev->dev, &priv->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "Cannot register visconti PWM\n");
diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c
index 7bfeacee05d0..016c82d65527 100644
--- a/drivers/pwm/pwm-vt8500.c
+++ b/drivers/pwm/pwm-vt8500.c
@@ -45,16 +45,19 @@
#define STATUS_ALL_UPDATE 0x0F
struct vt8500_chip {
- struct pwm_chip chip;
void __iomem *base;
struct clk *clk;
};
-#define to_vt8500_chip(chip) container_of(chip, struct vt8500_chip, chip)
+static inline struct vt8500_chip *to_vt8500_chip(struct pwm_chip *chip)
+{
+ return pwmchip_get_drvdata(chip);
+}
#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
-static inline void vt8500_pwm_busy_wait(struct vt8500_chip *vt8500, int nr, u8 bitmask)
+static inline void vt8500_pwm_busy_wait(struct pwm_chip *chip, int nr, u8 bitmask)
{
+ struct vt8500_chip *vt8500 = to_vt8500_chip(chip);
int loops = msecs_to_loops(10);
u32 mask = bitmask << (nr << 8);
@@ -62,7 +65,7 @@ static inline void vt8500_pwm_busy_wait(struct vt8500_chip *vt8500, int nr, u8 b
cpu_relax();
if (unlikely(!loops))
- dev_warn(vt8500->chip.dev, "Waiting for status bits 0x%x to clear timed out\n",
+ dev_warn(pwmchip_parent(chip), "Waiting for status bits 0x%x to clear timed out\n",
mask);
}
@@ -77,7 +80,7 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
err = clk_enable(vt8500->clk);
if (err < 0) {
- dev_err(chip->dev, "failed to enable clock\n");
+ dev_err(pwmchip_parent(chip), "failed to enable clock\n");
return err;
}
@@ -103,18 +106,18 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
dc = div64_u64(c, period_ns);
writel(prescale, vt8500->base + REG_SCALAR(pwm->hwpwm));
- vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_SCALAR_UPDATE);
+ vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_SCALAR_UPDATE);
writel(pv, vt8500->base + REG_PERIOD(pwm->hwpwm));
- vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_PERIOD_UPDATE);
+ vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_PERIOD_UPDATE);
writel(dc, vt8500->base + REG_DUTY(pwm->hwpwm));
- vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_DUTY_UPDATE);
+ vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_DUTY_UPDATE);
val = readl(vt8500->base + REG_CTRL(pwm->hwpwm));
val |= CTRL_AUTOLOAD;
writel(val, vt8500->base + REG_CTRL(pwm->hwpwm));
- vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE);
+ vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_CTRL_UPDATE);
clk_disable(vt8500->clk);
return 0;
@@ -128,14 +131,14 @@ static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
err = clk_enable(vt8500->clk);
if (err < 0) {
- dev_err(chip->dev, "failed to enable clock\n");
+ dev_err(pwmchip_parent(chip), "failed to enable clock\n");
return err;
}
val = readl(vt8500->base + REG_CTRL(pwm->hwpwm));
val |= CTRL_ENABLE;
writel(val, vt8500->base + REG_CTRL(pwm->hwpwm));
- vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE);
+ vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_CTRL_UPDATE);
return 0;
}
@@ -148,7 +151,7 @@ static void vt8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
val = readl(vt8500->base + REG_CTRL(pwm->hwpwm));
val &= ~CTRL_ENABLE;
writel(val, vt8500->base + REG_CTRL(pwm->hwpwm));
- vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE);
+ vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_CTRL_UPDATE);
clk_disable(vt8500->clk);
}
@@ -168,7 +171,7 @@ static int vt8500_pwm_set_polarity(struct pwm_chip *chip,
val &= ~CTRL_INVERT;
writel(val, vt8500->base + REG_CTRL(pwm->hwpwm));
- vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE);
+ vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_CTRL_UPDATE);
return 0;
}
@@ -231,6 +234,7 @@ MODULE_DEVICE_TABLE(of, vt8500_pwm_dt_ids);
static int vt8500_pwm_probe(struct platform_device *pdev)
{
+ struct pwm_chip *chip;
struct vt8500_chip *vt8500;
struct device_node *np = pdev->dev.of_node;
int ret;
@@ -238,13 +242,12 @@ static int vt8500_pwm_probe(struct platform_device *pdev)
if (!np)
return dev_err_probe(&pdev->dev, -EINVAL, "invalid devicetree node\n");
- vt8500 = devm_kzalloc(&pdev->dev, sizeof(*vt8500), GFP_KERNEL);
- if (vt8500 == NULL)
- return -ENOMEM;
+ chip = devm_pwmchip_alloc(&pdev->dev, VT8500_NR_PWMS, sizeof(*vt8500));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ vt8500 = to_vt8500_chip(chip);
- vt8500->chip.dev = &pdev->dev;
- vt8500->chip.ops = &vt8500_pwm_ops;
- vt8500->chip.npwm = VT8500_NR_PWMS;
+ chip->ops = &vt8500_pwm_ops;
vt8500->clk = devm_clk_get_prepared(&pdev->dev, NULL);
if (IS_ERR(vt8500->clk))
@@ -254,7 +257,7 @@ static int vt8500_pwm_probe(struct platform_device *pdev)
if (IS_ERR(vt8500->base))
return PTR_ERR(vt8500->base);
- ret = devm_pwmchip_add(&pdev->dev, &vt8500->chip);
+ ret = devm_pwmchip_add(&pdev->dev, chip);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n");
diff --git a/drivers/pwm/pwm-xilinx.c b/drivers/pwm/pwm-xilinx.c
index 5f3c2a6fed11..3a7deebb0d0c 100644
--- a/drivers/pwm/pwm-xilinx.c
+++ b/drivers/pwm/pwm-xilinx.c
@@ -80,15 +80,10 @@ unsigned int xilinx_timer_get_period(struct xilinx_timer_priv *priv,
#define TCSR_PWM_CLEAR (TCSR_MDT | TCSR_LOAD)
#define TCSR_PWM_MASK (TCSR_PWM_SET | TCSR_PWM_CLEAR)
-struct xilinx_pwm_device {
- struct pwm_chip chip;
- struct xilinx_timer_priv priv;
-};
-
static inline struct xilinx_timer_priv
*xilinx_pwm_chip_to_priv(struct pwm_chip *chip)
{
- return &container_of(chip, struct xilinx_pwm_device, chip)->priv;
+ return pwmchip_get_drvdata(chip);
}
static bool xilinx_timer_pwm_enabled(u32 tcsr0, u32 tcsr1)
@@ -214,7 +209,7 @@ static int xilinx_pwm_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct xilinx_timer_priv *priv;
- struct xilinx_pwm_device *xilinx_pwm;
+ struct pwm_chip *chip;
u32 pwm_cells, one_timer, width;
void __iomem *regs;
@@ -225,11 +220,11 @@ static int xilinx_pwm_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "could not read #pwm-cells\n");
- xilinx_pwm = devm_kzalloc(dev, sizeof(*xilinx_pwm), GFP_KERNEL);
- if (!xilinx_pwm)
- return -ENOMEM;
- platform_set_drvdata(pdev, xilinx_pwm);
- priv = &xilinx_pwm->priv;
+ chip = devm_pwmchip_alloc(dev, 1, sizeof(*priv));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ priv = xilinx_pwm_chip_to_priv(chip);
+ platform_set_drvdata(pdev, chip);
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
@@ -278,10 +273,8 @@ static int xilinx_pwm_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret, "Clock enable failed\n");
clk_rate_exclusive_get(priv->clk);
- xilinx_pwm->chip.dev = dev;
- xilinx_pwm->chip.ops = &xilinx_pwm_ops;
- xilinx_pwm->chip.npwm = 1;
- ret = pwmchip_add(&xilinx_pwm->chip);
+ chip->ops = &xilinx_pwm_ops;
+ ret = pwmchip_add(chip);
if (ret) {
clk_rate_exclusive_put(priv->clk);
clk_disable_unprepare(priv->clk);
@@ -293,11 +286,12 @@ static int xilinx_pwm_probe(struct platform_device *pdev)
static void xilinx_pwm_remove(struct platform_device *pdev)
{
- struct xilinx_pwm_device *xilinx_pwm = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = platform_get_drvdata(pdev);
+ struct xilinx_timer_priv *priv = xilinx_pwm_chip_to_priv(chip);
- pwmchip_remove(&xilinx_pwm->chip);
- clk_rate_exclusive_put(xilinx_pwm->priv.clk);
- clk_disable_unprepare(xilinx_pwm->priv.clk);
+ pwmchip_remove(chip);
+ clk_rate_exclusive_put(priv->clk);
+ clk_disable_unprepare(priv->clk);
}
static const struct of_device_id xilinx_pwm_of_match[] = {
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index 1698609d91c8..3f434a771fb5 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -509,10 +509,10 @@ void pwmchip_sysfs_export(struct pwm_chip *chip)
* If device_create() fails the pwm_chip is still usable by
* the kernel it's just not exported.
*/
- parent = device_create(&pwm_class, chip->dev, MKDEV(0, 0), chip,
+ parent = device_create(&pwm_class, pwmchip_parent(chip), MKDEV(0, 0), chip,
"pwmchip%d", chip->id);
if (IS_ERR(parent)) {
- dev_warn(chip->dev,
+ dev_warn(pwmchip_parent(chip),
"device_create failed for pwm_chip sysfs export\n");
}
}
diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c
index a3cb68cfa0f9..01883fbcd79b 100644
--- a/drivers/staging/greybus/pwm.c
+++ b/drivers/staging/greybus/pwm.c
@@ -16,8 +16,6 @@
struct gb_pwm_chip {
struct gb_connection *connection;
- u8 pwm_max; /* max pwm number */
-
struct pwm_chip chip;
};
@@ -26,32 +24,33 @@ static inline struct gb_pwm_chip *pwm_chip_to_gb_pwm_chip(struct pwm_chip *chip)
return container_of(chip, struct gb_pwm_chip, chip);
}
-static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc)
+static int gb_pwm_get_npwm(struct gb_connection *connection)
{
struct gb_pwm_count_response response;
int ret;
- ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PWM_COUNT,
+ ret = gb_operation_sync(connection, GB_PWM_TYPE_PWM_COUNT,
NULL, 0, &response, sizeof(response));
if (ret)
return ret;
- pwmc->pwm_max = response.count;
- return 0;
+
+ /*
+ * The request returns the highest allowed PWM id parameter. So add one
+ * to get the number of PWMs.
+ */
+ return response.count + 1;
}
-static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc,
- u8 which)
+static int gb_pwm_activate_operation(struct pwm_chip *chip, u8 which)
{
+ struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
struct gb_pwm_activate_request request;
struct gbphy_device *gbphy_dev;
int ret;
- if (which > pwmc->pwm_max)
- return -EINVAL;
-
request.which = which;
- gbphy_dev = to_gbphy_dev(pwmc->chip.dev);
+ gbphy_dev = to_gbphy_dev(pwmchip_parent(chip));
ret = gbphy_runtime_get_sync(gbphy_dev);
if (ret)
return ret;
@@ -64,19 +63,16 @@ static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc,
return ret;
}
-static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc,
- u8 which)
+static int gb_pwm_deactivate_operation(struct pwm_chip *chip, u8 which)
{
+ struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
struct gb_pwm_deactivate_request request;
struct gbphy_device *gbphy_dev;
int ret;
- if (which > pwmc->pwm_max)
- return -EINVAL;
-
request.which = which;
- gbphy_dev = to_gbphy_dev(pwmc->chip.dev);
+ gbphy_dev = to_gbphy_dev(pwmchip_parent(chip));
ret = gbphy_runtime_get_sync(gbphy_dev);
if (ret)
return ret;
@@ -89,21 +85,19 @@ static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc,
return ret;
}
-static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc,
+static int gb_pwm_config_operation(struct pwm_chip *chip,
u8 which, u32 duty, u32 period)
{
+ struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
struct gb_pwm_config_request request;
struct gbphy_device *gbphy_dev;
int ret;
- if (which > pwmc->pwm_max)
- return -EINVAL;
-
request.which = which;
request.duty = cpu_to_le32(duty);
request.period = cpu_to_le32(period);
- gbphy_dev = to_gbphy_dev(pwmc->chip.dev);
+ gbphy_dev = to_gbphy_dev(pwmchip_parent(chip));
ret = gbphy_runtime_get_sync(gbphy_dev);
if (ret)
return ret;
@@ -116,20 +110,18 @@ static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc,
return ret;
}
-static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc,
+static int gb_pwm_set_polarity_operation(struct pwm_chip *chip,
u8 which, u8 polarity)
{
+ struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
struct gb_pwm_polarity_request request;
struct gbphy_device *gbphy_dev;
int ret;
- if (which > pwmc->pwm_max)
- return -EINVAL;
-
request.which = which;
request.polarity = polarity;
- gbphy_dev = to_gbphy_dev(pwmc->chip.dev);
+ gbphy_dev = to_gbphy_dev(pwmchip_parent(chip));
ret = gbphy_runtime_get_sync(gbphy_dev);
if (ret)
return ret;
@@ -142,19 +134,16 @@ static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc,
return ret;
}
-static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc,
- u8 which)
+static int gb_pwm_enable_operation(struct pwm_chip *chip, u8 which)
{
+ struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
struct gb_pwm_enable_request request;
struct gbphy_device *gbphy_dev;
int ret;
- if (which > pwmc->pwm_max)
- return -EINVAL;
-
request.which = which;
- gbphy_dev = to_gbphy_dev(pwmc->chip.dev);
+ gbphy_dev = to_gbphy_dev(pwmchip_parent(chip));
ret = gbphy_runtime_get_sync(gbphy_dev);
if (ret)
return ret;
@@ -167,22 +156,19 @@ static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc,
return ret;
}
-static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc,
- u8 which)
+static int gb_pwm_disable_operation(struct pwm_chip *chip, u8 which)
{
+ struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
struct gb_pwm_disable_request request;
struct gbphy_device *gbphy_dev;
int ret;
- if (which > pwmc->pwm_max)
- return -EINVAL;
-
request.which = which;
ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DISABLE,
&request, sizeof(request), NULL, 0);
- gbphy_dev = to_gbphy_dev(pwmc->chip.dev);
+ gbphy_dev = to_gbphy_dev(pwmchip_parent(chip));
gbphy_runtime_put_autosuspend(gbphy_dev);
return ret;
@@ -190,19 +176,15 @@ static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc,
static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{
- struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
-
- return gb_pwm_activate_operation(pwmc, pwm->hwpwm);
+ return gb_pwm_activate_operation(chip, pwm->hwpwm);
};
static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
{
- struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
-
if (pwm_is_enabled(pwm))
- dev_warn(chip->dev, "freeing PWM device without disabling\n");
+ dev_warn(pwmchip_parent(chip), "freeing PWM device without disabling\n");
- gb_pwm_deactivate_operation(pwmc, pwm->hwpwm);
+ gb_pwm_deactivate_operation(chip, pwm->hwpwm);
}
static int gb_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -212,22 +194,21 @@ static int gb_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
bool enabled = pwm->state.enabled;
u64 period = state->period;
u64 duty_cycle = state->duty_cycle;
- struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
/* Set polarity */
if (state->polarity != pwm->state.polarity) {
if (enabled) {
- gb_pwm_disable_operation(pwmc, pwm->hwpwm);
+ gb_pwm_disable_operation(chip, pwm->hwpwm);
enabled = false;
}
- err = gb_pwm_set_polarity_operation(pwmc, pwm->hwpwm, state->polarity);
+ err = gb_pwm_set_polarity_operation(chip, pwm->hwpwm, state->polarity);
if (err)
return err;
}
if (!state->enabled) {
if (enabled)
- gb_pwm_disable_operation(pwmc, pwm->hwpwm);
+ gb_pwm_disable_operation(chip, pwm->hwpwm);
return 0;
}
@@ -243,13 +224,13 @@ static int gb_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (duty_cycle > period)
duty_cycle = period;
- err = gb_pwm_config_operation(pwmc, pwm->hwpwm, duty_cycle, period);
+ err = gb_pwm_config_operation(chip, pwm->hwpwm, duty_cycle, period);
if (err)
return err;
/* enable/disable */
if (!enabled)
- return gb_pwm_enable_operation(pwmc, pwm->hwpwm);
+ return gb_pwm_enable_operation(chip, pwm->hwpwm);
return 0;
}
@@ -266,61 +247,59 @@ static int gb_pwm_probe(struct gbphy_device *gbphy_dev,
struct gb_connection *connection;
struct gb_pwm_chip *pwmc;
struct pwm_chip *chip;
- int ret;
-
- pwmc = kzalloc(sizeof(*pwmc), GFP_KERNEL);
- if (!pwmc)
- return -ENOMEM;
+ int ret, npwm;
connection = gb_connection_create(gbphy_dev->bundle,
le16_to_cpu(gbphy_dev->cport_desc->id),
NULL);
- if (IS_ERR(connection)) {
- ret = PTR_ERR(connection);
- goto exit_pwmc_free;
- }
-
- pwmc->connection = connection;
- gb_connection_set_data(connection, pwmc);
- gb_gbphy_set_data(gbphy_dev, pwmc);
+ if (IS_ERR(connection))
+ return PTR_ERR(connection);
ret = gb_connection_enable(connection);
if (ret)
goto exit_connection_destroy;
/* Query number of pwms present */
- ret = gb_pwm_count_operation(pwmc);
- if (ret)
+ ret = gb_pwm_get_npwm(connection);
+ if (ret < 0)
+ goto exit_connection_disable;
+ npwm = ret;
+
+ chip = pwmchip_alloc(&gbphy_dev->dev, npwm, sizeof(*pwmc));
+ if (IS_ERR(chip)) {
+ ret = PTR_ERR(chip);
goto exit_connection_disable;
+ }
+ gb_gbphy_set_data(gbphy_dev, chip);
- chip = &pwmc->chip;
+ pwmc = pwm_chip_to_gb_pwm_chip(chip);
+ pwmc->connection = connection;
- chip->dev = &gbphy_dev->dev;
chip->ops = &gb_pwm_ops;
- chip->npwm = pwmc->pwm_max + 1;
ret = pwmchip_add(chip);
if (ret) {
dev_err(&gbphy_dev->dev,
"failed to register PWM: %d\n", ret);
- goto exit_connection_disable;
+ goto exit_pwmchip_put;
}
gbphy_runtime_put_autosuspend(gbphy_dev);
return 0;
+exit_pwmchip_put:
+ pwmchip_put(chip);
exit_connection_disable:
gb_connection_disable(connection);
exit_connection_destroy:
gb_connection_destroy(connection);
-exit_pwmc_free:
- kfree(pwmc);
return ret;
}
static void gb_pwm_remove(struct gbphy_device *gbphy_dev)
{
- struct gb_pwm_chip *pwmc = gb_gbphy_get_data(gbphy_dev);
+ struct pwm_chip *chip = gb_gbphy_get_data(gbphy_dev);
+ struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
struct gb_connection *connection = pwmc->connection;
int ret;
@@ -328,10 +307,10 @@ static void gb_pwm_remove(struct gbphy_device *gbphy_dev)
if (ret)
gbphy_runtime_get_noresume(gbphy_dev);
- pwmchip_remove(&pwmc->chip);
+ pwmchip_remove(chip);
+ pwmchip_put(chip);
gb_connection_disable(connection);
gb_connection_destroy(connection);
- kfree(pwmc);
}
static const struct gbphy_device_id gb_pwm_id_table[] = {
diff --git a/include/linux/platform_data/x86/pwm-lpss.h b/include/linux/platform_data/x86/pwm-lpss.h
index c852fe24fe2a..752c06b47cc8 100644
--- a/include/linux/platform_data/x86/pwm-lpss.h
+++ b/include/linux/platform_data/x86/pwm-lpss.h
@@ -27,7 +27,7 @@ struct pwm_lpss_boardinfo {
bool other_devices_aml_touches_pwm_regs;
};
-struct pwm_lpss_chip *devm_pwm_lpss_probe(struct device *dev, void __iomem *base,
- const struct pwm_lpss_boardinfo *info);
+struct pwm_chip *devm_pwm_lpss_probe(struct device *dev, void __iomem *base,
+ const struct pwm_lpss_boardinfo *info);
#endif /* __PLATFORM_DATA_X86_PWM_LPSS_H */
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index fcc2c4496f73..4a6568dfdf3f 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -271,8 +271,8 @@ struct pwm_ops {
* @id: unique number of this PWM chip
* @npwm: number of PWMs controlled by this chip
* @of_xlate: request a PWM device given a device tree PWM specifier
- * @of_pwm_n_cells: number of cells expected in the device tree PWM specifier
* @atomic: can the driver's ->apply() be called in atomic context
+ * @driver_data: Private pointer for driver specific info
* @pwms: array of PWM devices allocated by the framework
*/
struct pwm_chip {
@@ -284,13 +284,36 @@ struct pwm_chip {
struct pwm_device * (*of_xlate)(struct pwm_chip *chip,
const struct of_phandle_args *args);
- unsigned int of_pwm_n_cells;
bool atomic;
/* only used internally by the PWM framework */
+ void *driver_data;
struct pwm_device *pwms;
};
+static inline struct device *pwmchip_parent(const struct pwm_chip *chip)
+{
+ return chip->dev;
+}
+
+static inline void *pwmchip_get_drvdata(struct pwm_chip *chip)
+{
+ /*
+ * After pwm_chip got a dedicated struct device, this can be replaced by
+ * dev_get_drvdata(&chip->dev);
+ */
+ return chip->driver_data;
+}
+
+static inline void pwmchip_set_drvdata(struct pwm_chip *chip, void *data)
+{
+ /*
+ * After pwm_chip got a dedicated struct device, this can be replaced by
+ * dev_set_drvdata(&chip->dev, data);
+ */
+ chip->driver_data = data;
+}
+
#if IS_ENABLED(CONFIG_PWM)
/* PWM user APIs */
int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state);
@@ -380,6 +403,10 @@ static inline bool pwm_might_sleep(struct pwm_device *pwm)
int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
unsigned long timeout);
+void pwmchip_put(struct pwm_chip *chip);
+struct pwm_chip *pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv);
+struct pwm_chip *devm_pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv);
+
int __pwmchip_add(struct pwm_chip *chip, struct module *owner);
#define pwmchip_add(chip) __pwmchip_add(chip, THIS_MODULE)
void pwmchip_remove(struct pwm_chip *chip);
@@ -452,6 +479,24 @@ static inline int pwm_capture(struct pwm_device *pwm,
return -EINVAL;
}
+static inline void pwmchip_put(struct pwm_chip *chip)
+{
+}
+
+static inline struct pwm_chip *pwmchip_alloc(struct device *parent,
+ unsigned int npwm,
+ size_t sizeof_priv)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline struct pwm_chip *devm_pwmchip_alloc(struct device *parent,
+ unsigned int npwm,
+ size_t sizeof_priv)
+{
+ return pwmchip_alloc(parent, npwm, sizeof_priv);
+}
+
static inline int pwmchip_add(struct pwm_chip *chip)
{
return -EINVAL;