#ifndef SPIFLASH_H #define SPIFLASH_H #include #include #include #include "fwimg.h" /* SPI flash command opcodes */ enum romcmd { /* Standard SPI mode commands */ ROM_WRITE_ENABLE = 0x06, ROM_VOLATILE_SR_WRITE_ENABLE = 0x50, ROM_WRITE_DISABLE = 0x04, ROM_RELEASE_POWERDOWN_ID = 0xab, ROM_MANUFACTURER_DEVICE_ID = 0x90, ROM_JEDEC_ID = 0x9f, ROM_READ_UNIQUE_ID = 0x4b, ROM_READ_DATA = 0x03, /* DO NOT USE */ ROM_READ_DATA_32BIT = 0x13, /* DO NOT USE */ ROM_FAST_READ = 0x0b, ROM_FAST_READ_32BIT = 0x0c, ROM_PAGE_PROGRAM = 0x02, ROM_PAGE_PROGRAM_32BIT = 0x12, ROM_ERASE_4K = 0x20, ROM_ERASE_4K_32BIT = 0x21, ROM_ERASE_32K = 0x52, ROM_ERASE_64K = 0xd8, ROM_ERASE_64K_32BIT = 0xdc, ROM_ERASE_ALL = 0xc7, ROM_READ_SR1 = 0x05, ROM_WRITE_SR1 = 0x01, ROM_READ_SR2 = 0x35, ROM_WRITE_SR2 = 0x31, ROM_READ_SR3 = 0x15, ROM_WRITE_SR3 = 0x11, ROM_READ_EAR = 0xc8, /* Extended address register */ ROM_WRITE_EAR = 0xc5, ROM_READ_SFDP = 0x5a, ROM_ERASE_SECURITY = 0x44, ROM_PROGRAM_SECURITY = 0x42, ROM_READ_SECURITY = 0x48, ROM_GLOBAL_BLOCK_LOCK = 0x7e, ROM_GLOBAL_BLOCK_UNLOCK = 0x98, ROM_READ_BLOCK_LOCK = 0x3d, ROM_ONE_BLOCK_LOCK = 0x36, ROM_ONE_BLOCK_UNLOCK = 0x39, ROM_ERASE_PROGRAM_SUSPEND = 0x75, ROM_ERASE_PROGRAM_RESUME = 0x7a, ROM_POWER_DOWN = 0xb9, ROM_ENTER_32BIT = 0xb7, ROM_LEAVE_32BIT = 0xe9, ROM_ENTER_QPI = 0x48, ROM_ENABLE_RESET = 0x66, ROM_RESET = 0x99, /* Dual SPI commands */ ROM_FAST_READ_DUAL = 0x3b, ROM_FAST_READ_DUAL_32BIT = 0x3c }; #define SPIFLASH_SFDP_SIZE 256 /* * A page is an amount that can be programmed in one operation. * A sector is the minimum amount that can be erased in one operation. * A block is the optimal amount that can be erased in one operation. * * These are defined in hardware! */ #define SPIFLASH_PAGE_SHIFT 8 /* May be smaller than an actual page */ #define SPIFLASH_PAGE_SIZE (1 << SPIFLASH_PAGE_SHIFT) #define SPIFLASH_SECTOR_SHIFT 12 #define SPIFLASH_SECTOR_SIZE (1 << SPIFLASH_SECTOR_SHIFT) #define SPIFLASH_BLOCK_SHIFT 16 #define SPIFLASH_BLOCK_SIZE (1 << SPIFLASH_BLOCK_SHIFT) /* * Interface to the host. This structure should be passed in to the * initialization routine and will not be modified by the spiflash * routines. * * The spiflash code is reentrant if there are multiple SPI flash * devices. None are timing critical and may be preempted at any * time if applicable. When CS# is active (during spi_read or spi_write), * it MUST NOT be deasserted; if the bus is shared HOLD# can be asserted * (without deasserting CS#) to make the device release the bus without * affecting the state of the device. * * CS# will not be asserted while running in the core code or when * blocking for I/O; the host is obviously allowed to prefetch I/O * within the above constraints if the bus is shared. * * A private cookie pointer is passed to each function; this can be a * pointer back to the spiflash_ops structure, but does not have to * be. */ struct spiflash_ops { /* * Perform a SPI write operation. The SPI write operation consists of: * 1. Assert CS# (and deassert HOLD# if applicable) * 2. Transmit the command bytes (discard MISO input) * 3. Transmit the data bytes (discard MISO input) * 4. Deassert CS# * 5. Wait tCHSL (see SPI data table below) * * The number of data bytes may be zero. Note that the command * and data operations are identical and are separated only to * avoid unnecessary data copies. * * If this returns nonzero, no further operations are performed * and the top-level flash routine terminates immediately with * the returned value as a status code. * * It is not required that this routine blocks until tCHSL * is satisfied, however, the host is responsible to not assert * CS# again until tCHSL is satisfied. The SPI clock may run * or not during that time period. * * The SPI flash supports SPI modes 0 and 3. */ int (*spi_write)(void *cookie, const void *cmd, unsigned int cmd_len, const void *data, unsigned int data_len, int tshsl); /* * Perform a SPI read operation. The SPI read operation consists of: * 1. Assert CS# (and deassert HOLD# if applicable) * 2. Transmit the command bytes (discard MISO input) * 3. Receive the data bytes (MOSI is don't care) * 4. Deassert CS# * 5. Wait tCHSL (see SPI data table below) * * The number of data bytes may be zero. Note that the command * and data operations are identical and are separated only to * avoid unnecessary data copies. * * If this returns nonzero, no further operations are performed * and the top-level flash routine terminates immediately with * the returned value as a status code. * * It is not required that this routine blocks until tCHSL * is satisfied, however, the host is responsible to not assert * CS# again until tCHSL is satisfied. The SPI clock may run * or not during that time period. * * The SPI flash supports SPI modes 0 and 3. */ int (*spi_read)(void *cookie, const void *cmd, unsigned int cmd_len, void *data, unsigned int data_len, int tshsl); /* * Inform the host that the spiflash code is waiting for an * program or erase operation to complete. This can be used to * yield the host for other operations. * * The value passed in is the corresponding from the SPI data * table below; these are arbitrary cookies/units as far as the * spiflash code is concerned. * * This function may be NULL, in which case the SPI flash is polled * continously. */ void (*yield)(void *cookie, int delay); }; /* * This table provides some parameters for the SPI flash. */ enum spiflash_addr_mode { SPIFLASH_ADDR_DYNAMIC, /* 24-bit for < 16 MB, otherwise 32 bit */ SPIFLASH_ADDR_24BIT, /* 24-bit addressing only */ SPIFLASH_ADDR_32BIT /* 32-bit addressing only */ }; struct spiflash_param { /* * Addressing mode (see above.) If SPIFLASH_ADDR_DYNAMIC is * specified (default), the chip is assumed to be in 24-bit-default * mode, and 32-bit opcodes will be used as needed. */ enum spiflash_addr_mode addr; /* * CS# deselect times passed to spi_read() and spi_write(). * Arbitrary units or cookies that are only interpreted by * the spi_read and spi_write routines. */ int tshsl; /* All other operations */ int tshsl1; /* Read operations */ int tshsl2; /* Erase, Program, and Write operations */ /* * Delay values to pass to the yield operation. Arbitrary units * or cookies that are only interpreted by the yield routine. * * Not all of these are used by the current code, but are specified * for future-proofing reasons. */ int trst; /* Reset command to next instruction */ int tw; /* Write Status Register Time */ int tpp; /* Page Program Time */ int tse; /* Sector Erase Time (4K) */ int tbe1; /* Block Erase Time (32K) */ int tbe2; /* Block Erase Time (64K) */ int tce; /* Chip Erase Time */ }; /* Common structure for the above */ struct spiflash { /* * Read input data for flash write. Return the number of bytes * read. A short read or a 0 byte return value represents end of * file/end of data; a negative value is treated as 0, and will be * returned from the top-level operation as a status code. * * It is not required to detect end of input if and only if the * input is a gzip file, as in that case the gzip data will contain * an end of stream indicator. * * The buffer initially passed to this function will always be * aligned to a malloc() alignment boundary; it will preserve * alignment boundaries if and only if short read returns only byte * counts in multiple of those alignment boundaries. * * If there is a memory buffer available containing full or * partial input data on entry, pass it to spiflash_flash_file(); * If this memory buffer contains all available input, this * function can be NULL. * * A partial memory buffer must contain a full stream header block. */ int (*read_data)(void *cookie, void *buf, unsigned int bufsize); void *cookie; /* Pointer passed to spiflash_ops functions */ /* * Operations on the SPI flash itself; if ops == NULL then this is a * dry run operation. */ const struct spiflash_ops *ops; const struct spiflash_param *param; const char *target; /* What are we programming? */ }; /* * Top-level operations. These may return an error value from the ops * functions, any of the negative error values defined in zlib.h, * or one of the above error codes. */ int spiflash_flash_file(const struct spiflash *flash, void *data, size_t datalen); /* * Flash a single region of data to the SPI flash. */ int spiflash_flash_data(const struct spiflash *flash, uint32_t addr, const void *data, size_t datalen); /* * Read identifying data from SPI flash. */ #define SPIFLASH_ID_LEN 8 int spiflash_read_id(const struct spiflash *flash, void *id); #define SPIFLASH_VDID_LEN 2 int spiflash_read_vdid(const struct spiflash *flash, void *vdid); #endif