Changed length parameter in SPI methods to be a byte length, rather than
[people/xl0/gpxe.git] / src / include / gpxe / spi.h
index 3ea8584..dba4c74 100644 (file)
@@ -9,8 +9,170 @@
 
 #include <gpxe/bitbash.h>
 
-/** An SPI interface */
-struct spi_interface {
+/**
+ * @defgroup spicmds SPI commands
+ * @{
+ */
+
+/** Write status register */
+#define SPI_WRSR 0x01
+
+/** Write data to memory array */
+#define SPI_WRITE 0x02
+
+/** Read data from memory array */
+#define SPI_READ 0x03
+
+/** Reset write enable latch */
+#define SPI_WRDI 0x04
+
+/** Read status register */
+#define SPI_RDSR 0x05
+
+/** Set write enable latch */
+#define SPI_WREN 0x06
+
+/**
+ * @defgroup atmelcmds Atmel-specific SPI commands
+ * @{
+ */
+
+/** Erase one sector in memory array (Not supported on all devices) */
+#define ATMEL_SECTOR_ERASE 0x52
+
+/** Erase all sections in memory array (Not supported on all devices) */
+#define ATMEL_CHIP_ERASE 0x62
+
+/** Read manufacturer and product ID (Not supported on all devices) */
+#define ATMEL_RDID 0x15
+
+/** @} */
+
+/** @} */
+
+/**
+ * @defgroup spistatus SPI status register bits (not present on all devices)
+ * @{
+ */
+
+/** Write-protect pin enabled */
+#define SPI_STATUS_WPEN 0x80
+
+/** Block protection bit 2 */
+#define SPI_STATUS_BP2 0x10
+
+/** Block protection bit 1 */
+#define SPI_STATUS_BP1 0x08
+
+/** Block protection bit 0 */
+#define SPI_STATUS_BP0 0x04
+
+/** State of the write enable latch */
+#define SPI_STATUS_WEN 0x02
+
+/** Device busy flag */
+#define SPI_STATUS_NRDY 0x01
+
+/** @} */
+
+struct spi_device;
+
+/**
+ * An SPI device type
+ *
+ * This data structure represents all the characteristics belonging to
+ * a particular type of SPI device, e.g. "an Atmel 251024 serial flash",
+ * or "a Microchip 25040 serial EEPROM".
+ */
+struct spi_device_type {
+       /** Word length, in bits */
+       unsigned int word_len;
+       /** Device size (in words) */
+       unsigned int size;
+       /** Data block size (in words)
+        *
+        * This is the block size used by the device.  It must be a
+        * power of two.  Data reads and writes must not cross a block
+        * boundary.
+        *
+        * Many devices allow reads to cross a block boundary, and
+        * restrict only writes.  For the sake of simplicity, we
+        * assume that the same restriction applies to both reads and
+        * writes.
+        */
+       unsigned int block_size;
+       /** Command length, in bits */
+       unsigned int command_len;
+       /** Address length, in bits */
+       unsigned int address_len;
+       /** Address is munged
+        *
+        * 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.  If this flag is set, then
+        * commands should be munged in this way.
+        */
+       unsigned int munge_address : 1;
+       /** Read data from device
+        *
+        * @v device            SPI device
+        * @v address           Address from which to read
+        * @v data              Data buffer
+        * @v len               Length of data buffer
+        * @ret rc              Return status code
+        */
+       int ( * read ) ( struct spi_device *device, unsigned int address,
+                        void *data, size_t len );
+       /** Write data to device
+        *
+        * @v device            SPI device
+        * @v address           Address to which to write
+        * @v data              Data buffer
+        * @v len               Length of data buffer
+        * @ret rc              Return status code
+        */
+       int ( * write ) ( struct spi_device *device, unsigned int address,
+                         const void *data, size_t len );
+};
+
+/**
+ * @defgroup spidevs SPI device types
+ * @{
+ */
+
+/** Atmel AT25010 serial EEPROM */
+#define AT25010 {              \
+       .word_len = 8,          \
+       .size = 128,            \
+       .block_size = 8,        \
+       .command_len = 8,       \
+       .address_len = 8,       \
+       }
+
+/** @} */
+
+/**
+ * An SPI device
+ *
+ * This data structure represents a real, physical SPI device attached
+ * to an SPI controller.  It comprises the device type plus
+ * instantiation-specific information such as the slave number.
+ */
+struct spi_device {
+       /** SPI device type */
+       struct spi_device_type *type;
+       /** SPI bus to which device is attached */
+       struct spi_bus *bus;
+       /** Slave number */
+       unsigned int slave;
+};
+
+/**
+ * An SPI bus
+ *
+ * 
+ */
+struct spi_bus {
        /** SPI interface mode
         *
         * This is the bitwise OR of zero or more of @c SPI_MODE_CPHA
@@ -22,29 +184,23 @@ struct spi_interface {
         */
        unsigned int mode;
        /**
-        * Select slave
-        *
-        * @v spi               SPI interface
-        * @v slave             Slave number
-        */
-       void ( * select_slave ) ( struct spi_interface *spi,
-                                 unsigned int slave );
-       /**
-        * Deselect slave
-        *
-        * @v spi               SPI interface
-        */
-       void ( * deselect_slave ) ( struct spi_interface *spi );
-       /**
-        * Transfer bits over SPI bit-bashing interface
+        * Read/write data via SPI bus
         *
-        * @v spi               SPI interface
+        * @v bus               SPI bus
+        * @v device            SPI device
+        * @v command           Command
+        * @v address           Address to read/write (<0 for no address)
         * @v data_out          TX data buffer (or NULL)
         * @v data_in           RX data buffer (or NULL)
-        * @v len               Length of transfer (in @b bits)
+        * @v len               Length of data buffer(s)
+        *
+        * This issues the specified command and optional address to
+        * the SPI device, then reads and/or writes data to/from the
+        * data buffers.
         */
-       void ( * transfer ) ( struct spi_interface *spi, const void *data_out,
-                             void *data_in, unsigned int len );
+       int ( * rw ) ( struct spi_bus *bus, struct spi_device *device,
+                      unsigned int command, int address,
+                      const void *data_out, void *data_in, size_t len );
 };
 
 /** Clock phase (CPHA) mode bit
@@ -91,42 +247,4 @@ struct spi_interface {
  */
 #define SPI_MODE_THREEWIRE ( SPI_MODE_MICROWIRE_PLUS | SPI_MODE_SSPOL )
 
-/** A bit-bashing SPI interface */
-struct spi_bit_basher {
-       /** SPI interface */
-       struct spi_interface spi;
-       /** Bit-bashing interface */
-       struct bit_basher basher;
-       /** Currently selected slave
-        *
-        * Valid only when a slave is actually selected.
-        */
-       unsigned int slave;
-};
-
-/** Bit indices used for SPI bit-bashing interface */
-enum {
-       /** Serial clock */
-       SPI_BIT_SCLK = 0,
-       /** Master Out Slave In */
-       SPI_BIT_MOSI,
-       /** Master In Slave Out */
-       SPI_BIT_MISO,
-       /** Slave 0 select */
-       SPI_BIT_SS0,
-};
-
-/**
- * Determine bit index for a particular slave
- *
- * @v slave            Slave number
- * @ret index          Bit index (i.e. SPI_BIT_SSN, where N=slave) 
- */
-#define SPI_BIT_SS( slave ) ( SPI_BIT_SS0 + (slave) )
-
-/** Delay between SCLK transitions */
-#define SPI_UDELAY 1
-
-extern void init_spi_bit_basher ( struct spi_bit_basher *spibit );
-
 #endif /* _GPXE_SPI_H */