iPXE
Functions
spi.c File Reference

SPI devices. More...

#include <stddef.h>
#include <errno.h>
#include <unistd.h>
#include <ipxe/spi.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static unsigned int spi_command (unsigned int command, unsigned int address, int munge_address)
 Munge SPI device address into command.
static int spi_wait (struct spi_device *device)
 Wait for SPI device to complete operation.
int spi_read (struct nvs_device *nvs, unsigned int address, void *data, size_t len)
 Read data from SPI device.
int spi_write (struct nvs_device *nvs, unsigned int address, const void *data, size_t len)
 Write data to SPI device.

Detailed Description

SPI devices.

Definition in file spi.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static unsigned int spi_command ( unsigned int  command,
unsigned int  address,
int  munge_address 
) [inline, static]

Munge SPI device address into command.

Parameters:
commandSPI command
addressAddress
munge_addressDevice requires address munging
Return values:
commandActual SPI command to use

Some devices with 9-bit addresses (e.g. AT25040A EEPROM) use bit 3 of the command byte as address bit A8, rather than having a two-byte address. This function takes care of generating the appropriate command.

Definition at line 50 of file spi.c.

Referenced by spi_read(), and spi_write().

                                                             {
        return ( command | ( ( ( address >> 8 ) & munge_address ) << 3 ) );
}
static int spi_wait ( struct spi_device device) [static]

Wait for SPI device to complete operation.

Parameters:
deviceSPI device
Return values:
rcReturn status code

Definition at line 62 of file spi.c.

References spi_device::bus, bus, DBG, ETIMEDOUT, NULL, rc, spi_bus::rw, SPI_RDSR, SPI_STATUS_NRDY, status, and udelay().

Referenced by spi_write().

                                                  {
        struct spi_bus *bus = device->bus;
        uint8_t status;
        int i;
        int rc;

        for ( i = 0 ; i < 50 ; i++ ) {
                udelay ( 20 );
                if ( ( rc = bus->rw ( bus, device, SPI_RDSR, -1, NULL,
                                      &status, sizeof ( status ) ) ) != 0 )
                        return rc;
                if ( ! ( status & SPI_STATUS_NRDY ) )
                        return 0;
        }
        DBG ( "SPI %p timed out\n", device );
        return -ETIMEDOUT;
}
int spi_read ( struct nvs_device nvs,
unsigned int  address,
void *  data,
size_t  len 
)

Read data from SPI device.

Parameters:
nvsNVS device
addressAddress from which to read
dataData buffer
lenLength of data buffer
Return values:
rcReturn status code

Definition at line 89 of file spi.c.

References spi_device::bus, bus, DBG, spi_device::munge_address, NULL, rc, spi_bus::rw, spi_command(), and SPI_READ.

                                        {
        struct spi_device *device = nvs_to_spi ( nvs );
        struct spi_bus *bus = device->bus;
        unsigned int command = spi_command ( SPI_READ, address,
                                             device->munge_address );
        int rc;

        DBG ( "SPI %p reading %zd bytes from %#04x\n", device, len, address );
        if ( ( rc = bus->rw ( bus, device, command, address,
                              NULL, data, len ) ) != 0 ) {
                DBG ( "SPI %p failed to read data from device\n", device );
                return rc;
        }

        return 0;
}
int spi_write ( struct nvs_device nvs,
unsigned int  address,
const void *  data,
size_t  len 
)

Write data to SPI device.

Parameters:
nvsNVS device
addressAddress from which to read
dataData buffer
lenLength of data buffer
Return values:
rcReturn status code

Definition at line 116 of file spi.c.

References spi_device::bus, bus, DBG, spi_device::munge_address, NULL, rc, spi_bus::rw, spi_command(), spi_wait(), SPI_WREN, and SPI_WRITE.

                                               {
        struct spi_device *device = nvs_to_spi ( nvs );
        struct spi_bus *bus = device->bus;
        unsigned int command = spi_command ( SPI_WRITE, address,
                                             device->munge_address );
        int rc;

        DBG ( "SPI %p writing %zd bytes to %#04x\n", device, len, address );

        if ( ( rc = bus->rw ( bus, device, SPI_WREN, -1,
                              NULL, NULL, 0 ) ) != 0 ) {
                DBG ( "SPI %p failed to write-enable device\n", device );
                return rc;
        }

        if ( ( rc = bus->rw ( bus, device, command, address,
                              data, NULL, len ) ) != 0 ) {
                DBG ( "SPI %p failed to write data to device\n", device );
                return rc;
        }
        
        if ( ( rc = spi_wait ( device ) ) != 0 ) {
                DBG ( "SPI %p failed to complete write operation\n", device );
                return rc;
        }

        return 0;
}