Linux PWM subsystem development
 help / color / mirror / Atom feed
From: David Lechner <dlechner@baylibre.com>
To: "Uwe Kleine-König" <u.kleine-koenig@baylibre.com>,
	linux-pwm@vger.kernel.org
Cc: Kent Gibson <warthog618@gmail.com>
Subject: Re: [PATCH v4 3/7] pwm: Provide new consumer API functions for waveforms
Date: Fri, 6 Sep 2024 16:22:42 -0500	[thread overview]
Message-ID: <e1dfca79-a267-4c91-b504-b3f222dacc24@baylibre.com> (raw)
In-Reply-To: <857ae911c23a474e6de4a1ba0b224bc8d982d624.1725635013.git.u.kleine-koenig@baylibre.com>

On 9/6/24 10:42 AM, Uwe Kleine-König wrote:
> Provide API functions for consumers to work with waveforms.
> 
> Note that one relevant difference between pwm_get_state() and
> pwm_get_waveform*() is that the latter yields the actually configured
> hardware state, while the former yields the last state passed to
> pwm_apply*() and so doesn't account for hardware specific rounding.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
> ---

One thing I am wondering about is how to implement rounding up instead
of down. For example, I we need a >= 10 ns duty cycle.

Here is my attempt...

#define MIN_DUTY_NS 10

int some_func(struct pwm_device *pwm)
{
	struct pwm_waveform wf = {
		.period_length_ns = 400,
	};
	u64 trial_ns = MIN_DUTY_NS;
	int ret;

	do {
		wf.duty_length_ns = trial_ns;

		ret = pwm_round_waveform_might_sleep(pwm, &wf);
		if (ret < 0)
			return ret;

		/*
		 * ret == 1 could be either because duty or period
		 * is not attainable. In any case, we have to wait
		 * until the last trial to rule out earlier trials
		 * failing because of too small duty since we try
		 * again with larger duty. Maybe this check isn't
		 * needed though since pwm_round_waveform_might_sleep()
		 * should fail when trial_ns > wf.period_length_ns?
		 */
		if (ret == 1 && trial_ns == wf.period_length_ns)
			return -ERANGE;

		trial_ns++;
	} while (wf.duty_length_ns < MIN_DUTY_NS);

	return pwm_set_waveform_might_sleep(pwm, &wf, true);
}


1. This seems like it would waste time trying each 1 ns increment
   compared to being able to tell the low level driver which way
   we want to round.
2. Even with this, we could end up with an actual period of 9.5 ns
   which is < 10 ns but have to way to know since the returned value
   will be 10. Probably not likely that 0.5 ns is going to cause
   something to malfunction, but you never know.
3. Handling ret == 1 seems kind of messy since it could be caused
   by multiple different problems.

Maybe we could consider including a rounding direction (up/down/closest)
for each of the waveform parameters and pass that along to low level
driver to avoid much of this? Or at least have these parameters for
the high-level pwm_round_waveform_might_sleep() so each consumer doesn't
have to try to figure out how to do the rounding right?

> @@ -145,6 +192,220 @@ static int __pwm_write_waveform(struct pwm_chip *chip, struct pwm_device *pwm, c
>  
>  #define WFHWSIZE 20
>  
> +/**
> + * pwm_round_waveform_might_sleep - Query hardware capabilities
> + * Cannot be used in atomic context.
> + * @pwm: PWM device
> + * @wf: waveform to round and output parameter

It would be helpful to spell out in the description below that @wf will
be modified upon non-error return and what the modified values will
actually be. (Or refer to the other functions where the values are already
documented to avoid duplication.)

> + *
> + * Typically a given waveform cannot be implemented exactly by hardware, e.g.
> + * because hardware only supports coarse period resolution or no duty_offset.
> + * This function returns the actually implemented waveform if you pass wf to
> + * pwm_set_waveform_might_sleep now.
> + *
> + * Note however that the world doesn't stop turning when you call it, so when
> + * doing
> + *
> + * 	pwm_round_waveform_might_sleep(mypwm, &wf);
> + * 	pwm_set_waveform_might_sleep(mypwm, &wf, true);
> + *
> + * the latter might fail, e.g. because an input clock changed its rate between
> + * these two calls and the waveform determined by
> + * pwm_round_waveform_might_sleep() cannot be implemented any more.
> + *
> + * Returns 0 on success, 1 if there is no valid hardware configuration matching
> + * the input waveform under the PWM rounding rules or a negative errno.
> + */
> +int pwm_round_waveform_might_sleep(struct pwm_device *pwm, struct pwm_waveform *wf)
> +{

  reply	other threads:[~2024-09-06 21:22 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-06 15:42 [PATCH v4 0/7] pwm: New abstraction and userspace API Uwe Kleine-König
2024-09-06 15:42 ` [PATCH v4 1/7] pwm: Add more locking Uwe Kleine-König
2024-09-06 19:54   ` David Lechner
2024-09-17 16:01     ` Uwe Kleine-König
2024-09-06 15:42 ` [PATCH v4 2/7] pwm: New abstraction for PWM waveforms Uwe Kleine-König
2024-09-06 17:50   ` Trevor Gamblin
2024-09-06 20:33   ` David Lechner
2024-09-06 15:42 ` [PATCH v4 3/7] pwm: Provide new consumer API functions for waveforms Uwe Kleine-König
2024-09-06 21:22   ` David Lechner [this message]
2024-09-08 12:01     ` Uwe Kleine-König
2024-09-06 15:43 ` [PATCH v4 4/7] pwm: Add support for pwmchip devices for faster and easier userspace access Uwe Kleine-König
2024-09-06 22:26   ` David Lechner
2024-09-08 14:59     ` Uwe Kleine-König
2024-09-09 20:53       ` David Lechner
2024-09-17 17:10         ` Uwe Kleine-König
2024-09-18  9:21           ` Uwe Kleine-König
2024-09-07  1:58   ` Kent Gibson
2024-09-06 15:43 ` [PATCH v4 5/7] pwm: Add tracing for waveform callbacks Uwe Kleine-König
2024-09-06 15:43 ` [PATCH v4 6/7] pwm: axi-pwmgen: Implementation of the " Uwe Kleine-König
2024-09-06 17:44   ` Trevor Gamblin
2024-09-06 15:43 ` [PATCH v4 7/7] pwm: stm32: " Uwe Kleine-König
2024-09-06 18:08 ` [PATCH v4 0/7] pwm: New abstraction and userspace API Trevor Gamblin
2024-09-06 19:06 ` David Lechner
2024-09-08 11:32   ` Uwe Kleine-König

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=e1dfca79-a267-4c91-b504-b3f222dacc24@baylibre.com \
    --to=dlechner@baylibre.com \
    --cc=linux-pwm@vger.kernel.org \
    --cc=u.kleine-koenig@baylibre.com \
    --cc=warthog618@gmail.com \
    /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