spinor.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. /*
  2. * Copyright (c) 2017 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief SPINOR Flash driver for LARK
  9. */
  10. #include <irq.h>
  11. #include "spi_internal.h"
  12. #include "spimem.h"
  13. #include "../spi_flash.h"
  14. /* spinor parameters */
  15. #define SPINOR_WRITE_PAGE_SIZE_BITS 8
  16. #define SPINOR_ERASE_SECTOR_SIZE_BITS 12
  17. #define SPINOR_ERASE_BLOCK_SIZE_BITS 16
  18. #define SPINOR_WRITE_PAGE_SIZE (1 << SPINOR_WRITE_PAGE_SIZE_BITS)
  19. #define SPINOR_ERASE_SECTOR_SIZE (1 << SPINOR_ERASE_SECTOR_SIZE_BITS)
  20. #define SPINOR_ERASE_BLOCK_SIZE (1 << SPINOR_ERASE_BLOCK_SIZE_BITS)
  21. #define SPINOR_WRITE_PAGE_MASK (SPINOR_WRITE_PAGE_SIZE - 1)
  22. #define SPINOR_ERASE_SECTOR_MASK (SPINOR_ERASE_SECTOR_SIZE - 1)
  23. #define SPINOR_ERASE_BLOCK_MASK (SPINOR_ERASE_BLOCK_SIZE - 1)
  24. /* spinor commands */
  25. #define SPINOR_CMD_WRITE_PAGE 0x02 /* write one page */
  26. #define SPINOR_CMD_DISABLE_WRITE 0x04 /* disable write */
  27. #define SPINOR_CMD_READ_STATUS 0x05 /* read status1 */
  28. #define SPINOR_CMD_READ_STATUS2 0x35 /* read status2 */
  29. #define SPINOR_CMD_READ_STATUS3 0x15 /* read status3 */
  30. #define SPINOR_CMD_WRITE_STATUS 0x01 /* write status1 */
  31. #define SPINOR_CMD_WRITE_STATUS2 0x31 /* write status2 */
  32. #define SPINOR_CMD_WRITE_STATUS3 0x11 /* write status3 */
  33. #define SPINOR_CMD_ENABLE_WRITE 0x06 /* enable write */
  34. #define SPINOR_CMD_FAST_READ 0x0b /* fast read */
  35. #define SPINOR_CMD_ERASE_SECTOR 0x20 /* 4KB erase */
  36. #define SPINOR_CMD_ERASE_BLOCK_32K 0x52 /* 32KB erase */
  37. #define SPINOR_CMD_ERASE_BLOCK 0xd8 /* 64KB erase */
  38. #define SPINOR_CMD_READ_CHIPID 0x9f /* JEDEC ID */
  39. #define SPINOR_CMD_DISABLE_QSPI 0xff /* disable QSPI */
  40. #define SPINOR_CMD_PROGRAM_ERASE_RESUME 0x7a /* nor resume */
  41. #define SPINOR_CMD_PROGRAM_ERASE_SUSPEND 0x75 /* nor suspend */
  42. #define SPINOR_CMD_EN4B 0xB7 /* enter 4-byte address mode */
  43. #define SPINOR_CMD_EXIT4B 0xE9 /* exit 4-byte address mode */
  44. /* spinor 4byte address commands */
  45. #define SPINOR_CMD_WRITE_PAGE_4B 0x12 /* write one page by 4bytes address */
  46. #define SPINOR_CMD_ERASE_SECTOR_4B 0x21 /* 4KB erase by 4bytes address */
  47. #define SPINOR_CMD_ERASE_BLOCK_4B 0xdc /* 64KB erase by 4bytes address */
  48. #define SPINOR_CMD_WIRTE_EXT_ADDR_R 0xc5 /* write Extended Addr. Register cmd+1BYTE(ext addr)*/
  49. #define SPINOR_CMD_READ_EXT_ADDR_R 0xc8 /* Read Extended Addr. Register */
  50. /* NOR Flash vendors ID */
  51. #define SPINOR_MANU_ID_ALLIANCE 0x52 /* Alliance Semiconductor */
  52. #define SPINOR_MANU_ID_AMD 0x01 /* AMD */
  53. #define SPINOR_MANU_ID_AMIC 0x37 /* AMIC */
  54. #define SPINOR_MANU_ID_ATMEL 0x1f /* ATMEL */
  55. #define SPINOR_MANU_ID_CATALYST 0x31 /* Catalyst */
  56. #define SPINOR_MANU_ID_ESMT 0x8c /* ESMT */
  57. #define SPINOR_MANU_ID_EON 0x1c /* EON */
  58. #define SPINOR_MANU_ID_FD_MICRO 0xa1 /* shanghai fudan microelectronics */
  59. #define SPINOR_MANU_ID_FIDELIX 0xf8 /* FIDELIX */
  60. #define SPINOR_MANU_ID_FMD 0x0e /* Fremont Micro Device(FMD) */
  61. #define SPINOR_MANU_ID_FUJITSU 0x04 /* Fujitsu */
  62. #define SPINOR_MANU_ID_GIGADEVICE 0xc8 /* GigaDevice */
  63. #define SPINOR_MANU_ID_GIGADEVICE2 0x51 /* GigaDevice2 */
  64. #define SPINOR_MANU_ID_HYUNDAI 0xad /* Hyundai */
  65. #define SPINOR_MANU_ID_INTEL 0x89 /* Intel */
  66. #define SPINOR_MANU_ID_MACRONIX 0xc2 /* Macronix (MX) */
  67. #define SPINOR_MANU_ID_NANTRONIC 0xd5 /* Nantronics */
  68. #define SPINOR_MANU_ID_NUMONYX 0x20 /* Numonyx, Micron, ST */
  69. #define SPINOR_MANU_ID_PMC 0x9d /* PMC */
  70. #define SPINOR_MANU_ID_SANYO 0x62 /* SANYO */
  71. #define SPINOR_MANU_ID_SHARP 0xb0 /* SHARP */
  72. #define SPINOR_MANU_ID_SPANSION 0x01 /* SPANSION */
  73. #define SPINOR_MANU_ID_SST 0xbf /* SST */
  74. #define SPINOR_MANU_ID_SYNCMOS_MVC 0x40 /* SyncMOS (SM) and Mosel Vitelic Corporation (MVC) */
  75. #define SPINOR_MANU_ID_TI 0x97 /* Texas Instruments */
  76. #define SPINOR_MANU_ID_WINBOND 0xda /* Winbond */
  77. #define SPINOR_MANU_ID_WINBOND_NEX 0xef /* Winbond (ex Nexcom) */
  78. #define SPINOR_MANU_ID_ZH_BERG 0xe0 /* ZhuHai Berg microelectronics (Bo Guan) */
  79. //#define SPINOR_FLAG_UNLOCK_IRQ_WAIT_READY (1 << 0)
  80. #define NOR_DELAY_CHAIN 0x8
  81. /* system XIP spinor */
  82. static const struct spinor_info system_spi_nor = {
  83. .spi = {
  84. .base = SPI0_REG_BASE,
  85. .bus_width = 1,
  86. .delay_chain = NOR_DELAY_CHAIN,
  87. .flag = 0,
  88. #if 0
  89. .dma_base= 0x4001C600, //DMA5
  90. #endif
  91. }
  92. };
  93. _nor_fun static unsigned int spinor_read_status(struct spinor_info *sni, unsigned char cmd)
  94. {
  95. if (!sni)
  96. sni = (struct spinor_info *)&system_spi_nor;
  97. return spimem_read_status(&sni->spi, cmd);
  98. }
  99. _nor_fun static int spinor_wait_ready(struct spinor_info *sni)
  100. {
  101. unsigned char status;
  102. while (1) {
  103. status = spinor_read_status(sni, SPINOR_CMD_READ_STATUS);
  104. if (!(status & 0x1))
  105. break;
  106. }
  107. return 0;
  108. }
  109. _nor_fun static void spinor_write_data(struct spinor_info *sni, unsigned char cmd,
  110. unsigned int addr, int addr_len, const unsigned char *buf, int len)
  111. {
  112. struct spi_info *si = &sni->spi;
  113. unsigned int key = 0;
  114. if (!(si->flag & SPI_FLAG_NO_IRQ_LOCK)) {
  115. key = irq_lock();
  116. }
  117. spimem_set_write_protect(si, 0);
  118. spimem_transfer(si, cmd, addr, addr_len, (unsigned char *)buf, len,
  119. 0, SPIMEM_TFLAG_WRITE_DATA);
  120. if(sni->flag & SPINOR_FLAG_NO_WAIT_READY){
  121. if (!(si->flag & SPI_FLAG_NO_IRQ_LOCK))
  122. irq_unlock(key);
  123. }else{
  124. if (!(si->flag & SPI_FLAG_NO_IRQ_LOCK)) {
  125. if (sni->flag & SPINOR_FLAG_UNLOCK_IRQ_WAIT_READY) {
  126. irq_unlock(key);
  127. spinor_wait_ready(sni);
  128. } else {
  129. spinor_wait_ready(sni);
  130. irq_unlock(key);
  131. }
  132. }else{
  133. spinor_wait_ready(sni);
  134. }
  135. }
  136. }
  137. _nor_fun static void spinor_write_status(struct spinor_info *sni, unsigned char cmd,
  138. unsigned char *status, int len)
  139. {
  140. if (!sni)
  141. sni = (struct spinor_info *)&system_spi_nor;
  142. spinor_write_data(sni, cmd, 0, 0, status, len);
  143. spinor_wait_ready(sni);
  144. }
  145. _nor_fun static int spinor_erase_internal(struct spinor_info *sni,
  146. unsigned char cmd, unsigned int addr)
  147. {
  148. if (sni->flag & SPINOR_FLAG_4BYTE_ADDRESS_MODE_EN) {
  149. spinor_write_data(sni, cmd, addr, 4, 0, 0);
  150. } else {
  151. spinor_write_data(sni, cmd, addr, 3, 0, 0);
  152. }
  153. return 0;
  154. }
  155. _nor_fun static int spinor_write_internal(struct spinor_info *sni,
  156. unsigned int addr, const unsigned char *buf, int len)
  157. {
  158. if (sni->flag & SPINOR_FLAG_4BYTE_ADDRESS_MODE_EN) {
  159. spinor_write_data(sni, SPINOR_CMD_WRITE_PAGE_4B, addr, 4, buf, len);
  160. } else {
  161. spinor_write_data(sni, SPINOR_CMD_WRITE_PAGE, addr, 3, buf, len);
  162. }
  163. return 0;
  164. }
  165. _nor_fun static int spinor_read_internal(struct spinor_info *sni,
  166. unsigned int addr, unsigned char *buf, int len)
  167. {
  168. if (sni->flag & SPINOR_FLAG_4BYTE_ADDRESS_MODE_EN) {
  169. spimem_read_page(&sni->spi, addr, 4, buf, len);
  170. } else {
  171. spimem_read_page(&sni->spi, addr, 3, buf, len);
  172. }
  173. return 0;
  174. }
  175. _nor_fun int spinor_read(struct spinor_info *sni, unsigned int addr, void *data, int len)
  176. {
  177. if (!len)
  178. return 0;
  179. if (!sni)
  180. sni = (struct spinor_info *)&system_spi_nor;
  181. spinor_read_internal(sni, addr, data, len);
  182. return 0;
  183. }
  184. _nor_fun int spinor_write(struct spinor_info *sni, unsigned int addr,
  185. const void *data, int len)
  186. {
  187. int unaligned_len, remaining, write_size;
  188. if (!len)
  189. return 0;
  190. if (!sni)
  191. sni = (struct spinor_info *)&system_spi_nor;
  192. /* unaligned write? */
  193. if (addr & SPINOR_WRITE_PAGE_MASK)
  194. unaligned_len = SPINOR_WRITE_PAGE_SIZE - (addr & SPINOR_WRITE_PAGE_MASK);
  195. else
  196. unaligned_len = 0;
  197. remaining = len;
  198. while (remaining > 0) {
  199. if (unaligned_len) {
  200. /* write unaligned page data */
  201. if (unaligned_len > len)
  202. write_size = len;
  203. else
  204. write_size = unaligned_len;
  205. unaligned_len = 0;
  206. } else if (remaining < SPINOR_WRITE_PAGE_SIZE)
  207. write_size = remaining;
  208. else
  209. write_size = SPINOR_WRITE_PAGE_SIZE;
  210. spinor_write_internal(sni, addr, data, write_size);
  211. addr += write_size;
  212. data = (unsigned char *)data+write_size;
  213. remaining -= write_size;
  214. }
  215. return 0;
  216. }
  217. _nor_fun int spinor_write_with_randomizer(struct spinor_info *sni, unsigned int addr, const void *data, int len)
  218. {
  219. struct spi_info *si;
  220. u32_t key, page_addr, origin_spi_ctl;
  221. int wlen;
  222. unsigned char addr_len;
  223. unsigned char cmd;
  224. if (!sni)
  225. sni = (struct spinor_info *)&system_spi_nor;
  226. si = &sni->spi;
  227. key = irq_lock(); //ota diff upgrade, must be irq lock
  228. origin_spi_ctl = spi_read(si, SSPI_CTL);
  229. spimem_set_write_protect(si, 0);
  230. page_addr = (addr + len) & ~SPINOR_WRITE_PAGE_MASK;
  231. if ((addr & ~SPINOR_WRITE_PAGE_MASK) != page_addr) {
  232. /* data cross write page bound, need split */
  233. wlen = page_addr - addr;
  234. if (sni->flag & SPINOR_FLAG_4BYTE_ADDRESS_MODE_EN) {
  235. addr_len = 4;
  236. cmd = SPINOR_CMD_WRITE_PAGE_4B;
  237. } else {
  238. addr_len = 3;
  239. cmd = SPINOR_CMD_WRITE_PAGE;
  240. }
  241. spimem_transfer(si, cmd, addr, addr_len, (u8_t *)data, wlen,
  242. 0, SPIMEM_TFLAG_WRITE_DATA | SPIMEM_TFLAG_ENABLE_RANDOMIZE |
  243. SPIMEM_TFLAG_PAUSE_RANDOMIZE);
  244. spinor_wait_ready(sni);
  245. data = (unsigned char *)data + wlen;
  246. len -= wlen;
  247. addr = page_addr;
  248. spimem_set_write_protect(si, 0);
  249. }
  250. if (sni->flag & SPINOR_FLAG_4BYTE_ADDRESS_MODE_EN) {
  251. addr_len = 4;
  252. cmd = SPINOR_CMD_WRITE_PAGE_4B;
  253. } else {
  254. addr_len = 3;
  255. cmd = SPINOR_CMD_WRITE_PAGE;
  256. }
  257. spimem_transfer(si, cmd, addr, addr_len, (u8_t *)data, len,
  258. 0, SPIMEM_TFLAG_WRITE_DATA | SPIMEM_TFLAG_ENABLE_RANDOMIZE | SPIMEM_TFLAG_RESUME_RANDOMIZE);
  259. spinor_wait_ready(sni);
  260. spi_write(si, SSPI_CTL, origin_spi_ctl);
  261. spi_delay();
  262. irq_unlock(key);
  263. return 0;
  264. }
  265. _nor_fun int spinor_enter_4byte_address_mode(struct spinor_info *sni)
  266. {
  267. #ifdef CONFIG_NOR_CODE_IN_RAM
  268. printk("spinor code in ram\n");
  269. return 0;
  270. #else
  271. printk("spinor enter 4-byte address mode\n");
  272. sni->flag |= SPINOR_FLAG_4BYTE_ADDRESS_MODE_EN;
  273. return spimem_transfer(&sni->spi, SPINOR_CMD_EN4B, 0, 0, NULL, 0, 0, 0);
  274. #endif
  275. }
  276. _nor_fun int spinor_erase(struct spinor_info *sni, unsigned int addr, int size)
  277. {
  278. int remaining, erase_size;
  279. unsigned char cmd;
  280. if (!size)
  281. return 0;
  282. if (addr & SPINOR_ERASE_SECTOR_MASK || size & SPINOR_ERASE_SECTOR_MASK)
  283. return -1;
  284. if (!sni)
  285. sni = (struct spinor_info *)&system_spi_nor;
  286. /* write aligned page data */
  287. remaining = size;
  288. while (remaining > 0) {
  289. if (addr & SPINOR_ERASE_BLOCK_MASK || remaining < SPINOR_ERASE_BLOCK_SIZE) {
  290. if (sni->flag & SPINOR_FLAG_4BYTE_ADDRESS_MODE_EN) {
  291. cmd = SPINOR_CMD_ERASE_SECTOR_4B;
  292. } else {
  293. cmd = SPINOR_CMD_ERASE_SECTOR;
  294. }
  295. erase_size = SPINOR_ERASE_SECTOR_SIZE;
  296. } else {
  297. if (sni->flag & SPINOR_FLAG_4BYTE_ADDRESS_MODE_EN) {
  298. cmd = SPINOR_CMD_ERASE_BLOCK_4B;
  299. } else {
  300. cmd = SPINOR_CMD_ERASE_BLOCK;
  301. }
  302. erase_size = SPINOR_ERASE_BLOCK_SIZE;
  303. }
  304. spinor_erase_internal(sni, cmd, addr);
  305. addr += erase_size;
  306. remaining -= erase_size;
  307. }
  308. return 0;
  309. }
  310. _nor_fun unsigned int spinor_read_chipid(struct spinor_info *sni)
  311. {
  312. unsigned int chipid;
  313. if (!sni)
  314. sni = (struct spinor_info *)&system_spi_nor;
  315. spimem_read_chipid(&sni->spi, &chipid, 3);
  316. return chipid;
  317. }
  318. #ifdef CONFIG_NOR_CODE_IN_RAM
  319. #include "soc.h"
  320. #define XIP_CODE_ADDR (CONFIG_FLASH_BASE_ADDRESS + CONFIG_FLASH_LOAD_OFFSET)
  321. #define NOR_3B_ADDR_MAXLEN (1<<24) // 16MB
  322. static unsigned int xip_nor_offset;
  323. _nor_fun static void spinor_4byte_address_mode(struct spinor_info *sni, bool enter)
  324. {
  325. if(enter){
  326. sni->flag |= SPINOR_FLAG_4BYTE_ADDRESS_MODE_EN;
  327. spimem_write_cmd(&sni->spi, SPINOR_CMD_EN4B);
  328. }else{
  329. sni->flag &= ~SPINOR_FLAG_4BYTE_ADDRESS_MODE_EN;
  330. spimem_write_cmd(&sni->spi, SPINOR_CMD_EXIT4B);
  331. }
  332. }
  333. //#define CONFIG_NOR_XIP_READ
  334. #ifdef CONFIG_NOR_XIP_READ
  335. int spinor_xip_read(unsigned int addr, void *data, int len)
  336. {
  337. unsigned int xip_start;
  338. xip_start = 0x10000000 + addr - xip_nor_offset;
  339. pbrom_libc_api->p_memcpy(data, (void *)xip_start, len);
  340. return 0;
  341. }
  342. _nor_fun int spinor_ram_read(struct spinor_info *sni, unsigned int addr, void *data, int len)
  343. {
  344. int ret;
  345. unsigned int tlen;
  346. uint32_t key;
  347. if(addr < xip_nor_offset){
  348. tlen = xip_nor_offset - addr;
  349. if(tlen > len)
  350. tlen = len;
  351. key = irq_lock();
  352. spinor_read(sni, addr, data, tlen);
  353. irq_unlock(key);
  354. data =(void *) ((unsigned int)data + tlen);
  355. len -= tlen;
  356. addr += tlen;
  357. }
  358. if(len <= 0)
  359. return 0;
  360. if(addr+len > NOR_3B_ADDR_MAXLEN){
  361. if(addr < NOR_3B_ADDR_MAXLEN){
  362. tlen = NOR_3B_ADDR_MAXLEN - addr;
  363. spinor_xip_read(addr, data, tlen);
  364. data =(void *) ((unsigned int)data + tlen);
  365. len -= tlen;
  366. addr = NOR_3B_ADDR_MAXLEN;
  367. }
  368. key = irq_lock();
  369. spinor_4byte_address_mode(sni, true);
  370. ret = spinor_read(sni, addr, data, len);
  371. spinor_4byte_address_mode(sni, false);
  372. irq_unlock(key);
  373. }else{
  374. ret = spinor_xip_read(addr, data, len);
  375. }
  376. return ret;
  377. }
  378. static int spinor_xip_init(const struct device *arg)
  379. {
  380. xip_nor_offset = soc_boot_get_info()->nor_offset & (NOR_3B_ADDR_MAXLEN-1);
  381. printk("xip_nor_offset=0x%x-0x%x\n", xip_nor_offset, XIP_CODE_ADDR);
  382. return 0;
  383. }
  384. SYS_INIT(spinor_xip_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
  385. #else
  386. _nor_fun int spinor_ram_read(struct spinor_info *sni, unsigned int addr, void *data, int len)
  387. {
  388. int ret;
  389. uint32_t key;
  390. key = irq_lock();
  391. spinor_4byte_address_mode(sni, true);
  392. ret = spinor_read(sni, addr, data, len);
  393. spinor_4byte_address_mode(sni, false);
  394. irq_unlock(key);
  395. return ret;
  396. }
  397. #endif
  398. #if 0
  399. _nor_fun static void spinor_suspend(struct spinor_info *sni)
  400. {
  401. int i, j;
  402. // program/erase suspend
  403. for(j = 0; j < 3; j++){
  404. spimem_write_cmd(&sni->spi, SPINOR_CMD_PROGRAM_ERASE_SUSPEND);
  405. for(i = 0; i < 10; i++) { //tSUS must 20us
  406. soc_udelay(5);
  407. if (0 == (spinor_read_status(sni, SPINOR_CMD_READ_STATUS) & 0x1)){
  408. break;
  409. }
  410. }
  411. if(i != 10)
  412. break;
  413. }
  414. }
  415. _nor_fun static bool spinor_resume_and_check_idle(struct spinor_info *sni)
  416. {
  417. bool ret;
  418. uint32_t key, i;
  419. key = irq_lock();
  420. // program/erase resum
  421. spimem_write_cmd(&sni->spi, SPINOR_CMD_PROGRAM_ERASE_RESUME);
  422. soc_udelay(5);
  423. if (0 == (spinor_read_status(sni, SPINOR_CMD_READ_STATUS) & 0x1)) {
  424. ret = true;
  425. }else {
  426. for(i = 0; i < 10; i++){ // handle 200 us
  427. soc_udelay(20);
  428. if (0 == (spinor_read_status(sni, SPINOR_CMD_READ_STATUS) & 0x1)){
  429. break;
  430. }
  431. }
  432. if(i != 10){
  433. ret = true;
  434. }else{
  435. spinor_suspend(sni);
  436. ret = false;
  437. }
  438. }
  439. irq_unlock(key);
  440. return ret;
  441. }
  442. _nor_fun static void spinor_wait_finished(struct spinor_info *sni)
  443. {
  444. int i;
  445. for(i = 0; i < 1000; i++){
  446. if (spinor_resume_and_check_idle(sni))
  447. break;
  448. if(!k_is_in_isr()){
  449. if((i & 0x1) == 0)
  450. k_msleep(1);
  451. }
  452. }
  453. }
  454. #endif
  455. _nor_fun int spinor_ram_write(struct spinor_info *sni, unsigned int addr,
  456. const void *data, int len)
  457. {
  458. int ret;
  459. uint32_t key;
  460. //spinor_wait_finished(sni);
  461. key = irq_lock();
  462. spinor_4byte_address_mode(sni, true);
  463. ret = spinor_write(sni, addr, data, len);
  464. spinor_4byte_address_mode(sni, false);
  465. irq_unlock(key);
  466. return ret;
  467. }
  468. _nor_fun int spinor_ram_erase(struct spinor_info *sni, unsigned int addr, int len)
  469. {
  470. int ret = 0;
  471. uint32_t key;
  472. int erase_size = 0;
  473. uint32_t t0,t1, t2;
  474. printk("nor_e:off=0x%x,len=0x%x \n", addr, len);
  475. while (len > 0) {
  476. if (len < SPINOR_ERASE_BLOCK_SIZE) {
  477. erase_size = len;
  478. } else if (addr & SPINOR_ERASE_BLOCK_MASK) {
  479. erase_size = SPINOR_ERASE_BLOCK_SIZE - (addr & SPINOR_ERASE_BLOCK_MASK);
  480. } else {
  481. erase_size = SPINOR_ERASE_BLOCK_SIZE;
  482. }
  483. key = irq_lock();
  484. t0 = k_cycle_get_32();
  485. spinor_4byte_address_mode(sni, true);
  486. ret = spinor_erase(sni, addr, erase_size);
  487. spinor_4byte_address_mode(sni, false);
  488. t1 = k_cycle_get_32();
  489. irq_unlock(key);
  490. t2 = k_cycle_get_32();
  491. printk("nor_e:off=0x%x,len=0x%x, tran=%d us, wait=%d\n", addr, erase_size,
  492. k_cyc_to_us_ceil32(t1-t0), k_cyc_to_us_ceil32(t2-t1));
  493. len -= erase_size;
  494. addr += erase_size;
  495. }
  496. soc_memctrl_cache_invalid();
  497. printk("----erse end---\n");
  498. return ret;
  499. }
  500. const struct spinor_operation_api spinor_4b_addr_op_api = {
  501. .read_chipid = spinor_read_chipid,
  502. .read_status = spinor_read_status,
  503. .write_status = spinor_write_status,
  504. .read = spinor_ram_read,
  505. .write = spinor_ram_write,
  506. .erase = spinor_ram_erase,
  507. };
  508. #else
  509. const struct spinor_operation_api spinor_4b_addr_op_api = {
  510. .read_chipid = spinor_read_chipid,
  511. .read_status = spinor_read_status,
  512. .write_status = spinor_write_status,
  513. .read = spinor_read,
  514. .write = spinor_write,
  515. .erase = spinor_erase,
  516. };
  517. #endif