stm_m25p64.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. /****************************************************************************
  2. * SPI flash driver for M25P64
  3. ****************************************************************************/
  4. #include <common.h>
  5. #include <linux/ctype.h>
  6. #include <asm/io.h>
  7. #if defined(CONFIG_SPI)
  8. /* Application definitions */
  9. #define NUM_SECTORS 128 /* number of sectors */
  10. #define SECTOR_SIZE 0x10000
  11. #define NOP_NUM 1000
  12. #define COMMON_SPI_SETTINGS (SPE|MSTR|CPHA|CPOL) /* Settings to the SPI_CTL */
  13. #define TIMOD01 (0x01) /* stes the SPI to work with core instructions */
  14. /* Flash commands */
  15. #define SPI_WREN (0x06) /*Set Write Enable Latch */
  16. #define SPI_WRDI (0x04) /*Reset Write Enable Latch */
  17. #define SPI_RDSR (0x05) /*Read Status Register */
  18. #define SPI_WRSR (0x01) /*Write Status Register */
  19. #define SPI_READ (0x03) /*Read data from memory */
  20. #define SPI_FAST_READ (0x0B) /*Read data from memory */
  21. #define SPI_PP (0x02) /*Program Data into memory */
  22. #define SPI_SE (0xD8) /*Erase one sector in memory */
  23. #define SPI_BE (0xC7) /*Erase all memory */
  24. #define WIP (0x1) /*Check the write in progress bit of the SPI status register */
  25. #define WEL (0x2) /*Check the write enable bit of the SPI status register */
  26. #define TIMEOUT 350000000
  27. typedef enum {
  28. NO_ERR,
  29. POLL_TIMEOUT,
  30. INVALID_SECTOR,
  31. INVALID_BLOCK,
  32. } ERROR_CODE;
  33. void spi_init_f(void);
  34. void spi_init_r(void);
  35. ssize_t spi_read(uchar *, int, uchar *, int);
  36. ssize_t spi_write(uchar *, int, uchar *, int);
  37. char ReadStatusRegister(void);
  38. void Wait_For_SPIF(void);
  39. void SetupSPI(const int spi_setting);
  40. void SPI_OFF(void);
  41. void SendSingleCommand(const int iCommand);
  42. ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector);
  43. ERROR_CODE EraseBlock(int nBlock);
  44. ERROR_CODE ReadData(unsigned long ulStart, long lCount, int *pnData);
  45. ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData);
  46. ERROR_CODE Wait_For_Status(char Statusbit);
  47. ERROR_CODE Wait_For_WEL(void);
  48. /*
  49. * Function: spi_init_f
  50. * Description: Init SPI-Controller (ROM part)
  51. * return: ---
  52. */
  53. void spi_init_f(void)
  54. {
  55. }
  56. /*
  57. * Function: spi_init_r
  58. * Description: Init SPI-Controller (RAM part) -
  59. * The malloc engine is ready and we can move our buffers to
  60. * normal RAM
  61. * return: ---
  62. */
  63. void spi_init_r(void)
  64. {
  65. return;
  66. }
  67. /*
  68. * Function: spi_write
  69. */
  70. ssize_t spi_write(uchar * addr, int alen, uchar * buffer, int len)
  71. {
  72. unsigned long offset;
  73. int start_block, end_block;
  74. int start_byte, end_byte;
  75. ERROR_CODE result = NO_ERR;
  76. uchar temp[SECTOR_SIZE];
  77. int i, num;
  78. offset = addr[0] << 16 | addr[1] << 8 | addr[2];
  79. /* Get the start block number */
  80. result = GetSectorNumber(offset, &start_block);
  81. if (result == INVALID_SECTOR) {
  82. printf("Invalid sector! ");
  83. return 0;
  84. }
  85. /* Get the end block number */
  86. result = GetSectorNumber(offset + len - 1, &end_block);
  87. if (result == INVALID_SECTOR) {
  88. printf("Invalid sector! ");
  89. return 0;
  90. }
  91. for (num = start_block; num <= end_block; num++) {
  92. ReadData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp);
  93. start_byte = num * SECTOR_SIZE;
  94. end_byte = (num + 1) * SECTOR_SIZE - 1;
  95. if (start_byte < offset)
  96. start_byte = offset;
  97. if (end_byte > (offset + len))
  98. end_byte = (offset + len - 1);
  99. for (i = start_byte; i <= end_byte; i++)
  100. temp[i - num * SECTOR_SIZE] = buffer[i - offset];
  101. EraseBlock(num);
  102. result = WriteData(num * SECTOR_SIZE, SECTOR_SIZE, (int *)temp);
  103. if (result != NO_ERR)
  104. return 0;
  105. printf(".");
  106. }
  107. return len;
  108. }
  109. /*
  110. * Function: spi_read
  111. */
  112. ssize_t spi_read(uchar * addr, int alen, uchar * buffer, int len)
  113. {
  114. unsigned long offset;
  115. offset = addr[0] << 16 | addr[1] << 8 | addr[2];
  116. ReadData(offset, len, (int *)buffer);
  117. return len;
  118. }
  119. void SendSingleCommand(const int iCommand)
  120. {
  121. unsigned short dummy;
  122. /* turns on the SPI in single write mode */
  123. SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
  124. /* sends the actual command to the SPI TX register */
  125. *pSPI_TDBR = iCommand;
  126. sync();
  127. /* The SPI status register will be polled to check the SPIF bit */
  128. Wait_For_SPIF();
  129. dummy = *pSPI_RDBR;
  130. /* The SPI will be turned off */
  131. SPI_OFF();
  132. }
  133. void SetupSPI(const int spi_setting)
  134. {
  135. if (icache_status() || dcache_status())
  136. udelay(CONFIG_CCLK_HZ / 50000000);
  137. /*sets up the PF10 to be the slave select of the SPI */
  138. *pPORTF_FER |= (PF10 | PF11 | PF12 | PF13);
  139. *pSPI_FLG = 0xFF02;
  140. *pSPI_BAUD = CONFIG_SPI_BAUD;
  141. *pSPI_CTL = spi_setting;
  142. sync();
  143. *pSPI_FLG = 0xFD02;
  144. sync();
  145. }
  146. void SPI_OFF(void)
  147. {
  148. *pSPI_CTL = 0x0400; /* disable SPI */
  149. *pSPI_FLG = 0;
  150. *pSPI_BAUD = 0;
  151. sync();
  152. udelay(CONFIG_CCLK_HZ / 50000000);
  153. }
  154. void Wait_For_SPIF(void)
  155. {
  156. unsigned short dummyread;
  157. while ((*pSPI_STAT & TXS)) ;
  158. while (!(*pSPI_STAT & SPIF)) ;
  159. while (!(*pSPI_STAT & RXS)) ;
  160. /* Read dummy to empty the receive register */
  161. dummyread = *pSPI_RDBR;
  162. }
  163. ERROR_CODE Wait_For_WEL(void)
  164. {
  165. int i;
  166. char status_register = 0;
  167. ERROR_CODE ErrorCode = NO_ERR;
  168. for (i = 0; i < TIMEOUT; i++) {
  169. status_register = ReadStatusRegister();
  170. if ((status_register & WEL)) {
  171. ErrorCode = NO_ERR;
  172. break;
  173. }
  174. ErrorCode = POLL_TIMEOUT; /* Time out error */
  175. };
  176. return ErrorCode;
  177. }
  178. ERROR_CODE Wait_For_Status(char Statusbit)
  179. {
  180. int i;
  181. char status_register = 0xFF;
  182. ERROR_CODE ErrorCode = NO_ERR;
  183. for (i = 0; i < TIMEOUT; i++) {
  184. status_register = ReadStatusRegister();
  185. if (!(status_register & Statusbit)) {
  186. ErrorCode = NO_ERR;
  187. break;
  188. }
  189. ErrorCode = POLL_TIMEOUT; /* Time out error */
  190. };
  191. return ErrorCode;
  192. }
  193. char ReadStatusRegister(void)
  194. {
  195. char status_register = 0;
  196. SetupSPI((COMMON_SPI_SETTINGS | TIMOD01)); /* Turn on the SPI */
  197. *pSPI_TDBR = SPI_RDSR; /* send instruction to read status register */
  198. sync();
  199. Wait_For_SPIF(); /*wait until the instruction has been sent */
  200. *pSPI_TDBR = 0; /*send dummy to receive the status register */
  201. sync();
  202. Wait_For_SPIF(); /*wait until the data has been sent */
  203. status_register = *pSPI_RDBR; /*read the status register */
  204. SPI_OFF(); /* Turn off the SPI */
  205. return status_register;
  206. }
  207. ERROR_CODE GetSectorNumber(unsigned long ulOffset, int *pnSector)
  208. {
  209. int nSector = 0;
  210. ERROR_CODE ErrorCode = NO_ERR;
  211. if (ulOffset > (NUM_SECTORS * 0x10000 - 1)) {
  212. ErrorCode = INVALID_SECTOR;
  213. return ErrorCode;
  214. }
  215. nSector = (int)ulOffset / 0x10000;
  216. *pnSector = nSector;
  217. return ErrorCode;
  218. }
  219. ERROR_CODE EraseBlock(int nBlock)
  220. {
  221. unsigned long ulSectorOff = 0x0, ShiftValue;
  222. ERROR_CODE ErrorCode = NO_ERR;
  223. /* if the block is invalid just return */
  224. if ((nBlock < 0) || (nBlock > NUM_SECTORS)) {
  225. ErrorCode = INVALID_BLOCK;
  226. return ErrorCode;
  227. }
  228. /* figure out the offset of the block in flash */
  229. if ((nBlock >= 0) && (nBlock < NUM_SECTORS)) {
  230. ulSectorOff = (nBlock * SECTOR_SIZE);
  231. } else {
  232. ErrorCode = INVALID_BLOCK;
  233. return ErrorCode;
  234. }
  235. /* A write enable instruction must previously have been executed */
  236. SendSingleCommand(SPI_WREN);
  237. /* The status register will be polled to check the write enable latch "WREN" */
  238. ErrorCode = Wait_For_WEL();
  239. if (POLL_TIMEOUT == ErrorCode) {
  240. printf("SPI Erase block error\n");
  241. return ErrorCode;
  242. } else
  243. /* Turn on the SPI to send single commands */
  244. SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
  245. /*
  246. * Send the erase block command to the flash followed by the 24 address
  247. * to point to the start of a sector
  248. */
  249. *pSPI_TDBR = SPI_SE;
  250. sync();
  251. Wait_For_SPIF();
  252. /* Send the highest byte of the 24 bit address at first */
  253. ShiftValue = (ulSectorOff >> 16);
  254. *pSPI_TDBR = ShiftValue;
  255. sync();
  256. /* Wait until the instruction has been sent */
  257. Wait_For_SPIF();
  258. /* Send the middle byte of the 24 bit address at second */
  259. ShiftValue = (ulSectorOff >> 8);
  260. *pSPI_TDBR = ShiftValue;
  261. sync();
  262. /* Wait until the instruction has been sent */
  263. Wait_For_SPIF();
  264. /* Send the lowest byte of the 24 bit address finally */
  265. *pSPI_TDBR = ulSectorOff;
  266. sync();
  267. /* Wait until the instruction has been sent */
  268. Wait_For_SPIF();
  269. /* Turns off the SPI */
  270. SPI_OFF();
  271. /* Poll the status register to check the Write in Progress bit */
  272. /* Sector erase takes time */
  273. ErrorCode = Wait_For_Status(WIP);
  274. /* block erase should be complete */
  275. return ErrorCode;
  276. }
  277. /*
  278. * ERROR_CODE ReadData()
  279. * Read a value from flash for verify purpose
  280. * Inputs: unsigned long ulStart - holds the SPI start address
  281. * int pnData - pointer to store value read from flash
  282. * long lCount - number of elements to read
  283. */
  284. ERROR_CODE ReadData(unsigned long ulStart, long lCount, int *pnData)
  285. {
  286. unsigned long ShiftValue;
  287. char *cnData;
  288. int i;
  289. /* Pointer cast to be able to increment byte wise */
  290. cnData = (char *)pnData;
  291. /* Start SPI interface */
  292. SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
  293. #ifdef CONFIG_SPI_FLASH_FAST_READ
  294. /* Send the read command to SPI device */
  295. *pSPI_TDBR = SPI_FAST_READ;
  296. #else
  297. /* Send the read command to SPI device */
  298. *pSPI_TDBR = SPI_READ;
  299. #endif
  300. sync();
  301. /* Wait until the instruction has been sent */
  302. Wait_For_SPIF();
  303. /* Send the highest byte of the 24 bit address at first */
  304. ShiftValue = (ulStart >> 16);
  305. /* Send the byte to the SPI device */
  306. *pSPI_TDBR = ShiftValue;
  307. sync();
  308. /* Wait until the instruction has been sent */
  309. Wait_For_SPIF();
  310. /* Send the middle byte of the 24 bit address at second */
  311. ShiftValue = (ulStart >> 8);
  312. /* Send the byte to the SPI device */
  313. *pSPI_TDBR = ShiftValue;
  314. sync();
  315. /* Wait until the instruction has been sent */
  316. Wait_For_SPIF();
  317. /* Send the lowest byte of the 24 bit address finally */
  318. *pSPI_TDBR = ulStart;
  319. sync();
  320. /* Wait until the instruction has been sent */
  321. Wait_For_SPIF();
  322. #ifdef CONFIG_SPI_FLASH_FAST_READ
  323. /* Send dummy for FAST_READ */
  324. *pSPI_TDBR = 0;
  325. sync();
  326. /* Wait until the instruction has been sent */
  327. Wait_For_SPIF();
  328. #endif
  329. /* After the SPI device address has been placed on the MOSI pin the data can be */
  330. /* received on the MISO pin. */
  331. for (i = 0; i < lCount; i++) {
  332. *pSPI_TDBR = 0;
  333. sync();
  334. while (!(*pSPI_STAT & RXS)) ;
  335. *cnData++ = *pSPI_RDBR;
  336. if ((i >= SECTOR_SIZE) && (i % SECTOR_SIZE == 0))
  337. printf(".");
  338. }
  339. /* Turn off the SPI */
  340. SPI_OFF();
  341. return NO_ERR;
  342. }
  343. ERROR_CODE WriteFlash(unsigned long ulStartAddr, long lTransferCount,
  344. int *iDataSource, long *lWriteCount)
  345. {
  346. unsigned long ulWAddr;
  347. long lWTransferCount = 0;
  348. int i;
  349. char iData;
  350. char *temp = (char *)iDataSource;
  351. ERROR_CODE ErrorCode = NO_ERR;
  352. /* First, a Write Enable Command must be sent to the SPI. */
  353. SendSingleCommand(SPI_WREN);
  354. /*
  355. * Second, the SPI Status Register will be tested whether the
  356. * Write Enable Bit has been set
  357. */
  358. ErrorCode = Wait_For_WEL();
  359. if (POLL_TIMEOUT == ErrorCode) {
  360. printf("SPI Write Time Out\n");
  361. return ErrorCode;
  362. } else
  363. /* Third, the 24 bit address will be shifted out
  364. * the SPI MOSI bytewise.
  365. * Turns the SPI on
  366. */
  367. SetupSPI((COMMON_SPI_SETTINGS | TIMOD01));
  368. *pSPI_TDBR = SPI_PP;
  369. sync();
  370. /*wait until the instruction has been sent */
  371. Wait_For_SPIF();
  372. ulWAddr = (ulStartAddr >> 16);
  373. *pSPI_TDBR = ulWAddr;
  374. sync();
  375. /*wait until the instruction has been sent */
  376. Wait_For_SPIF();
  377. ulWAddr = (ulStartAddr >> 8);
  378. *pSPI_TDBR = ulWAddr;
  379. sync();
  380. /*wait until the instruction has been sent */
  381. Wait_For_SPIF();
  382. ulWAddr = ulStartAddr;
  383. *pSPI_TDBR = ulWAddr;
  384. sync();
  385. /*wait until the instruction has been sent */
  386. Wait_For_SPIF();
  387. /*
  388. * Fourth, maximum number of 256 bytes will be taken from the Buffer
  389. * and sent to the SPI device.
  390. */
  391. for (i = 0; (i < lTransferCount) && (i < 256); i++, lWTransferCount++) {
  392. iData = *temp;
  393. *pSPI_TDBR = iData;
  394. sync();
  395. /*wait until the instruction has been sent */
  396. Wait_For_SPIF();
  397. temp++;
  398. }
  399. /* Turns the SPI off */
  400. SPI_OFF();
  401. /*
  402. * Sixth, the SPI Write in Progress Bit must be toggled to ensure the
  403. * programming is done before start of next transfer
  404. */
  405. ErrorCode = Wait_For_Status(WIP);
  406. if (POLL_TIMEOUT == ErrorCode) {
  407. printf("SPI Program Time out!\n");
  408. return ErrorCode;
  409. } else
  410. *lWriteCount = lWTransferCount;
  411. return ErrorCode;
  412. }
  413. ERROR_CODE WriteData(unsigned long ulStart, long lCount, int *pnData)
  414. {
  415. unsigned long ulWStart = ulStart;
  416. long lWCount = lCount, lWriteCount;
  417. long *pnWriteCount = &lWriteCount;
  418. ERROR_CODE ErrorCode = NO_ERR;
  419. while (lWCount != 0) {
  420. ErrorCode = WriteFlash(ulWStart, lWCount, pnData, pnWriteCount);
  421. /*
  422. * After each function call of WriteFlash the counter
  423. * must be adjusted
  424. */
  425. lWCount -= *pnWriteCount;
  426. /* Also, both address pointers must be recalculated. */
  427. ulWStart += *pnWriteCount;
  428. pnData += *pnWriteCount / 4;
  429. }
  430. /* return the appropriate error code */
  431. return ErrorCode;
  432. }
  433. #endif /* CONFIG_SPI */