public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
To: u-boot@lists.denx.de
Subject: [U-Boot-Users] [RFC/PATCH 2/6] SPI API improvements
Date: Fri, 16 May 2008 14:22:19 +0200	[thread overview]
Message-ID: <20080516142219.6edc0ee5@siona.local> (raw)
In-Reply-To: <Pine.LNX.4.64.0805161225290.3714@axis700.grange>

On Fri, 16 May 2008 12:41:04 +0200 (CEST)
Guennadi Liakhovetski <lg@denx.de> wrote:

> On Fri, 16 May 2008, Haavard Skinnemoen wrote:
> 
> > From: Haavard Skinnemoen <hskinnemoen@atmel.com>
> > 
> > This patch gets rid of the spi_chipsel table and adds a handful of new
> > functions that makes the SPI layer cleaner and more flexible.
> 
> Ok, this looks good to me now. And it works too. Just one question:

Great!

> >  	do {
> >  		reg = 0x2c000000;
> > -		err = spi_xfer(0, 32, (uchar *)&reg, (uchar *)&day1);
> > +		err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day1,
> > +				SPI_XFER_BEGIN | SPI_XFER_END);
> >  
> >  		if (err)
> >  			return err;
> >  
> >  		reg = 0x28000000;
> > -		err = spi_xfer(0, 32, (uchar *)&reg, (uchar *)&time);
> > +		err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&time,
> > +				SPI_XFER_BEGIN | SPI_XFER_END);
> >  
> >  		if (err)
> >  			return err;
> >  
> >  		reg = 0x2c000000;
> > -		err = spi_xfer(0, 32, (uchar *)&reg, (uchar *)&day2);
> > +		err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day2,
> > +				SPI_XFER_BEGIN | SPI_XFER_END);
> 
> Here... We perform 3 transfers on SPI one after another, and every time we 
> do "SPI_XFER_BEGIN | SPI_XFER_EN"... Doesn't this defeat the whole purpose 
> of these flags? Would it be bad, if we did

Well, no, I wouldn't say it defeats the purpose of these flags...

> >  		reg = 0x2c000000;
> > -		err = spi_xfer(0, 32, (uchar *)&reg, (uchar *)&day1);
> > +		err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day1,
> > +				SPI_XFER_BEGIN);
> > - 
> > - 		if (err)
> > - 			return err;
> >  
> >  		reg = 0x28000000;
> > -		err = spi_xfer(0, 32, (uchar *)&reg, (uchar *)&time);
> > +		err |= spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&time, 0);
> > - 
> > - 		if (err)
> > - 			return err;
> >  
> >  		reg = 0x2c000000;
> > -		err = spi_xfer(0, 32, (uchar *)&reg, (uchar *)&day2);
> > +		err |= spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day2,
> > +				SPI_XFER_END);
> >  
> >  		if (err)
> >  			return err;
> 
> ? The worst that can happen with this, is that the first or the second 
> transfer return an error, and we go on with one or two more transfers 
> instead of aborting immediately. Can this have any negative effects?

While I don't know the RTC in question well enough to say for sure,
there's a very real possibility that your suggestion simply won't work.

The purpose of the spi_xfer flags parameter isn't to gang together
multiple transfers -- it's to allow more precise chip select control so
that you can split a transfer into multiple spi_xfer() calls. This is
useful for devices where you typically start with a command, possibly
with a few bytes of parameters, then transfer data without releasing
the chip select in between.

The SPI flash driver posted later in this thread does this -- it first
sends a command along with any address bytes, and then starts the
actual data transfer with the buffer provided by the caller. The chip
select must stay active during the whole sequence, so without this
tweak, it would have to copy everything into a temporary buffer first.

If you try to combine multiple transfers into one like you did above,
the chip select will stay active all the time. And many devices expect
the chip select to go inactive after each command, and may simply
ignore all but the first or last if it stays active.

It could be that your solution works, but I wanted to mimic the
existing behaviour as closely as possible. And I definitely don't want
to "optimize" chip select control without knowing the device in
question very well.

> >  	reg = 0x2c000000 | day | 0x80000000;
> > -	spi_xfer(0, 32, (uchar *)&reg, (uchar *)&day);
> > +	spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day,
> > +			SPI_XFER_BEGIN | SPI_XFER_END);
> >  
> >  	reg = 0x28000000 | time | 0x80000000;
> > -	spi_xfer(0, 32, (uchar *)&reg, (uchar *)&time);
> > +	spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&time,
> > +			SPI_XFER_BEGIN | SPI_XFER_END);
> > +
> > +	spi_release_bus(slave);
> >  }
> >  
> >  void rtc_reset(void)
> 
> Here error is not checked at all... So, it should be no problem doing only 
> SPI_XFER_BEGIN in the first xfer and only SPI_XFER_END in the second one.

No, I don't think that will work, for the reasons mentioned above.
There's no error checking because the existing code doesn't check for
errors...and there's no way to return an error status from the function
anyway.

Btw, there are a few spi_xfer() semantics that I want to be a bit more
clearly defined, but I forgot to document it before sending the patch.
These are:
  * If spi_xfer() fails, it automatically terminates the transfer as if
    the SPI_XFER_END flag was set.
  * If bitlen == 0, spi_xfer() must deactivate CS if the SPI_XFER_END
    flag is set.
  * If dout == NULL, spi_xfer() will transmit unspecified data.
    Alternatively, we could specify that it must send zeroes.
  * If din == NULL, spi_xfer() will ignore any received data.

If people agree that these semantics make sense, we should probably go
through the drivers and make sure it's handled appropriately.

Oh, and I want to do something about the "bitlen" parameter, but I
don't wanna open that particular can of worms in this patchset :-)

Haavard

  reply	other threads:[~2008-05-16 12:22 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-16  9:10 [U-Boot-Users] [RFC/PATCH 1/6] Move definition of container_of() to common.h Haavard Skinnemoen
2008-05-16  9:10 ` [U-Boot-Users] [RFC/PATCH 2/6] SPI API improvements Haavard Skinnemoen
2008-05-16  9:10   ` [U-Boot-Users] [RFC/PATCH 3/6] atmel_spi: Driver for the Atmel SPI controller Haavard Skinnemoen
2008-05-16  9:10     ` [U-Boot-Users] [RFC/PATCH 4/6] SPI Flash subsystem Haavard Skinnemoen
2008-05-16  9:10       ` [U-Boot-Users] [RFC/PATCH 5/6] SPI Flash: Add "sf" command Haavard Skinnemoen
2008-05-16  9:10         ` [U-Boot-Users] [RFC/PATCH 6/6] Add support for environment in SPI flash Haavard Skinnemoen
2008-06-04 22:06           ` Wolfgang Denk
2008-06-05 11:18             ` Haavard Skinnemoen
2008-06-04 22:06         ` [U-Boot-Users] [RFC/PATCH 5/6] SPI Flash: Add "sf" command Wolfgang Denk
2008-06-04 22:06       ` [U-Boot-Users] [RFC/PATCH 4/6] SPI Flash subsystem Wolfgang Denk
2008-06-04 22:06     ` [U-Boot-Users] [RFC/PATCH 3/6] atmel_spi: Driver for the Atmel SPI controller Wolfgang Denk
2008-05-16 10:41   ` [U-Boot-Users] [RFC/PATCH 2/6] SPI API improvements Guennadi Liakhovetski
2008-05-16 12:22     ` Haavard Skinnemoen [this message]
2008-05-16 12:51       ` Guennadi Liakhovetski
2008-05-17 10:56   ` Jean-Christophe PLAGNIOL-VILLARD
2008-05-18 17:37     ` Haavard Skinnemoen
2008-05-26  6:57   ` Ben Warren
2008-06-04 22:06   ` Wolfgang Denk
2008-05-16  9:56 ` [U-Boot-Users] [RFC/PATCH 1/6] Move definition of container_of() to common.h Jean-Christophe PLAGNIOL-VILLARD
2008-06-04 22:06 ` Wolfgang Denk

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=20080516142219.6edc0ee5@siona.local \
    --to=haavard.skinnemoen@atmel.com \
    --cc=u-boot@lists.denx.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox