Skip to content

Commit

Permalink
Merge tag 'pwm/for-5.3-rc1' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/thierry.reding/linux-pwm

Pull pwm updates from Thierry Reding:
 "This set of changes contains a new driver for SiFive SoCs as well as
  enhancements to the core (device links are used to track dependencies
  between PWM providers and consumers, support for PWM controllers via
  ACPI, sysfs will now suspend/resume PWMs that it has claimed) and
  various existing drivers"

* tag 'pwm/for-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (37 commits)
  pwm: fsl-ftm: Make sure to unlock mutex on failure
  pwm: fsl-ftm: Use write protection for prescaler & polarity
  pwm: fsl-ftm: More relaxed permissions for updating period
  pwm: atmel-hlcdc: Add compatible for SAM9X60 HLCDC's PWM
  pwm: bcm2835: Improve precision of PWM
  leds: pwm: Support ACPI via firmware-node framework
  pwm: Add support referencing PWMs from ACPI
  pwm: rcar: Remove suspend/resume support
  pwm: sysfs: Add suspend/resume support
  pwm: Add power management descriptions
  pwm: meson: Add documentation to the driver
  pwm: meson: Add support PWM_POLARITY_INVERSED when disabling
  pwm: meson: Don't cache struct pwm_state internally
  pwm: meson: Read the full hardware state in meson_pwm_get_state()
  pwm: meson: Simplify the calculation of the pre-divider and count
  pwm: meson: Move pwm_set_chip_data() to meson_pwm_request()
  pwm: meson: Add the per-channel register offsets and bits in a struct
  pwm: meson: Add the meson_pwm_channel data to struct meson_pwm
  pwm: meson: Pass struct pwm_device to meson_pwm_calc()
  pwm: meson: Don't duplicate the polarity internally
  ...
  • Loading branch information
torvalds committed Jul 9, 2019
2 parents 5ad18b2 + 3d25025 commit 6e2bbb6
Show file tree
Hide file tree
Showing 20 changed files with 1,154 additions and 482 deletions.
5 changes: 1 addition & 4 deletions Documentation/devicetree/bindings/pwm/ingenic,jz47xx-pwm.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ Ingenic JZ47xx PWM Controller
=============================

Required properties:
- compatible: One of:
* "ingenic,jz4740-pwm"
* "ingenic,jz4770-pwm"
* "ingenic,jz4780-pwm"
- compatible: Should be "ingenic,jz4740-pwm"
- #pwm-cells: Should be 3. See pwm.txt in this directory for a description
of the cells format.
- clocks : phandle to the external clock.
Expand Down
33 changes: 33 additions & 0 deletions Documentation/devicetree/bindings/pwm/pwm-sifive.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
SiFive PWM controller

Unlike most other PWM controllers, the SiFive PWM controller currently only
supports one period for all channels in the PWM. All PWMs need to run at
the same period. The period also has significant restrictions on the values
it can achieve, which the driver rounds to the nearest achievable period.
PWM RTL that corresponds to the IP block version numbers can be found
here:

https://github.com/sifive/sifive-blocks/tree/master/src/main/scala/devices/pwm

Required properties:
- compatible: Should be "sifive,<chip>-pwm" and "sifive,pwm<version>".
Supported compatible strings are: "sifive,fu540-c000-pwm" for the SiFive
PWM v0 as integrated onto the SiFive FU540 chip, and "sifive,pwm0" for the
SiFive PWM v0 IP block with no chip integration tweaks.
Please refer to sifive-blocks-ip-versioning.txt for details.
- reg: physical base address and length of the controller's registers
- clocks: Should contain a clock identifier for the PWM's parent clock.
- #pwm-cells: Should be 3. See pwm.txt in this directory
for a description of the cell format.
- interrupts: one interrupt per PWM channel

Examples:

pwm: pwm@10020000 {
compatible = "sifive,fu540-c000-pwm", "sifive,pwm0";
reg = <0x0 0x10020000 0x0 0x1000>;
clocks = <&tlclk>;
interrupt-parent = <&plic>;
interrupts = <42 43 44 45>;
#pwm-cells = <3>;
};
9 changes: 6 additions & 3 deletions Documentation/devicetree/bindings/pwm/pwm-stm32-lp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ Required parameters:
bindings defined in pwm.txt.

Optional properties:
- pinctrl-names: Set to "default".
- pinctrl-0: Phandle pointing to pin configuration node for PWM.
- pinctrl-names: Set to "default". An additional "sleep" state can be
defined to set pins in sleep state when in low power.
- pinctrl-n: Phandle(s) pointing to pin configuration node for PWM,
respectively for "default" and "sleep" states.

Example:
timer@40002400 {
Expand All @@ -21,7 +23,8 @@ Example:
pwm {
compatible = "st,stm32-pwm-lp";
#pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&lppwm1_pins>;
pinctrl-1 = <&lppwm1_sleep_pins>;
};
};
3 changes: 3 additions & 0 deletions Documentation/devicetree/bindings/pwm/pwm-stm32.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Required parameters:
- pinctrl-names: Set to "default".
- pinctrl-0: List of phandles pointing to pin configuration nodes for PWM module.
For Pinctrl properties see ../pinctrl/pinctrl-bindings.txt
- #pwm-cells: Should be set to 3. This PWM chip uses the default 3 cells
bindings defined in pwm.txt.

Optional parameters:
- st,breakinput: One or two <index level filter> to describe break input configurations.
Expand All @@ -28,6 +30,7 @@ Example:

pwm {
compatible = "st,stm32-pwm";
#pwm-cells = <3>;
pinctrl-0 = <&pwm1_pins>;
pinctrl-names = "default";
st,breakinput = <0 1 5>;
Expand Down
7 changes: 7 additions & 0 deletions Documentation/pwm.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ period). struct pwm_args contains 2 fields (period and polarity) and should
be used to set the initial PWM config (usually done in the probe function
of the PWM user). PWM arguments are retrieved with pwm_get_args().

All consumers should really be reconfiguring the PWM upon resume as
appropriate. This is the only way to ensure that everything is resumed in
the proper order.

Using PWMs with the sysfs interface
-----------------------------------

Expand Down Expand Up @@ -141,6 +145,9 @@ The implementation of ->get_state() (a method used to retrieve initial PWM
state) is also encouraged for the same reason: letting the PWM user know
about the current PWM state would allow him to avoid glitches.

Drivers should not implement any power management. In other words,
consumers should implement it as described in the "Using PWMs" section.

Locking
-------

Expand Down
45 changes: 27 additions & 18 deletions drivers/leds/leds-pwm.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ static inline size_t sizeof_pwm_leds_priv(int num_leds)
}

static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
struct led_pwm *led, struct device_node *child)
struct led_pwm *led, struct fwnode_handle *fwnode)
{
struct led_pwm_data *led_data = &priv->leds[priv->num_leds];
struct pwm_args pargs;
Expand All @@ -85,8 +85,8 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
led_data->cdev.max_brightness = led->max_brightness;
led_data->cdev.flags = LED_CORE_SUSPENDRESUME;

if (child)
led_data->pwm = devm_of_pwm_get(dev, child, NULL);
if (fwnode)
led_data->pwm = devm_fwnode_pwm_get(dev, fwnode, NULL);
else
led_data->pwm = devm_pwm_get(dev, led->name);
if (IS_ERR(led_data->pwm)) {
Expand All @@ -111,7 +111,8 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
if (!led_data->period && (led->pwm_period_ns > 0))
led_data->period = led->pwm_period_ns;

ret = devm_of_led_classdev_register(dev, child, &led_data->cdev);
ret = devm_of_led_classdev_register(dev, to_of_node(fwnode),
&led_data->cdev);
if (ret == 0) {
priv->num_leds++;
led_pwm_set(&led_data->cdev, led_data->cdev.brightness);
Expand All @@ -123,27 +124,35 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
return ret;
}

static int led_pwm_create_of(struct device *dev, struct led_pwm_priv *priv)
static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv)
{
struct device_node *child;
struct fwnode_handle *fwnode;
struct led_pwm led;
int ret = 0;

memset(&led, 0, sizeof(led));

for_each_child_of_node(dev->of_node, child) {
led.name = of_get_property(child, "label", NULL) ? :
child->name;
device_for_each_child_node(dev, fwnode) {
ret = fwnode_property_read_string(fwnode, "label", &led.name);
if (ret && is_of_node(fwnode))
led.name = to_of_node(fwnode)->name;

led.default_trigger = of_get_property(child,
"linux,default-trigger", NULL);
led.active_low = of_property_read_bool(child, "active-low");
of_property_read_u32(child, "max-brightness",
&led.max_brightness);
if (!led.name) {
fwnode_handle_put(fwnode);
return -EINVAL;
}

fwnode_property_read_string(fwnode, "linux,default-trigger",
&led.default_trigger);

led.active_low = fwnode_property_read_bool(fwnode,
"active-low");
fwnode_property_read_u32(fwnode, "max-brightness",
&led.max_brightness);

ret = led_pwm_add(dev, priv, &led, child);
ret = led_pwm_add(dev, priv, &led, fwnode);
if (ret) {
of_node_put(child);
fwnode_handle_put(fwnode);
break;
}
}
Expand All @@ -161,7 +170,7 @@ static int led_pwm_probe(struct platform_device *pdev)
if (pdata)
count = pdata->num_leds;
else
count = of_get_child_count(pdev->dev.of_node);
count = device_get_child_node_count(&pdev->dev);

if (!count)
return -EINVAL;
Expand All @@ -179,7 +188,7 @@ static int led_pwm_probe(struct platform_device *pdev)
break;
}
} else {
ret = led_pwm_create_of(&pdev->dev, priv);
ret = led_pwm_create_fwnode(&pdev->dev, priv);
}

if (ret)
Expand Down
11 changes: 11 additions & 0 deletions drivers/pwm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,17 @@ config PWM_SAMSUNG
To compile this driver as a module, choose M here: the module
will be called pwm-samsung.

config PWM_SIFIVE
tristate "SiFive PWM support"
depends on OF
depends on COMMON_CLK
depends on RISCV || COMPILE_TEST
help
Generic PWM framework driver for SiFive SoCs.

To compile this driver as a module, choose M here: the module
will be called pwm-sifive.

config PWM_SPEAR
tristate "STMicroelectronics SPEAr PWM support"
depends on PLAT_SPEAR
Expand Down
1 change: 1 addition & 0 deletions drivers/pwm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ obj-$(CONFIG_PWM_RCAR) += pwm-rcar.o
obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o
obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o
obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o
obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o
obj-$(CONFIG_PWM_STI) += pwm-sti.o
obj-$(CONFIG_PWM_STM32) += pwm-stm32.o
Expand Down
Loading

0 comments on commit 6e2bbb6

Please sign in to comment.