* [PATCH V3 0/2] pwm: Add GPIO PWM driver
@ 2024-01-28 16:36 Stefan Wahren
2024-01-28 16:36 ` [PATCH V3 1/2] dt-bindings: pwm: Add pwm-gpio Stefan Wahren
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Stefan Wahren @ 2024-01-28 16:36 UTC (permalink / raw)
To: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: andy.shevchenko, Angelo Compagnucci, Philip Howard, Linus Walleij,
linux-pwm, devicetree, linux-gpio, Stefan Wahren
Add a software PWM which toggles a GPIO from a high-resolution timer.
Recent discussions in the Raspberry Pi community revealt that a lot
of users still use MMIO userspace tools for GPIO access. One argument
for this approach is the lack of a GPIO PWM kernel driver. So this
series tries to fill this gap.
This continues the work of Vincent Whitchurch [1], which is easier
to read and more consequent by rejecting sleeping GPIOs than Nicola's
approach [2].
The work has been tested on a Raspberry Pi 3 B+ and a cheap logic
analyzer.
V3:
- rebase on top of v6.8-pwm-next
- cherry-pick improvements from Nicola's series
- try to address Uwe's, Linus' and Andy's comments
- try to avoid GPIO glitches during probe
- fix pwm_gpio_remove()
- some code clean up's and comments
V2:
- Rename gpio to gpios in binding
- Calculate next expiry from expected current expiry rather than "now"
- Only change configuration after current period ends
- Implement get_state()
- Add error message for probe failures
- Stop PWM before unregister
[1] - https://lore.kernel.org/all/20200915135445.al75xmjxudj2rgcp@axis.com/T/
[2] - https://lore.kernel.org/all/20201205214353.xapax46tt5snzd2v@einstein.dilieto.eu/
Nicola Di Lieto (1):
dt-bindings: pwm: Add pwm-gpio
Vincent Whitchurch (1):
pwm: Add GPIO PWM driver
.../devicetree/bindings/pwm/pwm-gpio.yaml | 42 ++++
drivers/pwm/Kconfig | 11 +
drivers/pwm/Makefile | 1 +
drivers/pwm/pwm-gpio.c | 221 ++++++++++++++++++
4 files changed, 275 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pwm/pwm-gpio.yaml
create mode 100644 drivers/pwm/pwm-gpio.c
--
2.34.1
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH V3 1/2] dt-bindings: pwm: Add pwm-gpio 2024-01-28 16:36 [PATCH V3 0/2] pwm: Add GPIO PWM driver Stefan Wahren @ 2024-01-28 16:36 ` Stefan Wahren 2024-01-28 17:08 ` Conor Dooley 2024-01-28 16:36 ` [PATCH V3 2/2] pwm: Add GPIO PWM driver Stefan Wahren 2024-02-02 13:19 ` [PATCH V3 0/2] " Phil Howard 2 siblings, 1 reply; 12+ messages in thread From: Stefan Wahren @ 2024-01-28 16:36 UTC (permalink / raw) To: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: andy.shevchenko, Angelo Compagnucci, Philip Howard, Linus Walleij, linux-pwm, devicetree, linux-gpio, Nicola Di Lieto, Stefan Wahren From: Nicola Di Lieto <nicola.dilieto@gmail.com> Add bindings for the pwm-gpio driver. Signed-off-by: Nicola Di Lieto <nicola.dilieto@gmail.com> Co-developed-by: Stefan Wahren <wahrenst@gmx.net> Signed-off-by: Stefan Wahren <wahrenst@gmx.net> --- .../devicetree/bindings/pwm/pwm-gpio.yaml | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 Documentation/devicetree/bindings/pwm/pwm-gpio.yaml diff --git a/Documentation/devicetree/bindings/pwm/pwm-gpio.yaml b/Documentation/devicetree/bindings/pwm/pwm-gpio.yaml new file mode 100644 index 000000000000..4932484563f9 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pwm-gpio.yaml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pwm/pwm-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Generic software PWM for modulating GPIOs + +maintainers: + - Stefan Wahren <wahrenst@gmx.net> + +properties: + "#pwm-cells": + description: | + It should be 3. See pwm.yaml in this directory for a + description of the cells format. + const: 3 + + compatible: + const: pwm-gpio + + gpios: + description: + GPIO to be modulated + maxItems: 1 + +required: + - "#pwm-cells" + - compatible + - gpios + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + pwm0 { + #pwm-cells = <3>; + compatible = "pwm-gpio"; + gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; + }; -- 2.34.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH V3 1/2] dt-bindings: pwm: Add pwm-gpio 2024-01-28 16:36 ` [PATCH V3 1/2] dt-bindings: pwm: Add pwm-gpio Stefan Wahren @ 2024-01-28 17:08 ` Conor Dooley 0 siblings, 0 replies; 12+ messages in thread From: Conor Dooley @ 2024-01-28 17:08 UTC (permalink / raw) To: Stefan Wahren Cc: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski, Conor Dooley, andy.shevchenko, Angelo Compagnucci, Philip Howard, Linus Walleij, linux-pwm, devicetree, linux-gpio, Nicola Di Lieto [-- Attachment #1: Type: text/plain, Size: 2202 bytes --] On Sun, Jan 28, 2024 at 05:36:29PM +0100, Stefan Wahren wrote: > From: Nicola Di Lieto <nicola.dilieto@gmail.com> > > Add bindings for the pwm-gpio driver. drop "driver" from here and instead explain in terms of what the hardware is doing. I think that's just as simple as saying that it is a binding for a gpio used as a pwm. > > Signed-off-by: Nicola Di Lieto <nicola.dilieto@gmail.com> > Co-developed-by: Stefan Wahren <wahrenst@gmx.net> > Signed-off-by: Stefan Wahren <wahrenst@gmx.net> > --- > .../devicetree/bindings/pwm/pwm-gpio.yaml | 42 +++++++++++++++++++ > 1 file changed, 42 insertions(+) > create mode 100644 Documentation/devicetree/bindings/pwm/pwm-gpio.yaml > > diff --git a/Documentation/devicetree/bindings/pwm/pwm-gpio.yaml b/Documentation/devicetree/bindings/pwm/pwm-gpio.yaml > new file mode 100644 > index 000000000000..4932484563f9 > --- /dev/null > +++ b/Documentation/devicetree/bindings/pwm/pwm-gpio.yaml > @@ -0,0 +1,42 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/pwm/pwm-gpio.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Generic software PWM for modulating GPIOs > + > +maintainers: > + - Stefan Wahren <wahrenst@gmx.net> > + > +properties: > + "#pwm-cells": > + description: | > + It should be 3. See pwm.yaml in this directory for a > + description of the cells format. Instead of this description (which I know isn't unique to this binding) I think you should have a ref: to pwm.yaml. > + const: 3 > + > + compatible: > + const: pwm-gpio > + > + gpios: > + description: > + GPIO to be modulated > + maxItems: 1 > + > +required: > + - "#pwm-cells" > + - compatible > + - gpios > + > +additionalProperties: false > + > +examples: > + - | > + #include <dt-bindings/gpio/gpio.h> > + > + pwm0 { Which may then lead to a complaint about the formatting of your node name. Cheers, Conor. > + #pwm-cells = <3>; > + compatible = "pwm-gpio"; > + gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; > + }; > -- > 2.34.1 > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V3 2/2] pwm: Add GPIO PWM driver 2024-01-28 16:36 [PATCH V3 0/2] pwm: Add GPIO PWM driver Stefan Wahren 2024-01-28 16:36 ` [PATCH V3 1/2] dt-bindings: pwm: Add pwm-gpio Stefan Wahren @ 2024-01-28 16:36 ` Stefan Wahren 2024-01-29 9:40 ` Krzysztof Kozlowski 2024-01-30 9:08 ` Sean Young 2024-02-02 13:19 ` [PATCH V3 0/2] " Phil Howard 2 siblings, 2 replies; 12+ messages in thread From: Stefan Wahren @ 2024-01-28 16:36 UTC (permalink / raw) To: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: andy.shevchenko, Angelo Compagnucci, Philip Howard, Linus Walleij, linux-pwm, devicetree, linux-gpio, Vincent Whitchurch, Stefan Wahren From: Vincent Whitchurch <vincent.whitchurch@axis.com> Add a software PWM which toggles a GPIO from a high-resolution timer. This will naturally not be as accurate or as efficient as a hardware PWM, but it is useful in some cases. I have for example used it for evaluating LED brightness handling (via leds-pwm) on a board where the LED was just hooked up to a GPIO, and for a simple verification of the timer frequency on another platform. Since high-resolution timers are used, sleeping gpio chips are not supported and are rejected in the probe function. Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com> Co-developed-by: Stefan Wahren <wahrenst@gmx.net> Signed-off-by: Stefan Wahren <wahrenst@gmx.net> --- drivers/pwm/Kconfig | 11 ++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-gpio.c | 221 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 drivers/pwm/pwm-gpio.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 4b956d661755..7cfda2cde130 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -227,6 +227,17 @@ config PWM_FSL_FTM To compile this driver as a module, choose M here: the module will be called pwm-fsl-ftm. +config PWM_GPIO + tristate "GPIO PWM support" + depends on GPIOLIB + depends on HIGH_RES_TIMERS + help + Generic PWM framework driver for a software PWM toggling a GPIO pin + from kernel high-resolution timers. + + To compile this driver as a module, choose M here: the module + will be called pwm-gpio. + config PWM_HIBVT tristate "HiSilicon BVT PWM support" depends on ARCH_HISI || COMPILE_TEST diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index c5ec9e168ee7..59d1a46bb1af 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_PWM_DWC_CORE) += pwm-dwc-core.o obj-$(CONFIG_PWM_DWC) += pwm-dwc.o obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o +obj-$(CONFIG_PWM_GPIO) += pwm-gpio.o obj-$(CONFIG_PWM_HIBVT) += pwm-hibvt.o obj-$(CONFIG_PWM_IMG) += pwm-img.o obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o diff --git a/drivers/pwm/pwm-gpio.c b/drivers/pwm/pwm-gpio.c new file mode 100644 index 000000000000..14637abe465b --- /dev/null +++ b/drivers/pwm/pwm-gpio.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Generic software PWM for modulating GPIOs + * + * Copyright (C) 2020 Axis Communications AB + * Copyright (C) 2020 Nicola Di Lieto + * Copyright (C) 2024 Stefan Wahren + */ + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/gpio/consumer.h> +#include <linux/hrtimer.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> +#include <linux/pwm.h> +#include <linux/spinlock.h> + +struct pwm_gpio { + struct pwm_chip chip; + struct hrtimer gpio_timer; + struct gpio_desc *gpio; + struct pwm_state state; + struct pwm_state next_state; + + /* Protect internal state between pwm_ops and hrtimer */ + spinlock_t lock; + + bool changing; + bool running; + bool level; +}; + +static unsigned long pwm_gpio_toggle(struct pwm_gpio *gpwm, bool level) +{ + const struct pwm_state *state = &gpwm->state; + bool invert = state->polarity == PWM_POLARITY_INVERSED; + + gpwm->level = level; + gpiod_set_value(gpwm->gpio, gpwm->level ^ invert); + + if (!state->duty_cycle || state->duty_cycle == state->period) { + gpwm->running = false; + return 0; + } + + gpwm->running = true; + return level ? state->duty_cycle : state->period - state->duty_cycle; +} + +static enum hrtimer_restart pwm_gpio_timer(struct hrtimer *gpio_timer) +{ + struct pwm_gpio *gpwm = container_of(gpio_timer, struct pwm_gpio, + gpio_timer); + unsigned long next_toggle; + unsigned long flags; + bool new_level; + + spin_lock_irqsave(&gpwm->lock, flags); + + /* Apply new state at end of current period */ + if (!gpwm->level && gpwm->changing) { + gpwm->changing = false; + gpwm->state = gpwm->next_state; + new_level = !!gpwm->state.duty_cycle; + } else { + new_level = !gpwm->level; + } + + next_toggle = pwm_gpio_toggle(gpwm, new_level); + if (next_toggle) { + hrtimer_forward(gpio_timer, hrtimer_get_expires(gpio_timer), + ns_to_ktime(next_toggle)); + } + + spin_unlock_irqrestore(&gpwm->lock, flags); + + return next_toggle ? HRTIMER_RESTART : HRTIMER_NORESTART; +} + +static int pwm_gpio_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct pwm_gpio *gpwm = container_of(chip, struct pwm_gpio, chip); + bool invert = state->polarity == PWM_POLARITY_INVERSED; + unsigned long flags; + + if (!state->enabled) { + hrtimer_cancel(&gpwm->gpio_timer); + } else if (!gpwm->running) { + /* + * This just enables the output, but pwm_gpio_toggle() + * really starts the duty cycle. + */ + int ret = gpiod_direction_output(gpwm->gpio, invert); + + if (ret) + return ret; + } + + spin_lock_irqsave(&gpwm->lock, flags); + + if (!state->enabled) { + gpwm->state = *state; + gpwm->running = false; + gpwm->changing = false; + + gpiod_set_value(gpwm->gpio, invert); + } else if (gpwm->running) { + gpwm->next_state = *state; + gpwm->changing = true; + } else { + unsigned long next_toggle; + + gpwm->state = *state; + gpwm->changing = false; + + next_toggle = pwm_gpio_toggle(gpwm, !!state->duty_cycle); + if (next_toggle) { + hrtimer_start(&gpwm->gpio_timer, next_toggle, + HRTIMER_MODE_REL); + } + } + + spin_unlock_irqrestore(&gpwm->lock, flags); + + return 0; +} + +static int pwm_gpio_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct pwm_gpio *gpwm = container_of(chip, struct pwm_gpio, chip); + unsigned long flags; + + spin_lock_irqsave(&gpwm->lock, flags); + + if (gpwm->changing) + *state = gpwm->next_state; + else + *state = gpwm->state; + + spin_unlock_irqrestore(&gpwm->lock, flags); + + return 0; +} + +static const struct pwm_ops pwm_gpio_ops = { + .apply = pwm_gpio_apply, + .get_state = pwm_gpio_get_state, +}; + +static int pwm_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pwm_gpio *gpwm; + int ret; + + gpwm = devm_kzalloc(dev, sizeof(*gpwm), GFP_KERNEL); + if (!gpwm) + return -ENOMEM; + + spin_lock_init(&gpwm->lock); + + gpwm->gpio = devm_gpiod_get(dev, NULL, GPIOD_ASIS); + if (IS_ERR(gpwm->gpio)) { + return dev_err_probe(dev, PTR_ERR(gpwm->gpio), + "could not get gpio\n"); + } + + if (gpiod_cansleep(gpwm->gpio)) { + return dev_err_probe(dev, -EINVAL, + "sleeping GPIO %d not supported\n", + desc_to_gpio(gpwm->gpio)); + } + + gpwm->chip.dev = dev; + gpwm->chip.ops = &pwm_gpio_ops; + gpwm->chip.npwm = 1; + + hrtimer_init(&gpwm->gpio_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + gpwm->gpio_timer.function = pwm_gpio_timer; + + ret = pwmchip_add(&gpwm->chip); + if (ret < 0) + return dev_err_probe(dev, ret, "could not add pwmchip\n"); + + platform_set_drvdata(pdev, gpwm); + + return 0; +} + +static void pwm_gpio_remove(struct platform_device *pdev) +{ + struct pwm_gpio *gpwm = platform_get_drvdata(pdev); + + pwmchip_remove(&gpwm->chip); + hrtimer_cancel(&gpwm->gpio_timer); +} + +static const struct of_device_id pwm_gpio_dt_ids[] = { + { .compatible = "pwm-gpio" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, pwm_gpio_dt_ids); + +static struct platform_driver pwm_gpio_driver = { + .driver = { + .name = "pwm-gpio", + .of_match_table = pwm_gpio_dt_ids, + }, + .probe = pwm_gpio_probe, + .remove_new = pwm_gpio_remove, +}; +module_platform_driver(pwm_gpio_driver); + +MODULE_DESCRIPTION("PWM GPIO driver"); +MODULE_ALIAS("platform:pwm-gpio"); +MODULE_AUTHOR("Vincent Whitchurch"); +MODULE_LICENSE("GPL"); -- 2.34.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH V3 2/2] pwm: Add GPIO PWM driver 2024-01-28 16:36 ` [PATCH V3 2/2] pwm: Add GPIO PWM driver Stefan Wahren @ 2024-01-29 9:40 ` Krzysztof Kozlowski 2024-01-29 13:55 ` Linus Walleij 2024-01-30 9:08 ` Sean Young 1 sibling, 1 reply; 12+ messages in thread From: Krzysztof Kozlowski @ 2024-01-29 9:40 UTC (permalink / raw) To: Stefan Wahren, Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: andy.shevchenko, Angelo Compagnucci, Philip Howard, Linus Walleij, linux-pwm, devicetree, linux-gpio, Vincent Whitchurch On 28/01/2024 17:36, Stefan Wahren wrote: > From: Vincent Whitchurch <vincent.whitchurch@axis.com> > > Add a software PWM which toggles a GPIO from a high-resolution timer. > > This will naturally not be as accurate or as efficient as a hardware > PWM, but it is useful in some cases. I have for example used it for > evaluating LED brightness handling (via leds-pwm) on a board where the > LED was just hooked up to a GPIO, and for a simple verification of the > timer frequency on another platform. > ... > + > +static struct platform_driver pwm_gpio_driver = { > + .driver = { > + .name = "pwm-gpio", > + .of_match_table = pwm_gpio_dt_ids, > + }, > + .probe = pwm_gpio_probe, > + .remove_new = pwm_gpio_remove, > +}; > +module_platform_driver(pwm_gpio_driver); > + > +MODULE_DESCRIPTION("PWM GPIO driver"); > +MODULE_ALIAS("platform:pwm-gpio"); You should not need MODULE_ALIAS() in normal cases. If you need it, usually it means your device ID table is wrong (e.g. misses either entries or MODULE_DEVICE_TABLE()). MODULE_ALIAS() is not a substitute for incomplete ID table. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V3 2/2] pwm: Add GPIO PWM driver 2024-01-29 9:40 ` Krzysztof Kozlowski @ 2024-01-29 13:55 ` Linus Walleij 2024-01-30 8:36 ` Krzysztof Kozlowski 0 siblings, 1 reply; 12+ messages in thread From: Linus Walleij @ 2024-01-29 13:55 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: Stefan Wahren, Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski, Conor Dooley, andy.shevchenko, Angelo Compagnucci, Philip Howard, linux-pwm, devicetree, linux-gpio, Vincent Whitchurch On Mon, Jan 29, 2024 at 10:40 AM Krzysztof Kozlowski <krzk@kernel.org> wrote: > On 28/01/2024 17:36, Stefan Wahren wrote: > > +MODULE_ALIAS("platform:pwm-gpio"); > > You should not need MODULE_ALIAS() in normal cases. If you need it, > usually it means your device ID table is wrong (e.g. misses either > entries or MODULE_DEVICE_TABLE()). MODULE_ALIAS() is not a substitute > for incomplete ID table. I was under the impression that MODULE_ALIAS was something people put in to make platforms using udev behave better by default, e.g. autoprobing these devices better (on coldplug for "platform:*"). For example: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4f46d6e7e5ffbce0ee1d1a80767fdf45e56cc863 But I might have got it all wrong :/ Yours, Linus Walleij ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V3 2/2] pwm: Add GPIO PWM driver 2024-01-29 13:55 ` Linus Walleij @ 2024-01-30 8:36 ` Krzysztof Kozlowski 0 siblings, 0 replies; 12+ messages in thread From: Krzysztof Kozlowski @ 2024-01-30 8:36 UTC (permalink / raw) To: Linus Walleij Cc: Stefan Wahren, Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski, Conor Dooley, andy.shevchenko, Angelo Compagnucci, Philip Howard, linux-pwm, devicetree, linux-gpio, Vincent Whitchurch On 29/01/2024 14:55, Linus Walleij wrote: > On Mon, Jan 29, 2024 at 10:40 AM Krzysztof Kozlowski <krzk@kernel.org> wrote: >> On 28/01/2024 17:36, Stefan Wahren wrote: > >>> +MODULE_ALIAS("platform:pwm-gpio"); >> >> You should not need MODULE_ALIAS() in normal cases. If you need it, >> usually it means your device ID table is wrong (e.g. misses either >> entries or MODULE_DEVICE_TABLE()). MODULE_ALIAS() is not a substitute >> for incomplete ID table. > > I was under the impression that MODULE_ALIAS > was something people put in to make platforms using > udev behave better by default, e.g. autoprobing these > devices better (on coldplug for "platform:*"). > > For example: > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4f46d6e7e5ffbce0ee1d1a80767fdf45e56cc863 > > But I might have got it all wrong :/ That was 2008 :), but answering to the problem: people put MODULE_ALIAS because they (do not have / forgot / don't want to add)* proper id table for platform devices with MODULE_DEVICE_TABLE. While it works, it does not offer the same scalability as proper ID table and is confusing, because it suggests that driver should be autoloaded by a platform ID, but not matched/bound by platform ID! Such situation is very rare and would deserve a comment anyway. * choose appropriate See also: https://lore.kernel.org/all/?q=f%3Akozlowski+drop+unneeded+module_alias Best regards, Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V3 2/2] pwm: Add GPIO PWM driver 2024-01-28 16:36 ` [PATCH V3 2/2] pwm: Add GPIO PWM driver Stefan Wahren 2024-01-29 9:40 ` Krzysztof Kozlowski @ 2024-01-30 9:08 ` Sean Young 2024-01-30 11:21 ` Stefan Wahren 1 sibling, 1 reply; 12+ messages in thread From: Sean Young @ 2024-01-30 9:08 UTC (permalink / raw) To: Stefan Wahren Cc: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski, Conor Dooley, andy.shevchenko, Angelo Compagnucci, Philip Howard, Linus Walleij, linux-pwm, devicetree, linux-gpio, Vincent Whitchurch On Sun, Jan 28, 2024 at 05:36:30PM +0100, Stefan Wahren wrote: > From: Vincent Whitchurch <vincent.whitchurch@axis.com> > > Add a software PWM which toggles a GPIO from a high-resolution timer. > > This will naturally not be as accurate or as efficient as a hardware > PWM, but it is useful in some cases. I have for example used it for > evaluating LED brightness handling (via leds-pwm) on a board where the > LED was just hooked up to a GPIO, and for a simple verification of the > timer frequency on another platform. > > Since high-resolution timers are used, sleeping gpio chips are not > supported and are rejected in the probe function. > > Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com> > Co-developed-by: Stefan Wahren <wahrenst@gmx.net> > Signed-off-by: Stefan Wahren <wahrenst@gmx.net> > --- > drivers/pwm/Kconfig | 11 ++ > drivers/pwm/Makefile | 1 + > drivers/pwm/pwm-gpio.c | 221 +++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 233 insertions(+) > create mode 100644 drivers/pwm/pwm-gpio.c > > diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig > index 4b956d661755..7cfda2cde130 100644 > --- a/drivers/pwm/Kconfig > +++ b/drivers/pwm/Kconfig > @@ -227,6 +227,17 @@ config PWM_FSL_FTM > To compile this driver as a module, choose M here: the module > will be called pwm-fsl-ftm. > > +config PWM_GPIO > + tristate "GPIO PWM support" > + depends on GPIOLIB > + depends on HIGH_RES_TIMERS > + help > + Generic PWM framework driver for a software PWM toggling a GPIO pin > + from kernel high-resolution timers. > + > + To compile this driver as a module, choose M here: the module > + will be called pwm-gpio. > + > config PWM_HIBVT > tristate "HiSilicon BVT PWM support" > depends on ARCH_HISI || COMPILE_TEST > diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile > index c5ec9e168ee7..59d1a46bb1af 100644 > --- a/drivers/pwm/Makefile > +++ b/drivers/pwm/Makefile > @@ -19,6 +19,7 @@ obj-$(CONFIG_PWM_DWC_CORE) += pwm-dwc-core.o > obj-$(CONFIG_PWM_DWC) += pwm-dwc.o > obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o > obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o > +obj-$(CONFIG_PWM_GPIO) += pwm-gpio.o > obj-$(CONFIG_PWM_HIBVT) += pwm-hibvt.o > obj-$(CONFIG_PWM_IMG) += pwm-img.o > obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o > diff --git a/drivers/pwm/pwm-gpio.c b/drivers/pwm/pwm-gpio.c > new file mode 100644 > index 000000000000..14637abe465b > --- /dev/null > +++ b/drivers/pwm/pwm-gpio.c > @@ -0,0 +1,221 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Generic software PWM for modulating GPIOs > + * > + * Copyright (C) 2020 Axis Communications AB > + * Copyright (C) 2020 Nicola Di Lieto > + * Copyright (C) 2024 Stefan Wahren > + */ > + > +#include <linux/device.h> > +#include <linux/err.h> > +#include <linux/gpio/consumer.h> > +#include <linux/hrtimer.h> > +#include <linux/module.h> > +#include <linux/mod_devicetable.h> > +#include <linux/platform_device.h> > +#include <linux/pwm.h> > +#include <linux/spinlock.h> > + > +struct pwm_gpio { > + struct pwm_chip chip; > + struct hrtimer gpio_timer; > + struct gpio_desc *gpio; > + struct pwm_state state; > + struct pwm_state next_state; > + > + /* Protect internal state between pwm_ops and hrtimer */ > + spinlock_t lock; > + > + bool changing; > + bool running; > + bool level; > +}; > + > +static unsigned long pwm_gpio_toggle(struct pwm_gpio *gpwm, bool level) > +{ > + const struct pwm_state *state = &gpwm->state; > + bool invert = state->polarity == PWM_POLARITY_INVERSED; > + > + gpwm->level = level; > + gpiod_set_value(gpwm->gpio, gpwm->level ^ invert); > + > + if (!state->duty_cycle || state->duty_cycle == state->period) { > + gpwm->running = false; > + return 0; > + } > + > + gpwm->running = true; > + return level ? state->duty_cycle : state->period - state->duty_cycle; > +} > + > +static enum hrtimer_restart pwm_gpio_timer(struct hrtimer *gpio_timer) > +{ > + struct pwm_gpio *gpwm = container_of(gpio_timer, struct pwm_gpio, > + gpio_timer); > + unsigned long next_toggle; > + unsigned long flags; > + bool new_level; > + > + spin_lock_irqsave(&gpwm->lock, flags); > + > + /* Apply new state at end of current period */ > + if (!gpwm->level && gpwm->changing) { > + gpwm->changing = false; > + gpwm->state = gpwm->next_state; > + new_level = !!gpwm->state.duty_cycle; > + } else { > + new_level = !gpwm->level; > + } > + > + next_toggle = pwm_gpio_toggle(gpwm, new_level); > + if (next_toggle) { > + hrtimer_forward(gpio_timer, hrtimer_get_expires(gpio_timer), > + ns_to_ktime(next_toggle)); > + } > + > + spin_unlock_irqrestore(&gpwm->lock, flags); > + > + return next_toggle ? HRTIMER_RESTART : HRTIMER_NORESTART; > +} > + > +static int pwm_gpio_apply(struct pwm_chip *chip, struct pwm_device *pwm, > + const struct pwm_state *state) > +{ > + struct pwm_gpio *gpwm = container_of(chip, struct pwm_gpio, chip); > + bool invert = state->polarity == PWM_POLARITY_INVERSED; > + unsigned long flags; Not sure this is necessary but how about: if (state->duty_cycle < hrtimer_resolution || state->period - state->duty_cycle < hrtimer_resolution) return -EINVAL; > + > + if (!state->enabled) { > + hrtimer_cancel(&gpwm->gpio_timer); > + } else if (!gpwm->running) { > + /* > + * This just enables the output, but pwm_gpio_toggle() > + * really starts the duty cycle. > + */ > + int ret = gpiod_direction_output(gpwm->gpio, invert); > + > + if (ret) > + return ret; > + } > + > + spin_lock_irqsave(&gpwm->lock, flags); > + > + if (!state->enabled) { > + gpwm->state = *state; > + gpwm->running = false; > + gpwm->changing = false; > + > + gpiod_set_value(gpwm->gpio, invert); > + } else if (gpwm->running) { > + gpwm->next_state = *state; > + gpwm->changing = true; > + } else { > + unsigned long next_toggle; > + > + gpwm->state = *state; > + gpwm->changing = false; > + > + next_toggle = pwm_gpio_toggle(gpwm, !!state->duty_cycle); > + if (next_toggle) { > + hrtimer_start(&gpwm->gpio_timer, next_toggle, > + HRTIMER_MODE_REL); > + } > + } > + > + spin_unlock_irqrestore(&gpwm->lock, flags); > + > + return 0; > +} > + > +static int pwm_gpio_get_state(struct pwm_chip *chip, struct pwm_device *pwm, > + struct pwm_state *state) > +{ > + struct pwm_gpio *gpwm = container_of(chip, struct pwm_gpio, chip); > + unsigned long flags; > + > + spin_lock_irqsave(&gpwm->lock, flags); > + > + if (gpwm->changing) > + *state = gpwm->next_state; > + else > + *state = gpwm->state; > + > + spin_unlock_irqrestore(&gpwm->lock, flags); > + > + return 0; > +} > + > +static const struct pwm_ops pwm_gpio_ops = { > + .apply = pwm_gpio_apply, > + .get_state = pwm_gpio_get_state, > +}; > + > +static int pwm_gpio_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct pwm_gpio *gpwm; > + int ret; > + > + gpwm = devm_kzalloc(dev, sizeof(*gpwm), GFP_KERNEL); > + if (!gpwm) > + return -ENOMEM; > + > + spin_lock_init(&gpwm->lock); > + > + gpwm->gpio = devm_gpiod_get(dev, NULL, GPIOD_ASIS); > + if (IS_ERR(gpwm->gpio)) { > + return dev_err_probe(dev, PTR_ERR(gpwm->gpio), > + "could not get gpio\n"); > + } > + > + if (gpiod_cansleep(gpwm->gpio)) { > + return dev_err_probe(dev, -EINVAL, > + "sleeping GPIO %d not supported\n", > + desc_to_gpio(gpwm->gpio)); > + } > + > + gpwm->chip.dev = dev; > + gpwm->chip.ops = &pwm_gpio_ops; > + gpwm->chip.npwm = 1; gpwm->chip.atomic = true; ? > + > + hrtimer_init(&gpwm->gpio_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); > + gpwm->gpio_timer.function = pwm_gpio_timer; > + > + ret = pwmchip_add(&gpwm->chip); > + if (ret < 0) > + return dev_err_probe(dev, ret, "could not add pwmchip\n"); > + > + platform_set_drvdata(pdev, gpwm); > + > + return 0; > +} > + > +static void pwm_gpio_remove(struct platform_device *pdev) > +{ > + struct pwm_gpio *gpwm = platform_get_drvdata(pdev); > + > + pwmchip_remove(&gpwm->chip); > + hrtimer_cancel(&gpwm->gpio_timer); > +} > + > +static const struct of_device_id pwm_gpio_dt_ids[] = { > + { .compatible = "pwm-gpio" }, > + { /* sentinel */ } > +}; > +MODULE_DEVICE_TABLE(of, pwm_gpio_dt_ids); > + > +static struct platform_driver pwm_gpio_driver = { > + .driver = { > + .name = "pwm-gpio", > + .of_match_table = pwm_gpio_dt_ids, > + }, > + .probe = pwm_gpio_probe, > + .remove_new = pwm_gpio_remove, > +}; > +module_platform_driver(pwm_gpio_driver); > + > +MODULE_DESCRIPTION("PWM GPIO driver"); > +MODULE_ALIAS("platform:pwm-gpio"); > +MODULE_AUTHOR("Vincent Whitchurch"); > +MODULE_LICENSE("GPL"); > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V3 2/2] pwm: Add GPIO PWM driver 2024-01-30 9:08 ` Sean Young @ 2024-01-30 11:21 ` Stefan Wahren 0 siblings, 0 replies; 12+ messages in thread From: Stefan Wahren @ 2024-01-30 11:21 UTC (permalink / raw) To: Sean Young Cc: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski, Conor Dooley, andy.shevchenko, Angelo Compagnucci, Philip Howard, Linus Walleij, linux-pwm, devicetree, linux-gpio, Vincent Whitchurch Hi Sean, Am 30.01.24 um 10:08 schrieb Sean Young: > On Sun, Jan 28, 2024 at 05:36:30PM +0100, Stefan Wahren wrote: >> From: Vincent Whitchurch <vincent.whitchurch@axis.com> >> >> Add a software PWM which toggles a GPIO from a high-resolution timer. >> >> This will naturally not be as accurate or as efficient as a hardware >> PWM, but it is useful in some cases. I have for example used it for >> evaluating LED brightness handling (via leds-pwm) on a board where the >> LED was just hooked up to a GPIO, and for a simple verification of the >> timer frequency on another platform. >> >> Since high-resolution timers are used, sleeping gpio chips are not >> supported and are rejected in the probe function. >> >> Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com> >> Co-developed-by: Stefan Wahren <wahrenst@gmx.net> >> Signed-off-by: Stefan Wahren <wahrenst@gmx.net> >> --- ... >> + >> +static int pwm_gpio_apply(struct pwm_chip *chip, struct pwm_device *pwm, >> + const struct pwm_state *state) >> +{ >> + struct pwm_gpio *gpwm = container_of(chip, struct pwm_gpio, chip); >> + bool invert = state->polarity == PWM_POLARITY_INVERSED; >> + unsigned long flags; > Not sure this is necessary but how about: > > if (state->duty_cycle < hrtimer_resolution || > state->period - state->duty_cycle < hrtimer_resolution) > return -EINVAL; > i think i get the idea, but we need to care about corner cases like duty_cycle = 0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V3 0/2] pwm: Add GPIO PWM driver 2024-01-28 16:36 [PATCH V3 0/2] pwm: Add GPIO PWM driver Stefan Wahren 2024-01-28 16:36 ` [PATCH V3 1/2] dt-bindings: pwm: Add pwm-gpio Stefan Wahren 2024-01-28 16:36 ` [PATCH V3 2/2] pwm: Add GPIO PWM driver Stefan Wahren @ 2024-02-02 13:19 ` Phil Howard 2024-02-02 20:13 ` Stefan Wahren 2 siblings, 1 reply; 12+ messages in thread From: Phil Howard @ 2024-02-02 13:19 UTC (permalink / raw) To: Stefan Wahren Cc: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski, Conor Dooley, andy.shevchenko, Angelo Compagnucci, Linus Walleij, linux-pwm, devicetree, linux-gpio On Sun, 28 Jan 2024 at 16:37, Stefan Wahren <wahrenst@gmx.net> wrote: > > Add a software PWM which toggles a GPIO from a high-resolution timer. > > Recent discussions in the Raspberry Pi community revealt that a lot > of users still use MMIO userspace tools for GPIO access. One argument > for this approach is the lack of a GPIO PWM kernel driver. So this > series tries to fill this gap. *Thank you* for picking this up. I've been stuck down by covid but am aiming to build and test this on a Pi 5 (with a gpio chip over PCIe) to see if it runs- though I am fully expecting a PIO solution (using the Pi 5s RP1) to handle PWM in this case, and hope to rely upon this gpio-pwm module for previous iterations. > > This continues the work of Vincent Whitchurch [1], which is easier > to read and more consequent by rejecting sleeping GPIOs than Nicola's > approach [2]. > > The work has been tested on a Raspberry Pi 3 B+ and a cheap logic > analyzer. > > V3: > - rebase on top of v6.8-pwm-next > - cherry-pick improvements from Nicola's series > - try to address Uwe's, Linus' and Andy's comments > - try to avoid GPIO glitches during probe > - fix pwm_gpio_remove() > - some code clean up's and comments > > V2: > - Rename gpio to gpios in binding > - Calculate next expiry from expected current expiry rather than "now" > - Only change configuration after current period ends > - Implement get_state() > - Add error message for probe failures > - Stop PWM before unregister > > [1] - https://lore.kernel.org/all/20200915135445.al75xmjxudj2rgcp@axis.com/T/ > [2] - https://lore.kernel.org/all/20201205214353.xapax46tt5snzd2v@einstein.dilieto.eu/ > > Nicola Di Lieto (1): > dt-bindings: pwm: Add pwm-gpio > > Vincent Whitchurch (1): > pwm: Add GPIO PWM driver > > .../devicetree/bindings/pwm/pwm-gpio.yaml | 42 ++++ > drivers/pwm/Kconfig | 11 + > drivers/pwm/Makefile | 1 + > drivers/pwm/pwm-gpio.c | 221 ++++++++++++++++++ > 4 files changed, 275 insertions(+) > create mode 100644 Documentation/devicetree/bindings/pwm/pwm-gpio.yaml > create mode 100644 drivers/pwm/pwm-gpio.c > > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V3 0/2] pwm: Add GPIO PWM driver 2024-02-02 13:19 ` [PATCH V3 0/2] " Phil Howard @ 2024-02-02 20:13 ` Stefan Wahren 2024-02-04 19:21 ` Phil Howard 0 siblings, 1 reply; 12+ messages in thread From: Stefan Wahren @ 2024-02-02 20:13 UTC (permalink / raw) To: Phil Howard Cc: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski, Conor Dooley, andy.shevchenko, Angelo Compagnucci, Linus Walleij, linux-pwm, devicetree, linux-gpio Hi Phil, Am 02.02.24 um 14:19 schrieb Phil Howard: > On Sun, 28 Jan 2024 at 16:37, Stefan Wahren <wahrenst@gmx.net> wrote: >> Add a software PWM which toggles a GPIO from a high-resolution timer. >> >> Recent discussions in the Raspberry Pi community revealt that a lot >> of users still use MMIO userspace tools for GPIO access. One argument >> for this approach is the lack of a GPIO PWM kernel driver. So this >> series tries to fill this gap. > *Thank you* for picking this up. I've been stuck down by covid but am aiming > to build and test this on a Pi 5 (with a gpio chip over PCIe) to see if it runs- > though I am fully expecting a PIO solution (using the Pi 5s RP1) to handle > PWM in this case, and hope to rely upon this gpio-pwm module for previous > iterations. i hope you are doing well. There will be small functional changes in V4. Since this series based on Linux 6.8 and there is no RPi 5 mainline support, you will need to apply it on top of rpi-6.8.y. Should i wait for your test results (no pressure) before sending V4? > >> This continues the work of Vincent Whitchurch [1], which is easier >> to read and more consequent by rejecting sleeping GPIOs than Nicola's >> approach [2]. >> >> The work has been tested on a Raspberry Pi 3 B+ and a cheap logic >> analyzer. >> >> V3: >> - rebase on top of v6.8-pwm-next >> - cherry-pick improvements from Nicola's series >> - try to address Uwe's, Linus' and Andy's comments >> - try to avoid GPIO glitches during probe >> - fix pwm_gpio_remove() >> - some code clean up's and comments >> >> V2: >> - Rename gpio to gpios in binding >> - Calculate next expiry from expected current expiry rather than "now" >> - Only change configuration after current period ends >> - Implement get_state() >> - Add error message for probe failures >> - Stop PWM before unregister >> >> [1] - https://lore.kernel.org/all/20200915135445.al75xmjxudj2rgcp@axis.com/T/ >> [2] - https://lore.kernel.org/all/20201205214353.xapax46tt5snzd2v@einstein.dilieto.eu/ >> >> Nicola Di Lieto (1): >> dt-bindings: pwm: Add pwm-gpio >> >> Vincent Whitchurch (1): >> pwm: Add GPIO PWM driver >> >> .../devicetree/bindings/pwm/pwm-gpio.yaml | 42 ++++ >> drivers/pwm/Kconfig | 11 + >> drivers/pwm/Makefile | 1 + >> drivers/pwm/pwm-gpio.c | 221 ++++++++++++++++++ >> 4 files changed, 275 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/pwm/pwm-gpio.yaml >> create mode 100644 drivers/pwm/pwm-gpio.c >> >> -- >> 2.34.1 >> ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V3 0/2] pwm: Add GPIO PWM driver 2024-02-02 20:13 ` Stefan Wahren @ 2024-02-04 19:21 ` Phil Howard 0 siblings, 0 replies; 12+ messages in thread From: Phil Howard @ 2024-02-04 19:21 UTC (permalink / raw) To: Stefan Wahren Cc: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski, Conor Dooley, andy.shevchenko, Angelo Compagnucci, Linus Walleij, linux-pwm, devicetree, linux-gpio On Fri, 2 Feb 2024 at 20:13, Stefan Wahren <wahrenst@gmx.net> wrote: > > Hi Phil, > > Am 02.02.24 um 14:19 schrieb Phil Howard: > > On Sun, 28 Jan 2024 at 16:37, Stefan Wahren <wahrenst@gmx.net> wrote: > >> Add a software PWM which toggles a GPIO from a high-resolution timer. > >> > >> Recent discussions in the Raspberry Pi community revealt that a lot > >> of users still use MMIO userspace tools for GPIO access. One argument > >> for this approach is the lack of a GPIO PWM kernel driver. So this > >> series tries to fill this gap. > > *Thank you* for picking this up. I've been stuck down by covid but am aiming > > to build and test this on a Pi 5 (with a gpio chip over PCIe) to see if it runs- > > though I am fully expecting a PIO solution (using the Pi 5s RP1) to handle > > PWM in this case, and hope to rely upon this gpio-pwm module for previous > > iterations. > i hope you are doing well. > > There will be small functional changes in V4. Since this series based on > Linux 6.8 and there is no RPi 5 mainline support, you will need to apply > it on top of rpi-6.8.y. I've got as far as applying the patches and building myself a 6.8.y kernel, just dragging the ol' brain kicking and screaming into dts world again. > > Should i wait for your test results (no pressure) before sending V4? Don't wait on my account- (no really, it's chaos here)- send away! > > > >> This continues the work of Vincent Whitchurch [1], which is easier > >> to read and more consequent by rejecting sleeping GPIOs than Nicola's > >> approach [2]. > >> > >> The work has been tested on a Raspberry Pi 3 B+ and a cheap logic > >> analyzer. > >> > >> V3: > >> - rebase on top of v6.8-pwm-next > >> - cherry-pick improvements from Nicola's series > >> - try to address Uwe's, Linus' and Andy's comments > >> - try to avoid GPIO glitches during probe > >> - fix pwm_gpio_remove() > >> - some code clean up's and comments > >> > >> V2: > >> - Rename gpio to gpios in binding > >> - Calculate next expiry from expected current expiry rather than "now" > >> - Only change configuration after current period ends > >> - Implement get_state() > >> - Add error message for probe failures > >> - Stop PWM before unregister > >> > >> [1] - https://lore.kernel.org/all/20200915135445.al75xmjxudj2rgcp@axis.com/T/ > >> [2] - https://lore.kernel.org/all/20201205214353.xapax46tt5snzd2v@einstein.dilieto.eu/ > >> > >> Nicola Di Lieto (1): > >> dt-bindings: pwm: Add pwm-gpio > >> > >> Vincent Whitchurch (1): > >> pwm: Add GPIO PWM driver > >> > >> .../devicetree/bindings/pwm/pwm-gpio.yaml | 42 ++++ > >> drivers/pwm/Kconfig | 11 + > >> drivers/pwm/Makefile | 1 + > >> drivers/pwm/pwm-gpio.c | 221 ++++++++++++++++++ > >> 4 files changed, 275 insertions(+) > >> create mode 100644 Documentation/devicetree/bindings/pwm/pwm-gpio.yaml > >> create mode 100644 drivers/pwm/pwm-gpio.c > >> > >> -- > >> 2.34.1 > >> > -- Philip Howard Technology & Lifestyle Writer gadgetoid.com Gadgetoid gadg-et-oid [gaj-it-oid] -adjective 1. having the characteristics or form of a gadget; resembling a mechanical contrivance or device. ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-02-04 19:21 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-01-28 16:36 [PATCH V3 0/2] pwm: Add GPIO PWM driver Stefan Wahren 2024-01-28 16:36 ` [PATCH V3 1/2] dt-bindings: pwm: Add pwm-gpio Stefan Wahren 2024-01-28 17:08 ` Conor Dooley 2024-01-28 16:36 ` [PATCH V3 2/2] pwm: Add GPIO PWM driver Stefan Wahren 2024-01-29 9:40 ` Krzysztof Kozlowski 2024-01-29 13:55 ` Linus Walleij 2024-01-30 8:36 ` Krzysztof Kozlowski 2024-01-30 9:08 ` Sean Young 2024-01-30 11:21 ` Stefan Wahren 2024-02-02 13:19 ` [PATCH V3 0/2] " Phil Howard 2024-02-02 20:13 ` Stefan Wahren 2024-02-04 19:21 ` Phil Howard
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).