lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:   Wed, 20 Mar 2019 12:44:05 +0000
From:   Anson Huang <anson.huang@....com>
To:     Uwe Kleine-König 
        <u.kleine-koenig@...gutronix.de>
CC:     "thierry.reding@...il.com" <thierry.reding@...il.com>,
        "robh+dt@...nel.org" <robh+dt@...nel.org>,
        "mark.rutland@....com" <mark.rutland@....com>,
        "shawnguo@...nel.org" <shawnguo@...nel.org>,
        "s.hauer@...gutronix.de" <s.hauer@...gutronix.de>,
        "kernel@...gutronix.de" <kernel@...gutronix.de>,
        "festevam@...il.com" <festevam@...il.com>,
        "linux@...linux.org.uk" <linux@...linux.org.uk>,
        "otavio@...ystems.com.br" <otavio@...ystems.com.br>,
        "stefan@...er.ch" <stefan@...er.ch>,
        Leonard Crestez <leonard.crestez@....com>,
        "schnitzeltony@...il.com" <schnitzeltony@...il.com>,
        Robin Gong <yibin.gong@....com>,
        "linux-pwm@...r.kernel.org" <linux-pwm@...r.kernel.org>,
        "devicetree@...r.kernel.org" <devicetree@...r.kernel.org>,
        "linux-arm-kernel@...ts.infradead.org" 
        <linux-arm-kernel@...ts.infradead.org>,
        "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
        dl-linux-imx <linux-imx@....com>
Subject: RE: [PATCH V7 2/5] pwm: Add i.MX TPM PWM driver support

Hi, Uwe

Best Regards!
Anson Huang

> -----Original Message-----
> From: Anson Huang
> Sent: 2019年3月20日 19:21
> To: 'Uwe Kleine-König' <u.kleine-koenig@...gutronix.de>
> Cc: thierry.reding@...il.com; robh+dt@...nel.org; mark.rutland@....com;
> shawnguo@...nel.org; s.hauer@...gutronix.de; kernel@...gutronix.de;
> festevam@...il.com; linux@...linux.org.uk; otavio@...ystems.com.br;
> stefan@...er.ch; Leonard Crestez <leonard.crestez@....com>;
> schnitzeltony@...il.com; Robin Gong <yibin.gong@....com>; linux-
> pwm@...r.kernel.org; devicetree@...r.kernel.org; linux-arm-
> kernel@...ts.infradead.org; linux-kernel@...r.kernel.org; dl-linux-imx
> <linux-imx@....com>
> Subject: RE: [PATCH V7 2/5] pwm: Add i.MX TPM PWM driver support
> 
> Hi, Uwe
> 
> Best Regards!
> Anson Huang
> 
> > -----Original Message-----
> > From: Uwe Kleine-König [mailto:u.kleine-koenig@...gutronix.de]
> > Sent: 2019年3月20日 18:58
> > To: Anson Huang <anson.huang@....com>
> > Cc: thierry.reding@...il.com; robh+dt@...nel.org;
> > mark.rutland@....com; shawnguo@...nel.org; s.hauer@...gutronix.de;
> > kernel@...gutronix.de; festevam@...il.com; linux@...linux.org.uk;
> > otavio@...ystems.com.br; stefan@...er.ch; Leonard Crestez
> > <leonard.crestez@....com>; schnitzeltony@...il.com; Robin Gong
> > <yibin.gong@....com>; linux- pwm@...r.kernel.org;
> > devicetree@...r.kernel.org; linux-arm- kernel@...ts.infradead.org;
> > linux-kernel@...r.kernel.org; dl-linux-imx <linux-imx@....com>
> > Subject: Re: [PATCH V7 2/5] pwm: Add i.MX TPM PWM driver support
> >
> > Hello Anson,
> >
> > On Wed, Mar 20, 2019 at 10:17:50AM +0000, Anson Huang wrote:
> > > > On Wed, Mar 20, 2019 at 05:06:21AM +0000, Anson Huang wrote:
> > > > > +	/* make sure counter is disabled for programming prescale
> */
> > > > > +	val = readl(tpm->base + PWM_IMX_TPM_SC);
> > > > > +	saved_cmod = FIELD_GET(PWM_IMX_TPM_SC_CMOD, val);
> > > > > +	if (saved_cmod) {
> > > > > +		val &= ~PWM_IMX_TPM_SC_CMOD;
> > > > > +		writel(val, tpm->base + PWM_IMX_TPM_SC);
> > > >
> > > > I thought we agreed on not stopping the counter if the PS field
> > > > isn't
> > changed?
> > >
> > > If the PS field no need to change, the round state should already
> > > return the period equal to current period settings, so this function
> > > will NOT
> > be called, right?
> > >
> > >          if (real_state.period != tpm->real_period) {
> > >                  if (tpm->user_count > 1) {
> > >                          ret = -EBUSY;
> > >                          goto exit;
> > >                  }
> > >
> > > 	pwm_imx_tpm_setup_period(chip, param);
> > >                  tpm->real_period = real_state.period;
> > >         }
> >
> > If the PS field is already right .period might still not match as its
> > value depends on SC.PS and MOD.MOD.
> 
> Ah, my bad... I did NOT know what I was thinking...
> Yes, I will add the PS check to decide whether disabling counter..

I added below additional check for current PS and the new PS

         cur_prescale = FIELD_GET(PWM_IMX_TPM_SC_PS, val);
         if (saved_cmod && cur_prescale != p->prescale) {
                 val &= ~PWM_IMX_TPM_SC_CMOD;
                 writel(val, tpm->base + PWM_IMX_TPM_SC);
         }


> 
> 
> >
> > > > > +	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: according to RM, the MOD register is
> > > > > +	 * updated immediately after CMOD[1:0] = 2b'00 above
> > > > > +	 */
> > > >
> > > > So the current period isn't completed? That's wrong.
> > >
> > > So you mean we have to wait for the current period to finish here?
> > > I did NOT know this, so we have to compare the counter value with
> >
> > Yeah, see
> > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatc
> > h
> work.ozlabs.org%2Fpatch%2F1021566%2F&amp;data=02%7C01%7Canson.h
> >
> uang%40nxp.com%7C626a6f5603f74ae0d37e08d6ad22e774%7C686ea1d3bc
> >
> 2b4c6fa92cd99c5c301635%7C0%7C0%7C636886762757876916&amp;sdata=r
> >
> wu%2BUo3GlRX8j4lXSOVuAs7n1yEuP5P2W6vhY%2BjiXdQ%3D&amp;reserve
> > d=0 which documents this but waits for feedback by Thierry since some
> time.
> >
> > > the MOD value until they match then proceed the period change?
> >
> > If the hardware doesn't support you here (usually it does) I think
> > it's not reliable enough to try to sync in software. I assume you can
> > get the right wave form if you don't change SC.PS but only MOD.MOD? So
> > maybe the sanest approach is to refuse changing SC.PS if the PWM is
> running.
> >
> > Or disable (which also should wait for the current period to finish),
> > poll for the end (or use an irq?) and then setup the new configuration.
> 
> Let me try to poll the TOF (timer overflow) before setup the new
> configuration.
> And will also need to add timeout for the polling, what shoud the timeout
> value be, 100ms? As ideally the max period can be very large, several
> seconds or even large, so is the 100mS good here?

After further check, the reference manual has below statement, so I think we no
need to care about it, the hardware make sure of that, I added below comment
before programming the MOD register, if counter is disabled, the MOD register
will be updated immediately, if counter is enabled, the CPWM bit is fixed as 0 in
our driver, so the MOD register will be updated when counter changes from MOD
to zero.

         /*
          * set period count: according to RM, the MOD register is
          * updated immediately if CMOD[1:0] = 2b'00.
          * if CMOD[1:0] != 2b'00, then MOD register is updated
          * according to the CPWMS bit, that is:
          *
          * If the selected mode is not CPWM then MOD register is
          * updated after MOD register was written and the TPM
          * counter changes from MOD to zero.
          *
          * If the selected mode is CPWM then MOD register is updated
          * after MOD register was written and the TPM counter changes
          * from MOD to (MOD – 1).
          */



> 
> >
> > > > > +{
> > > > > +	struct imx_tpm_pwm_chip *tpm =
> to_imx_tpm_pwm_chip(chip);
> > > > > +	struct pwm_state c;
> > > > > +	u32 val, sc_val;
> > > > > +	u64 tmp;
> > > > > +
> > > > > +	pwm_imx_tpm_get_state(chip, pwm, &c);
> > > > > +
> > > > > +	if (state.duty_cycle != c.duty_cycle) {
> > > > > +		/* set duty counter */
> > > > > +		tmp = readl(tpm->base + PWM_IMX_TPM_MOD) &
> > PWM_IMX_TPM_MOD_MOD;
> > > > > +		tmp *= state.duty_cycle;
> > > > > +		val = DIV_ROUND_CLOSEST_ULL(tmp, state.period);
> > > > > +		writel(val, tpm->base + PWM_IMX_TPM_CnV(pwm-
> > >hwpwm));
> > > > > +	}
> > > > > +
> > > > > +	if (state.enabled != c.enabled) {
> > > >
> > > > This is wrong. If the PWM was running (c.enabled == true) and you
> > > > are supposed to disable (state.enabled == false) you enable the
> > > > hardware once more.
> > >
> > > A little confused here, as the case you assume, inside this block,
> > > there is another check for state.enabled, if it is false, the
> > > polarity will be set to channel disabled mode, the polarity setting
> > > is combined
> > together with the enable status here, am I wrong?
> >
> > Ah, you're right. I missed that probably because I saw register
> > accesses after the state.enabled != c.enabled check.
> >
> > > > > +			val |= (state.polarity ==
> PWM_POLARITY_NORMAL) ?
> > > > > +
> 	FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 0x2) :
> > > > > +
> 	FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 0x1);
> > > >
> > > > Introduce PWM_IMX_TPM_CnSC_ELS_POLARITY_NORMAL and use it
> > together
> > > > with PWM_IMX_TPM_CnSC_ELS_POLARITY_INVERSED here. If you put
> > the
> > > > FIELD_PREP into the definition the line doesn't get excessively long.
> > > >
> > >
> > > I put the FIELD_PREP into definition, the line still long, but I
> > > agree using
> > definition is better.
> > >
> > > #define PWM_IMX_TPM_CnSC_ELS_INVERSED
> > FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 1)
> > > #define PWM_IMX_TPM_CnSC_ELS_NORMAL
> > FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 2)
> > >
> > >                          val |= (state->polarity == PWM_POLARITY_NORMAL) ?
> > >                                  PWM_IMX_TPM_CnSC_ELS_NORMAL :
> > >                                  PWM_IMX_TPM_CnSC_ELS_INVERSED;
> > >
> > > > Maybe also add
> > > >
> > > > 	#define PWM_IMX_TPM_CnSC_ELS_INACTIVE
> > > > FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 0)
> > > >
> > >
> > > I did NOT use the FIELD_PREP(PWM_IMX_TPM_CnSC_ELS, 0) at all, so
> why
> > add it?
> > > I don't quite understand.
> >
> > You use it implicitly in pwm_imx_tpm_apply_hw() if state.enabled ==
> > false and c.enabled == true:

But the place I used is just to clear the PWM_IMX_TPM_CnSC_ELS field, so
just the MASK is enough for me, if you don't mind, I will leave it as what it is now.

Anson.

> >
> > 	val = readl(tpm->base + PWM_IMX_TPM_CnSC(pwm->hwpwm));
> > 	val &= ~(PWM_IMX_TPM_CnSC_ELS | ...);
> > 	...
> > 	writel(val, tpm->base + PWM_IMX_TPM_CnSC(pwm->hwpwm));
> 
> Ah, OK, I can replace the register field clear with the field prepare definition.
> 
> >
> > > > > +static int pwm_imx_tpm_apply(struct pwm_chip *chip,
> > > > > +			      struct pwm_device *pwm,
> > > > > +			     struct pwm_state *state) {
> > > > > +	struct imx_tpm_pwm_chip *tpm =
> to_imx_tpm_pwm_chip(chip);
> > > > > +	struct imx_tpm_pwm_param param;
> > > > > +	struct pwm_state real_state;
> > > > > +	int ret;
> > > > > +
> > > > > +	ret = pwm_imx_tpm_round_state(chip, &param, state,
> &real_state);
> > > > > +	if (ret)
> > > > > +		return -EINVAL;
> > > > > +
> > > > > +	mutex_lock(&tpm->lock);
> > > > > +
> > > > > +	/*
> > > > > +	 * 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 (real_state.period != tpm->real_period) {
> > > > > +		if (tpm->user_count > 1) {
> > > > > +			ret = -EBUSY;
> > > > > +			goto exit;
> > > > > +		}
> > > > > +
> > > > > +		pwm_imx_tpm_config_counter(chip, param);
> > > > > +		tpm->real_period = real_state.period;
> > > > > +	}
> > > >
> > > > Maybe add a comment that this could still be optimized. For
> > > > example if pwm_imx_tpm_round_state returned prescale = 5 but
> > > > prescale is currently 6, you might still be able to configure
> > >
> > > You meant for multiple users request different period case? In this
> > > block, if there is ONLY one user and the requested period can be met
> > > by HW, it will anyway re-configure the HW for the prescale and
> > > period I
> > think, or I did NOT get your point?
> >
> > My idea has a flaw. I thought that if there is another user, the
> > duty_cycle can still be represented if the actually used prescale
> > value is slightly higher. But then there is still a problem with the
> > period length that I missed. So my remark was wrong, sorry for that.
> 
> Thanks,
> Anson
> 
> >
> > Best regards
> > Uwe
> >
> > --
> > Pengutronix e.K.                           | Uwe Kleine-König            |
> > Industrial Linux Solutions                 |
> >
> https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.p
> >
> engutronix.de%2F&amp;data=02%7C01%7Canson.huang%40nxp.com%7C62
> >
> 6a6f5603f74ae0d37e08d6ad22e774%7C686ea1d3bc2b4c6fa92cd99c5c30163
> >
> 5%7C0%7C0%7C636886762757876916&amp;sdata=JsNRa8DuGYizE7FCyHVuY
> > QSUu4eUu5qTh6Edpf3Azm8%3D&amp;reserved=0  |

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ