[U-Boot] [PATCH] dm: serial: Add .pre_probe() function to to wait for previous transmission end

Lukasz Majewski lukma at denx.de
Thu Oct 26 22:51:03 UTC 2017


Hi Philipp,

> 
> > On 27 Oct 2017, at 00:13, Lukasz Majewski <lukma at denx.de> wrote:
> > 
> > It may happen that the serial IP block is performing some ongoing
> > transmission (started at e.g. board_init()) when the serial "probe"
> > is called.
> > 
> > As a result the serial port IP block is reset, so transmitted data
> > is corrupted:
> > 
> >    I2C:   ready
> >    DRAM:  1 GiB
> >    jSS('HH��SL_SDHC: 04 rev 0x0
> > 
> > This patch prevents from this situation, by defining pre_probe()
> > callback in which we wait till the TX buffer is empty (from
> > previous transmission):
> > 
> >    I2C:   ready
> >    DRAM:  1 GiB
> >    ID:    unit type 0x4 rev 0x0
> > 
> > All defined ->pending callbacks at ./drivers/serial are non blocking
> > - just simple reading from registers and testing flags. Hence, it
> > should be enough to not use any timeout from timer.
> > One shall also note that we enable console very early - not all
> > timers may be ready for work - adding timeout here would impose
> > implicit dependency that timers are setup before serial.
> 
> Given that this is effectively a busy polling loop, why can’t this be
> done from the probe-function of serial drivers that require this
> functionality?

That would be one of the options. 

Originally, this code was placed at iMX specific function - namely
_mxc_serial_init() [1]. 

However, Simon suggested to solve this problem globally via DM's
serial-uclass, which offers pre_probe() callback for such purpose.

The problem here is the polling loop. I've checked and ->pending on
real SoCs is just a read from the register - which should not block (a
similar approach is used in Linux kernel).

Having timeout from timer would impose dependency on timer init'ed
first - before serial.

[1] - https://patchwork.ozlabs.org/patch/820824/

> 
> > 
> > 
> > Signed-off-by: Lukasz Majewski <lukma at denx.de>
> > ---
> > 
> > drivers/serial/serial-uclass.c | 20 ++++++++++++++++++++
> > 1 file changed, 20 insertions(+)
> > 
> > diff --git a/drivers/serial/serial-uclass.c
> > b/drivers/serial/serial-uclass.c index 2e5116f..5e6964d 100644
> > --- a/drivers/serial/serial-uclass.c
> > +++ b/drivers/serial/serial-uclass.c
> > @@ -420,10 +420,30 @@ static int serial_pre_remove(struct udevice
> > *dev) return 0;
> > }
> > 
> > +static int serial_pre_probe(struct udevice *dev)
> > +{
> > +	struct dm_serial_ops *ops = serial_get_ops(dev);
> > +	int ret = 0;
> > +
> > +	/*
> > +	 * Wait for any ongoing transmission to finish - for
> > example
> > +	 * from pre-relocation enabled UART
> > +	 */
> > +	if (ops && ops->pending)
> > +		do {
> > +			ret = ops->pending(dev, false);
> > +			if (ret < 0)
> > +				break;
> > +		} while (ret > 0);
> > +
> > +	return ret;
> > +}
> > +
> > UCLASS_DRIVER(serial) = {
> > 	.id		= UCLASS_SERIAL,
> > 	.name		= "serial",
> > 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
> > +	.pre_probe	= serial_pre_probe,
> > 	.post_probe	= serial_post_probe,
> > 	.pre_remove	= serial_pre_remove,
> > 	.per_device_auto_alloc_size = sizeof(struct
> > serial_dev_priv), -- 
> > 2.1.4
> > 
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de


More information about the U-Boot mailing list