SpiBooter.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. #include <string.h>
  2. #include "typedef.h"
  3. #include "amt630h.h"
  4. #include "uart.h"
  5. #include "timer.h"
  6. #include "gpio.h"
  7. #include "spi.h"
  8. #include "cp15.h"
  9. #include "sysinfo.h"
  10. #include "crc32.h"
  11. #include "update.h"
  12. #include "board.h"
  13. #include "os_adapt.h"
  14. #define SPI_CS_GPIO 32
  15. #define SPI_RXFIFO_FULL (1<<4)
  16. #define SPI_RXFIFO_NOTEMPTY (1<<3)
  17. #define SPI_TXFIFO_EMPTY (1<<2)
  18. #define SPI_TXFIFO_NOTFULL (1<<1)
  19. #define SPIFLASH_BUSY (1<<0)
  20. /* SFUD support manufacturer JEDEC ID */
  21. #define SFUD_MF_ID_CYPRESS 0x01
  22. #define SFUD_MF_ID_FUJITSU 0x04
  23. #define SFUD_MF_ID_EON 0x1C
  24. #define SFUD_MF_ID_ATMEL 0x1F
  25. #define SFUD_MF_ID_MICRON 0x20
  26. #define SFUD_MF_ID_AMIC 0x37
  27. #define SFUD_MF_ID_SANYO 0x62
  28. #define SFUD_MF_ID_INTEL 0x89
  29. #define SFUD_MF_ID_ESMT 0x8C
  30. #define SFUD_MF_ID_FUDAN 0xA1
  31. #define SFUD_MF_ID_HYUNDAI 0xAD
  32. #define SFUD_MF_ID_SST 0xBF
  33. #define SFUD_MF_ID_MICRONIX 0xC2
  34. #define SFUD_MF_ID_GIGADEVICE 0xC8
  35. #define SFUD_MF_ID_ISSI 0xD5
  36. #define SFUD_MF_ID_WINBOND 0xEF
  37. static void SpiWriteEnable(void);
  38. /* flash chip information */
  39. typedef struct {
  40. char *name; /**< flash chip name */
  41. uint8_t mf_id; /**< manufacturer ID */
  42. uint8_t type_id; /**< memory type ID */
  43. uint8_t capacity_id; /**< capacity ID */
  44. uint32_t capacity; /**< flash capacity (bytes) */
  45. } flash_chip;
  46. static const flash_chip flash_chip_table[] =
  47. { \
  48. {"W25Q40BV", SFUD_MF_ID_WINBOND, 0x40, 0x13, 512L*1024L}, \
  49. {"W25Q16BV", SFUD_MF_ID_WINBOND, 0x40, 0x15, 2L*1024L*1024L}, \
  50. {"W25Q32BV", SFUD_MF_ID_WINBOND, 0x40, 0x16, 4L*1024L*1024L}, \
  51. {"W25Q64CV", SFUD_MF_ID_WINBOND, 0x40, 0x17, 8L*1024L*1024L}, \
  52. {"W25Q64DW", SFUD_MF_ID_WINBOND, 0x60, 0x17, 8L*1024L*1024L}, \
  53. {"W25Q128BV", SFUD_MF_ID_WINBOND, 0x40, 0x18, 16L*1024L*1024L}, \
  54. {"W25Q256FV", SFUD_MF_ID_WINBOND, 0x40, 0x19, 32L*1024L*1024L}, \
  55. {"W25H256JV", SFUD_MF_ID_WINBOND, 0x90, 0x19, 32L*1024L*1024L}, \
  56. {"W25Q512JVFM", SFUD_MF_ID_WINBOND, 0x70, 0x20, 64L*1024L*1024L}, \
  57. {"SST25VF080B", SFUD_MF_ID_SST, 0x25, 0x8E, 1L*1024L*1024L}, \
  58. {"SST25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L}, \
  59. {"EN25Q32B", SFUD_MF_ID_EON, 0x30, 0x16, 4L*1024L*1024L}, \
  60. {"GD25Q64B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, 8L*1024L*1024L}, \
  61. {"GD25Q16B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x15, 2L*1024L*1024L}, \
  62. {"GD25Q32C", SFUD_MF_ID_GIGADEVICE, 0x40, 0x16, 4L*1024L*1024L}, \
  63. {"S25FL216K", SFUD_MF_ID_CYPRESS, 0x40, 0x15, 2L*1024L*1024L}, \
  64. {"S25FL032P", SFUD_MF_ID_CYPRESS, 0x02, 0x15, 4L*1024L*1024L}, \
  65. {"A25L080", SFUD_MF_ID_AMIC, 0x30, 0x14, 1L*1024L*1024L}, \
  66. {"F25L004", SFUD_MF_ID_ESMT, 0x20, 0x13, 512L*1024L}, \
  67. {"MX25L6433F", SFUD_MF_ID_MICRONIX, 0x20, 0x17, 8L*1024L*1024L}, \
  68. {"MX25L12845G", SFUD_MF_ID_MICRONIX, 0x20, 0x18, 16L*1024L*1024L}, \
  69. {"MX25L25645G", SFUD_MF_ID_MICRONIX, 0x20, 0x19, 32L*1024L*1024L},\
  70. {"PCT25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L}, \
  71. {"GD25B128c", SFUD_MF_ID_GIGADEVICE, 0x43, 0x19, 32L*1024L*1024L},\
  72. {"GD25B256", SFUD_MF_ID_GIGADEVICE, 0x43, 0x19, 32L*1024L*1024L},\
  73. {"GD25B512ME", SFUD_MF_ID_GIGADEVICE, 0x47, 0x1A, 64L*1024L*1024L},
  74. };
  75. static int addr_in_4_byte = 0;
  76. static void SetCSGpioEnable(int enable)
  77. {
  78. gpio_direction_output(SPI_CS_GPIO, !enable);
  79. }
  80. static void SetSpiDataMode(unsigned int bitMode)
  81. {
  82. unsigned int val = 0;
  83. (void)val;
  84. while((rSPI_SR & SPI_BUSY));
  85. rSPI_SSIENR = 0;
  86. val = rSPI_CTLR0;
  87. val &=~(0x1f<<16);
  88. val |=((bitMode-1)<<16);
  89. rSPI_CTLR0 = val;
  90. rSPI_SSIENR = 1;
  91. }
  92. static void SpiWaitIdle(void)
  93. {
  94. while(rSPI_SR & SPIFLASH_BUSY);
  95. udelay(2);
  96. }
  97. static void SpiEmptyRxFIFO(void)
  98. {
  99. INT32 data = 0;
  100. (void)data;
  101. while(rSPI_SR & SPI_RXFIFO_NOTEMPTY)
  102. data = rSPI_DR;
  103. }
  104. #ifdef SPI0_QSPI_MODE
  105. static void SpiWriteSta2(uint8_t status)
  106. {
  107. SpiWriteEnable();
  108. SetSpiDataMode(8);
  109. SetCSGpioEnable(1);
  110. rSPI_DR = SPI_WRITE_STATUS2;
  111. rSPI_DR = status;
  112. SpiWaitIdle();
  113. SetCSGpioEnable(0);
  114. SetSpiDataMode(32);
  115. }
  116. static UINT8 SpiReadSta2(void)
  117. {
  118. UINT8 status;
  119. SetSpiDataMode(8);
  120. SetCSGpioEnable(1);
  121. rSPI_DR = SPI_READ_STATUS2;
  122. rSPI_DR = 0;
  123. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  124. status = rSPI_DR;
  125. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  126. status = rSPI_DR;
  127. PrintVariableValueHex("status s2 :", status);
  128. SpiWaitIdle();
  129. SetCSGpioEnable(0);
  130. SetSpiDataMode(32);
  131. return status;
  132. }
  133. static void SpiWriteSta(uint8_t status)
  134. {
  135. SpiWriteEnable();
  136. SetSpiDataMode(8);
  137. SetCSGpioEnable(1);
  138. rSPI_DR = SPI_WRITE_STATUS;
  139. rSPI_DR = status;
  140. SpiWaitIdle();
  141. SetCSGpioEnable(0);
  142. SetSpiDataMode(32);
  143. }
  144. #endif
  145. static UINT8 SpiReadSta3(void)
  146. {
  147. UINT8 status;
  148. SetSpiDataMode(8);
  149. SetCSGpioEnable(1);
  150. rSPI_DR = SPI_READ_STATUS3;
  151. rSPI_DR = 0;
  152. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  153. status = rSPI_DR;
  154. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  155. status = rSPI_DR;
  156. PrintVariableValueHex("status s3 :", status);
  157. SpiWaitIdle();
  158. SetCSGpioEnable(0);
  159. SetSpiDataMode(32);
  160. return status;
  161. }
  162. static UINT8 SpiReadSta(void)
  163. {
  164. UINT8 status;
  165. SetSpiDataMode(8);
  166. SetCSGpioEnable(1);
  167. rSPI_DR = SPI_READ_STATUS;
  168. rSPI_DR = 0;
  169. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  170. status = rSPI_DR;
  171. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  172. status = rSPI_DR;
  173. //PrintVariableValueHex("status:", status);
  174. SpiWaitIdle();
  175. SetCSGpioEnable(0);
  176. SetSpiDataMode(32);
  177. return status;
  178. }
  179. static void SpiDisable4ByteMode(void)
  180. {
  181. SetSpiDataMode(8);
  182. SetCSGpioEnable(1);
  183. rSPI_DR = SPI_DISABLE_4BYTE_MODE;
  184. while(!(rSPI_SR & SPI_TXFIFO_EMPTY));
  185. SpiWaitIdle();
  186. SetCSGpioEnable(0);
  187. SetSpiDataMode(32);
  188. }
  189. static void SpiEnable4ByteMode(void)
  190. {
  191. SetSpiDataMode(8);
  192. SetCSGpioEnable(1);
  193. rSPI_DR = SPI_ENABLE_4BYTE_MODE;
  194. while(!(rSPI_SR & SPI_TXFIFO_EMPTY));
  195. SpiWaitIdle();
  196. SetCSGpioEnable(0);
  197. SetSpiDataMode(32);
  198. }
  199. static void SpiReadPage(UINT32 pagenum, UINT32 *buf)
  200. {
  201. UINT32 addr;
  202. UINT32 val = 0;
  203. INT32 i, j;
  204. UINT8 tmpaddr[4];
  205. UINT8 *data = (UINT8*)buf;
  206. (void)val;
  207. addr = pagenum*BYTESPERPAGE;
  208. tmpaddr[0] = addr;
  209. tmpaddr[1] = addr>>8;
  210. tmpaddr[2] = addr>>16;
  211. tmpaddr[3] = addr>>24;
  212. SpiEmptyRxFIFO();
  213. SetCSGpioEnable(1);
  214. if (addr_in_4_byte) {
  215. SetSpiDataMode(8);
  216. rSPI_DR = SPI_4BYTEADDR_READ_DATA;
  217. rSPI_DR = tmpaddr[3];
  218. rSPI_DR = tmpaddr[2];
  219. rSPI_DR = tmpaddr[1];
  220. rSPI_DR = tmpaddr[0];
  221. for (i = 0; i < 5; i++) {
  222. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  223. val = rSPI_DR;
  224. }
  225. } else {
  226. rSPI_DR = (tmpaddr[0]<<24) | (tmpaddr[1]<<16) | (tmpaddr[2]<<8) | SPI_READ_DATA;
  227. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  228. val = rSPI_DR;
  229. }
  230. if (addr_in_4_byte) {
  231. for (i = 0; i < 4; i++) {
  232. for (j = 0; j < WORDSPERPAGE; j++) {
  233. while(!(rSPI_SR & SPI_TXFIFO_NOTFULL));
  234. rSPI_DR = 0;
  235. }
  236. for (j = 0; j < WORDSPERPAGE; j++) {
  237. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  238. *data++ = rSPI_DR;
  239. }
  240. }
  241. } else {
  242. for (i = 0; i < WORDSPERPAGE; i++) {
  243. while(!(rSPI_SR & SPI_TXFIFO_NOTFULL));
  244. rSPI_DR = 0;
  245. }
  246. for(i = 0; i < WORDSPERPAGE; i++) {
  247. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  248. *buf++ = rSPI_DR;
  249. }
  250. }
  251. SpiWaitIdle();
  252. SetCSGpioEnable(0);
  253. if (addr_in_4_byte)
  254. SetSpiDataMode(32);
  255. }
  256. #ifdef SPI0_QSPI_MODE
  257. //********format*********
  258. //00 – Standard SPI Format
  259. // 01 – Dual SPI Format
  260. // 10 – Quad SPI Format
  261. // 11 – Reserved
  262. //********tmod**********
  263. //00 –- Transmit & Receive
  264. //01 –- Transmit Only
  265. //10 –- Receive Only
  266. //11 –- EEPROM Read
  267. static void SpiSetFrameFormatMode(unsigned char format, unsigned char tmod)
  268. {
  269. unsigned int val = 0;
  270. while((rSPI_SR & SPI_BUSY));
  271. rSPI_SSIENR = 0;
  272. val = rSPI_CTLR0;
  273. val &= ~((0x3 << 21) | (0x3 << 8));
  274. val |= ((format << 21) | (tmod << 8));
  275. rSPI_CTLR0 = val;
  276. rSPI_SSIENR = 1;
  277. }
  278. static void SpiReadPageQuadMode(UINT32 pagenum, UINT32 *buf)
  279. {
  280. UINT32 addr;
  281. UINT32 val = 0;
  282. INT32 i;
  283. UINT8 tmpaddr[4];
  284. (void)val;
  285. addr = pagenum*BYTESPERPAGE;
  286. tmpaddr[0] = addr;
  287. tmpaddr[1] = addr>>8;
  288. tmpaddr[2] = addr>>16;
  289. tmpaddr[3] = addr>>24;
  290. SpiEmptyRxFIFO();
  291. SetCSGpioEnable(1);
  292. SpiSetFrameFormatMode(2, 2);
  293. rSPI_SSIENR = 0;
  294. if (addr_in_4_byte) {
  295. //set instruction 8bits,1byte mode; addr 32bit,4bytes mode; 6 dummy clocks
  296. rSPI_SPI_CTRLR0 = (6 << 11) | (2 << 8) | (8 << 2) | 1;
  297. rSPI_CTLR1 = WORDSPERPAGE - 1;
  298. rSPI_SSIENR = 1;
  299. rSPI_DR = SPI_QUAD_IO_READ_DATA + 1;
  300. rSPI_DR = (tmpaddr[0] << 24) | (tmpaddr[1] << 16) | (tmpaddr[2] << 8) | tmpaddr[3];
  301. } else {
  302. //set instruction 8bits,1byte mode; addr 24bit,4bytes mode; 6 dummy clocks
  303. rSPI_SPI_CTRLR0 = (6 << 11) | (2 << 8) | (6 << 2) | 1;
  304. rSPI_CTLR1 = WORDSPERPAGE - 1;
  305. rSPI_SSIENR = 1;
  306. rSPI_DR = SPI_QUAD_IO_READ_DATA;
  307. rSPI_DR = (tmpaddr[0] << 16) | (tmpaddr[1] << 8) | (tmpaddr[2] << 0);
  308. }
  309. for(i=0; i<WORDSPERPAGE; i++)
  310. {
  311. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  312. *buf++ = rSPI_DR;
  313. }
  314. SpiWaitIdle();
  315. rSPI_SSIENR = 0;
  316. rSPI_SPI_CTRLR0 = 0;
  317. rSPI_CTLR1 = 0;
  318. rSPI_SSIENR = 1;
  319. SpiSetFrameFormatMode(0, 0);
  320. SetCSGpioEnable(0);
  321. }
  322. #endif
  323. void SpiSelectPad()
  324. {
  325. UINT32 val;
  326. val = rSYS_PAD_CTRL02;
  327. val &= ~0xfff;
  328. val |= (0x1<<10)|(0x1 << 8)|(0x1 << 6)|(0x1 << 4)| (0x1 << 2);
  329. rSYS_PAD_CTRL02 = val;
  330. val = rSYS_SSP_CLK_CFG;
  331. val &= ~((0x1<<31)|(0x1<<30));
  332. val |= (0x1<<31)|(0x1<<30);
  333. rSYS_SSP_CLK_CFG = val;
  334. //cs inactive first
  335. SetCSGpioEnable(0);
  336. }
  337. void Reset(void)
  338. {
  339. SetSpiDataMode(8);
  340. rSPI_DR = 0x66;
  341. while((SpiReadSta() & SPI_BUSY));
  342. // while(!(SpiReadSta() & SPIFLASH_WRITEENABLE));
  343. rSPI_DR = 0x99;
  344. while((SpiReadSta() & SPI_BUSY));
  345. // while(!(SpiReadSta() & SPIFLASH_WRITEENABLE));
  346. SetSpiDataMode(32);
  347. }
  348. #define SPI0_CS0_GPIO 32
  349. #define SPI0_IO0_GPIO 34
  350. static void dwspi_jedec252_reset(void)
  351. {
  352. int i;
  353. int si = 0;
  354. UINT32 val;
  355. val = rSYS_PAD_CTRL02;
  356. val &= ~((3 << 4) | 3);
  357. rSYS_PAD_CTRL02 = val;
  358. gpio_direction_output(SPI0_CS0_GPIO, 1);
  359. gpio_direction_output(SPI0_IO0_GPIO, 1);
  360. udelay(300);
  361. for (i = 0; i < 4; i++) {
  362. gpio_direction_output(SPI0_CS0_GPIO, 0);
  363. gpio_direction_output(SPI0_IO0_GPIO, si);
  364. si = !si;
  365. udelay(300);
  366. gpio_direction_output(SPI0_CS0_GPIO, 1);
  367. udelay(300);
  368. }
  369. }
  370. static void SpiReadDeviceId(UINT8 *mfid, UINT8 *devid)
  371. {
  372. UINT8 val[6];
  373. int i;
  374. SetSpiDataMode(8);
  375. SetCSGpioEnable(1);
  376. rSPI_DR = SPI_MF_DEVICE_ID;
  377. rSPI_DR = 0;
  378. rSPI_DR = 0;
  379. rSPI_DR = 0;
  380. rSPI_DR = 0;
  381. rSPI_DR = 0;
  382. for (i = 0; i < 6; i++)
  383. {
  384. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  385. val[i] = rSPI_DR;
  386. }
  387. *mfid = val[4];
  388. *devid = val[5];
  389. SpiWaitIdle();
  390. SetCSGpioEnable(0);
  391. SetSpiDataMode(32);
  392. }
  393. static void SpiReadJedecId(UINT8 *mfid, UINT8 *memid, UINT8 *capid)
  394. {
  395. UINT8 val[4];
  396. int i;
  397. SetSpiDataMode(8);
  398. SetCSGpioEnable(1);
  399. rSPI_DR = SPI_READ_JEDEC_ID;
  400. rSPI_DR = 0;
  401. rSPI_DR = 0;
  402. rSPI_DR = 0;
  403. for (i = 0; i < 4; i++)
  404. {
  405. while(!(rSPI_SR & SPI_RXFIFO_NOTEMPTY));
  406. val[i] = rSPI_DR;
  407. }
  408. *mfid = val[1];
  409. *memid = val[2];
  410. *capid = val[3];
  411. SpiWaitIdle();
  412. SetCSGpioEnable(0);
  413. SetSpiDataMode(32);
  414. }
  415. void SpiReadId(void)
  416. {
  417. UINT8 mfid,devid,memid,capid;
  418. SpiReadDeviceId(&mfid,&devid);
  419. SpiReadJedecId(&mfid,&memid,&capid);
  420. PrintVariableValueHex("ManufacturerID: ", mfid);
  421. PrintVariableValueHex("DeviceID: ", devid);
  422. PrintVariableValueHex("Memory Type ID: ", memid);
  423. PrintVariableValueHex("Capacity ID: ", capid);
  424. }
  425. void SpiInit()
  426. {
  427. uint8_t mfid, typeid, capid;
  428. unsigned int val;
  429. int i;
  430. dwspi_jedec252_reset();
  431. SpiSelectPad();
  432. val = rSYS_SOFT_RST;
  433. val &= ~(0x1<<8);
  434. rSYS_SOFT_RST = val;
  435. udelay(10);
  436. val |= (0x1<<8);
  437. rSYS_SOFT_RST = val;
  438. rSPI_SSIENR = 0;
  439. rSPI_CTLR0 = 0;
  440. rSPI_CTLR0 |=(0<<21)|(0x1f<<16)|(0x0<<12)|(0x0<<8)|(0x0<<4);
  441. // rSPI_CTLR1 = 63;
  442. rSPI_BAUDR = 4;//42;//16;//2;
  443. rSPI_SER = 1;
  444. rSPI_IMR = 0;
  445. rSPI_SSIENR = 1;
  446. // Reset();
  447. SpiReadJedecId(&mfid, &typeid, &capid);
  448. for (i = 0; i < sizeof(flash_chip_table) / sizeof(flash_chip); i++) {
  449. if ((flash_chip_table[i].mf_id == mfid)
  450. && (flash_chip_table[i].type_id == typeid)
  451. && (flash_chip_table[i].capacity_id == capid)) {
  452. if (flash_chip_table[i].capacity > 0x1000000) {
  453. addr_in_4_byte = 1;
  454. SpiEnable4ByteMode();
  455. }
  456. break;
  457. }
  458. }
  459. if (!addr_in_4_byte)
  460. SpiDisable4ByteMode();
  461. #ifdef SPI0_QSPI_MODE
  462. if (i < sizeof(flash_chip_table) / sizeof(flash_chip) &&
  463. (SFUD_MF_ID_ISSI == flash_chip_table[i].mf_id ||
  464. SFUD_MF_ID_MICRONIX == flash_chip_table[i].mf_id)) {
  465. uint8_t status = SpiReadSta();
  466. status |= SPI_QE2;
  467. SpiWriteSta(status);
  468. } else {
  469. uint8_t status = SpiReadSta2();
  470. status |= SPI_QE;
  471. SpiWriteSta2(status);
  472. }
  473. #endif
  474. SpiReadSta3();
  475. udelay(10000);
  476. }
  477. #define SPI_READ_MAXLEN BYTESPERPAGE
  478. static void SpiLoadImage(void (*readfunc)(UINT32, UINT32 *))
  479. {
  480. unsigned int i = 0;
  481. UINT32 *buf = (UINT32*)IMAGE_ENTRY;
  482. UpFileHeader *header;
  483. UpFileInfo *appfile;
  484. UINT32 nPageCount;
  485. UINT32 nPageStart;
  486. UINT32 appsize;
  487. SysInfo *sysinfo = GetSysInfo();
  488. readfunc(IMAGE_OFFSET / BYTESPERPAGE, buf);
  489. header = (UpFileHeader*)buf;
  490. appfile = &header->files[0];
  491. if (appfile->offset & (BYTESPERPAGE - 1)) {
  492. SendUartString("\nImage positon is not align to flash pagesize, can't load.\r\n");
  493. while(1);
  494. }
  495. if (sysinfo->app_size)
  496. appsize = sysinfo->app_size;
  497. else
  498. appsize = appfile->size;
  499. nPageCount = (appsize + BYTESPERPAGE - 1) / BYTESPERPAGE;
  500. nPageStart = (appfile->offset + IMAGE_OFFSET) / BYTESPERPAGE;
  501. for(i = nPageStart; i < nPageStart + nPageCount; i++)
  502. {
  503. readfunc(i, buf);
  504. buf += BYTESPERPAGE/4;
  505. }
  506. #ifdef MMU_ENABLE
  507. CP15_clean_dcache_for_dma(IMAGE_ENTRY, IMAGE_ENTRY + appsize);
  508. #endif
  509. }
  510. static void SpiWriteEnable(void)
  511. {
  512. SetSpiDataMode(8);
  513. SetCSGpioEnable(1);
  514. rSPI_DR = SPI_WRITE_ENABLE;
  515. SpiWaitIdle();
  516. SetCSGpioEnable(0);
  517. while((SpiReadSta() & SPI_BUSY));
  518. while(!(SpiReadSta() & SPIFLASH_WRITEENABLE));
  519. SetSpiDataMode(32);
  520. }
  521. static void SpiEraseSector(UINT32 sectorNum)
  522. {
  523. UINT32 addr;
  524. UINT8 tmpaddr[4];
  525. addr = BYTESPERSECTOR*sectorNum;
  526. tmpaddr[0] = addr;
  527. tmpaddr[1] = addr>>8;
  528. tmpaddr[2] = addr>>16;
  529. tmpaddr[3] = addr>>24;
  530. SpiWriteEnable();
  531. SetCSGpioEnable(1);
  532. if (addr_in_4_byte) {
  533. SetSpiDataMode(8);
  534. rSPI_DR = SPI_4BYTEADD_SECTOR_ERASE;
  535. rSPI_DR = tmpaddr[3];
  536. rSPI_DR = tmpaddr[2];
  537. rSPI_DR = tmpaddr[1];
  538. rSPI_DR = tmpaddr[0];
  539. } else {
  540. rSPI_DR = (tmpaddr[0]<<24) | (tmpaddr[1]<<16) | (tmpaddr[2]<<8) | SPI_SECTOR_ERASE;
  541. }
  542. SpiWaitIdle();
  543. SetCSGpioEnable(0);
  544. while((SpiReadSta() & SPIFLASH_WRITEENABLE));
  545. }
  546. static void SpiEraseBlock(UINT32 blockNum)
  547. {
  548. UINT32 addr;
  549. UINT8 tmpaddr[4];
  550. addr = BYTESPERBLOCK*blockNum;
  551. tmpaddr[0] = addr;
  552. tmpaddr[1] = addr>>8;
  553. tmpaddr[2] = addr>>16;
  554. tmpaddr[3] = addr>>24;
  555. SpiWriteEnable();
  556. SetCSGpioEnable(1);
  557. if (addr_in_4_byte) {
  558. SetSpiDataMode(8);
  559. rSPI_DR = SPI_4BYTEADD_BLOCK_ERASE;
  560. rSPI_DR = tmpaddr[3];
  561. rSPI_DR = tmpaddr[2];
  562. rSPI_DR = tmpaddr[1];
  563. rSPI_DR = tmpaddr[0];
  564. } else {
  565. rSPI_DR = (tmpaddr[0]<<24) | (tmpaddr[1]<<16) | (tmpaddr[2]<<8) | SPI_BLOCK_ERASE;
  566. }
  567. SpiWaitIdle();
  568. SetCSGpioEnable(0);
  569. while((SpiReadSta() & SPIFLASH_WRITEENABLE));
  570. }
  571. static void SpiWritePage(UINT32 pagenum, UINT32 *buf)
  572. {
  573. UINT32 addr;
  574. UINT32 val = 0;;
  575. INT32 i;
  576. UINT8 tmpaddr[4];
  577. UINT8 *data = (UINT8*)buf;
  578. (void)val;
  579. addr = pagenum*BYTESPERPAGE;
  580. tmpaddr[0] = addr;
  581. tmpaddr[1] = addr>>8;
  582. tmpaddr[2] = addr>>16;
  583. tmpaddr[3] = addr>>24;
  584. SpiWriteEnable();
  585. SetCSGpioEnable(1);
  586. if (addr_in_4_byte) {
  587. SetSpiDataMode(8);
  588. rSPI_DR = SPI_4BYTEADD_PAGE_PROGRAM;
  589. rSPI_DR = tmpaddr[3];
  590. rSPI_DR = tmpaddr[2];
  591. rSPI_DR = tmpaddr[1];
  592. rSPI_DR = tmpaddr[0];
  593. } else {
  594. rSPI_DR = (tmpaddr[0]<<24) | (tmpaddr[1]<<16) | (tmpaddr[2]<<8) | SPI_PAGE_PROGRAM;
  595. }
  596. if (addr_in_4_byte) {
  597. for (i = 0; i < BYTESPERPAGE; i++) {
  598. while(!(rSPI_SR & SPI_TXFIFO_NOTFULL));
  599. rSPI_DR = *data++;
  600. }
  601. } else {
  602. for (i = 0; i < WORDSPERPAGE; i++) {
  603. while(!(rSPI_SR & SPI_TXFIFO_NOTFULL));
  604. rSPI_DR = *buf++;
  605. }
  606. }
  607. SpiWaitIdle();
  608. SetCSGpioEnable(0);
  609. while(SpiReadSta() & SPI_BUSY);
  610. }
  611. void bootFromSPI(void)
  612. {
  613. void (*funPtr)(void);
  614. #ifdef SPI0_QSPI_MODE
  615. SpiLoadImage(SpiReadPageQuadMode);
  616. #else
  617. SpiLoadImage(SpiReadPage);
  618. #endif
  619. funPtr = (void (*)(void))IMAGE_ENTRY;
  620. funPtr();
  621. }
  622. static unsigned int pagecheck[WORDSPERPAGE];
  623. /* offset is at least align to SECOTR_SIZE */
  624. static int SpiNorBurnPage(int pagenum, unsigned int *buf)
  625. {
  626. int timeout = 3;
  627. unsigned int *tmp = (unsigned int *)buf;
  628. int i;
  629. retry:
  630. SpiWritePage(pagenum, buf);
  631. SpiReadPage(pagenum, pagecheck);
  632. for (i = 0; i < WORDSPERPAGE; i++) {
  633. if (tmp[i] != pagecheck[i]) {
  634. if (timeout-- > 0) {
  635. PrintVariableValueHex("write: ", tmp[i]);
  636. PrintVariableValueHex("read: ", pagecheck[i]);
  637. SendUartString("burn check data fail, retry...\r\n");
  638. goto retry;
  639. } else {
  640. SendUartString("burn error!\r\n");
  641. return -1;
  642. }
  643. }
  644. }
  645. return 0;
  646. }
  647. /* offset is at least align to SECOTR_SIZE */
  648. int SpiNorBurn(void *buf, unsigned int offset, unsigned int size, int show_progress)
  649. {
  650. int i, j;
  651. int secstart, secnum;
  652. int blkstart, blknum;
  653. int pagestart, pagenum, pageburned;
  654. int remain = size;
  655. unsigned int *pbuf = (unsigned int *)buf;
  656. pagestart = offset / BYTESPERPAGE;
  657. pagenum = (size + BYTESPERPAGE - 1) / BYTESPERPAGE;
  658. pageburned = 0;
  659. while (remain > 0) {
  660. unsigned int tmp = offset & (BYTESPERBLOCK - 1);
  661. if (tmp) {
  662. tmp = (BYTESPERBLOCK - tmp) / BYTESPERSECTOR;
  663. secnum = (remain + BYTESPERSECTOR - 1) / BYTESPERSECTOR;
  664. secnum = min(tmp, secnum);
  665. secstart = offset / BYTESPERSECTOR;
  666. for (i = 0; i < secnum; i++) {
  667. SpiEraseSector(secstart + i);
  668. for (j = 0; j < PAGESPERSECTORS; j++) {
  669. if (SpiNorBurnPage(pagestart + j, pbuf))
  670. return -1;
  671. pbuf += WORDSPERPAGE;
  672. pageburned++;
  673. remain -= BYTESPERPAGE;
  674. if (remain <= 0) goto finish;
  675. if (show_progress)
  676. update_progress_set(pageburned * 100 / pagenum);
  677. }
  678. pagestart += PAGESPERSECTORS;
  679. }
  680. offset += secnum * BYTESPERSECTOR;
  681. } else {
  682. blkstart = offset / BYTESPERBLOCK;
  683. blknum = remain / BYTESPERBLOCK;
  684. for (i = 0; i < blknum; i++) {
  685. SpiEraseBlock(blkstart + i);
  686. for (j = 0; j < PAGESPERSECTORS * SECTORSPERBLOCK; j++) {
  687. if (SpiNorBurnPage(pagestart + j, pbuf))
  688. return -1;
  689. pbuf += WORDSPERPAGE;
  690. pageburned++;
  691. remain -= BYTESPERPAGE;
  692. if (remain <= 0) goto finish;
  693. if (show_progress)
  694. update_progress_set(pageburned * 100 / pagenum);
  695. }
  696. pagestart += PAGESPERSECTORS * SECTORSPERBLOCK;
  697. }
  698. offset += blknum * BYTESPERBLOCK;
  699. if (remain > 0) {
  700. secstart = offset / BYTESPERSECTOR;
  701. secnum = (remain + BYTESPERSECTOR - 1) / BYTESPERSECTOR;
  702. for (i = 0; i < secnum; i++) {
  703. SpiEraseSector(secstart + i);
  704. for (j = 0; j < PAGESPERSECTORS; j++) {
  705. if (SpiNorBurnPage(pagestart + j, pbuf))
  706. return -1;
  707. pbuf += WORDSPERPAGE;
  708. pageburned++;
  709. remain -= BYTESPERPAGE;
  710. if (remain <= 0) goto finish;
  711. if (show_progress)
  712. update_progress_set(pageburned * 100 / pagenum);
  713. }
  714. pagestart += PAGESPERSECTORS;
  715. }
  716. offset += secnum * BYTESPERSECTOR;
  717. }
  718. }
  719. }
  720. finish:
  721. if (show_progress)
  722. update_progress_set(100);
  723. return 0;
  724. }
  725. int SpiReadSysInfo(SysInfo *info)
  726. {
  727. UINT32 *buf = (UINT32*)IMAGE_ENTRY;
  728. int pagestart;
  729. int pagenum;
  730. UINT32 checksum;
  731. UINT32 calc_checksum;
  732. int i;
  733. pagestart = SYSINFOA_OFFSET / BYTESPERPAGE;
  734. pagenum = (sizeof(SysInfo) + BYTESPERPAGE - 1) / BYTESPERPAGE;
  735. for(i = pagestart; i < pagestart + pagenum; i++)
  736. {
  737. SpiReadPage(i, buf);
  738. buf += BYTESPERPAGE/4;
  739. }
  740. checksum = *(UINT32*)(IMAGE_ENTRY + sizeof(SysInfo) - 4);
  741. calc_checksum = xcrc32((unsigned char*)IMAGE_ENTRY, sizeof(SysInfo) - 4, 0xffffffff);
  742. if (calc_checksum == checksum) {
  743. memcpy(info, (void*)IMAGE_ENTRY, sizeof(SysInfo));
  744. return 0;
  745. }
  746. buf = (UINT32*)IMAGE_ENTRY;
  747. pagestart = SYSINFOB_OFFSET / BYTESPERPAGE;
  748. for(i = pagestart; i < pagestart + pagenum; i++)
  749. {
  750. SpiReadPage(i, buf);
  751. buf += BYTESPERPAGE/4;
  752. }
  753. checksum = *(UINT32*)(IMAGE_ENTRY + sizeof(SysInfo) - 4);
  754. calc_checksum = xcrc32((unsigned char*)IMAGE_ENTRY, sizeof(SysInfo) - 4, 0xffffffff);
  755. if (calc_checksum == checksum) {
  756. memcpy(info, (void*)IMAGE_ENTRY, sizeof(SysInfo));
  757. return 0;
  758. }
  759. return -1;
  760. }
  761. void SpiWriteSysInfo(SysInfo *info)
  762. {
  763. SpiNorBurn(info, SYSINFOB_OFFSET, sizeof(SysInfo), 0);
  764. SpiNorBurn(info, SYSINFOA_OFFSET, sizeof(SysInfo), 0);
  765. }
  766. unsigned int SpiGetUpfileOffset(int type)
  767. {
  768. if (type == UPFILE_TYPE_WHOLE) {
  769. return IMAGE_OFFSET;
  770. } else if (type == UPFILE_TYPE_SPILDR) {
  771. return LOADER_OFFSET;
  772. } else if (type == UPFILE_TYPE_STEPLDR) {
  773. SysInfo *sysinfo = GetSysInfo();
  774. if (sysinfo->stepldr_offset == STEPLDRA_OFFSET)
  775. sysinfo->stepldr_offset = STEPLDRB_OFFSET;
  776. else
  777. sysinfo->stepldr_offset = STEPLDRA_OFFSET;
  778. return sysinfo->stepldr_offset;
  779. } else {
  780. unsigned int buf[WORDSPERPAGE];
  781. UpFileHeader *header;
  782. UpFileInfo *appfile;
  783. unsigned int offset;
  784. int i;
  785. SpiReadPage(IMAGE_OFFSET / BYTESPERPAGE, buf);
  786. header = (UpFileHeader*)buf;
  787. if (header->magic != MKTAG('U', 'P', 'D', 'F')) {
  788. SendUartString("old update file isn't found in flash, can't support module update.\n");
  789. return 0xffffffff;
  790. }
  791. for (i = 0; i < header->filenum; i++) {
  792. appfile = &header->files[i];
  793. if ((appfile->magic == UPFILE_APP_MAGIC && type == UPFILE_TYPE_APP) ||
  794. (appfile->magic == MKTAG('R', 'O', 'M', 'A') && type == UPFILE_TYPE_RESOURCE) ||
  795. (appfile->magic == MKTAG('B', 'A', 'N', 'I') && type == UPFILE_TYPE_ANIMATION)) {
  796. offset = appfile->offset;
  797. if (offset & (BYTESPERSECTOR - 1)) {
  798. SendUartString("offset isn't align to sector erase size, can't support module update.\n");
  799. return 0xffffffff;
  800. }
  801. return offset + IMAGE_OFFSET;
  802. }
  803. }
  804. }
  805. return 0xffffffff;
  806. }