All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff LaBundy <jeff@labundy.com>
To: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
Cc: lee.jones@linaro.org, dmitry.torokhov@gmail.com,
	jdelvare@suse.com, linux@roeck-us.net, thierry.reding@gmail.com,
	jic23@kernel.org, devicetree@vger.kernel.org,
	linux-input@vger.kernel.org, linux-hwmon@vger.kernel.org,
	linux-pwm@vger.kernel.org, knaack.h@gmx.de, lars@metafoo.de,
	pmeerw@pmeerw.net, linux-iio@vger.kernel.org, robh+dt@kernel.org,
	mark.rutland@arm.com
Subject: Re: [PATCH 5/8] pwm: Add support for Azoteq IQS620A PWM generator
Date: Wed, 23 Oct 2019 22:02:16 -0500	[thread overview]
Message-ID: <20191024030216.GB3321@labundy.com> (raw)
In-Reply-To: <20191023072304.7qmw4skssfm7iykm@pengutronix.de>

Hi Uwe,

On Wed, Oct 23, 2019 at 09:23:04AM +0200, Uwe Kleine-König wrote:
> Hello Jeff,
> 
> On Tue, Oct 22, 2019 at 09:45:25PM -0500, Jeff LaBundy wrote:
> > On Tue, Oct 22, 2019 at 08:54:15AM +0200, Uwe Kleine-König wrote:
> > > On Mon, Oct 21, 2019 at 11:36:49PM -0500, Jeff LaBundy wrote:
> > > > On Mon, Oct 21, 2019 at 09:34:19AM +0200, Uwe Kleine-König wrote:
> > > > > > +{
> > > > > > +	struct iqs620_pwm_private *iqs620_pwm;
> > > > > > +	struct iqs62x_core *iqs62x;
> > > > > > +	int error;
> > > > > > +	int duty_calc = state->duty_cycle * 256 / IQS620_PWM_PERIOD_NS - 1;
> > > > > > +	u8 duty_clamp = clamp(duty_calc, 0, 0xFF);
> > > 
> > > Another problem that we have here is that the period is fixed to 1 ms
> > > and if a consumer requests for example:
> > > 
> > > 	.period = 5000000,
> > > 	.duty_cycle = 1000000,
> > > 
> > > the hardware is actually configured for
> > > 
> > > 	.period = 1000000,
> > > 	.duty_cycle = 1000000,
> > > 
> > > . I don't have a good suggestion how to fix this. We'd need to
> > > draw a line somewhere and decline a request that is too far from the
> > > result. But where this line should be is not obvious, it should
> > > definitively not be implemented in the driver itself IMHO.
> > > 
> > > (The only halfway sane approach would be to let lowlevel drivers
> > > implement a .round_state callback and then let the framework judge. But
> > > we're a long way from having that, so that's not a solution for today.)
> > > 
> > 
> > Agreed on all counts. For now, I will mention in the 'Limitations' heading that
> > the period cannot be adjusted.
> 
> Ack. My longterm plan is to require .apply_state() to round down both
> .period and .duty_cycle. This isn't wrong already today, so I suggest
> you decline a request to set the period to something smaller than 1 ms
> with an error code. (I think most drivers use -EINVAL here, conceptually
> -EDOM might be sensible. I'd stick to EINVAL for now.)
> 

Sure thing; will do.

> > > > > > +	iqs620_pwm = container_of(chip, struct iqs620_pwm_private, chip);
> > > > > > +	iqs62x = iqs620_pwm->iqs62x;
> > > > > > +
> > > > > > +	error = regmap_write(iqs62x->map, IQS620_PWM_DUTY_CYCLE, duty_clamp);
> > > > > > +	if (error)
> > > > > > +		return error;
> > > > > > +
> > > > > > +	state->period = IQS620_PWM_PERIOD_NS;
> > > > > > +	state->duty_cycle = (duty_clamp + 1) * IQS620_PWM_PERIOD_NS / 256;
> > > > > 
> > > > > This suggests that if the value in the IQS620_PWM_DUTY_CYCLE is 0 the
> > > > > duty cycle is 1/256 ms with a period of 1 ms and the output cannot be
> > > > > constant inactive. If this is right please add a paragraph in the
> > > > > driver's comment at the top:
> > > > > 
> > > > > 	* Limitations:
> > > > > 	* - The hardware cannot generate a 0% duty cycle
> > > > > 
> > > > > (Please stick to this format, other drivers use it, too.)
> > > > 
> > > > That's correct; the lowest duty cycle that can be achieved using only the
> > > > IQS620_PWM_DUTY_CYCLE register is 0.4%. We can, however, generate 0% duty
> > > > cycle by disabling the output altogether using a separate register. Would
> > > > that be better than flat-out saying it's impossible?
> > > 
> > > There is (maybe) a small difference between disabled and 0% duty cycle,
> > > at least from the framework's POV: If you do:
> > > 
> > > 	pwm_apply_state(pwm, { .enabled = true, .period = 1000000, .duty_cycle = 1000000, });
> > > 	pwm_apply_state(pwm, { .enabled = false, .period = $DC, .duty_cycle = $DC, });
> > > 	pwm_apply_state(pwm, { .enabled = true, .period = 1000000, .duty_cycle = 1000000, });
> > > 
> > > and compare it to the expected result of
> > > 
> > > 	pwm_apply_state(pwm, { .enabled = true, .period = 1000000, .duty_cycle = 1000000, });
> > > 	pwm_apply_state(pwm, { .enabled = true, .period = 1000000, .duty_cycle = 0, });
> > > 	pwm_apply_state(pwm, { .enabled = true, .period = 1000000, .duty_cycle = 1000000, });
> > > 
> > > the difference is that the duration of the inactive phase in the latter
> > > case is a multiple of 1 ms.
> > > 
> > > There is no policy for lowlevel drivers what to do, but disabling when
> > > 0% is requested is at least not unseen and probably more what consumers
> > > expect.
> > > 
> > 
> > With the change I am proposing, the output will be driven to zero if enabled = false
> > OR duty_cycle < 4000 ns. Stated another way:
> > 
> > enable duty_cycle IQS620_PWR_SETTINGS[7] IQS620_PWM_DUTY_CYCLE
> > ------ ---------- ---------------------- ---------------------
> >   0    don't care           0                  don't care
> >   1    0 ... 3999           0                  don't care
> >   1    4000 ... x           1                      0
> >   1    x+1  ... y           1                      1
> > 
> > ...and so on. For context, if IQS620_PWR_SETTINGS[7] = 0 then the output is held to
> > zero. If IQS620_PWR_SETTINGS[7] = 1 then the output toggles at a duty cycle between
> > 0.4% and 100% as a function of IQS620_PWM_DUTY_CYCLE.
> 
> Your table isn't accurate. IQS620_PWM_DUTY_CYCLE=0 results in a
> duty_cycle of 3906.25 ns so the table should look as follows:
> 
> enable  duty_cycle  IQS620_PWR_SETTINGS[7] IQS620_PWM_DUTY_CYCLE
> ------ ------------ ---------------------- ---------------------
>   0     don't care           0                  don't care
>   1       [0, 3906]          0                  don't care
>   1    [3907, 7812]          1                      0
>   1    [7813,11718]          1                      1
> 
> In general:
> 
> 	dc = state->duty_cycle * 256 / 1000000
> 	if state->enabled == false or dc == 0:
> 	    IQS620_PWR_SETTINGS[7] = 0
> 
> 	else:
> 	    IQS620_PWM_DUTY_CYCLE = min(dc - 1, 0xff)
> 	    IQS620_PWR_SETTINGS[7] = 1
> 

Sure thing; will do. Thank you for catching that!

> > Based on how the device behaves in response to its two available
> > registers, I think your two examples will appear equal, but please let
> > me know if I have understood.
> 
> Yeah, that's the expectation.
> 
> With the rounding as I suggested above this yields strange effects like
> if
> 
> 	.period = 1 s, .duty_cycle = 0.5 s
> 
> is requested you end up in
> 
> 	.period = 1 ms, .duty_cycle = 1 ms
> 
> but I think there is nothing we can reasonably do about this.
> 

Acknowledged on all counts. FWIW, I expect the most common consumer of this PWM
to be leds-pwm. That is to say, I think the limitations in this case are pretty
harmless. Users will typically pin the period to 1000000 ns like the example in
patch [1/8].

> Best regards
> Uwe
> 
> -- 
> Pengutronix e.K.                           | Uwe Kleine-König            |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> 

Kind regards,
Jeff LaBundy

  reply	other threads:[~2019-10-24  3:02 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-21  4:11 [PATCH 0/8] Add support for Azoteq IQS620A/621/622/624/625 Jeff LaBundy
2019-10-21  4:11 ` [PATCH 1/8] dt-bindings: mfd: iqs62x: Add bindings Jeff LaBundy
2019-10-22 11:00   ` Jonathan Cameron
2019-10-23  3:36     ` Jeff LaBundy
2019-10-23  9:30       ` Lee Jones
2019-10-24  2:38         ` Jeff LaBundy
2019-10-21  4:11 ` [PATCH 2/8] mfd: Add support for Azoteq IQS620A/621/622/624/625 Jeff LaBundy
2019-10-31 13:44   ` Lee Jones
2019-10-31 18:42     ` Dmitry Torokhov
2019-11-01  4:59     ` Jeff LaBundy
2019-11-01  8:56       ` Lee Jones
2019-11-02  2:49         ` Jeff LaBundy
2019-10-21  4:11 ` [PATCH 3/8] input: keyboard: " Jeff LaBundy
2019-10-23  0:22   ` Dmitry Torokhov
2019-10-23  1:29     ` Jeff LaBundy
2019-10-23 23:08       ` Dmitry Torokhov
2019-10-21  4:11 ` [PATCH 4/8] hwmon: Add support for Azoteq IQS620AT temperature sensor Jeff LaBundy
2019-10-21 15:38   ` Guenter Roeck
2019-10-22  2:26     ` Jeff LaBundy
2019-10-22  3:22       ` Guenter Roeck
2019-10-22 11:38         ` Jonathan Cameron
2019-10-23  2:04           ` Jeff LaBundy
2019-10-21  4:11 ` [PATCH 5/8] pwm: Add support for Azoteq IQS620A PWM generator Jeff LaBundy
2019-10-21  7:34   ` Uwe Kleine-König
2019-10-22  4:36     ` Jeff LaBundy
2019-10-22  6:54       ` Uwe Kleine-König
2019-10-23  2:45         ` Jeff LaBundy
2019-10-23  7:23           ` Uwe Kleine-König
2019-10-24  3:02             ` Jeff LaBundy [this message]
2019-10-21  4:11 ` [PATCH 6/8] iio: light: Add support for Azoteq IQS621 ambient light sensor Jeff LaBundy
2019-10-22 11:23   ` Jonathan Cameron
2019-10-23  2:59     ` Jeff LaBundy
2019-10-21  4:11 ` [PATCH 7/8] iio: proximity: Add support for Azoteq IQS622 proximity sensor Jeff LaBundy
2019-10-22 11:23   ` Jonathan Cameron
2019-10-23  3:09     ` Jeff LaBundy
2019-10-21  4:11 ` [PATCH 8/8] iio: position: Add support for Azoteq IQS624/625 angle sensor Jeff LaBundy
2019-10-22 11:28   ` Jonathan Cameron

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=20191024030216.GB3321@labundy.com \
    --to=jeff@labundy.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=jdelvare@suse.com \
    --cc=jic23@kernel.org \
    --cc=knaack.h@gmx.de \
    --cc=lars@metafoo.de \
    --cc=lee.jones@linaro.org \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=mark.rutland@arm.com \
    --cc=pmeerw@pmeerw.net \
    --cc=robh+dt@kernel.org \
    --cc=thierry.reding@gmail.com \
    --cc=u.kleine-koenig@pengutronix.de \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.