37 #ifdef SHOW_WRITES_READS
45 #define _SF_PP 0x02 // 3 byte page program
46 #define _SF_READ 0x03 // 3 byte address read
47 #define _SF_SE 0xD8 // 3 byte sector erase
49 #define _SF_4READ 0x13 // 4 byte address read
50 #define _SF_4PP 0x12 // 4 byte address page program
51 #define _SF_4SE 0xDC // 4 byte sector erase
52 #define _SF_RDID 0x9F // Read identification
53 #define _SF_WRDI 0x04 // Write disable
54 #define _SF_WREN 0x06 // Write enable
55 #define _SF_RDSR 0x05 // Read status register
56 #define _SF_RDSR_BUSY 0x01 // Busy flag
57 #define _SF_RDSR_WEL 0x02 // Write enable latch.
62 #define _SF_SP_CLSR 0x30 // Clear status register (clear error)
64 #define _SF_SP_RDSR_E_PROG BIT(6)
65 #define _SF_SP_RDSR_E_ERASE BIT(5)
66 #define _SF_SP_RDSR_ERROR ( _SF_SP_RDSR_E_PROG | _SF_SP_RDSR_E_ERASE )
68 #define _SF_SP_RDCR 0x35
69 #define _SF_SP_RDCR_QUAD 0x02
71 #define _SF_SP_ASPRD 0x2B
72 #define _SF_SP_ASPP 0x2F
74 #define _SF_SP_ASP_DEFAULT 0xFFFF
76 #define _SF_SP_ASP_PWDMLB_ BIT(2)
77 #define _SF_SP_ASP_PSTMLB_ BIT(1)
79 #define _SF_SP_PLBRD 0xA7
80 #define _SF_SP_PLBWR 0xA6
82 #define _SF_SP_RESET 0xF0
84 #define _SF_SP_PPBRD 0xE2
85 #define _SF_SP_PPBP 0xE3
86 #define _SF_SP_PPBE 0xE4
88 #define _SF_SP_PASSRD 0xE7
89 #define _SF_SP_PASSP 0xE8
90 #define _SF_SP_PASSU 0xE9
93 #define _SF_SP_ABRD 0x14
95 #define _SF_SP_WRR 0x01
99 #define _SF_MI_RFLGR 0x70 // Read flags register
100 #define _SF_MI_CFLGR 0x50 // Clear status register (clear error)
101 #define _SF_MI_ENTER4 0xB7 // Enter 4 byte address mode
102 #define _SF_MI_RESET 0x66
105 #define _SF_RFLGR_E_PROT BIT(1)
106 #define _SF_RFLGR_E_VPP BIT(3)
107 #define _SF_RFLGR_E_PROGRAM BIT(4)
108 #define _SF_RFLGR_E_ERASE BIT(5)
109 #define _SF_RFLGS_ERROR ( _SF_RFLGR_E_PROT | _SF_RFLGR_E_VPP | _SF_RFLGR_E_PROGRAM | _SF_RFLGR_E_ERASE )
110 #define _SF_RFLGR_BUSY BIT(7)
140 _SF_4PP, _SF_4READ, _SF_4SE, _SF_SP_RESET,
141 _SF_RDSR, _SF_SP_RDSR_ERROR, _SF_SP_CLSR,
146 _SF_PP, _SF_READ, _SF_SE, _SF_MI_RESET,
147 _SF_MI_RFLGR, _SF_RFLGS_ERROR, _SF_MI_CFLGR,
152 _SF_PP, _SF_READ, _SF_SE, _SF_MI_RESET,
153 _SF_MI_RFLGR, _SF_RFLGS_ERROR, _SF_MI_CFLGR,
158 #define _SF_DEV_COUNT ( sizeof(devList) / sizeof(SfDevDesc) )
165 static bool sfReadReg(uint8_t reg, uint8_t * result,
int len) {
171 if (!
spiTxRx(FLASH_SPI_DEV, dta, dta, 1 + len))
goto fail;
173 for (i = 0; i < len; ++i) {
174 result[i] = dta[1 + i];
179 printf(
"Reading reg %02x:", reg);
180 for (i = 0; i < len; ++i) {
181 printf(
" %02x", result[i]);
195 static inline bool sfWriteReg(uint8_t reg, uint8_t * sequence,
int len) {
198 printf(
"Writing reg %02x:", reg);
199 for (i = 0; i < len; ++i) {
200 printf(
" %02x", sequence[i]);
206 static bool sfWriteReg(uint8_t reg, uint8_t * sequence,
int len)
213 printf(
"Writing reg %02x:", reg);
214 for (i = 0; i < len; ++i) {
215 printf(
" %02x", sequence[i]);
222 for (i = 0; i < len; ++i) dta[i + 1] = sequence[i];
225 r =
spiTxRx(FLASH_SPI_DEV, dta, NULL, 1 + len);
234 static bool sfAllOk()
237 if (!sfReadReg(dev->stsReg, &result, 1))
return false;
241 if (result & dev->stsRegErr) {
256 if (!sfReadReg(_SF_RDSR, &result, 1))
return false;
257 return result & _SF_RDSR_BUSY;
262 static inline bool sfPrepare()
275 static void sfCmdAddr(uint8_t cmd, uint32_t address, uint8_t * cmdOut)
278 switch (dev->addrBytes) {
280 cmdOut[1] = 0xff & ( address >> 16 );
281 cmdOut[2] = 0xff & ( address >> 8 );
282 cmdOut[3] = 0xff & ( address );
285 cmdOut[1] = 0xff & ( address >> 24 );
286 cmdOut[2] = 0xff & ( address >> 16 );
287 cmdOut[3] = 0xff & ( address >> 8 );
288 cmdOut[4] = 0xff & ( address );
296 static bool sfSimpleCommand(uint8_t cmd) {
298 if (!
spiTxRx(FLASH_SPI_DEV, &cmd, 0, 1))
goto fail;
313 static inline bool sfWriteEnable()
315 return sfSimpleCommand(_SF_WREN);
322 if (!sfSimpleCommand(dev->resetCmd))
return false;
328 static bool sfReadInfo()
337 sfSimpleCommand(_SF_SP_RESET);
347 uint8_t cmd[4] = { _SF_RDID, 0, 0, 0 };
350 if (!
spiTxRx(FLASH_SPI_DEV, cmd, rpl,
sizeof(cmd)))
goto fail;
353 sfInfo.
mfId = rpl[1];
354 sfInfo.
devId = rpl[2];
359 for (i = 0; i < _SF_DEV_COUNT; ++i) {
361 if (sfInfo.
mfId == devList[i].mfId && sfInfo.
devId == devList[i].devId && \
362 devList[i].capacity == sfInfo.
devCap) {
378 sfInfo.
sectorSize = dev->pageSize * dev->sectorSize;
379 sfInfo.
flashSize = dev->pageSize * dev->sectorSize * dev->flashSize;
381 sfInfo.
cap = dev->capability;
387 puts(
"Entering 4 byte mode");
389 if (!sfReadReg(0xB5, data, 2))
goto fail;
391 printf(
"Before: %02x %02x\n", data[0], data[1]);
393 if (!sfSimpleCommand(_SF_WREN))
goto fail;
394 if (!sfSimpleCommand(_SF_MI_ENTER4))
goto fail;
398 if (!sfReadReg(0xB5, data, 2))
goto fail;
400 printf(
"After: %02x %02x\n", data[0], data[1]);
406 if (!sfReadReg(_SF_SP_ASPRD, v.bytes, 2))
return false;
407 v.uint = LE2NS(v.uint);
408 if ((v.uint & _SF_SP_ASP_PWDMLB_) == 0) {
414 if (!sfReadReg(0xA7, &tmp, 1))
return false;
448 if (!sfPrepare())
return false;
451 if (!sfReadReg(_SF_SP_RDCR, &cr, 1))
goto fail;
454 if ((cr & _SF_SP_RDCR_QUAD) == ( enable ? _SF_SP_RDCR_QUAD : 0 ) )
return true;
460 if (!
spiTxRx(FLASH_SPI_DEV, cmd, 0, 1))
goto fail;
466 cmd[2] = enable? _SF_SP_RDCR_QUAD : 0;
467 if (!
spiTxRx(FLASH_SPI_DEV, cmd, 0, 3))
goto fail;
480 #ifdef SHOW_WRITES_READS
481 void sfDbgShow(
const char * op, uint32_t address, uint8_t * data, uint32_t len)
484 memset(title, 0,
sizeof(title));
485 sprintf(title,
"sf%s @ %08x", op, address);
486 showHex8(title, data, len);
491 bool sfRead(uint32_t address, uint8_t * data, uint32_t count)
493 if (!sfPrepare())
return false;
496 sfCmdAddr(dev->readCmd, address, cmd);
499 if (!
spiTxRx(FLASH_SPI_DEV, cmd, 0, dev->addrBytes + 1))
goto fail;
500 if (!
spiTxRx(FLASH_SPI_DEV, 0, data, count))
goto fail;
503 #ifdef SHOW_WRITES_READS
504 sfDbgShow(
"Read", address, data, count);
519 bool sfProg(uint32_t address, uint8_t * data, uint32_t count)
521 if (!sfPrepare())
return false;
522 if (!sfWriteEnable())
return false;
524 #ifdef SHOW_WRITES_READS
525 sfDbgShow(
"Prog", address, data, count);
531 sfCmdAddr(dev->progCmd, address, cmd);
534 if (!
spiTxRx(FLASH_SPI_DEV, cmd, 0, dev->addrBytes + 1))
goto fail;
535 if (!
spiTxRx(FLASH_SPI_DEV, data, 0, count))
goto fail;
547 bool sfProgXPage(uint32_t address, uint8_t * data, uint32_t count)
552 int bytes = count > free ? free : count;
553 if (!
sfProg(address, data, bytes)) {
566 if (!sfPrepare())
return false;
568 if (!sfWriteEnable())
return false;
571 sfCmdAddr(dev->eraseCmd, address, cmd);
573 if (!
spiTxRx(FLASH_SPI_DEV, cmd, 0, dev->addrBytes + 1))
goto fail;
598 if (!sfPrepare())
return false;
599 if (!sfWriteEnable())
return false;
601 if (!sfWriteReg(_SF_SP_PASSP, &((*password)[0]),
sizeof(
SfPassword))) {
602 puts(
"Could not write password");
606 if (!sfPrepare())
return false;
607 if (!sfReadReg(_SF_SP_PASSRD, &( verify[0]),
sizeof(
SfPassword)))
return false;
609 if (memcmp(&(verify[0]), &((*password)[0]),
sizeof(
SfPassword)) != 0)
614 if (!sfPrepare())
return false;
615 if (!sfWriteEnable())
return false;
617 b16_t asp = { .uint = 0xFFFF };
618 asp.uint ^= _SF_SP_ASP_PWDMLB_;
619 asp.uint = N2LES(asp.uint);
620 if (!sfWriteReg(_SF_SP_ASPP, asp.bytes,
sizeof(asp)))
return false;
632 sfReadReg(_SF_RDSR, &u8,
sizeof(u8));
633 printf(
"SR1 : %02x\n", u8);
634 sfReadReg(_SF_SP_RDCR, &u8,
sizeof(u8));
635 printf(
"CR1 : %02x\n", u8);
636 sfReadReg(_SF_SP_ASPRD, b16.bytes,
sizeof(b16));
637 b16.uint = LE2NS(b16.uint);
638 printf(
"ASP : %04x\n", b16.uint);
639 sfReadReg(_SF_SP_PLBRD, &u8,
sizeof(u8));
640 printf(
"PPBL: %02x\n", u8);
650 if (password == NULL) {
651 if (!sfWriteEnable())
return false;
652 if (!sfSimpleCommand(_SF_SP_PLBWR))
return false;
658 if (!sfWriteReg(_SF_SP_PASSU, &((*password)[0]),
sizeof(
SfPassword)))
return false;
676 if (!sfPrepare())
return false;
678 if (!sfWriteEnable())
return false;
682 sfCmdAddr(_SF_SP_PPBP, address, cmd);
684 r =
spiTxRx(FLASH_SPI_DEV, cmd, 0, dev->addrBytes + 1);
693 if (!sfPrepare())
return false;
695 if (!sfWriteEnable())
return false;
697 return sfSimpleCommand(_SF_SP_PPBE);
bool sfQuadEnable(bool enable)
Quad enable,.
bool sfLockUnlock(SfPassword *password)
Unlocks or locks the flash with the specified password.
uint8_t SfPassword[8]
Serial Flash password.
bool sfInit()
Initializes the Serial Flash.
void spiSelect(SPI_Device *dev, uint32_t slaveNo)
Selects a specific slave.
uint32_t flashSize
flash size in bytes
uint8_t mfId
Manufacturer ID.
#define SF_INFO_CAP_SECTOR_PROTECT
Device support per sector protection.
uint8_t _status
Hardware status register value.
#define SF_INFO_STS_PASSWORD_PROTECT
Whether (part of) the flash is password.
This driver wraps the functions of the OpenCores SPI master.
uint8_t cap
Device capabilities, see SF_INF_CAP_*.
SfInfo sfInfo
Flash info, only valid after successful initialization.
uint16_t pageSize
Page size in bytes.
void timeDelay(uint32_t msec)
Simple busy-wait delay.
uint32_t sectorSize
Sector size in bytes.
#define E_INVSTATE
Generic error: Module is in a state in which.
static uint32_t timeOutInit(uint32_t msec)
Initializes a timeout with the specified no of msecs.
static bool timeOut(uint32_t to)
Checks whether or not the timeout has expired.
bool sfReset()
Resets the flash.
Manages the global system error.
bool sfErase(uint32_t address)
Erase a sector in flash.
#define SF_INFO_STS_LOCKED
Whether part of the flash is locked.
void errPrint(bool clear)
Prints the last error.
uint8_t sts
Device status, see SF_INFO_STS_*.
bool sfSetPasswordOTP(SfPassword *password)
Password protects specific sectors from being modified.
#define SF_MF_SPANSION
Manufacturer Spansion.
#define SF_MF_MICRON
Manufacturer Micron.
bool sfProtect(uint32_t address)
Protects a specific sector from being erased or programmed.
void errClear()
Clears the current error.
bool sfProgXPage(uint32_t address, uint8_t *data, uint32_t count)
Program cross pages.
void spiDeselect(SPI_Device *dev)
Deselects all slaves.
This module is responsible for distributing error codes.
Various useful functions.
#define E_TIMEOUT
Generic error: Timeout error.
uint8_t devCap
Device capacity ID.
bool sfRead(uint32_t address, uint8_t *data, uint32_t count)
Read from a specific address in flash.
#define SF_INFO_CAP_PASSWORD
Device supports password protection.
This file assigns all device structures to memory mapped structures.
bool spiTxRx(SPI_Device *dev, uint8_t *dataIn, uint8_t *dataOut, int len)
Transfers a specific number of bytes in a synchronous way.
bool errSet(uint32_t code, const char *error, const char *name)
Sets an error.
#define ERROR(CODE,...)
Expands an error code to an error code with a description (if ERROR_W_DESCR is declared).
This driver implements access to the Serial Flash.
#define E_UNKNOWN
Generic error: Unknown error.
bool sfProg(uint32_t address, uint8_t *data, uint32_t count)
Program an page in flash.
void sfSpDiag()
Shows diagnostic state of Spansion Flash.
#define E_NOTSUPPORTED
Generic error: not supported.
Configures the board-specific peripherals, like I2C, SPI etc...
bool sfUnProtect()
Unprotects the entire flash array.