All of lore.kernel.org
 help / color / mirror / Atom feed
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
To: Neil Armstrong <narmstrong@baylibre.com>
Cc: linux-amlogic@lists.infradead.org, linux-pwm@vger.kernel.org,
	thierry.reding@gmail.com, u.kleine-koenig@pengutronix.de,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH 13/14] pwm: meson: add support PWM_POLARITY_INVERSED when disabling
Date: Mon, 27 May 2019 19:50:33 +0200	[thread overview]
Message-ID: <CAFBinCCPsnX+OqjHgVi+tshE3EdVWS0Bk9qK1V+cg6DALnT1qA@mail.gmail.com> (raw)
In-Reply-To: <4de7d436-32b7-e4ed-39b2-e85f75a17c16@baylibre.com>

Hi Neil,

On Mon, May 27, 2019 at 2:33 PM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> On 25/05/2019 20:11, Martin Blumenstingl wrote:
> > meson_pwm_apply() has to consider the PWM polarity when disabling the
> > output.
> > With enabled=false and polarity=PWM_POLARITY_NORMAL the output needs to
> > be LOW. The driver already supports this.
> > With enabled=false and polarity=PWM_POLARITY_INVERSED the output needs
> > to be HIGH. Implement this in the driver by internally enabling the
> > output with the same settings that we already use for "period == duty".
> >
> > This fixes a PWM API violation which expects that the driver honors the
> > polarity also for enabled=false. Due to the IP block not supporting this
> > natively we only get "an as close as possible" to 100% HIGH signal (in
> > my test setup with input clock of 24MHz and measuring the output with a
> > logic analyzer at 24MHz sampling rate I got a duty cycle of 99.998475%
> > on a Khadas VIM).
> >
> > Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> > ---
> >  drivers/pwm/pwm-meson.c | 23 ++++++++++++++++++++++-
> >  1 file changed, 22 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
> > index 900d362ec3c9..bb48ba85f756 100644
> > --- a/drivers/pwm/pwm-meson.c
> > +++ b/drivers/pwm/pwm-meson.c
> > @@ -245,6 +245,7 @@ static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm)
> >  static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> >                          struct pwm_state *state)
> >  {
> > +     struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
> >       struct meson_pwm *meson = to_meson_pwm(chip);
> >       int err = 0;
> >
> > @@ -252,7 +253,27 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> >               return -EINVAL;
> >
> >       if (!state->enabled) {
> > -             meson_pwm_disable(meson, pwm);
> > +             if (state->polarity == PWM_POLARITY_INVERSED) {
> > +                     /*
> > +                      * This IP block revision doesn't have an "always high"
> > +                      * setting which we can use for "inverted disabled".
> > +                      * Instead we achieve this using the same settings
> > +                      * that we use a pre_div of 0 (to get the shortest
> > +                      * possible duration for one "count") and
> > +                      * "period == duty_cycle". This results in a signal
> > +                      * which is LOW for one "count", while being HIGH for
> > +                      * the rest of the (so the signal is HIGH for slightly
> > +                      * less than 100% of the period, but this is the best
> > +                      * we can achieve).
> > +                      */
> > +                     channel->pre_div = 0;
> > +                     channel->hi = ~0;
> > +                     channel->lo = 0;
> > +
> > +                     meson_pwm_enable(meson, pwm);
> > +             } else {
> > +                     meson_pwm_disable(meson, pwm);
> > +             }
> >       } else {
> >               err = meson_pwm_calc(meson, pwm, state);
> >               if (err < 0)
> >
>
> While not perfect, it almost fills the gap.
> Another way would be to use a specific pinctrl state setting the pin
> in GPIO output in high level, but this implementation could stay
> if the pinctrl state isn't available.
I just noticed that Amlogic updated the PWM IP block in G12A:
it now supports "constant enable" (REG_MISC_AB bits 28 and 29) as well
as PWM_POLARITY_INVERSED (REG_MISC_AB bits 26 and 27) natively!

I like your idea of having a specific pinctrl state.
we can implement that for anything older than G12A once we actually need it.
for G12A we can do better thanks to the updated IP block


Martin

WARNING: multiple messages have this Message-ID (diff)
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
To: Neil Armstrong <narmstrong@baylibre.com>
Cc: linux-pwm@vger.kernel.org, linux-kernel@vger.kernel.org,
	thierry.reding@gmail.com, u.kleine-koenig@pengutronix.de,
	linux-amlogic@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH 13/14] pwm: meson: add support PWM_POLARITY_INVERSED when disabling
Date: Mon, 27 May 2019 19:50:33 +0200	[thread overview]
Message-ID: <CAFBinCCPsnX+OqjHgVi+tshE3EdVWS0Bk9qK1V+cg6DALnT1qA@mail.gmail.com> (raw)
In-Reply-To: <4de7d436-32b7-e4ed-39b2-e85f75a17c16@baylibre.com>

Hi Neil,

On Mon, May 27, 2019 at 2:33 PM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> On 25/05/2019 20:11, Martin Blumenstingl wrote:
> > meson_pwm_apply() has to consider the PWM polarity when disabling the
> > output.
> > With enabled=false and polarity=PWM_POLARITY_NORMAL the output needs to
> > be LOW. The driver already supports this.
> > With enabled=false and polarity=PWM_POLARITY_INVERSED the output needs
> > to be HIGH. Implement this in the driver by internally enabling the
> > output with the same settings that we already use for "period == duty".
> >
> > This fixes a PWM API violation which expects that the driver honors the
> > polarity also for enabled=false. Due to the IP block not supporting this
> > natively we only get "an as close as possible" to 100% HIGH signal (in
> > my test setup with input clock of 24MHz and measuring the output with a
> > logic analyzer at 24MHz sampling rate I got a duty cycle of 99.998475%
> > on a Khadas VIM).
> >
> > Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> > ---
> >  drivers/pwm/pwm-meson.c | 23 ++++++++++++++++++++++-
> >  1 file changed, 22 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
> > index 900d362ec3c9..bb48ba85f756 100644
> > --- a/drivers/pwm/pwm-meson.c
> > +++ b/drivers/pwm/pwm-meson.c
> > @@ -245,6 +245,7 @@ static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm)
> >  static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> >                          struct pwm_state *state)
> >  {
> > +     struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
> >       struct meson_pwm *meson = to_meson_pwm(chip);
> >       int err = 0;
> >
> > @@ -252,7 +253,27 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> >               return -EINVAL;
> >
> >       if (!state->enabled) {
> > -             meson_pwm_disable(meson, pwm);
> > +             if (state->polarity == PWM_POLARITY_INVERSED) {
> > +                     /*
> > +                      * This IP block revision doesn't have an "always high"
> > +                      * setting which we can use for "inverted disabled".
> > +                      * Instead we achieve this using the same settings
> > +                      * that we use a pre_div of 0 (to get the shortest
> > +                      * possible duration for one "count") and
> > +                      * "period == duty_cycle". This results in a signal
> > +                      * which is LOW for one "count", while being HIGH for
> > +                      * the rest of the (so the signal is HIGH for slightly
> > +                      * less than 100% of the period, but this is the best
> > +                      * we can achieve).
> > +                      */
> > +                     channel->pre_div = 0;
> > +                     channel->hi = ~0;
> > +                     channel->lo = 0;
> > +
> > +                     meson_pwm_enable(meson, pwm);
> > +             } else {
> > +                     meson_pwm_disable(meson, pwm);
> > +             }
> >       } else {
> >               err = meson_pwm_calc(meson, pwm, state);
> >               if (err < 0)
> >
>
> While not perfect, it almost fills the gap.
> Another way would be to use a specific pinctrl state setting the pin
> in GPIO output in high level, but this implementation could stay
> if the pinctrl state isn't available.
I just noticed that Amlogic updated the PWM IP block in G12A:
it now supports "constant enable" (REG_MISC_AB bits 28 and 29) as well
as PWM_POLARITY_INVERSED (REG_MISC_AB bits 26 and 27) natively!

I like your idea of having a specific pinctrl state.
we can implement that for anything older than G12A once we actually need it.
for G12A we can do better thanks to the updated IP block


Martin

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
To: Neil Armstrong <narmstrong@baylibre.com>
Cc: linux-pwm@vger.kernel.org, linux-kernel@vger.kernel.org,
	thierry.reding@gmail.com, u.kleine-koenig@pengutronix.de,
	linux-amlogic@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH 13/14] pwm: meson: add support PWM_POLARITY_INVERSED when disabling
Date: Mon, 27 May 2019 19:50:33 +0200	[thread overview]
Message-ID: <CAFBinCCPsnX+OqjHgVi+tshE3EdVWS0Bk9qK1V+cg6DALnT1qA@mail.gmail.com> (raw)
In-Reply-To: <4de7d436-32b7-e4ed-39b2-e85f75a17c16@baylibre.com>

Hi Neil,

On Mon, May 27, 2019 at 2:33 PM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> On 25/05/2019 20:11, Martin Blumenstingl wrote:
> > meson_pwm_apply() has to consider the PWM polarity when disabling the
> > output.
> > With enabled=false and polarity=PWM_POLARITY_NORMAL the output needs to
> > be LOW. The driver already supports this.
> > With enabled=false and polarity=PWM_POLARITY_INVERSED the output needs
> > to be HIGH. Implement this in the driver by internally enabling the
> > output with the same settings that we already use for "period == duty".
> >
> > This fixes a PWM API violation which expects that the driver honors the
> > polarity also for enabled=false. Due to the IP block not supporting this
> > natively we only get "an as close as possible" to 100% HIGH signal (in
> > my test setup with input clock of 24MHz and measuring the output with a
> > logic analyzer at 24MHz sampling rate I got a duty cycle of 99.998475%
> > on a Khadas VIM).
> >
> > Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> > ---
> >  drivers/pwm/pwm-meson.c | 23 ++++++++++++++++++++++-
> >  1 file changed, 22 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
> > index 900d362ec3c9..bb48ba85f756 100644
> > --- a/drivers/pwm/pwm-meson.c
> > +++ b/drivers/pwm/pwm-meson.c
> > @@ -245,6 +245,7 @@ static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm)
> >  static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> >                          struct pwm_state *state)
> >  {
> > +     struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
> >       struct meson_pwm *meson = to_meson_pwm(chip);
> >       int err = 0;
> >
> > @@ -252,7 +253,27 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> >               return -EINVAL;
> >
> >       if (!state->enabled) {
> > -             meson_pwm_disable(meson, pwm);
> > +             if (state->polarity == PWM_POLARITY_INVERSED) {
> > +                     /*
> > +                      * This IP block revision doesn't have an "always high"
> > +                      * setting which we can use for "inverted disabled".
> > +                      * Instead we achieve this using the same settings
> > +                      * that we use a pre_div of 0 (to get the shortest
> > +                      * possible duration for one "count") and
> > +                      * "period == duty_cycle". This results in a signal
> > +                      * which is LOW for one "count", while being HIGH for
> > +                      * the rest of the (so the signal is HIGH for slightly
> > +                      * less than 100% of the period, but this is the best
> > +                      * we can achieve).
> > +                      */
> > +                     channel->pre_div = 0;
> > +                     channel->hi = ~0;
> > +                     channel->lo = 0;
> > +
> > +                     meson_pwm_enable(meson, pwm);
> > +             } else {
> > +                     meson_pwm_disable(meson, pwm);
> > +             }
> >       } else {
> >               err = meson_pwm_calc(meson, pwm, state);
> >               if (err < 0)
> >
>
> While not perfect, it almost fills the gap.
> Another way would be to use a specific pinctrl state setting the pin
> in GPIO output in high level, but this implementation could stay
> if the pinctrl state isn't available.
I just noticed that Amlogic updated the PWM IP block in G12A:
it now supports "constant enable" (REG_MISC_AB bits 28 and 29) as well
as PWM_POLARITY_INVERSED (REG_MISC_AB bits 26 and 27) natively!

I like your idea of having a specific pinctrl state.
we can implement that for anything older than G12A once we actually need it.
for G12A we can do better thanks to the updated IP block


Martin

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

  reply	other threads:[~2019-05-27 17:50 UTC|newest]

Thread overview: 112+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-25 18:11 [PATCH 00/14] pwm-meson: cleanups and improvements Martin Blumenstingl
2019-05-25 18:11 ` Martin Blumenstingl
2019-05-25 18:11 ` Martin Blumenstingl
2019-05-25 18:11 ` [PATCH 01/14] pwm: meson: unify the parameter list of meson_pwm_{enable,disable} Martin Blumenstingl
2019-05-25 18:11   ` [PATCH 01/14] pwm: meson: unify the parameter list of meson_pwm_{enable, disable} Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:25   ` Neil Armstrong
2019-05-27 12:25     ` Neil Armstrong
2019-05-27 12:25     ` Neil Armstrong
2019-05-25 18:11 ` [PATCH 02/14] pwm: meson: use devm_clk_get_optional() to get the input clock Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:25   ` Neil Armstrong
2019-05-27 12:25     ` Neil Armstrong
2019-05-27 12:25     ` Neil Armstrong
2019-05-25 18:11 ` [PATCH 03/14] pwm: meson: use GENMASK and FIELD_PREP for the lo and hi values Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:25   ` Neil Armstrong
2019-05-27 12:25     ` Neil Armstrong
2019-05-27 12:25     ` Neil Armstrong
2019-05-25 18:11 ` [PATCH 04/14] pwm: meson: change MISC_CLK_SEL_WIDTH to MISC_CLK_SEL_MASK Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:26   ` Neil Armstrong
2019-05-27 12:26     ` Neil Armstrong
2019-05-27 12:26     ` Neil Armstrong
2019-05-27 17:46     ` Martin Blumenstingl
2019-05-27 17:46       ` Martin Blumenstingl
2019-05-27 17:46       ` Martin Blumenstingl
2019-05-27 18:00       ` Uwe Kleine-König
2019-05-27 18:00         ` Uwe Kleine-König
2019-05-27 18:00         ` Uwe Kleine-König
2019-05-28 18:04         ` Martin Blumenstingl
2019-05-28 18:04           ` Martin Blumenstingl
2019-05-28 18:04           ` Martin Blumenstingl
2019-05-25 18:11 ` [PATCH 05/14] pwm: meson: don't duplicate the polarity internally Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:26   ` Neil Armstrong
2019-05-27 12:26     ` Neil Armstrong
2019-05-27 12:26     ` Neil Armstrong
2019-05-25 18:11 ` [PATCH 06/14] pwm: meson: pass struct pwm_device to meson_pwm_calc() Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:27   ` Neil Armstrong
2019-05-27 12:27     ` Neil Armstrong
2019-05-27 12:27     ` Neil Armstrong
2019-05-25 18:11 ` [PATCH 07/14] pwm: meson: add the meson_pwm_channel data to struct meson_pwm Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:27   ` Neil Armstrong
2019-05-27 12:27     ` Neil Armstrong
2019-05-27 12:27     ` Neil Armstrong
2019-05-27 17:52   ` Martin Blumenstingl
2019-05-27 17:52     ` Martin Blumenstingl
2019-05-27 17:52     ` Martin Blumenstingl
2019-05-25 18:11 ` [PATCH 08/14] pwm: meson: add the per-channel register offsets and bits in a struct Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:28   ` Neil Armstrong
2019-05-27 12:28     ` Neil Armstrong
2019-05-27 12:28     ` Neil Armstrong
2019-05-27 17:57     ` Martin Blumenstingl
2019-05-27 17:57       ` Martin Blumenstingl
2019-05-27 17:57       ` Martin Blumenstingl
2019-05-28  8:11       ` Neil Armstrong
2019-05-28  8:11         ` Neil Armstrong
2019-05-28  8:11         ` Neil Armstrong
2019-05-25 18:11 ` [PATCH 09/14] pwm: meson: move pwm_set_chip_data() to meson_pwm_request() Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:30   ` Neil Armstrong
2019-05-27 12:30     ` Neil Armstrong
2019-05-27 12:30     ` Neil Armstrong
2019-05-25 18:11 ` [PATCH 10/14] pwm: meson: simplify the calculation of the pre-divider and count Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-26 19:41   ` Uwe Kleine-König
2019-05-26 19:41     ` Uwe Kleine-König
2019-05-26 19:41     ` Uwe Kleine-König
2019-05-26 19:41     ` Uwe Kleine-König
2019-05-27 12:37     ` Neil Armstrong
2019-05-27 12:37       ` Neil Armstrong
2019-05-27 12:37       ` Neil Armstrong
2019-05-25 18:11 ` [PATCH 11/14] pwm: meson: read the full hardware state in meson_pwm_get_state() Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:31   ` Neil Armstrong
2019-05-27 12:31     ` Neil Armstrong
2019-05-27 12:31     ` Neil Armstrong
2019-05-25 18:11 ` [PATCH 12/14] pwm: meson: don't cache struct pwm_state internally Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:31   ` Neil Armstrong
2019-05-27 12:31     ` Neil Armstrong
2019-05-27 12:31     ` Neil Armstrong
2019-05-25 18:11 ` [PATCH 13/14] pwm: meson: add support PWM_POLARITY_INVERSED when disabling Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:33   ` Neil Armstrong
2019-05-27 12:33     ` Neil Armstrong
2019-05-27 12:33     ` Neil Armstrong
2019-05-27 17:50     ` Martin Blumenstingl [this message]
2019-05-27 17:50       ` Martin Blumenstingl
2019-05-27 17:50       ` Martin Blumenstingl
2019-05-25 18:11 ` [PATCH 14/14] pwm: meson: add documentation to the driver Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-25 18:11   ` Martin Blumenstingl
2019-05-27 12:33   ` Neil Armstrong
2019-05-27 12:33     ` Neil Armstrong
2019-05-27 12:33     ` Neil Armstrong

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=CAFBinCCPsnX+OqjHgVi+tshE3EdVWS0Bk9qK1V+cg6DALnT1qA@mail.gmail.com \
    --to=martin.blumenstingl@googlemail.com \
    --cc=linux-amlogic@lists.infradead.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=narmstrong@baylibre.com \
    --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.