mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
To: Anson Huang <anson.huang@nxp.com>
Cc: "mark.rutland@arm.com" <mark.rutland@arm.com>,
	"linux-pwm@vger.kernel.org" <linux-pwm@vger.kernel.org>,
	Robin Gong <yibin.gong@nxp.com>,
	"schnitzeltony@gmail.com" <schnitzeltony@gmail.com>,
	"otavio@ossystems.com.br" <otavio@ossystems.com.br>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	"festevam@gmail.com" <festevam@gmail.com>,
	"s.hauer@pengutronix.de" <s.hauer@pengutronix.de>,
	"linux@armlinux.org.uk" <linux@armlinux.org.uk>,
	"robh+dt@kernel.org" <robh+dt@kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"thierry.reding@gmail.com" <thierry.reding@gmail.com>,
	"stefan@agner.ch" <stefan@agner.ch>,
	"kernel@pengutronix.de" <kernel@pengutronix.de>,
	Leonard Crestez <leonard.crestez@nxp.com>,
	"shawnguo@kernel.org" <shawnguo@kernel.org>,
	"linux-arm-kernel@lists.infradead.org" 
	<linux-arm-kernel@lists.infradead.org>,
	dl-linux-imx <linux-imx@nxp.com>
Subject: Re: [EXT] Re: [PATCH V10 2/5] pwm: Add i.MX TPM PWM driver support
Date: Tue, 9 Apr 2019 11:28:59 +0200	[thread overview]
Message-ID: <20190409092859.qj4rgpljokdsokes@pengutronix.de> (raw)
In-Reply-To: <DB3PR0402MB391632F693646A5D600B74F9F52D0@DB3PR0402MB3916.eurprd04.prod.outlook.com>

Hello,

On Tue, Apr 09, 2019 at 08:51:48AM +0000, Anson Huang wrote:
> > On Tue, Mar 26, 2019 at 06:52:33AM +0000, Anson Huang wrote:
> > > +     /* get polarity */
> > > +     if (chan) {
> > > +             state->polarity = chan->polarity;
> > > +     } else {
> > > +             /* in case no channel requested yet, return HW status */
> > > +             val = readl(tpm->base + PWM_IMX_TPM_CnSC(pwm->hwpwm));
> > > +             if (FIELD_GET(PWM_IMX_TPM_CnSC_ELS, val) ==
> > > +                 PWM_IMX_TPM_CnSC_ELS_POLARITY_INVERSED)
> > > +                     state->polarity = PWM_POLARITY_INVERSED;
> > > +             else
> > > +                     /*
> > > +                      * Assume reserved values (2b00 and 2b11) to yield
> > > +                      * normal polarity.
> > > +                      */
> > > +                     state->polarity = PWM_POLARITY_NORMAL;
> > > +     }
> > 
> > What is the good reason to prefer chan->polarity over reading out the
> > hardware state?
> 
> Reading it from DDR is faster than accessing HW register as per
> previous comment?

How much time do you save here? Is it worth to complicate the function
for that?

> > > +     /* get channel status */
> > > +     state->enabled = FIELD_GET(PWM_IMX_TPM_CnSC_ELS, val) ? true :
> > > +false; }
> > > +
> > > +/* this function is supposed to be called with mutex hold */ static
> > > +int pwm_imx_tpm_apply_hw(struct pwm_chip *chip,
> > > +                             struct pwm_device *pwm,
> > > +                             struct pwm_state *state,
> > > +                             struct imx_tpm_pwm_param *p) {
> > > +     struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip);
> > > +     struct imx_tpm_pwm_channel *chan = pwm_get_chip_data(pwm);
> > > +     bool period_update = false;
> > > +     bool duty_update = false;
> > > +     u32 val, cmod, cur_prescale;
> > > +     unsigned long timeout;
> > > +     struct pwm_state c;
> > > +
> > > +     if (state->period != tpm->real_period) {
> > > +             /*
> > > +              * TPM counter is shared by multiple channels, so
> > > +              * prescale and period can NOT be modified when
> > > +              * there are multiple channels in use with different
> > > +              * period settings.
> > > +              */
> > > +             if (tpm->user_count > 1)
> > > +                     return -EBUSY;
> > > +
> > > +             val = readl(tpm->base + PWM_IMX_TPM_SC);
> > > +             cmod = FIELD_GET(PWM_IMX_TPM_SC_CMOD, val);
> > > +             cur_prescale = FIELD_GET(PWM_IMX_TPM_SC_PS, val);
> > > +             if (cmod && cur_prescale != p->prescale)
> > > +                     return -EBUSY;
> > > +
> > > +             /* set TPM counter prescale */
> > > +             val &= ~PWM_IMX_TPM_SC_PS;
> > > +             val |= FIELD_PREP(PWM_IMX_TPM_SC_PS, p->prescale);
> > > +             writel(val, tpm->base + PWM_IMX_TPM_SC);
> > > +
> > > +             /*
> > > +              * set period count:
> > > +              * if the PWM is disabled (CMOD[1:0] = 2b00), then MOD register
> > > +              * is updated when MOD register is written.
> > > +              *
> > > +              * if the PWM is enabled (CMOD[1:0] ≠ 2b00), the period length
> > > +              * is latched into hardware when the next period starts.
> > > +              */
> > > +             writel(p->mod, tpm->base + PWM_IMX_TPM_MOD);
> > > +             tpm->real_period = state->period;
> > > +             period_update = true;
> > > +     }
> > > +
> > > +     pwm_imx_tpm_get_state(chip, pwm, &c);
> > 
> > If you move this call above the previous if block you can use c.period instead
> > of tpm->real_period which is easier to follow.
> 
> I think the period could be changed by the if block, so duty also be changed, need
> to put the .get_state here, am I right?

As you don't use c.period below this shouldn't matter. Where does duty
change?

> > > +     if (state->duty_cycle != c.duty_cycle) {
> > > +             /*
> > > +              * set channel value:
> > > +              * if the PWM is disabled (CMOD[1:0] = 2b00), then CnV register
> > > +              * is updated when CnV register is written.
> > > +              *
> > > +              * if the PWM is enabled (CMOD[1:0] ≠ 2b00), the duty length
> > > +              * is latched into hardware when the next period starts.
> > > +              */
> > > +             writel(p->val, tpm->base + PWM_IMX_TPM_CnV(pwm->hwpwm));
> > > +             duty_update = true;
> > > +     }
> > > +
> > > +     /* make sure MOD & CnV registers are updated */
> > > +     if (period_update || duty_update) {
> > > +             timeout = jiffies + msecs_to_jiffies(tpm->real_period /
> > > +                                                  NSEC_PER_MSEC + 1);
> > > +             while (readl(tpm->base + PWM_IMX_TPM_MOD) != p->mod
> > > +                    || readl(tpm->base + PWM_IMX_TPM_CnV(pwm->hwpwm))
> > > +                    != p->val) {
> > > +                     if (time_after(jiffies, timeout))
> > > +                             return -ETIME;
> > > +                     cpu_relax();
> > > +             }
> > > +     }
> > 
> > If the PWM is running you wait in the above loop until the new values are
> > active but before you configure the period. I think in the case where the
> > PWM is active and a change of polarity is requested it would be more correct
> > to refuse the change.
> 
> Not very understand, the period is changed at the beginning, and most of the time,
> period should be fixed, changing polarity should be allowed even PWM is active?

Changing polarity should be atomic (that is, get active with the next
period's start). As the hardware doesn't support that, claiming it does
is a bad idea.

> That does NOT introduce too many trouble, is it a common case that dynamic changing
> polarity is NOT good? 
> 
> 
> > 
> > > +     val = readl(tpm->base + PWM_IMX_TPM_CnSC(pwm->hwpwm));
> > > +     val &= ~(PWM_IMX_TPM_CnSC_ELS | PWM_IMX_TPM_CnSC_MSA |
> > > +              PWM_IMX_TPM_CnSC_MSB);
> > > +     if (state->enabled) {
> > > +             /*
> > > +              * set polarity (for edge-aligned PWM modes)
> > > +              *
> > > +              * ELS[1:0] = 2b10 yields normal polarity behaviour,
> > > +              * ELS[1:0] = 2b01 yields inversed polarity.
> > > +              * The other values are reserved.
> > > +              *
> > > +              * polarity settings will enabled/disable output status
> > > +              * immediately, so if the channel is disabled, need to
> > > +              * make sure MSA/MSB/ELS are set to 0 which means channel
> > > +              * disabled.
> > 
> > I don't understand this comment. Either ELS = 0 is reserved or it can be used.
> > What is an output status?
> 
> The reference manual ONLY states it as reserved, so how to add comments here?

The problem might just be, that I don't get what you intend to say in
the last paragraph.

Best regards
Uwe

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

  reply	other threads:[~2019-04-09  9:29 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-26  6:52 [PATCH V10 0/5] Add i.MX7ULP EVK PWM backlight support Anson Huang
2019-03-26  6:52 ` [PATCH V10 1/5] dt-bindings: pwm: Add i.MX TPM PWM binding Anson Huang
2019-03-28 16:51   ` Rob Herring
2019-03-26  6:52 ` [PATCH V10 2/5] pwm: Add i.MX TPM PWM driver support Anson Huang
2019-03-28 19:36   ` Uwe Kleine-König
2019-04-09  6:47   ` Uwe Kleine-König
2019-04-09  8:51     ` [EXT] " Anson Huang
2019-04-09  9:28       ` Uwe Kleine-König [this message]
2019-04-09 12:04         ` Anson Huang
2019-04-09 12:10           ` Anson Huang
2019-03-26  6:52 ` [PATCH V10 3/5] ARM: imx_v6_v7_defconfig: Add TPM PWM support by default Anson Huang
2019-03-26  6:52 ` [PATCH V10 4/5] ARM: dts: imx7ulp: Add tpm pwm support Anson Huang
2019-03-26  6:53 ` [PATCH V10 5/5] ARM: dts: imx7ulp-evk: Add backlight support Anson Huang

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=20190409092859.qj4rgpljokdsokes@pengutronix.de \
    --to=u.kleine-koenig@pengutronix.de \
    --cc=anson.huang@nxp.com \
    --cc=devicetree@vger.kernel.org \
    --cc=festevam@gmail.com \
    --cc=kernel@pengutronix.de \
    --cc=leonard.crestez@nxp.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-imx@nxp.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=mark.rutland@arm.com \
    --cc=otavio@ossystems.com.br \
    --cc=robh+dt@kernel.org \
    --cc=s.hauer@pengutronix.de \
    --cc=schnitzeltony@gmail.com \
    --cc=shawnguo@kernel.org \
    --cc=stefan@agner.ch \
    --cc=thierry.reding@gmail.com \
    --cc=yibin.gong@nxp.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

all inboxes | Powered by JetHome®