Am 02.03.2012 23:51 schrieb Stefan Tauner:
> On Fri, 02 Mar 2012 22:43:44 +0100
> Carl-Daniel Hailfinger <[email protected]> wrote:
>
>> Am 02.03.2012 00:43 schrieb Stefan Tauner:
>>> Previously we relied on a correctly set up state.
>>>
>>> ---
>>> untested.
>>>
>>> Signed-off-by: Stefan Tauner <[email protected]>
>>> ---
>>>  linux_spi.c |   23 +++++++++++++++++++++++
>>>  1 files changed, 23 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/linux_spi.c b/linux_spi.c
>>> index d994389..d29c59a 100644
>>> --- a/linux_spi.c
>>> +++ b/linux_spi.c
>>> @@ -57,6 +57,8 @@ int linux_spi_init(void)
>>>  {
>>>     char *p, *endp, *dev;
>>>     uint32_t speed = 0;
>>> +   /* FIXME: make the following configurable by CLI options. */
>>> +   uint8_t mode = SPI_MODE_0, lsb = 0, bits = 0; /* mode 0, msb first, 8 
>>> bits */
>> Can you move that comment above the variable definitions?
> done, reads now:
> /* SPI mode 0, msb first, 8 bits (i.e. value=0) */
>
>> Where should we note that SPI_MODE_0 also implies CS# active low?
> it does not. the test program seems to be outdated, the actual code
> masks the CPOL/CPHA bits.

Let me rephrase that: Setting the SPI mode handles CPOL/CPHA/CS/LSB/...
all in one. The bits which are not set have their default value (0).
http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/drivers/spi/spidev.c#L72
#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST
| SPI_3WIRE | SPI_LOOP | SPI_NO_CS | SPI_READY)


>>>  
>>>     dev = extract_programmer_param("dev");
>>>     if (!dev || !strlen(dev)) {
>>> @@ -92,6 +94,27 @@ int linux_spi_init(void)
>>>             msg_pdbg("Using %d kHz clock\n", speed);
>>>     }
>>>  
>>> +   if (ioctl(fd, SPI_IOC_WR_MODE, &mode) == -1) {
>>> +           msg_perr("%s: failed to set SPI mode to %u: %s\n",
>>> +                    __func__, mode, strerror(errno));
>>> +           close(fd);
>>> +           return 1;
>>> +   }
>>> +
>>> +   if (ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb) == -1) {
>>> +           msg_perr("%s: failed to set SPI justification to %u: %s\n",
>>> +                    __func__, lsb, strerror(errno));
>> This message would benefit from an explanation what SPI justification
>> is. Suggestion:
>> msg_perr("%s: failed to set SPI bit order to %s first: %s\n", __func_,
>> lsb ? "LSB" : "MSB", strerror(errno));
> right, was too lazy to think about a better term/solution at the
> time; fixed.
>
>>> +           close(fd);
>>> +           return 1;
>>> +   }
>>> +
>>> +   if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits) == -1) {
>>> +           msg_perr("%s: failed to set the number of bits in an SPI word 
>>> to %u: %s\n",
>>> +                    __func__, bits, strerror(errno));
>> bits is 0. The error message would suggest that we tried to set the
>> number of bits to 0. Does 0 also mean 8 bits, or would we have to set 8
>> bits with bits=8?
> bits = 0 is the only defined value in the documentation and is actually
> the only one implemented in the code and means 8 bits per word.

The documentation is explicit that bits is the number of bits, unless
bits=0, in which case it is treated as 8 bits.
I also have checked the code in the Linux kernel and it agrees with me.

Note that retval in ioctl handling is _not_ the value entered by the
user, but an error/success code for accessing user data.
http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/drivers/spi/spidev.c#L408
http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/drivers/spi/spi.c#L727


> i have changed the message to this:
>               msg_perr("%s: failed to set the number of bits per SPI word to 
> %s: %s\n",
>                        __func__, bits == 0 ? "8" : "<undef>", 
> strerror(errno));
>
>>> +           close(fd);
>>> +           return 1;
>>> +   }
>>> +
>>>     if (register_shutdown(linux_spi_shutdown, NULL))
>>>             return 1;
>>>  
>> As an alternative, we could avoid the whole close(fd) dance by calling
>> register_shutdown() first, and then letting it do the work for us
>> automatically after we return 1.
> how do we do it in other programmers? we should probably define and
> document a single suggested way so that we dont have to discuss this
> every time. :)

A single suggested way (or maybe two ways, depending on the hardware
interface design we're using) is a good idea as long as it's not a hard
unbreakable rule afterwards.
The following two ways seem to make sense for linux_spi IMHO:
ret = 1; goto out_shutdown;
or
setting everything after register_shutdown.

If we want to restore old settings on shutdown, it gets a bit hackier.
One possible way would be:
int restore_settings;
init (){
open fd else return 1;
restore_settings=0;
register_shutdown() else return 1;
get all settings and store them in file-level variables or a file-level
struct else return 1;
restore_settings=1;
set all settings else return 1;
return 0;
}
shutdown() {
if (restore_settings){
  restore settings;
}
close(fd);
}

> in this particular case i think it makes sense. in general relying on
> the shutdown function only may be a bit hard to grasp/implement for
> complicated init functions that allocate/manipulate lots of stuff (e.g.
> serprog).

Agreed.

Side note: How should we handle a failed register_shutdown()? Call the
shutdown function manually and return 1? Or is there any other good way
to clean up?

Regards,
Carl-Daniel

-- 
http://www.hailfinger.org/


_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to