您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

741 行
19 KiB

  1. /**
  2. *
  3. * \file
  4. *
  5. * \brief WINC1500 SPI Flash.
  6. *
  7. * Copyright (c) 2017-2018 Atmel Corporation. All rights reserved.
  8. *
  9. * \asf_license_start
  10. *
  11. * \page License
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions are met:
  15. *
  16. * 1. Redistributions of source code must retain the above copyright notice,
  17. * this list of conditions and the following disclaimer.
  18. *
  19. * 2. Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. *
  23. * 3. The name of Atmel may not be used to endorse or promote products derived
  24. * from this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
  27. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  28. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  29. * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
  30. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  34. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  35. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * \asf_license_stop
  39. *
  40. */
  41. #ifdef PROFILING
  42. #include "windows.h"
  43. #endif
  44. #include "spi_flash/include/spi_flash.h"
  45. #define DUMMY_REGISTER (0x1084)
  46. #define TIMEOUT (-1) /*MS*/
  47. //#define DISABLE_UNSED_FLASH_FUNCTIONS
  48. #define FLASH_BLOCK_SIZE (32UL * 1024)
  49. /*!<Block Size in Flash Memory
  50. */
  51. #define FLASH_SECTOR_SZ (4 * 1024UL)
  52. /*!<Sector Size in Flash Memory
  53. */
  54. #define FLASH_PAGE_SZ (256)
  55. /*!<Page Size in Flash Memory */
  56. #define HOST_SHARE_MEM_BASE (0xd0000UL)
  57. #define CORTUS_SHARE_MEM_BASE (0x60000000UL)
  58. #define NMI_SPI_FLASH_ADDR (0x111c)
  59. /***********************************************************
  60. SPI Flash DMA
  61. ***********************************************************/
  62. #define GET_UINT32(X, Y) (X[0 + Y] + ((uint32)X[1 + Y] << 8) + ((uint32)X[2 + Y] << 16) + ((uint32)X[3 + Y] << 24))
  63. #define SPI_FLASH_BASE (0x10200)
  64. #define SPI_FLASH_MODE (SPI_FLASH_BASE + 0x00)
  65. #define SPI_FLASH_CMD_CNT (SPI_FLASH_BASE + 0x04)
  66. #define SPI_FLASH_DATA_CNT (SPI_FLASH_BASE + 0x08)
  67. #define SPI_FLASH_BUF1 (SPI_FLASH_BASE + 0x0c)
  68. #define SPI_FLASH_BUF2 (SPI_FLASH_BASE + 0x10)
  69. #define SPI_FLASH_BUF_DIR (SPI_FLASH_BASE + 0x14)
  70. #define SPI_FLASH_TR_DONE (SPI_FLASH_BASE + 0x18)
  71. #define SPI_FLASH_DMA_ADDR (SPI_FLASH_BASE + 0x1c)
  72. #define SPI_FLASH_MSB_CTL (SPI_FLASH_BASE + 0x20)
  73. #define SPI_FLASH_TX_CTL (SPI_FLASH_BASE + 0x24)
  74. /*********************************************/
  75. /* STATIC FUNCTIONS */
  76. /*********************************************/
  77. /**
  78. * @fn spi_flash_read_status_reg
  79. * @brief Read status register
  80. * @param[OUT] val
  81. value of status reg
  82. * @return Status of execution
  83. * @note Compatible with MX25L6465E
  84. * @author M. Abdelmawla
  85. * @version 1.0
  86. */
  87. static sint8 spi_flash_read_status_reg(uint8 *val)
  88. {
  89. sint8 ret = M2M_SUCCESS;
  90. uint8 cmd[1];
  91. uint32 reg;
  92. cmd[0] = 0x05;
  93. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 4);
  94. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  95. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
  96. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER);
  97. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7));
  98. do {
  99. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&reg);
  100. if (M2M_SUCCESS != ret)
  101. break;
  102. } while (reg != 1);
  103. reg = (M2M_SUCCESS == ret) ? (nm_read_reg(DUMMY_REGISTER)) : (0);
  104. *val = (uint8)(reg & 0xff);
  105. return ret;
  106. }
  107. #ifdef DISABLE_UNSED_FLASH_FUNCTIONS
  108. /**
  109. * @fn spi_flash_read_security_reg
  110. * @brief Read security register
  111. * @return Security register value
  112. * @note Compatible with MX25L6465E
  113. * @author M. Abdelmawla
  114. * @version 1.0
  115. */
  116. static uint8 spi_flash_read_security_reg(void)
  117. {
  118. uint8 cmd[1];
  119. uint32 reg;
  120. sint8 ret = M2M_SUCCESS;
  121. cmd[0] = 0x2b;
  122. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 1);
  123. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  124. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
  125. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER);
  126. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7));
  127. do {
  128. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&reg);
  129. if (M2M_SUCCESS != ret)
  130. break;
  131. } while (reg != 1);
  132. reg = (M2M_SUCCESS == ret) ? (nm_read_reg(DUMMY_REGISTER)) : (0);
  133. return (sint8)reg & 0xff;
  134. }
  135. /**
  136. * @fn spi_flash_gang_unblock
  137. * @brief Unblock all flash area
  138. * @note Compatible with MX25L6465E
  139. * @author M. Abdelmawla
  140. * @version 1.0
  141. */
  142. static sint8 spi_flash_gang_unblock(void)
  143. {
  144. uint8 cmd[1];
  145. uint32 val = 0;
  146. sint8 ret = M2M_SUCCESS;
  147. cmd[0] = 0x98;
  148. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  149. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  150. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
  151. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
  152. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7));
  153. do {
  154. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  155. if (M2M_SUCCESS != ret)
  156. break;
  157. } while (val != 1);
  158. return ret;
  159. }
  160. /**
  161. * @fn spi_flash_clear_security_flags
  162. * @brief Clear all security flags
  163. * @note Compatible with MX25L6465E
  164. * @author M. Abdelmawla
  165. * @version 1.0
  166. */
  167. static sint8 spi_flash_clear_security_flags(void)
  168. {
  169. uint8 cmd[1];
  170. uint32 val = 0;
  171. sint8 ret = M2M_SUCCESS;
  172. cmd[0] = 0x30;
  173. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  174. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  175. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
  176. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
  177. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7));
  178. do {
  179. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  180. if (M2M_SUCCESS != ret)
  181. break;
  182. } while (val != 1);
  183. return ret;
  184. }
  185. #endif
  186. /**
  187. * @fn spi_flash_load_to_cortus_mem
  188. * @brief Load data from SPI flash into cortus memory
  189. * @param[IN] u32MemAdr
  190. * Cortus load address. It must be set to its AHB access address
  191. * @param[IN] u32FlashAdr
  192. * Address to read from at the SPI flash
  193. * @param[IN] u32Sz
  194. * Data size
  195. * @return Status of execution
  196. * @note Compatible with MX25L6465E and should be working with other types
  197. * @author M. Abdelmawla
  198. * @version 1.0
  199. */
  200. static sint8 spi_flash_load_to_cortus_mem(uint32 u32MemAdr, uint32 u32FlashAdr, uint32 u32Sz)
  201. {
  202. uint8 cmd[5];
  203. uint32 val = 0;
  204. sint8 ret = M2M_SUCCESS;
  205. cmd[0] = 0x0b;
  206. cmd[1] = (uint8)(u32FlashAdr >> 16);
  207. cmd[2] = (uint8)(u32FlashAdr >> 8);
  208. cmd[3] = (uint8)(u32FlashAdr);
  209. cmd[4] = 0xA5;
  210. ret += nm_write_reg(SPI_FLASH_DATA_CNT, u32Sz);
  211. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0] | (cmd[1] << 8) | (cmd[2] << 16) | (cmd[3] << 24));
  212. ret += nm_write_reg(SPI_FLASH_BUF2, cmd[4]);
  213. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x1f);
  214. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, u32MemAdr);
  215. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 5 | (1 << 7));
  216. do {
  217. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  218. if (M2M_SUCCESS != ret)
  219. break;
  220. } while (val != 1);
  221. return ret;
  222. }
  223. /**
  224. * @fn spi_flash_sector_erase
  225. * @brief Erase sector (4KB)
  226. * @param[IN] u32FlashAdr
  227. * Any memory address within the sector
  228. * @return Status of execution
  229. * @note Compatible with MX25L6465E and should be working with other types
  230. * @author M. Abdelmawla
  231. * @version 1.0
  232. */
  233. static sint8 spi_flash_sector_erase(uint32 u32FlashAdr)
  234. {
  235. uint8 cmd[4];
  236. uint32 val = 0;
  237. sint8 ret = M2M_SUCCESS;
  238. cmd[0] = 0x20;
  239. cmd[1] = (uint8)(u32FlashAdr >> 16);
  240. cmd[2] = (uint8)(u32FlashAdr >> 8);
  241. cmd[3] = (uint8)(u32FlashAdr);
  242. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  243. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0] | (cmd[1] << 8) | (cmd[2] << 16) | (cmd[3] << 24));
  244. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x0f);
  245. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
  246. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 4 | (1 << 7));
  247. do {
  248. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  249. if (M2M_SUCCESS != ret)
  250. break;
  251. } while (val != 1);
  252. return ret;
  253. }
  254. /**
  255. * @fn spi_flash_write_enable
  256. * @brief Send write enable command to SPI flash
  257. * @return Status of execution
  258. * @note Compatible with MX25L6465E and should be working with other types
  259. * @author M. Abdelmawla
  260. * @version 1.0
  261. */
  262. static sint8 spi_flash_write_enable(void)
  263. {
  264. uint8 cmd[1];
  265. uint32 val = 0;
  266. sint8 ret = M2M_SUCCESS;
  267. cmd[0] = 0x06;
  268. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  269. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  270. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
  271. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
  272. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7));
  273. do {
  274. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  275. if (M2M_SUCCESS != ret)
  276. break;
  277. } while (val != 1);
  278. return ret;
  279. }
  280. /**
  281. * @fn spi_flash_write_disable
  282. * @brief Send write disable command to SPI flash
  283. * @note Compatible with MX25L6465E and should be working with other types
  284. * @author M. Abdelmawla
  285. * @version 1.0
  286. */
  287. static sint8 spi_flash_write_disable(void)
  288. {
  289. uint8 cmd[1];
  290. uint32 val = 0;
  291. sint8 ret = M2M_SUCCESS;
  292. cmd[0] = 0x04;
  293. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  294. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  295. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
  296. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
  297. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7));
  298. do {
  299. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  300. if (M2M_SUCCESS != ret)
  301. break;
  302. } while (val != 1);
  303. return ret;
  304. }
  305. /**
  306. * @fn spi_flash_page_program
  307. * @brief Write data (less than page size) from cortus memory to SPI flash
  308. * @param[IN] u32MemAdr
  309. * Cortus data address. It must be set to its AHB access address
  310. * @param[IN] u32FlashAdr
  311. * Address to write to at the SPI flash
  312. * @param[IN] u32Sz
  313. * Data size
  314. * @note Compatible with MX25L6465E and should be working with other types
  315. * @author M. Abdelmawla
  316. * @version 1.0
  317. */
  318. static sint8 spi_flash_page_program(uint32 u32MemAdr, uint32 u32FlashAdr, uint32 u32Sz)
  319. {
  320. uint8 cmd[4];
  321. uint32 val = 0;
  322. sint8 ret = M2M_SUCCESS;
  323. cmd[0] = 0x02;
  324. cmd[1] = (uint8)(u32FlashAdr >> 16);
  325. cmd[2] = (uint8)(u32FlashAdr >> 8);
  326. cmd[3] = (uint8)(u32FlashAdr);
  327. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  328. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0] | (cmd[1] << 8) | (cmd[2] << 16) | (cmd[3] << 24));
  329. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x0f);
  330. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, u32MemAdr);
  331. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 4 | (1 << 7) | ((u32Sz & 0xfffff) << 8));
  332. do {
  333. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
  334. if (M2M_SUCCESS != ret)
  335. break;
  336. } while (val != 1);
  337. return ret;
  338. }
  339. /**
  340. * @fn spi_flash_read_internal
  341. * @brief Read from data from SPI flash
  342. * @param[OUT] pu8Buf
  343. * Pointer to data buffer
  344. * @param[IN] u32Addr
  345. * Address to read from at the SPI flash
  346. * @param[IN] u32Sz
  347. * Data size
  348. * @note Data size must be < 64KB (limitation imposed by the bus wrapper)
  349. * @author M. Abdelmawla
  350. * @version 1.0
  351. */
  352. static sint8 spi_flash_read_internal(uint8 *pu8Buf, uint32 u32Addr, uint32 u32Sz)
  353. {
  354. sint8 ret = M2M_SUCCESS;
  355. /* read size must be < 64KB */
  356. ret = spi_flash_load_to_cortus_mem(HOST_SHARE_MEM_BASE, u32Addr, u32Sz);
  357. if (M2M_SUCCESS != ret)
  358. goto ERR;
  359. ret = nm_read_block(HOST_SHARE_MEM_BASE, pu8Buf, u32Sz);
  360. ERR:
  361. return ret;
  362. }
  363. /**
  364. * @fn spi_flash_pp
  365. * @brief Program data of size less than a page (256 bytes) at the SPI flash
  366. * @param[IN] u32Offset
  367. * Address to write to at the SPI flash
  368. * @param[IN] pu8Buf
  369. * Pointer to data buffer
  370. * @param[IN] u32Sz
  371. * Data size
  372. * @return Status of execution
  373. * @author M. Abdelmawla
  374. * @version 1.0
  375. */
  376. static sint8 spi_flash_pp(uint32 u32Offset, uint8 *pu8Buf, uint16 u16Sz)
  377. {
  378. sint8 ret = M2M_SUCCESS;
  379. uint8 tmp;
  380. spi_flash_write_enable();
  381. /* use shared packet memory as temp mem */
  382. ret += nm_write_block(HOST_SHARE_MEM_BASE, pu8Buf, u16Sz);
  383. ret += spi_flash_page_program(HOST_SHARE_MEM_BASE, u32Offset, u16Sz);
  384. ret += spi_flash_read_status_reg(&tmp);
  385. do {
  386. if (ret != M2M_SUCCESS)
  387. goto ERR;
  388. ret += spi_flash_read_status_reg(&tmp);
  389. } while (tmp & 0x01);
  390. ret += spi_flash_write_disable();
  391. ERR:
  392. return ret;
  393. }
  394. /**
  395. * @fn spi_flash_rdid
  396. * @brief Read SPI Flash ID
  397. * @return SPI FLash ID
  398. * @author M.S.M
  399. * @version 1.0
  400. */
  401. static uint32 spi_flash_rdid(void)
  402. {
  403. unsigned char cmd[1];
  404. uint32 reg = 0;
  405. uint32 cnt = 0;
  406. sint8 ret = M2M_SUCCESS;
  407. cmd[0] = 0x9f;
  408. ret += nm_write_reg(SPI_FLASH_DATA_CNT, 4);
  409. ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  410. ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x1);
  411. ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER);
  412. ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7));
  413. do {
  414. ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&reg);
  415. if (M2M_SUCCESS != ret)
  416. break;
  417. if (++cnt > 500) {
  418. ret = M2M_ERR_INIT;
  419. break;
  420. }
  421. } while (reg != 1);
  422. reg = (M2M_SUCCESS == ret) ? (nm_read_reg(DUMMY_REGISTER)) : (0);
  423. M2M_PRINT("Flash ID %x \n", (unsigned int)reg);
  424. return reg;
  425. }
  426. /**
  427. * @fn spi_flash_unlock
  428. * @brief Unlock SPI Flash
  429. * @author M.S.M
  430. * @version 1.0
  431. */
  432. #if 0
  433. static void spi_flash_unlock(void)
  434. {
  435. uint8 tmp;
  436. tmp = spi_flash_read_security_reg();
  437. spi_flash_clear_security_flags();
  438. if(tmp & 0x80)
  439. {
  440. spi_flash_write_enable();
  441. spi_flash_gang_unblock();
  442. }
  443. }
  444. #endif
  445. static void spi_flash_enter_low_power_mode(void)
  446. {
  447. volatile unsigned long tmp;
  448. unsigned char * cmd = (unsigned char *)&tmp;
  449. unsigned int count = 0;
  450. cmd[0] = 0xb9;
  451. nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  452. nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  453. nm_write_reg(SPI_FLASH_BUF_DIR, 0x1);
  454. nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
  455. nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7));
  456. while (nm_read_reg(SPI_FLASH_TR_DONE) != 1) //JFM ajouté compteur...
  457. {
  458. if(count++ >= 5000)
  459. return;
  460. }
  461. }
  462. static void spi_flash_leave_low_power_mode(void)
  463. {
  464. volatile unsigned long tmp;
  465. unsigned char * cmd = (unsigned char *)&tmp;
  466. cmd[0] = 0xab;
  467. nm_write_reg(SPI_FLASH_DATA_CNT, 0);
  468. nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
  469. nm_write_reg(SPI_FLASH_BUF_DIR, 0x1);
  470. nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
  471. nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7));
  472. while (nm_read_reg(SPI_FLASH_TR_DONE) != 1)
  473. ;
  474. }
  475. /*********************************************/
  476. /* GLOBAL FUNCTIONS */
  477. /*********************************************/
  478. /**
  479. * @fn spi_flash_enable
  480. * @brief Enable spi flash operations
  481. * @author M. Abdelmawla
  482. * @version 1.0
  483. */
  484. sint8 spi_flash_enable(uint8 enable)
  485. {
  486. sint8 s8Ret = M2M_SUCCESS;
  487. if (REV(nmi_get_chipid()) >= REV_3A0) {
  488. uint32 u32Val;
  489. /* Enable pinmux to SPI flash. */
  490. s8Ret = nm_read_reg_with_ret(0x1410, &u32Val);
  491. if (s8Ret != M2M_SUCCESS) {
  492. goto ERR1;
  493. }
  494. /* GPIO15/16/17/18 */
  495. u32Val &= ~((0x7777ul) << 12);
  496. u32Val |= ((0x1111ul) << 12);
  497. nm_write_reg(0x1410, u32Val);
  498. if (enable) {
  499. spi_flash_leave_low_power_mode();
  500. } else {
  501. spi_flash_enter_low_power_mode();
  502. }
  503. /* Disable pinmux to SPI flash to minimize leakage. */
  504. u32Val &= ~((0x7777ul) << 12);
  505. u32Val |= ((0x0010ul) << 12);
  506. nm_write_reg(0x1410, u32Val);
  507. }
  508. ERR1:
  509. return s8Ret;
  510. }
  511. /**
  512. * @fn spi_flash_read
  513. * @brief Read from data from SPI flash
  514. * @param[OUT] pu8Buf
  515. * Pointer to data buffer
  516. * @param[IN] u32offset
  517. * Address to read from at the SPI flash
  518. * @param[IN] u32Sz
  519. * Data size
  520. * @return Status of execution
  521. * @note Data size is limited by the SPI flash size only
  522. * @author M. Abdelmawla
  523. * @version 1.0
  524. */
  525. sint8 spi_flash_read(uint8 *pu8Buf, uint32 u32offset, uint32 u32Sz)
  526. {
  527. sint8 ret = M2M_SUCCESS;
  528. if (u32Sz > FLASH_BLOCK_SIZE) {
  529. do {
  530. ret = spi_flash_read_internal(pu8Buf, u32offset, FLASH_BLOCK_SIZE);
  531. if (M2M_SUCCESS != ret)
  532. goto ERR;
  533. u32Sz -= FLASH_BLOCK_SIZE;
  534. u32offset += FLASH_BLOCK_SIZE;
  535. pu8Buf += FLASH_BLOCK_SIZE;
  536. } while (u32Sz > FLASH_BLOCK_SIZE);
  537. }
  538. ret = spi_flash_read_internal(pu8Buf, u32offset, u32Sz);
  539. ERR:
  540. return ret;
  541. }
  542. /**
  543. * @fn spi_flash_write
  544. * @brief Proram SPI flash
  545. * @param[IN] pu8Buf
  546. * Pointer to data buffer
  547. * @param[IN] u32Offset
  548. * Address to write to at the SPI flash
  549. * @param[IN] u32Sz
  550. * Data size
  551. * @return Status of execution
  552. * @author M. Abdelmawla
  553. * @version 1.0
  554. */
  555. sint8 spi_flash_write(uint8 *pu8Buf, uint32 u32Offset, uint32 u32Sz)
  556. {
  557. #ifdef PROFILING
  558. uint32 t1 = 0;
  559. uint32 percent = 0;
  560. uint32 tpercent = 0;
  561. #endif
  562. sint8 ret = M2M_SUCCESS;
  563. uint32 u32wsz;
  564. uint32 u32off;
  565. uint32 u32Blksz;
  566. u32Blksz = FLASH_PAGE_SZ;
  567. u32off = u32Offset % u32Blksz;
  568. #ifdef PROFILING
  569. tpercent = (u32Sz / u32Blksz) + ((u32Sz % u32Blksz) > 0);
  570. t1 = GetTickCount();
  571. M2M_PRINT(">Start programming...\r\n");
  572. #endif
  573. if (u32Sz <= 0) {
  574. M2M_ERR("Data size = %d", (int)u32Sz);
  575. ret = M2M_ERR_FAIL;
  576. goto ERR;
  577. }
  578. if (u32off) /*first part of data in the address page*/
  579. {
  580. u32wsz = u32Blksz - u32off;
  581. if (spi_flash_pp(u32Offset, pu8Buf, (uint16)BSP_MIN(u32Sz, u32wsz)) != M2M_SUCCESS) {
  582. ret = M2M_ERR_FAIL;
  583. goto ERR;
  584. }
  585. if (u32Sz < u32wsz)
  586. goto EXIT;
  587. pu8Buf += u32wsz;
  588. u32Offset += u32wsz;
  589. u32Sz -= u32wsz;
  590. }
  591. while (u32Sz > 0) {
  592. u32wsz = BSP_MIN(u32Sz, u32Blksz);
  593. /*write complete page or the remaining data*/
  594. if (spi_flash_pp(u32Offset, pu8Buf, (uint16)u32wsz) != M2M_SUCCESS) {
  595. ret = M2M_ERR_FAIL;
  596. goto ERR;
  597. }
  598. pu8Buf += u32wsz;
  599. u32Offset += u32wsz;
  600. u32Sz -= u32wsz;
  601. #ifdef PROFILING
  602. percent++;
  603. printf("\r>Complete Percentage = %d%%.\r", ((percent * 100) / tpercent));
  604. #endif
  605. }
  606. EXIT:
  607. #ifdef PROFILING
  608. M2M_PRINT("\rDone\t\t\t\t\t\t");
  609. M2M_PRINT("\n#Programming time = %f sec\n\r", (GetTickCount() - t1) / 1000.0);
  610. #endif
  611. ERR:
  612. return ret;
  613. }
  614. /**
  615. * @fn spi_flash_erase
  616. * @brief Erase from data from SPI flash
  617. * @param[IN] u32Offset
  618. * Address to write to at the SPI flash
  619. * @param[IN] u32Sz
  620. * Data size
  621. * @return Status of execution
  622. * @note Data size is limited by the SPI flash size only
  623. * @author M. Abdelmawla
  624. * @version 1.0
  625. */
  626. sint8 spi_flash_erase(uint32 u32Offset, uint32 u32Sz)
  627. {
  628. uint32 i = 0;
  629. sint8 ret = M2M_SUCCESS;
  630. uint8 tmp = 0;
  631. #ifdef PROFILING
  632. uint32 t;
  633. t = GetTickCount();
  634. #endif
  635. M2M_PRINT("\r\n>Start erasing...\r\n");
  636. for (i = u32Offset; i < (u32Sz + u32Offset); i += (16 * FLASH_PAGE_SZ)) {
  637. ret += spi_flash_write_enable();
  638. ret += spi_flash_read_status_reg(&tmp);
  639. ret += spi_flash_sector_erase(i + 10);
  640. ret += spi_flash_read_status_reg(&tmp);
  641. do {
  642. if (ret != M2M_SUCCESS)
  643. goto ERR;
  644. ret += spi_flash_read_status_reg(&tmp);
  645. } while (tmp & 0x01);
  646. }
  647. M2M_PRINT("Done\r\n");
  648. #ifdef PROFILING
  649. M2M_PRINT("#Erase time = %f sec\n", (GetTickCount() - t) / 1000.0);
  650. #endif
  651. ERR:
  652. return ret;
  653. }
  654. /**
  655. * @fn spi_flash_get_size
  656. * @brief Get size of SPI Flash
  657. * @return Size of Flash
  658. * @author M.S.M
  659. * @version 1.0
  660. */
  661. uint32 spi_flash_get_size(void)
  662. {
  663. uint32 u32FlashId = 0, u32FlashPwr = 0;
  664. static uint32 gu32InernalFlashSize = 0;
  665. if (!gu32InernalFlashSize) {
  666. u32FlashId = spi_flash_rdid(); // spi_flash_probe();
  667. if (u32FlashId != 0xffffffff) {
  668. /*flash size is the third byte from the FLASH RDID*/
  669. u32FlashPwr = ((u32FlashId >> 16) & 0xff) - 0x11; /*2MBIT is the min*/
  670. /*That number power 2 to get the flash size*/
  671. gu32InernalFlashSize = 1 << u32FlashPwr;
  672. M2M_INFO("Flash Size %lu Mb\n", gu32InernalFlashSize);
  673. } else {
  674. M2M_ERR("Cann't Detect Flash size\n");
  675. }
  676. }
  677. return gu32InernalFlashSize;
  678. }