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] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200927211044.GC2510@latitude>
Date:   Sun, 27 Sep 2020 23:10:44 +0200
From:   Jonathan Neuschäfer <j.neuschaefer@....net>
To:     Uwe Kleine-König <u.kleine-koenig@...gutronix.de>
Cc:     Jonathan Neuschäfer <j.neuschaefer@....net>,
        linux-kernel@...r.kernel.org,
        Alexandre Belloni <alexandre.belloni@...tlin.com>,
        Heiko Stuebner <heiko@...ech.de>, linux-pwm@...r.kernel.org,
        Linus Walleij <linus.walleij@...aro.org>,
        Thierry Reding <thierry.reding@...il.com>,
        Fabio Estevam <festevam@...il.com>, linux-rtc@...r.kernel.org,
        Arnd Bergmann <arnd@...db.de>,
        Mauro Carvalho Chehab <mchehab+huawei@...nel.org>,
        Sam Ravnborg <sam@...nborg.org>,
        Daniel Palmer <daniel@...f.com>,
        Andy Shevchenko <andy.shevchenko@...il.com>,
        Andreas Kemnade <andreas@...nade.info>,
        NXP Linux Team <linux-imx@....com>,
        devicetree@...r.kernel.org, Stephan Gerhold <stephan@...hold.net>,
        allen <allen.chen@....com.tw>,
        Sascha Hauer <s.hauer@...gutronix.de>,
        Lubomir Rintel <lkundrak@...sk>,
        Rob Herring <robh+dt@...nel.org>,
        Lee Jones <lee.jones@...aro.org>,
        linux-arm-kernel@...ts.infradead.org,
        Alessandro Zummo <a.zummo@...ertech.it>,
        Mark Brown <broonie@...nel.org>,
        Pengutronix Kernel Team <kernel@...gutronix.de>,
        Heiko Stuebner <heiko.stuebner@...obroma-systems.com>,
        Josua Mayer <josua.mayer@....eu>,
        Shawn Guo <shawnguo@...nel.org>,
        "David S. Miller" <davem@...emloft.net>
Subject: Re: [PATCH v3 4/7] pwm: ntxec: Add driver for PWM function in
 Netronix EC

On Fri, Sep 25, 2020 at 08:30:37AM +0200, Uwe Kleine-König wrote:
> Hello Jonathan,
[...]
> > +config PWM_NTXEC
> > +	tristate "Netronix embedded controller PWM support"
> > +	depends on MFD_NTXEC
> > +	help
> > +	  Say yes here if you want to support the PWM output of the embedded
> > +	  controller found in certain e-book readers designed by the ODM
> > +	  Netronix.
> 
> Is it only me who had to look up what ODM means? If not, maybe spell it
> out?

I'm sure other readers will have the same problem. I'll spell it out.

> > +/*
> > + * The maximum input value (in nanoseconds) is determined by the time base and
> > + * the range of the hardware registers that hold the converted value.
> > + * It fits into 32 bits, so we can do our calculations in 32 bits as well.
> > + */
> > +#define MAX_PERIOD_NS (TIME_BASE_NS * 0x10000 - 1)
> 
> The maximal configurable period length is 0xffff, so I would have
> expected MAX_PERIOD_NS to be 0xffff * TIME_BASE_NS?

Due to the division rounding down, TIME_BASE_NS * 0x10000 - 1 would be
the highest input that results in a representable value after the
division, but I'm not sure it otherwise makes sense.

> 
> > +static int ntxec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm_dev,
> > +			   const struct pwm_state *state)
> > +{
> > +	struct ntxec_pwm *pwm = pwmchip_to_pwm(pwm_dev->chip);
> > +	unsigned int duty = state->duty_cycle;
> > +	unsigned int period = state->period;
> > +	int res = 0;
> > +
> 
> I assume your device only supports normal polarity? If so, please check
> for it here and point out this limitation in the header (in the format
> that is for example used in pwm-sifive.c to make it easy to grep for
> that).

I haven't seen any indication that it supports inverted polarity. I'll
point it out in the header comment, and add a check.

> 
> > +	if (period > MAX_PERIOD_NS) {
> > +		dev_warn(pwm->dev,
> > +			 "Period is not representable in 16 bits after division by %u: %u\n",
> > +			 TIME_BASE_NS, period);
> 
> No error messages in .apply() please; this might spam the kernel log.
>
> Also the expectation when a too big period is requested is to configure
> for the biggest possible period. So just do:
> 
> 	if (period > MAX_PERIOD_NS) {
> 		period = MAX_PERIOD_NS;
> 
> 		if (duty > period)
> 			duty = period;
> 	}
> 
> (or something equivalent).

Okay, I'll adjust it.

> > +	/*
> > +	 * Writing a duty cycle of zone puts the device into a state where
> 
> What is "zone"? A mixture of zero and one and so approximately 0.5?

Oops, that's a typo. I just meant "zero".

> > +	 * writing a higher duty cycle doesn't result in the brightness that it
> > +	 * usually results in. This can be fixed by cycling the ENABLE register.
> > +	 *
> > +	 * As a workaround, write ENABLE=0 when the duty cycle is zero.
> > +	 */
> > +	if (state->enabled && duty != 0) {
> > +		res = regmap_write(pwm->ec->regmap, NTXEC_REG_ENABLE, ntxec_reg8(1));
> > +		if (res)
> > +			return res;
> > +
> > +		/* Disable the auto-off timer */
> > +		res = regmap_write(pwm->ec->regmap, NTXEC_REG_AUTO_OFF_HI, ntxec_reg8(0xff));
> > +		if (res)
> > +			return res;
> > +
> > +		return regmap_write(pwm->ec->regmap, NTXEC_REG_AUTO_OFF_LO, ntxec_reg8(0xff));
> > +	} else {
> > +		return regmap_write(pwm->ec->regmap, NTXEC_REG_ENABLE, ntxec_reg8(0));
> > +	}
> 
> This code is wrong for state->enabled = false.

Why?

> How does the PWM behave when .apply is called? Does it complete the
> currently running period? Can it happen that when you switch from say
> 
> 	.duty_cycle = 900 * TIME_BASE_NS (0x384)
> 	.period = 1800 * TIME_BASE_NS (0x708)
> 
> to
> 
> 	.duty_cycle = 300 * TIME_BASE_NS (0x12c)
> 	.period = 600 * TIME_BASE_NS (0x258)
> 
> that a period with
> 
> 	.duty_cycle = 388 * TIME_BASE_NS (0x184)
> 	.period = 1800 * TIME_BASE_NS (0x708)
> 	
> (because only NTXEC_REG_PERIOD_HIGH was written when the new period
> started) or something similar is emitted?

Changes take effect after the low byte is written, so a result like 0x184
in the above example should not happen.

When the period and duty cycle are both changed, it temporarily results
in an inconsistent state:

 - period = 1800ns, duty cycle = 900ns
 - period =  600ns, duty cycle = 900ns (!)
 - period =  600ns, duty cycle = 300ns

The inconsistent state of duty cycle > period is handled gracefully by
the EC and it outputs a 100% duty cycle, as far as I can tell.

I currently don't have a logic analyzer / oscilloscope to measure
whether we get full PWM periods, or some kind of glitch when the new
period starts in the middle of the last one.

> > +}
> > +
> > +static struct pwm_ops ntxec_pwm_ops = {
> > +	.apply = ntxec_pwm_apply,
> 
> Please implement a .get_state() callback. And enable PWM_DEBUG during
> your tests.

The device doesn't support reading back the PWM state. What should a
driver do in this case?

> > +	.owner = THIS_MODULE,
> > +};
> > +
> > +static int ntxec_pwm_probe(struct platform_device *pdev)
> > +{
> > +	struct ntxec *ec = dev_get_drvdata(pdev->dev.parent);
> > +	struct ntxec_pwm *pwm;
> 
> Please don't call this variable pwm. I would expect that a variable with
> this name is of type pwm_device. I would have called it "ddata" (and the
> type would be named ntxec_pwm_ddata for me); another usual name is "priv".

Ok, I'll rename it.

> > +	chip->npwm = 1;
> > +
> > +	res = pwmchip_add(chip);
> > +	if (res < 0)
> > +		return res;
> > +
> > +	platform_set_drvdata(pdev, pwm);
> 
> If you do the platform_set_drvdata earlier you can just do
> 
> 	return pwmchip_add(chip);

Good idea, I'll do that.


Thanks,
Jonathan Neuschäfer

Download attachment "signature.asc" of type "application/pgp-signature" (834 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ