iPXE
spi.h
Go to the documentation of this file.
00001 #ifndef _IPXE_SPI_H
00002 #define _IPXE_SPI_H
00003 
00004 /** @file
00005  *
00006  * SPI interface
00007  *
00008  */
00009 
00010 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00011 
00012 #include <ipxe/nvs.h>
00013 
00014 /**
00015  * @defgroup spicmds SPI commands
00016  * @{
00017  */
00018 
00019 /** Write status register */
00020 #define SPI_WRSR 0x01
00021 
00022 /** Write data to memory array */
00023 #define SPI_WRITE 0x02
00024 
00025 /** Read data from memory array */
00026 #define SPI_READ 0x03
00027 
00028 /** Reset write enable latch */
00029 #define SPI_WRDI 0x04
00030 
00031 /** Read status register */
00032 #define SPI_RDSR 0x05
00033 
00034 /** Set write enable latch */
00035 #define SPI_WREN 0x06
00036 
00037 /**
00038  * @defgroup atmelcmds Atmel-specific SPI commands
00039  * @{
00040  */
00041 
00042 /** Erase one sector in memory array (Not supported on all devices) */
00043 #define ATMEL_SECTOR_ERASE 0x52
00044 
00045 /** Erase all sections in memory array (Not supported on all devices) */
00046 #define ATMEL_CHIP_ERASE 0x62
00047 
00048 /** Read manufacturer and product ID (Not supported on all devices) */
00049 #define ATMEL_RDID 0x15
00050 
00051 /** @} */
00052 
00053 /** @} */
00054 
00055 /**
00056  * @defgroup spistatus SPI status register bits (not present on all devices)
00057  * @{
00058  */
00059 
00060 /** Write-protect pin enabled */
00061 #define SPI_STATUS_WPEN 0x80
00062 
00063 /** Block protection bit 2 */
00064 #define SPI_STATUS_BP2 0x10
00065 
00066 /** Block protection bit 1 */
00067 #define SPI_STATUS_BP1 0x08
00068 
00069 /** Block protection bit 0 */
00070 #define SPI_STATUS_BP0 0x04
00071 
00072 /** State of the write enable latch */
00073 #define SPI_STATUS_WEN 0x02
00074 
00075 /** Device busy flag */
00076 #define SPI_STATUS_NRDY 0x01
00077 
00078 /** @} */
00079 
00080 /**
00081  * An SPI device
00082  *
00083  * This data structure represents a physical SPI device attached to an
00084  * SPI bus.
00085  */
00086 struct spi_device {
00087         /** NVS device */
00088         struct nvs_device nvs;
00089         /** SPI bus to which device is attached */
00090         struct spi_bus *bus;
00091         /** Slave number */
00092         unsigned int slave;
00093         /** Command length, in bits */
00094         unsigned int command_len;
00095         /** Address length, in bits */
00096         unsigned int address_len;
00097         /** Address is munged
00098          *
00099          * Some devices with 9-bit addresses (e.g. AT25040A EEPROM)
00100          * use bit 3 of the command byte as address bit A8, rather
00101          * than having a two-byte address.  If this flag is set, then
00102          * commands should be munged in this way.
00103          */
00104         unsigned int munge_address : 1;
00105 };
00106 
00107 /**
00108  * SPI magic autodetection address length
00109  *
00110  * Set @c spi_device::address_len to @c SPI_AUTODETECT_ADDRESS_LEN if
00111  * the address length should be autodetected.
00112  */
00113 #define SPI_AUTODETECT_ADDRESS_LEN 0
00114 
00115 static inline __attribute__ (( always_inline )) struct spi_device *
00116 nvs_to_spi ( struct nvs_device *nvs ) {
00117         return container_of ( nvs, struct spi_device, nvs );
00118 }
00119 
00120 /**
00121  * An SPI bus
00122  *
00123  * This data structure represents an SPI bus controller capable of
00124  * issuing commands to attached SPI devices.
00125  */
00126 struct spi_bus {
00127         /** SPI interface mode
00128          *
00129          * This is the bitwise OR of zero or more of @c SPI_MODE_CPHA
00130          * and @c SPI_MODE_CPOL.  It is also the number conventionally
00131          * used to describe the SPI interface mode.  For example, SPI
00132          * mode 1 is the mode in which CPOL=0 and CPHA=1, which
00133          * therefore corresponds to a mode value of (0|SPI_MODE_CPHA)
00134          * which, happily, equals 1.
00135          */
00136         unsigned int mode;
00137         /**
00138          * Read/write data via SPI bus
00139          *
00140          * @v bus               SPI bus
00141          * @v device            SPI device
00142          * @v command           Command
00143          * @v address           Address to read/write (<0 for no address)
00144          * @v data_out          TX data buffer (or NULL)
00145          * @v data_in           RX data buffer (or NULL)
00146          * @v len               Length of data buffer(s)
00147          *
00148          * This issues the specified command and optional address to
00149          * the SPI device, then reads and/or writes data to/from the
00150          * data buffers.
00151          */
00152         int ( * rw ) ( struct spi_bus *bus, struct spi_device *device,
00153                        unsigned int command, int address,
00154                        const void *data_out, void *data_in, size_t len );
00155 };
00156 
00157 /** Clock phase (CPHA) mode bit
00158  *
00159  * Phase 0 is sample on rising edge, shift data on falling edge.
00160  *
00161  * Phase 1 is shift data on rising edge, sample data on falling edge.
00162  */
00163 #define SPI_MODE_CPHA 0x01
00164 
00165 /** Clock polarity (CPOL) mode bit
00166  *
00167  * This bit reflects the idle state of the clock line (SCLK).
00168  */
00169 #define SPI_MODE_CPOL 0x02
00170 
00171 /** Slave select polarity mode bit
00172  *
00173  * This bit reflects that active state of the slave select lines.  It
00174  * is not part of the normal SPI mode number (which covers only @c
00175  * SPI_MODE_CPOL and @c SPI_MODE_CPHA), but is included here for
00176  * convenience.
00177  */
00178 #define SPI_MODE_SSPOL 0x10
00179 
00180 /** Microwire-compatible mode
00181  *
00182  * This is SPI mode 1 (i.e. CPOL=0, CPHA=1), and is compatible with
00183  * the original Microwire protocol.
00184  */
00185 #define SPI_MODE_MICROWIRE 1
00186 
00187 /** Microwire/Plus-compatible mode
00188  *
00189  * This is SPI mode 0 (i.e. CPOL=0, CPHA=0), and is compatible with
00190  * the Microwire/Plus protocol
00191  */
00192 #define SPI_MODE_MICROWIRE_PLUS 0
00193 
00194 /** Threewire-compatible mode
00195  *
00196  * This mode is compatible with Atmel's series of "three-wire"
00197  * interfaces.
00198  */
00199 #define SPI_MODE_THREEWIRE ( SPI_MODE_MICROWIRE_PLUS | SPI_MODE_SSPOL )
00200 
00201 extern int spi_read ( struct nvs_device *nvs, unsigned int address,
00202                       void *data, size_t len );
00203 extern int spi_write ( struct nvs_device *nvs, unsigned int address,
00204                        const void *data, size_t len );
00205 
00206 /**
00207  * @defgroup spidevs SPI device types
00208  * @{
00209  */
00210 
00211 static inline __attribute__ (( always_inline )) void
00212 init_spi ( struct spi_device *device ) {
00213         device->nvs.word_len_log2 = 0;
00214         device->command_len = 8,
00215         device->nvs.read = spi_read;
00216         device->nvs.write = spi_write;  
00217 }
00218 
00219 /** Atmel AT25F1024 serial flash */
00220 static inline __attribute__ (( always_inline )) void
00221 init_at25f1024 ( struct spi_device *device ) {
00222         device->address_len = 24;
00223         device->nvs.size = ( 128 * 1024 );
00224         device->nvs.block_size = 256;
00225         init_spi ( device );
00226 }
00227 
00228 /** Atmel 25040 serial EEPROM */
00229 static inline __attribute__ (( always_inline )) void
00230 init_at25040 ( struct spi_device *device ) {
00231         device->address_len = 8;
00232         device->munge_address = 1;
00233         device->nvs.size = 512;
00234         device->nvs.block_size = 8;
00235         init_spi ( device );
00236 }
00237 
00238 /** ST M25P32 serial flash */
00239 static inline __attribute__ (( always_inline )) void
00240 init_m25p32 ( struct spi_device *device ) {
00241         device->address_len = 24;
00242         device->nvs.size = ( 4 * 1024 * 1024 );
00243         device->nvs.block_size = 256;
00244         init_spi ( device );
00245 }
00246 
00247 /** Microchip 25XX640 serial EEPROM */
00248 static inline __attribute__ (( always_inline )) void
00249 init_mc25xx640 ( struct spi_device *device ) {
00250         device->address_len = 16;
00251         device->nvs.size = ( 8 * 1024 );
00252         device->nvs.block_size = 32;
00253         init_spi ( device );
00254 }
00255 
00256 /** @} */
00257 
00258 #endif /* _IPXE_SPI_H */