drv_spiflash.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. #include "xparameters.h"
  2. #include "xqspips.h"
  3. #define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
  4. #include <rthw.h>
  5. #include <rtdevice.h>
  6. #include "board.h"
  7. #define DBG_TAG "drv.spiflash"
  8. #define DBG_LVL DBG_INFO
  9. #include <rtdbg.h>
  10. #define WRITE_STATUS_CMD 0x01
  11. #define WRITE_CMD 0x02
  12. #define READ_CMD 0x03
  13. #define WRITE_DISABLE_CMD 0x04
  14. #define READ_STATUS_CMD 0x05
  15. #define WRITE_ENABLE_CMD 0x06
  16. #define FAST_READ_CMD 0x0B
  17. #define DUAL_READ_CMD 0x3B
  18. #define QUAD_READ_CMD 0x6B
  19. #define BULK_ERASE_CMD 0xC7
  20. #define SEC_ERASE_CMD 0xD8
  21. #define READ_ID 0x9F
  22. #define COMMAND_OFFSET 0 // FLASH instruction */
  23. #define ADDRESS_1_OFFSET 1 // MSB byte of address to read or write */
  24. #define ADDRESS_2_OFFSET 2 // Middle byte of address to read or write */
  25. #define ADDRESS_3_OFFSET 3 // LSB byte of address to read or write */
  26. #define DATA_OFFSET 4 // Start of Data for Read/Write */
  27. #define DUMMY_OFFSET 4 // Dummy byte offset for fast, dual and quad reads
  28. #define DUMMY_SIZE 1 // Number of dummy bytes for fast, dual and quad reads
  29. #define RD_ID_SIZE 4 // Read ID command + 3 bytes ID response */
  30. #define BULK_ERASE_SIZE 1 // Bulk Erase command size */
  31. #define SEC_ERASE_SIZE 4 // Sector Erase command + Sector address */
  32. #define OVERHEAD_SIZE 4 // control information: command and address
  33. #define SECTOR_SIZE 0x10000
  34. #define NUM_SECTORS 0x200
  35. #define NUM_PAGES 0x10000
  36. #define PAGE_SIZE 256
  37. static XQspiPs qspi_dev;
  38. static u8 ReadBuffer[PAGE_SIZE + DATA_OFFSET + DUMMY_SIZE];
  39. static u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET];
  40. static int FlashReadID(void);
  41. static void FlashQuadEnable(XQspiPs *QspiPtr);
  42. static int init(void)
  43. {
  44. int Status;
  45. XQspiPs_Config *QspiConfig;
  46. QspiConfig = XQspiPs_LookupConfig(QSPI_DEVICE_ID);
  47. if (QspiConfig == NULL) {
  48. LOG_E("lockup failed");
  49. return XST_FAILURE;
  50. }
  51. Status = XQspiPs_CfgInitialize(&qspi_dev, QspiConfig,
  52. QspiConfig->BaseAddress);
  53. if (Status != XST_SUCCESS) {
  54. LOG_E("cfg init failed : %d", Status);
  55. return XST_FAILURE;
  56. }
  57. XQspiPs_SetOptions(&qspi_dev, XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION);
  58. XQspiPs_SetClkPrescaler(&qspi_dev, XQSPIPS_CLK_PRESCALE_8);
  59. XQspiPs_SetSlaveSelect(&qspi_dev);
  60. FlashReadID();
  61. FlashQuadEnable(&qspi_dev);
  62. return XST_SUCCESS;
  63. }
  64. /*****************************************************************************/
  65. /**
  66. *
  67. * This function writes to the serial FLASH connected to the QSPI interface.
  68. * All the data put into the buffer must be in the same page of the device with
  69. * page boundaries being on 256 byte boundaries.
  70. *
  71. * @param QspiPtr is a pointer to the QSPI driver component to use.
  72. * @param Address contains the address to write data to in the FLASH.
  73. * @param ByteCount contains the number of bytes to write.
  74. * @param Command is the command used to write data to the flash. QSPI
  75. * device supports only Page Program command to write data to the
  76. * flash.
  77. *
  78. * @return None.
  79. *
  80. * @note None.
  81. *
  82. ******************************************************************************/
  83. rt_inline void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
  84. {
  85. u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
  86. u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
  87. u8 FlashStatus[2];
  88. /*
  89. * Send the write enable command to the FLASH so that it can be
  90. * written to, this needs to be sent as a seperate transfer before
  91. * the write
  92. */
  93. XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
  94. sizeof(WriteEnableCmd));
  95. /*
  96. * Setup the write command with the specified address and data for the
  97. * FLASH
  98. */
  99. WriteBuffer[COMMAND_OFFSET] = Command;
  100. WriteBuffer[ADDRESS_1_OFFSET] = (u8) ((Address & 0xFF0000) >> 16);
  101. WriteBuffer[ADDRESS_2_OFFSET] = (u8) ((Address & 0xFF00) >> 8);
  102. WriteBuffer[ADDRESS_3_OFFSET] = (u8) (Address & 0xFF);
  103. /*
  104. * Send the write command, address, and data to the FLASH to be
  105. * written, no receive buffer is specified since there is nothing to
  106. * receive
  107. */
  108. XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
  109. ByteCount + OVERHEAD_SIZE);
  110. /*
  111. * Wait for the write command to the FLASH to be completed, it takes
  112. * some time for the data to be written
  113. */
  114. while (1) {
  115. /*
  116. * Poll the status register of the FLASH to determine when it
  117. * completes, by sending a read status command and receiving the
  118. * status byte
  119. */
  120. XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
  121. sizeof(ReadStatusCmd));
  122. /*
  123. * If the status indicates the write is done, then stop waiting,
  124. * if a value of 0xFF in the status byte is read from the
  125. * device and this loop never exits, the device slave select is
  126. * possibly incorrect such that the device status is not being
  127. * read
  128. */
  129. if ((FlashStatus[1] & 0x01) == 0) {
  130. break;
  131. }
  132. }
  133. }
  134. static int write(long offset, const uint8_t *buf, size_t size)
  135. {
  136. RT_ASSERT(size > 0 && size % PAGE_SIZE == 0 && offset % PAGE_SIZE == 0);
  137. for (int pos = 0; pos < size; pos += PAGE_SIZE)
  138. {
  139. rt_memcpy(&WriteBuffer[DATA_OFFSET], &buf[pos], PAGE_SIZE);
  140. FlashWrite(&qspi_dev, offset + pos, PAGE_SIZE, WRITE_CMD);
  141. }
  142. return size;
  143. }
  144. /*****************************************************************************/
  145. /**
  146. *
  147. * This function reads from the serial FLASH connected to the
  148. * QSPI interface.
  149. *
  150. * @param QspiPtr is a pointer to the QSPI driver component to use.
  151. * @param Address contains the address to read data from in the FLASH.
  152. * @param ByteCount contains the number of bytes to read.
  153. * @param Command is the command used to read data from the flash. QSPI
  154. * device supports one of the Read, Fast Read, Dual Read and Fast
  155. * Read commands to read data from the flash.
  156. *
  157. * @return None.
  158. *
  159. * @note None.
  160. *
  161. ******************************************************************************/
  162. rt_inline void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
  163. {
  164. /*
  165. * Setup the write command with the specified address and data for the
  166. * FLASH
  167. */
  168. WriteBuffer[COMMAND_OFFSET] = Command;
  169. WriteBuffer[ADDRESS_1_OFFSET] = (u8) ((Address & 0xFF0000) >> 16);
  170. WriteBuffer[ADDRESS_2_OFFSET] = (u8) ((Address & 0xFF00) >> 8);
  171. WriteBuffer[ADDRESS_3_OFFSET] = (u8) (Address & 0xFF);
  172. if ((Command == FAST_READ_CMD) || (Command == DUAL_READ_CMD)
  173. || (Command == QUAD_READ_CMD)) {
  174. ByteCount += DUMMY_SIZE;
  175. }
  176. /*
  177. * Send the read command to the FLASH to read the specified number
  178. * of bytes from the FLASH, send the read command and address and
  179. * receive the specified number of bytes of data in the data buffer
  180. */
  181. XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, ReadBuffer,
  182. ByteCount + OVERHEAD_SIZE);
  183. }
  184. static int read(long offset, uint8_t *buf, size_t size)
  185. {
  186. RT_ASSERT(size > 0 && size % PAGE_SIZE == 0 && offset % PAGE_SIZE == 0);
  187. for (int pos = 0; pos < size; pos += PAGE_SIZE)
  188. {
  189. FlashRead(&qspi_dev, offset + pos, PAGE_SIZE, QUAD_READ_CMD);
  190. rt_memcpy(&buf[pos], &ReadBuffer[DATA_OFFSET + DUMMY_SIZE], PAGE_SIZE);
  191. }
  192. return size;
  193. }
  194. /*****************************************************************************/
  195. /**
  196. *
  197. * This function erases the sectors in the serial FLASH connected to the
  198. * QSPI interface.
  199. *
  200. * @param QspiPtr is a pointer to the QSPI driver component to use.
  201. * @param Address contains the address of the first sector which needs to
  202. * be erased.
  203. * @param ByteCount contains the total size to be erased.
  204. *
  205. * @return None.
  206. *
  207. * @note None.
  208. *
  209. ******************************************************************************/
  210. rt_inline void Erase (XQspiPs *QspiPtr, u32 Address, u32 ByteCount)
  211. {
  212. u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
  213. u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
  214. u8 FlashStatus[2];
  215. int Sector;
  216. int total_sector;
  217. /*
  218. * If erase size is same as the total size of the flash, use bulk erase
  219. * command
  220. */
  221. if (ByteCount == (NUM_SECTORS * SECTOR_SIZE)) {
  222. /*
  223. * Send the write enable command to the FLASH so that it can be
  224. * written to, this needs to be sent as a seperate transfer
  225. * before the erase
  226. */
  227. XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
  228. sizeof(WriteEnableCmd));
  229. /* Setup the bulk erase command*/
  230. WriteBuffer[COMMAND_OFFSET] = BULK_ERASE_CMD;
  231. /*
  232. * Send the bulk erase command; no receive buffer is specified
  233. * since there is nothing to receive
  234. */
  235. XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
  236. BULK_ERASE_SIZE);
  237. /* Wait for the erase command to the FLASH to be completed*/
  238. while (1) {
  239. /*
  240. * Poll the status register of the device to determine
  241. * when it completes, by sending a read status command
  242. * and receiving the status byte
  243. */
  244. XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
  245. sizeof(ReadStatusCmd));
  246. /*
  247. * If the status indicates the write is done, then stop
  248. * waiting; if a value of 0xFF in the status byte is
  249. * read from the device and this loop never exits, the
  250. * device slave select is possibly incorrect such that
  251. * the device status is not being read
  252. */
  253. if ((FlashStatus[1] & 0x01) == 0) {
  254. break;
  255. }
  256. }
  257. return;
  258. }
  259. /*
  260. * If the erase size is less than the total size of the flash, use
  261. * sector erase command
  262. */
  263. total_sector = RT_ALIGN(ByteCount, SECTOR_SIZE) / SECTOR_SIZE;
  264. for (Sector = 0; Sector < total_sector; Sector++) {
  265. /*
  266. * Send the write enable command to the SEEPOM so that it can be
  267. * written to, this needs to be sent as a seperate transfer
  268. * before the write
  269. */
  270. XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
  271. sizeof(WriteEnableCmd));
  272. /*
  273. * Setup the write command with the specified address and data
  274. * for the FLASH
  275. */
  276. WriteBuffer[COMMAND_OFFSET] = SEC_ERASE_CMD;
  277. WriteBuffer[ADDRESS_1_OFFSET] = (u8) (Address >> 16);
  278. WriteBuffer[ADDRESS_2_OFFSET] = (u8) (Address >> 8);
  279. WriteBuffer[ADDRESS_3_OFFSET] = (u8) (Address & 0xFF);
  280. /*
  281. * Send the sector erase command and address; no receive buffer
  282. * is specified since there is nothing to receive
  283. */
  284. XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
  285. SEC_ERASE_SIZE);
  286. /*
  287. * Wait for the sector erse command to the
  288. * FLASH to be completed
  289. */
  290. while (1) {
  291. /*
  292. * Poll the status register of the device to determine
  293. * when it completes, by sending a read status command
  294. * and receiving the status byte
  295. */
  296. XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
  297. sizeof(ReadStatusCmd));
  298. /*
  299. * If the status indicates the write is done, then stop
  300. * waiting, if a value of 0xFF in the status byte is
  301. * read from the device and this loop never exits, the
  302. * device slave select is possibly incorrect such that
  303. * the device status is not being read
  304. */
  305. if ((FlashStatus[1] & 0x01) == 0) {
  306. break;
  307. }
  308. }
  309. Address += SECTOR_SIZE;
  310. }
  311. }
  312. static int erase(long offset, size_t size)
  313. {
  314. Erase(&qspi_dev, offset, size);
  315. return size % SECTOR_SIZE == 0? size : (size / SECTOR_SIZE + 1) * SECTOR_SIZE;
  316. }
  317. /*****************************************************************************/
  318. /**
  319. *
  320. * This function reads serial FLASH ID connected to the SPI interface.
  321. *
  322. * @param None.
  323. *
  324. * @return XST_SUCCESS if read id, otherwise XST_FAILURE.
  325. *
  326. * @note None.
  327. *
  328. ******************************************************************************/
  329. static int FlashReadID(void)
  330. {
  331. int Status;
  332. /* Read ID in Auto mode.*/
  333. WriteBuffer[COMMAND_OFFSET] = READ_ID;
  334. WriteBuffer[ADDRESS_1_OFFSET] = 0x23; /* 3 dummy bytes */
  335. WriteBuffer[ADDRESS_2_OFFSET] = 0x08;
  336. WriteBuffer[ADDRESS_3_OFFSET] = 0x09;
  337. Status = XQspiPs_PolledTransfer(&qspi_dev, WriteBuffer, ReadBuffer, RD_ID_SIZE);
  338. if (Status != XST_SUCCESS) {
  339. return XST_FAILURE;
  340. }
  341. LOG_I("FlashID=0x%x 0x%x 0x%x\n\r", ReadBuffer[1], ReadBuffer[2], ReadBuffer[3]);
  342. return XST_SUCCESS;
  343. }
  344. /*****************************************************************************/
  345. /**
  346. *
  347. * This function enables quad mode in the serial flash connected to the
  348. * SPI interface.
  349. *
  350. * @param QspiPtr is a pointer to the QSPI driver component to use.
  351. *
  352. * @return None.
  353. *
  354. * @note None.
  355. *
  356. ******************************************************************************/
  357. static void FlashQuadEnable(XQspiPs *QspiPtr)
  358. {
  359. u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
  360. u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 };
  361. u8 QuadEnableCmd[] = { WRITE_STATUS_CMD, 0 };
  362. u8 FlashStatus[2];
  363. if (ReadBuffer[1] == 0x9D) {
  364. XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
  365. sizeof(ReadStatusCmd));
  366. QuadEnableCmd[1] = FlashStatus[1] | 1 << 6;
  367. XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
  368. sizeof(WriteEnableCmd));
  369. XQspiPs_PolledTransfer(QspiPtr, QuadEnableCmd, NULL,
  370. sizeof(QuadEnableCmd));
  371. }
  372. }
  373. #include "fal.h"
  374. const struct fal_flash_dev spi_flash =
  375. {
  376. .name = "spi_flash",
  377. .addr = 0x00000000,
  378. .len = NUM_SECTORS * SECTOR_SIZE,
  379. .blk_size = PAGE_SIZE,
  380. .ops = {init, read, write, erase},
  381. .write_gran = PAGE_SIZE,
  382. };
  383. static int rt_hw_on_chip_flash_init(void)
  384. {
  385. fal_init();
  386. return RT_EOK;
  387. }
  388. INIT_ENV_EXPORT(rt_hw_on_chip_flash_init);