1 #ifndef _GPXE_SPI_H 2 #define _GPXE_SPI_H 3 4 /** @file 5 * 6 * SPI interface 7 * 8 */ 9 10 FILE_LICENCE ( GPL2_OR_LATER ); 11 12 #include <gpxe/nvs.h> 13 14 /** 15 * @defgroup spicmds SPI commands 16 * @{ 17 */ 18 19 /** Write status register */ 20 #define SPI_WRSR 0x01 21 22 /** Write data to memory array */ 23 #define SPI_WRITE 0x02 24 25 /** Read data from memory array */ 26 #define SPI_READ 0x03 27 28 /** Reset write enable latch */ 29 #define SPI_WRDI 0x04 30 31 /** Read status register */ 32 #define SPI_RDSR 0x05 33 34 /** Set write enable latch */ 35 #define SPI_WREN 0x06 36 37 /** 38 * @defgroup atmelcmds Atmel-specific SPI commands 39 * @{ 40 */ 41 42 /** Erase one sector in memory array (Not supported on all devices) */ 43 #define ATMEL_SECTOR_ERASE 0x52 44 45 /** Erase all sections in memory array (Not supported on all devices) */ 46 #define ATMEL_CHIP_ERASE 0x62 47 48 /** Read manufacturer and product ID (Not supported on all devices) */ 49 #define ATMEL_RDID 0x15 50 51 /** @} */ 52 53 /** @} */ 54 55 /** 56 * @defgroup spistatus SPI status register bits (not present on all devices) 57 * @{ 58 */ 59 60 /** Write-protect pin enabled */ 61 #define SPI_STATUS_WPEN 0x80 62 63 /** Block protection bit 2 */ 64 #define SPI_STATUS_BP2 0x10 65 66 /** Block protection bit 1 */ 67 #define SPI_STATUS_BP1 0x08 68 69 /** Block protection bit 0 */ 70 #define SPI_STATUS_BP0 0x04 71 72 /** State of the write enable latch */ 73 #define SPI_STATUS_WEN 0x02 74 75 /** Device busy flag */ 76 #define SPI_STATUS_NRDY 0x01 77 78 /** @} */ 79 80 /** 81 * An SPI device 82 * 83 * This data structure represents a physical SPI device attached to an 84 * SPI bus. 85 */ 86 struct spi_device { 87 /** NVS device */ 88 struct nvs_device nvs; 89 /** SPI bus to which device is attached */ 90 struct spi_bus *bus; 91 /** Slave number */ 92 unsigned int slave; 93 /** Command length, in bits */ 94 unsigned int command_len; 95 /** Address length, in bits */ 96 unsigned int address_len; 97 /** Address is munged 98 * 99 * Some devices with 9-bit addresses (e.g. AT25040A EEPROM) 100 * use bit 3 of the command byte as address bit A8, rather 101 * than having a two-byte address. If this flag is set, then 102 * commands should be munged in this way. 103 */ 104 unsigned int munge_address : 1; 105 }; 106 107 /** 108 * SPI magic autodetection address length 109 * 110 * Set @c spi_device::address_len to @c SPI_AUTODETECT_ADDRESS_LEN if 111 * the address length should be autodetected. 112 */ 113 #define SPI_AUTODETECT_ADDRESS_LEN 0 114 115 static inline __attribute__ (( always_inline )) struct spi_device * 116 nvs_to_spi ( struct nvs_device *nvs ) { 117 return container_of ( nvs, struct spi_device, nvs ); 118 } 119 120 /** 121 * An SPI bus 122 * 123 * This data structure represents an SPI bus controller capable of 124 * issuing commands to attached SPI devices. 125 */ 126 struct spi_bus { 127 /** SPI interface mode 128 * 129 * This is the bitwise OR of zero or more of @c SPI_MODE_CPHA 130 * and @c SPI_MODE_CPOL. It is also the number conventionally 131 * used to describe the SPI interface mode. For example, SPI 132 * mode 1 is the mode in which CPOL=0 and CPHA=1, which 133 * therefore corresponds to a mode value of (0|SPI_MODE_CPHA) 134 * which, happily, equals 1. 135 */ 136 unsigned int mode; 137 /** 138 * Read/write data via SPI bus 139 * 140 * @v bus SPI bus 141 * @v device SPI device 142 * @v command Command 143 * @v address Address to read/write (<0 for no address) 144 * @v data_out TX data buffer (or NULL) 145 * @v data_in RX data buffer (or NULL) 146 * @v len Length of data buffer(s) 147 * 148 * This issues the specified command and optional address to 149 * the SPI device, then reads and/or writes data to/from the 150 * data buffers. 151 */ 152 int ( * rw ) ( struct spi_bus *bus, struct spi_device *device, 153 unsigned int command, int address, 154 const void *data_out, void *data_in, size_t len ); 155 }; 156 157 /** Clock phase (CPHA) mode bit 158 * 159 * Phase 0 is sample on rising edge, shift data on falling edge. 160 * 161 * Phase 1 is shift data on rising edge, sample data on falling edge. 162 */ 163 #define SPI_MODE_CPHA 0x01 164 165 /** Clock polarity (CPOL) mode bit 166 * 167 * This bit reflects the idle state of the clock line (SCLK). 168 */ 169 #define SPI_MODE_CPOL 0x02 170 171 /** Slave select polarity mode bit 172 * 173 * This bit reflects that active state of the slave select lines. It 174 * is not part of the normal SPI mode number (which covers only @c 175 * SPI_MODE_CPOL and @c SPI_MODE_CPHA), but is included here for 176 * convenience. 177 */ 178 #define SPI_MODE_SSPOL 0x10 179 180 /** Microwire-compatible mode 181 * 182 * This is SPI mode 1 (i.e. CPOL=0, CPHA=1), and is compatible with 183 * the original Microwire protocol. 184 */ 185 #define SPI_MODE_MICROWIRE 1 186 187 /** Microwire/Plus-compatible mode 188 * 189 * This is SPI mode 0 (i.e. CPOL=0, CPHA=0), and is compatible with 190 * the Microwire/Plus protocol 191 */ 192 #define SPI_MODE_MICROWIRE_PLUS 0 193 194 /** Threewire-compatible mode 195 * 196 * This mode is compatible with Atmel's series of "three-wire" 197 * interfaces. 198 */ 199 #define SPI_MODE_THREEWIRE ( SPI_MODE_MICROWIRE_PLUS | SPI_MODE_SSPOL ) 200 201 extern int spi_read ( struct nvs_device *nvs, unsigned int address, 202 void *data, size_t len ); 203 extern int spi_write ( struct nvs_device *nvs, unsigned int address, 204 const void *data, size_t len ); 205 206 /** 207 * @defgroup spidevs SPI device types 208 * @{ 209 */ 210 211 static inline __attribute__ (( always_inline )) void 212 init_spi ( struct spi_device *device ) { 213 device->nvs.word_len_log2 = 0; 214 device->command_len = 8, 215 device->nvs.read = spi_read; 216 device->nvs.write = spi_write; 217 } 218 219 /** Atmel AT25F1024 serial flash */ 220 static inline __attribute__ (( always_inline )) void 221 init_at25f1024 ( struct spi_device *device ) { 222 device->address_len = 24; 223 device->nvs.size = ( 128 * 1024 ); 224 device->nvs.block_size = 256; 225 init_spi ( device ); 226 } 227 228 /** Atmel 25040 serial EEPROM */ 229 static inline __attribute__ (( always_inline )) void 230 init_at25040 ( struct spi_device *device ) { 231 device->address_len = 8; 232 device->munge_address = 1; 233 device->nvs.size = 512; 234 device->nvs.block_size = 8; 235 init_spi ( device ); 236 } 237 238 /** ST M25P32 serial flash */ 239 static inline __attribute__ (( always_inline )) void 240 init_m25p32 ( struct spi_device *device ) { 241 device->address_len = 24; 242 device->nvs.size = ( 4 * 1024 * 1024 ); 243 device->nvs.block_size = 256; 244 init_spi ( device ); 245 } 246 247 /** Microchip 25XX640 serial EEPROM */ 248 static inline __attribute__ (( always_inline )) void 249 init_mc25xx640 ( struct spi_device *device ) { 250 device->address_len = 16; 251 device->nvs.size = ( 8 * 1024 ); 252 device->nvs.block_size = 32; 253 init_spi ( device ); 254 } 255 256 /** @} */ 257 258 #endif /* _GPXE_SPI_H */ 259