mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-27 03:55:37 +08:00
Merge branch 'pwm/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux.git
This commit is contained in:
commit
beb6573a52
35
Documentation/devicetree/bindings/pwm/atmel,hlcdc-pwm.yaml
Normal file
35
Documentation/devicetree/bindings/pwm/atmel,hlcdc-pwm.yaml
Normal file
@ -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
|
@ -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>;
|
||||
};
|
||||
};
|
51
Documentation/devicetree/bindings/pwm/marvell,pxa-pwm.yaml
Normal file
51
Documentation/devicetree/bindings/pwm/marvell,pxa-pwm.yaml
Normal file
@ -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>;
|
||||
};
|
@ -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
|
||||
|
@ -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>;
|
||||
};
|
||||
|
@ -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>;
|
||||
...
|
||||
}
|
@ -420,6 +420,7 @@ POWER
|
||||
devm_reboot_mode_unregister()
|
||||
|
||||
PWM
|
||||
devm_pwmchip_alloc()
|
||||
devm_pwmchip_add()
|
||||
devm_pwm_get()
|
||||
devm_fwnode_pwm_get()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -109,7 +109,7 @@ struct lpg {
|
||||
|
||||
struct mutex lock;
|
||||
|
||||
struct pwm_chip pwm;
|
||||
struct pwm_chip *pwm;
|
||||
|
||||
const struct lpg_data *data;
|
||||
|
||||
@ -1199,7 +1199,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)
|
||||
@ -1314,13 +1314,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");
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
@ -523,33 +224,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);
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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[] = {
|
||||
|
@ -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 = {
|
||||
|
@ -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, ¶ms->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,35 +262,35 @@ 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"))
|
||||
ec_pwm->use_pwm_type = true;
|
||||
|
||||
/* 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;
|
||||
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_pwm);
|
||||
ret = cros_ec_num_pwms(ec);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Couldn't find PWMs\n");
|
||||
chip->npwm = ret;
|
||||
npwm = ret;
|
||||
}
|
||||
|
||||
chip = devm_pwmchip_alloc(dev, npwm, sizeof(*ec_pwm));
|
||||
if (IS_ERR(chip))
|
||||
return PTR_ERR(chip);
|
||||
|
||||
ec_pwm = pwm_to_cros_ec_pwm(chip);
|
||||
ec_pwm->use_pwm_type = use_pwm_type;
|
||||
ec_pwm->ec = ec;
|
||||
|
||||
/* PWM chip */
|
||||
chip->ops = &cros_ec_pwm_ops;
|
||||
chip->of_xlate = cros_ec_pwm_xlate;
|
||||
|
||||
ec_pwm->channel = devm_kcalloc(dev, chip->npwm, sizeof(*ec_pwm->channel),
|
||||
GFP_KERNEL);
|
||||
if (!ec_pwm->channel)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -25,39 +25,54 @@
|
||||
|
||||
#include "pwm-dwc.h"
|
||||
|
||||
/* 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 pwm_chip *chip;
|
||||
struct dwc_pwm *dwc;
|
||||
|
||||
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;
|
||||
struct dwc_pwm *dwc;
|
||||
int ret;
|
||||
|
||||
dwc = dwc_pwm_alloc(dev);
|
||||
if (!dwc)
|
||||
return -ENOMEM;
|
||||
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),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
struct pwm_chip *chip = platform_get_drvdata(pdev);
|
||||
struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip);
|
||||
|
||||
pwm_chip = platform_get_drvdata(pdev);
|
||||
pwmchip_remove(chip);
|
||||
|
||||
pwmchip_remove(&pwm_chip->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[] = {
|
||||
|
@ -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,
|
||||
|
@ -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,40 @@ 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;
|
||||
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);
|
||||
|
||||
/* get number of channels */
|
||||
val = readl(base + PWM_IMX_TPM_PARAM);
|
||||
npwm = FIELD_GET(PWM_IMX_TPM_PARAM_CHAN, val);
|
||||
|
||||
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->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(tpm->base))
|
||||
return PTR_ERR(tpm->base);
|
||||
tpm->base = base;
|
||||
|
||||
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");
|
||||
|
||||
tpm->chip.dev = &pdev->dev;
|
||||
tpm->chip.ops = &imx_tpm_pwm_ops;
|
||||
|
||||
/* 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");
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
pc->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 = 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 },
|
||||
|
@ -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");
|
||||
|
@ -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, ®s);
|
||||
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");
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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, ®);
|
||||
ret = pca9685_read_reg(chip, PCA9685_MODE2, ®);
|
||||
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, ®);
|
||||
pca9685_read_reg(chip, PCA9685_MODE1, ®);
|
||||
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);
|
||||
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.ops = &pca9685_pwm_ops;
|
||||
/* Add an extra channel for ALL_LED */
|
||||
pca->chip.npwm = PCA9685_MAXCHAN + 1;
|
||||
chip->ops = &pca9685_pwm_ops;
|
||||
|
||||
pca->chip.dev = &client->dev;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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[] = {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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;
|
||||
memcpy(spc->chn, chn, sizeof(chn));
|
||||
|
||||
ret = sprd_pwm_clk_init(spc);
|
||||
if (ret)
|
||||
return ret;
|
||||
chip->ops = &sprd_pwm_ops;
|
||||
|
||||
spc->chip.dev = &pdev->dev;
|
||||
spc->chip.ops = &sprd_pwm_ops;
|
||||
spc->chip.npwm = spc->num_pwms;
|
||||
|
||||
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");
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
chip = devm_pwmchip_alloc(&pdev->dev, 3, sizeof(*stmpe_pwm));
|
||||
if (IS_ERR(chip))
|
||||
return PTR_ERR(chip);
|
||||
stmpe_pwm = to_stmpe_pwm(chip);
|
||||
|
||||
stmpe_pwm->stmpe = stmpe;
|
||||
stmpe_pwm->chip.dev = &pdev->dev;
|
||||
|
||||
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");
|
||||
|
||||
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;
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
|
||||
pc->soc = of_device_get_match_data(&pdev->dev);
|
||||
pc->dev = &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 = 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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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[] = {
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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 = &pwmc->chip;
|
||||
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);
|
||||
|
||||
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[] = {
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user