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
next prev parent 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 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).