From: Andy Shevchenko <andriy.shevchenko@intel.com>
To: Nicolae-Daniel Deaconescu <Nicolae-daniel.Deaconescu@analog.com>
Cc: "Jonathan Cameron" <jic23@kernel.org>,
"Uwe Kleine-König" <ukleinek@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Rob Herring" <robh@kernel.org>,
"David Lechner" <dlechner@baylibre.com>,
"Nuno Sá" <nuno.sa@analog.com>,
"Andy Shevchenko" <andy@kernel.org>,
"Michael Hennerich" <michael.hennerich@analog.com>,
"Trevor Gamblin" <tgamblin@baylibre.com>,
"Joshua Crofts" <crofts@kernel.org>,
"Sergiu Cuciurean" <sergiu.cuciurean@analog.com>,
linux-iio@vger.kernel.org, devicetree@vger.kernel.org,
linux-pwm@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 1/5] pwm: core: add pwm_get_waveform_step_might_sleep()
Date: Wed, 4 Nov 2026 21:51:31 +0200 [thread overview]
Message-ID: <auuMw8tKvGynTKsr@ashevche-desk.local> (raw)
In-Reply-To: <20261104132143.215581-2-Nicolae-daniel.Deaconescu@analog.com>
On Wed, Nov 04, 2026 at 03:21:39PM +0200, Nicolae-Daniel Deaconescu wrote:
> A consumer that has to meet minimum times, or place an edge relative to
> the cycles of a clock that a PWM gates, cannot do that with the waveform
> API alone. The rounding functions round down, so a minimum has to be
> requested with some margin, and the size of that margin is the step of
> the PWM, which only the provider knows.
>
> A provider can report the rate of the clock its timing is derived from
> and how many cycles of that clock one step lasts. A consumer can then
> work in whole steps, convert them to nanoseconds rounding up, and get
> that waveform back from the hardware. Without this, a consumer has to
> read the rate from a clock it gets on its own, which describes
> a relationship the hardware doesn't have, and is wrong if
> PWM divides the clock.
...
> +/**
> + * pwm_get_waveform_step_might_sleep - Query the granularity of the waveforms
> + * Cannot be used in atomic context.
> + * @pwm: PWM device
> + * @step: output parameter
> + *
> + * Stores in @step the clock rate the timing of @pwm is derived from and how
> + * many cycles of that clock one step lasts. Period, duty length and duty
> + * offset are multiples of that step, so a waveform asked for in whole steps
> + * is not changed by rounding. Compute the length in nanoseconds of n steps
> + * as n * @step->clk_cycles_per_step * NSEC_PER_SEC / @step->clk_rate_hz and
> + * round it up, because pwm_round_waveform_might_sleep() and
> + * pwm_set_waveform_might_sleep() round down.
> + *
> + * The values can change when a clock changes its rate, so they are only valid
> + * as long as the provider's input clocks are not reconfigured.
> + *
> + * Returns: 0 on success, -EOPNOTSUPP if the provider doesn't report it or a
> + * negative errno
> + * Context: May sleep.
This is incorrect. The Returns section has to be the last one in the
kernel-doc. It's documented.
> + */
> +int pwm_get_waveform_step_might_sleep(struct pwm_device *pwm,
> + struct pwm_waveform_step *step)
> +{
> + struct pwm_chip *chip = pwm->chip;
> + const struct pwm_ops *ops = chip->ops;
> + int ret;
> +
> + if (!pwmchip_supports_waveform(chip) || !ops->get_waveform_step)
> + return -EOPNOTSUPP;
> +
> + might_sleep();
> +
> + guard(pwmchip)(chip);
> +
> + if (!chip->operational)
> + return -ENODEV;
> +
> + if (IS_ENABLED(CONFIG_PWM_DEBUG) && chip->atomic) {
> + /*
> + * Catch any drivers that have been marked as atomic but
> + * that will sleep anyway.
> + */
> + non_block_start();
> + ret = ops->get_waveform_step(chip, pwm, step);
> + non_block_end();
> + } else {
> + ret = ops->get_waveform_step(chip, pwm, step);
> + }
> + if (ret)
> + return ret;
> +
> + if (!step->clk_rate_hz || !step->clk_cycles_per_step ||
The second check is unneeded, the third one covers it.
> + step->clk_rate_hz > (u64)step->clk_cycles_per_step * NSEC_PER_SEC)
> + return -EINVAL;
> +
> + return 0;
> +}
...
> +/**
> + * struct pwm_waveform_step - granularity of the waveforms a PWM can generate
> + * @clk_rate_hz: rate of the clock the PWM's timing is derived from
> + * @clk_cycles_per_step: number of those clock cycles one step lasts
> + *
> + * The period, the duty length and the duty offset of a waveform are multiples
> + * of one step, which lasts @clk_cycles_per_step / @clk_rate_hz seconds. A PWM
> + * that divides its input clock in hardware has @clk_cycles_per_step > 1.
> + *
> + * The step is the same for every waveform and for the period, the duty length
> + * and the duty offset, so a provider whose granularity depends on the
> + * requested period (for example through a prescaler) can't describe itself
> + * with it. One step also has to last at least 1 ns, otherwise rounding a
> + * length in nanoseconds up can add a whole step.
> + *
> + * A consumer that needs a minimum time, or that has to place an edge relative
> + * to the cycles of the clock a PWM channel gates, can use this to ask for
> + * the next possible value instead of one that is rounded down, and to compute
> + * the frequency a rounded period results in without the error of the
> + * nanosecond resolution of struct pwm_waveform.
> + */
> +struct pwm_waveform_step {
> + unsigned long clk_rate_hz;
_Hz ?
> + unsigned int clk_cycles_per_step;
> +};
--
With Best Regards,
Andy Shevchenko
next prev parent reply other threads:[~2026-11-04 19:51 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 13:21 [PATCH v2 0/5] iio: adc: ad7625: add LTC2387 and ADAQ2387x support Nicolae-Daniel Deaconescu
2026-11-04 13:21 ` [PATCH v2 1/5] pwm: core: add pwm_get_waveform_step_might_sleep() Nicolae-Daniel Deaconescu
2026-11-04 19:51 ` Andy Shevchenko [this message]
2026-11-04 13:21 ` [PATCH v2 2/5] pwm: axi-pwmgen: report the waveform step Nicolae-Daniel Deaconescu
2026-11-04 13:21 ` [PATCH v2 3/5] iio: adc: ad7625: fix sampling frequency handling Nicolae-Daniel Deaconescu
2026-11-04 13:21 ` [PATCH v2 4/5] dt-bindings: iio: adc: adi,ad7625: add LTC2387 and ADAQ2387x Nicolae-Daniel Deaconescu
2026-11-05 0:23 ` Conor Dooley
2026-11-04 13:21 ` [PATCH v2 5/5] iio: adc: ad7625: add LTC2387 and ADAQ2387x support Nicolae-Daniel Deaconescu
2026-11-04 20:22 ` Andy Shevchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=auuMw8tKvGynTKsr@ashevche-desk.local \
--to=andriy.shevchenko@intel.com \
--cc=Nicolae-daniel.Deaconescu@analog.com \
--cc=andy@kernel.org \
--cc=conor+dt@kernel.org \
--cc=crofts@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dlechner@baylibre.com \
--cc=jic23@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pwm@vger.kernel.org \
--cc=michael.hennerich@analog.com \
--cc=nuno.sa@analog.com \
--cc=robh@kernel.org \
--cc=sergiu.cuciurean@analog.com \
--cc=tgamblin@baylibre.com \
--cc=ukleinek@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®