spi_bit.c File Reference

SPI bit-bashing interface. More...

#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <byteswap.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <gpxe/bitbash.h>
#include <gpxe/spi_bit.h>

Go to the source code of this file.

Defines

#define SELECT_SLAVE   0
 Chip select line will be asserted.
#define DESELECT_SLAVE   SPI_MODE_SSPOL
 Chip select line will be deasserted.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static void spi_bit_delay (void)
 Delay between SCLK changes and around SS changes.
static void spi_bit_set_slave_select (struct spi_bit_basher *spibit, unsigned int slave, unsigned int state)
 Select/deselect slave.
static void spi_bit_transfer (struct spi_bit_basher *spibit, const void *data_out, void *data_in, unsigned int len, int endianness)
 Transfer bits over SPI bit-bashing bus.
static int spi_bit_rw (struct spi_bus *bus, struct spi_device *device, unsigned int command, int address, const void *data_out, void *data_in, size_t len)
 Read/write data via SPI bit-bashing bus.
void init_spi_bit_basher (struct spi_bit_basher *spibit)
 Initialise SPI bit-bashing interface.


Detailed Description

SPI bit-bashing interface.

Definition in file spi_bit.c.


Define Documentation

#define SELECT_SLAVE   0

Chip select line will be asserted.

Definition at line 43 of file spi_bit.c.

Referenced by spi_bit_rw().

#define DESELECT_SLAVE   SPI_MODE_SSPOL

Chip select line will be deasserted.

Definition at line 46 of file spi_bit.c.

Referenced by spi_bit_rw().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

static void spi_bit_delay ( void   )  [static]

Delay between SCLK changes and around SS changes.

Definition at line 38 of file spi_bit.c.

References SPI_BIT_UDELAY, and udelay().

Referenced by spi_bit_set_slave_select(), and spi_bit_transfer().

00038                                    {
00039         udelay ( SPI_BIT_UDELAY );
00040 }

static void spi_bit_set_slave_select ( struct spi_bit_basher spibit,
unsigned int  slave,
unsigned int  state 
) [static]

Select/deselect slave.

Parameters:
spibit SPI bit-bashing interface
slave Slave number
state Slave select state
state must be SELECT_SLAVE or DESELECT_SLAVE.

Definition at line 57 of file spi_bit.c.

References spi_bit_basher::basher, spi_bit_basher::bus, DBGC2, spi_bus::mode, spi_bit_delay(), SPI_BIT_SS, SPI_MODE_SSPOL, and write_bit().

Referenced by spi_bit_rw().

00059                                                             {
00060         struct bit_basher *basher = &spibit->basher;
00061 
00062         state ^= ( spibit->bus.mode & SPI_MODE_SSPOL );
00063         DBGC2 ( spibit, "SPIBIT %p setting slave %d select %s\n",
00064                 spibit, slave, ( state ? "high" : "low" ) );
00065 
00066         spi_bit_delay();
00067         write_bit ( basher, SPI_BIT_SS ( slave ), state );
00068         spi_bit_delay();
00069 }

static void spi_bit_transfer ( struct spi_bit_basher spibit,
const void *  data_out,
void *  data_in,
unsigned int  len,
int  endianness 
) [static]

Transfer bits over SPI bit-bashing bus.

Parameters:
bus SPI bus
data_out TX data buffer (or NULL)
data_in RX data buffer (or NULL)
len Length of transfer (in bits)
endianness Endianness of this data transfer
This issues len clock cycles on the SPI bus, shifting out data from the data_out buffer to the MOSI line and shifting in data from the MISO line to the data_in buffer. If data_out is NULL, then the data sent will be all zeroes. If data_in is NULL, then the incoming data will be discarded.

Definition at line 86 of file spi_bit.c.

References spi_bit_basher::basher, spi_bit_basher::bus, DBGC2, DBGCP, spi_bus::mode, read_bit(), SPI_BIT_BIG_ENDIAN, spi_bit_delay(), SPI_BIT_MISO, SPI_BIT_MOSI, SPI_BIT_SCLK, SPI_MODE_CPHA, SPI_MODE_CPOL, step(), and write_bit().

Referenced by spi_bit_rw().

00088                                                                   {
00089         struct spi_bus *bus = &spibit->bus;
00090         struct bit_basher *basher = &spibit->basher;
00091         unsigned int sclk = ( ( bus->mode & SPI_MODE_CPOL ) ? 1 : 0 );
00092         unsigned int cpha = ( ( bus->mode & SPI_MODE_CPHA ) ? 1 : 0 );
00093         unsigned int bit_offset;
00094         unsigned int byte_offset;
00095         unsigned int byte_mask;
00096         unsigned int bit;
00097         unsigned int step;
00098 
00099         DBGC2 ( spibit, "SPIBIT %p transferring %d bits in mode %#x\n",
00100                 spibit, len, bus->mode );
00101 
00102         for ( step = 0 ; step < ( len * 2 ) ; step++ ) {
00103                 /* Calculate byte offset and byte mask */
00104                 bit_offset = ( ( endianness == SPI_BIT_BIG_ENDIAN ) ?
00105                                ( len - ( step / 2 ) - 1 ) : ( step / 2 ) );
00106                 byte_offset = ( bit_offset / 8 );
00107                 byte_mask = ( 1 << ( bit_offset % 8 ) );
00108 
00109                 /* Shift data in or out */
00110                 if ( sclk == cpha ) {
00111                         const uint8_t *byte;
00112 
00113                         /* Shift data out */
00114                         if ( data_out ) {
00115                                 byte = ( data_out + byte_offset );
00116                                 bit = ( *byte & byte_mask );
00117                                 DBGCP ( spibit, "SPIBIT %p wrote bit %d\n",
00118                                         spibit, ( bit ? 1 : 0 ) );
00119                         } else {
00120                                 bit = 0;
00121                         }
00122                         write_bit ( basher, SPI_BIT_MOSI, bit );
00123                 } else {
00124                         uint8_t *byte;
00125 
00126                         /* Shift data in */
00127                         bit = read_bit ( basher, SPI_BIT_MISO );
00128                         if ( data_in ) {
00129                                 DBGCP ( spibit, "SPIBIT %p read bit %d\n",
00130                                         spibit, ( bit ? 1 : 0 ) );
00131                                 byte = ( data_in + byte_offset );
00132                                 *byte &= ~byte_mask;
00133                                 *byte |= ( bit & byte_mask );
00134                         }
00135                 }
00136 
00137                 /* Toggle clock line */
00138                 spi_bit_delay();
00139                 sclk ^= 1;
00140                 write_bit ( basher, SPI_BIT_SCLK, sclk );
00141         }
00142 }

static int spi_bit_rw ( struct spi_bus bus,
struct spi_device device,
unsigned int  command,
int  address,
const void *  data_out,
void *  data_in,
size_t  len 
) [static]

Read/write data via SPI bit-bashing bus.

Parameters:
bus SPI bus
device SPI device
command Command
address Address to read/write (<0 for no address)
data_out TX data buffer (or NULL)
data_in RX data buffer (or NULL)
len Length of transfer
Return values:
rc Return status code

Definition at line 156 of file spi_bit.c.

References spi_device::address_len, assert, spi_bit_basher::basher, spi_device::command_len, container_of, cpu_to_le32, DBGC, DESELECT_SLAVE, spi_bit_basher::endianness, le32_to_cpu, spi_bus::mode, NULL, SELECT_SLAVE, spi_device::slave, SPI_AUTODETECT_ADDRESS_LEN, SPI_BIT_BIG_ENDIAN, SPI_BIT_SCLK, spi_bit_set_slave_select(), spi_bit_transfer(), SPI_MODE_CPOL, and write_bit().

Referenced by init_spi_bit_basher().

00158                                                                           {
00159         struct spi_bit_basher *spibit
00160                 = container_of ( bus, struct spi_bit_basher, bus );
00161         uint32_t tmp_command;
00162         uint32_t tmp_address;
00163         uint32_t tmp_address_detect;
00164 
00165         /* Set clock line to idle state */
00166         write_bit ( &spibit->basher, SPI_BIT_SCLK, 
00167                     ( bus->mode & SPI_MODE_CPOL ) );
00168 
00169         /* Assert chip select on specified slave */
00170         spi_bit_set_slave_select ( spibit, device->slave, SELECT_SLAVE );
00171 
00172         /* Transmit command */
00173         assert ( device->command_len <= ( 8 * sizeof ( tmp_command ) ) );
00174         tmp_command = cpu_to_le32 ( command );
00175         spi_bit_transfer ( spibit, &tmp_command, NULL, device->command_len,
00176                            SPI_BIT_BIG_ENDIAN );
00177 
00178         /* Transmit address, if present */
00179         if ( address >= 0 ) {
00180                 assert ( device->address_len <= ( 8 * sizeof ( tmp_address )));
00181                 tmp_address = cpu_to_le32 ( address );
00182                 if ( device->address_len == SPI_AUTODETECT_ADDRESS_LEN ) {
00183                         /* Autodetect address length.  This relies on
00184                          * the device responding with a dummy zero
00185                          * data bit before the first real data bit.
00186                          */
00187                         DBGC ( spibit, "SPIBIT %p autodetecting device "
00188                                "address length\n", spibit );
00189                         assert ( address == 0 );
00190                         device->address_len = 0;
00191                         do {
00192                                 spi_bit_transfer ( spibit, &tmp_address,
00193                                                    &tmp_address_detect, 1,
00194                                                    SPI_BIT_BIG_ENDIAN );
00195                                 device->address_len++;
00196                         } while ( le32_to_cpu ( tmp_address_detect ) & 1 );
00197                         DBGC ( spibit, "SPIBIT %p autodetected device address "
00198                                "length %d\n", spibit, device->address_len );
00199                 } else {
00200                         spi_bit_transfer ( spibit, &tmp_address, NULL,
00201                                            device->address_len,
00202                                            SPI_BIT_BIG_ENDIAN );
00203                 }
00204         }
00205 
00206         /* Transmit/receive data */
00207         spi_bit_transfer ( spibit, data_out, data_in, ( len * 8 ),
00208                            spibit->endianness );
00209 
00210         /* Deassert chip select on specified slave */
00211         spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE );
00212 
00213         return 0;
00214 }

void init_spi_bit_basher ( struct spi_bit_basher spibit  ) 

Initialise SPI bit-bashing interface.

Parameters:
spibit SPI bit-bashing interface

Definition at line 221 of file spi_bit.c.

References assert, spi_bit_basher::basher, spi_bit_basher::bus, NULL, bit_basher::op, bit_basher_operations::read, spi_bus::rw, spi_bit_rw(), and bit_basher_operations::write.

Referenced by ifec_init_eeprom(), natsemi_init_eeprom(), rtl818x_probe(), and rtl_init_eeprom().

00221                                                            {
00222         assert ( &spibit->basher.op->read != NULL );
00223         assert ( &spibit->basher.op->write != NULL );
00224         spibit->bus.rw = spi_bit_rw;
00225 }


Generated on Tue Apr 6 20:01:16 2010 for gPXE by  doxygen 1.5.7.1