1 #include <string.h>
2 #include <stdlib.h>
3 #include <time.h>
4 #include <pthread.h>
5 #include <errno.h>
6 #include <unistd.h>
7 #include <hal_timer.h>
8
9 #include "inter.h"
10
11 #define NOR_CMD_READ 0x03
12 #define NOR_CMD_FAST_READ 0x0B
13 #define NOR_CMD_DUAL_READ 0x3B
14 #define NOR_CMD_QUAD_READ 0x6B
15 #define NOR_CMD_DUAL_IO_READ 0xBB
16 #define NOR_CMD_QUAD_IO_READ 0xEB
17 #define NOR_CMD_PROG 0x02
18 #define NOR_CMD_QUAD_PROG 0x32
19 #define NOR_CMD_QUAD_IO_PROG 0x38
20 #define NOR_CMD_ERASE_BLK4K 0x20
21 #define NOR_CMD_ERASE_BLK32K 0x52
22 #define NOR_CMD_ERASE_BLK64K 0xD8
23 #define NOR_CMD_ERASE_CHIP 0x60
24 #define NOR_CMD_WREN 0x06
25 #define NOR_CMD_WRDI 0x04
26 #define NOR_CMD_READ_SR 0x05
27 #define NOR_CMD_WRITE_SR 0x01
28 #define NOR_CMD_READ_CR 0x15
29 #define NOR_CMD_READ_SCUR 0x2B
30 #define NOR_CMD_RESET_EN 0x66
31 #define NOR_CMD_RESET 0x99
32 #define NOR_CMD_RDID 0x9F
33
34 #define cmd_4bytes(cmd) (nor->addr_width == 4 ? cmd ## 4B : cmd)
35 #define NOR_CMD_EN4B 0xB7
36 #define NOR_CMD_EX4B 0xE9
37 #define NOR_CMD_MXC_EX4B 0x29
38 #define NOR_CMD_READ4B 0x13
39 #define NOR_CMD_FAST_READ4B 0x0C
40 #define NOR_CMD_DUAL_READ4B 0x3C
41 #define NOR_CMD_QUAD_READ4B 0x6C
42 #define NOR_CMD_DUAL_IO_READ4B 0xBC
43 #define NOR_CMD_QUAD_IO_READ4B 0xEC
44 #define NOR_CMD_PROG4B 0x12
45 #define NOR_CMD_QUAD_PROG4B 0x34
46 #define NOR_CMD_QUAD_IO_PROG4B 0x3E
47 #define NOR_CMD_ERASE_BLK4K4B 0x21
48 #define NOR_CMD_ERASE_BLK32K4B 0x5C
49 #define NOR_CMD_ERASE_BLK64K4B 0xDC
50
51 #define NOR_BUSY_MASK BIT(0)
52 #define NOR_SR_BIT_WEL BIT(1)
53
54 static struct nor_flash g_nor, *nor = &g_nor;
55 static struct nor_factory g_fhead;
56
nor_lock_init(void)57 static inline int nor_lock_init(void)
58 {
59 nor->hal_sem = hal_sem_create(1);
60 if (!nor->hal_sem) {
61 SPINOR_ERR("create hal_sem lock for nor_flash failed");
62 return -1;
63 }
64 return 0;
65 }
66
nor_lock(void)67 static inline int nor_lock(void)
68 {
69 return hal_sem_wait(nor->hal_sem);
70 }
71
nor_unlock(void)72 static inline int nor_unlock(void)
73 {
74 return hal_sem_post(nor->hal_sem);
75 }
76
nor_msleep(unsigned int msec)77 static inline void nor_msleep(unsigned int msec)
78 {
79 hal_usleep(msec * 1000);
80 }
81
cmd_bit(unsigned char cmd)82 static int cmd_bit(unsigned char cmd)
83 {
84 switch (cmd)
85 {
86 case NOR_CMD_DUAL_READ:
87 case NOR_CMD_DUAL_IO_READ:
88 case NOR_CMD_DUAL_READ4B:
89 case NOR_CMD_DUAL_IO_READ4B:
90 return 2;
91 case NOR_CMD_QUAD_READ:
92 case NOR_CMD_QUAD_IO_READ:
93 case NOR_CMD_QUAD_READ4B:
94 case NOR_CMD_QUAD_IO_READ4B:
95 case NOR_CMD_QUAD_PROG:
96 case NOR_CMD_QUAD_IO_PROG:
97 case NOR_CMD_QUAD_PROG4B:
98 case NOR_CMD_QUAD_IO_PROG4B:
99 return 4;
100 default:
101 return 1;
102 }
103 }
104
nor_register_factory(struct nor_factory * f)105 int nor_register_factory(struct nor_factory *f)
106 {
107 struct nor_factory *p = &g_fhead;
108
109 if (!f)
110 return -1;
111
112 while (p->next)
113 p = p->next;
114 p->next = f;
115 f->next = NULL;
116
117 SPINOR_DEBUG("register factory 0x%x", f->factory);
118 return 0;
119 }
120
nor_transfer(int single_len,void * tbuf,int tlen,void * rbuf,int rlen)121 int nor_transfer(int single_len, void *tbuf, int tlen, void *rbuf, int rlen)
122 {
123 hal_spi_master_transfer_t tr;
124 unsigned char cmd = *(unsigned char *)tbuf;
125 int ret;
126
127 tr.tx_buf = tbuf;
128 tr.tx_len = tlen;
129 tr.rx_buf = rbuf;
130 tr.rx_len = rlen;
131 tr.tx_single_len = single_len;
132 tr.dummy_byte = 0;
133
134 tr.rx_nbits = tr.tx_nbits = SPI_NBITS_SINGLE;
135 switch (cmd)
136 {
137 case NOR_CMD_FAST_READ:
138 case NOR_CMD_FAST_READ4B:
139 tr.dummy_byte = 1;
140 break;
141 case NOR_CMD_DUAL_READ:
142 case NOR_CMD_DUAL_IO_READ:
143 case NOR_CMD_DUAL_READ4B:
144 case NOR_CMD_DUAL_IO_READ4B:
145 tr.rx_nbits = SPI_NBITS_DUAL;
146 tr.dummy_byte = 1;
147 break;
148 case NOR_CMD_QUAD_READ:
149 case NOR_CMD_QUAD_IO_READ:
150 case NOR_CMD_QUAD_READ4B:
151 case NOR_CMD_QUAD_IO_READ4B:
152 tr.rx_nbits = SPI_NBITS_QUAD;
153 tr.dummy_byte = 1;
154 break;
155 case NOR_CMD_QUAD_PROG:
156 case NOR_CMD_QUAD_IO_PROG:
157 case NOR_CMD_QUAD_PROG4B:
158 case NOR_CMD_QUAD_IO_PROG4B:
159 tr.tx_nbits = SPI_NBITS_QUAD;
160 break;
161 }
162
163 ret = hal_spi_xfer(nor->spim.port, &tr);
164 if (ret)
165 SPINOR_ERR("spi transfer failed %d", ret);
166 return ret;
167 }
168
nor_read_status(unsigned char * sr)169 int nor_read_status(unsigned char *sr)
170 {
171 int ret;
172 char cmd[1] = {NOR_CMD_READ_SR};
173 char reg[2] = {0};
174
175 ret = nor_transfer(1, cmd, 1, reg, 2);
176 if (ret) {
177 SPINOR_ERR("read status register fail");
178 return ret;
179 }
180
181 *sr = reg[1];
182 return 0;
183 }
184
nor_is_busy(void)185 static int nor_is_busy(void)
186 {
187 int ret;
188 unsigned char reg;
189
190 ret = nor_read_status(®);
191 if (ret)
192 return ret;
193
194 if (reg & NOR_BUSY_MASK)
195 return true;
196 else
197 return false;
198 }
199
200 /**
201 * As the minimum time is 1ms, to save time, we wait ready under 2 step:
202 * 1. sleep on ms, which take mush time.
203 * 2. check times on cpu. It will be ready soon in this case
204 */
nor_wait_ready(unsigned int ms,unsigned int times)205 int nor_wait_ready(unsigned int ms, unsigned int times)
206 {
207 unsigned int _ms = ms, _times = times;
208
209 do {
210 if (nor_is_busy() == false)
211 return 0;
212 if (_ms)
213 nor_msleep(1);
214 } while (--_ms > 0);
215
216 do {
217 if (nor_is_busy() == false)
218 return 0;
219 } while (--_times > 0);
220
221 /* check the last time */
222 if (nor_is_busy() == false)
223 return 0;
224
225 SPINOR_ERR("wait nor flash for %d ms and %d loop timeout", ms, times);
226 return -EBUSY;
227 }
228
nor_send_cmd(unsigned char cmd)229 int nor_send_cmd(unsigned char cmd)
230 {
231 int ret;
232 ret = nor_transfer(1, &cmd, 1, NULL, 0);
233 if (ret)
234 return ret;
235 return nor_wait_ready(0, 500);
236 }
237
nor_set_4byte(int enable)238 static int nor_set_4byte(int enable)
239 {
240 int ret;
241 struct nor_factory *f = nor->factory;
242
243 if (f && f->set_4bytes_addr)
244 return f->set_4bytes_addr(nor, enable);
245
246 ret = nor_send_cmd(NOR_CMD_EN4B);
247 if (ret) {
248 SPINOR_ERR("set 4byte %d fail", enable);
249 return ret;
250 }
251 SPINOR_DEBUG("set 4byte %d success", enable);
252 return 0;
253 }
254
nor_write_enable(void)255 int nor_write_enable(void)
256 {
257 int ret;
258 unsigned char sr;
259
260 ret = nor_send_cmd(NOR_CMD_WREN);
261 if (ret) {
262 SPINOR_ERR("send WREN failed - %d", ret);
263 return ret;
264 }
265
266 ret = nor_read_status(&sr);
267 if (ret)
268 return ret;
269
270 if (!(sr & NOR_SR_BIT_WEL)) {
271 SPINOR_ERR("enable write failed");
272 return -EINVAL;
273 }
274 return 0;
275 }
276
nor_write_status(unsigned char * sr,unsigned int len)277 int nor_write_status(unsigned char *sr, unsigned int len)
278 {
279 int ret, i;
280 char tbuf[5] = {0};
281
282 ret = nor_write_enable();
283 if (ret)
284 return ret;
285
286 if (len > 5)
287 return -EINVAL;
288
289 tbuf[0] = NOR_CMD_WRITE_SR;
290 for (i = 0; i < len; i++)
291 tbuf[i + 1] = *(sr + i);
292 i++;
293 ret = nor_transfer(i, tbuf, i, NULL, 0);
294 if (ret) {
295 SPINOR_ERR("write status register fail");
296 return ret;
297 }
298
299 return nor_wait_ready(10, MAX_WAIT_LOOP);
300 }
301
nor_read_id(char * id,int len)302 static int nor_read_id(char *id, int len)
303 {
304 int ret;
305 char cmd[1] = {NOR_CMD_RDID};
306
307 if (nor_wait_ready(0, 500)) {
308 SPINOR_ERR("nor is busy before read id");
309 return -EBUSY;
310 }
311
312 ret = nor_transfer(1, cmd, 1, id, MIN(len, (int)MAX_ID_LEN));
313 if (ret)
314 SPINOR_ERR("read nor id failed - %d", ret);
315 return ret;
316 }
317
nor_reset(void)318 static int nor_reset(void)
319 {
320 int ret;
321 char cmd[2] = {NOR_CMD_RESET_EN, NOR_CMD_RESET};
322
323 ret = nor_transfer(2, cmd, 2, NULL, 0);
324 if (ret)
325 SPINOR_ERR("reset nor failed - %d", ret);
326 return ret;
327 }
328
nor_spi_master_init(struct nor_spi_master * spim)329 static int nor_spi_master_init(struct nor_spi_master *spim)
330 {
331 int ret;
332
333 spim->port = HAL_SPI_MASTER_0;
334
335 #ifdef CONFIG_DRIVERS_SPINOR_FREQ
336 spim->cfg.clock_frequency = CONFIG_DRIVERS_SPINOR_FREQ;
337 #else
338 spim->cfg.clock_frequency = NOR_DEFAULT_FREQUENCY;
339 #endif
340 spim->cfg.clock_frequency *= 1000 * 1000;
341 spim->cfg.slave_port = HAL_SPI_MASTER_SLAVE_0;
342 spim->cfg.cpha = HAL_SPI_MASTER_CLOCK_PHASE0;
343 spim->cfg.cpol = HAL_SPI_MASTER_CLOCK_POLARITY0;
344 spim->cfg.bit_order = HAL_SPI_MASTER_LSB_FIRST;
345
346 ret = hal_spi_init(spim->port, &spim->cfg);
347 if (ret != HAL_SPI_MASTER_STATUS_OK)
348 SPINOR_ERR("init spi master failed - %d", ret);
349 return ret;
350 }
351
nor_spi_master_deinit(struct nor_spi_master * spim)352 static int nor_spi_master_deinit(struct nor_spi_master *spim)
353 {
354 return hal_spi_deinit(spim->port);
355 }
356
match_nor(struct nor_flash * nor,char * id,int id_len)357 static int match_nor(struct nor_flash *nor, char *id, int id_len)
358 {
359 struct nor_factory *f = g_fhead.next;
360 struct nor_info *info;
361 int i;
362
363 for (; f; f = f->next) {
364 if (f->factory != (unsigned char)id[0])
365 continue;
366 for (i = 0; i < f->idt_cnt; i++) {
367 info = &f->idt[i];
368 if (!memcmp(info->id, id, id_len)) {
369 SPINOR_DEBUG("match nor %s on table", info->model);
370 nor->factory = f;
371 nor->info = info;
372 return 0;
373 }
374 }
375 /* the factory already check all ids but not match */
376 SPINOR_ERR("not match any id on factory 0x%x ids table", f->factory);
377 return -1;
378 }
379 SPINOR_ERR("not match any factory 0x%x ids table", id[0]);
380 return -1;
381 }
382
nor_set_quad_mode(void)383 static int nor_set_quad_mode(void)
384 {
385 if (nor->factory->set_quad_mode)
386 return nor->factory->set_quad_mode(nor);
387 return 0;
388 }
389
nor_factory_register(void)390 static int nor_factory_register(void)
391 {
392 nor_register_factory_gd();
393 nor_register_factory_mxic();
394 nor_register_factory_winbond();
395 nor_register_factory_xtx();
396 nor_register_factory_esmt();
397 nor_register_factory_fm();
398 nor_register_factory_xmc();
399 nor_register_factory_puya();
400 nor_register_factory_zetta();
401 return 0;
402 }
403
nor_factory_init(void)404 static int nor_factory_init(void)
405 {
406 if (nor->factory->init)
407 return nor->factory->init(nor);
408 return 0;
409 }
410
nor_factory_deinit(void)411 static void nor_factory_deinit(void)
412 {
413 if (nor->factory->deinit)
414 nor->factory->deinit(nor);
415 }
416
nor_scan(void)417 static int nor_scan(void)
418 {
419 int ret;
420 char id[MAX_ID_LEN];
421
422 ret = nor_read_id(id, MAX_ID_LEN);
423 if (ret) {
424 goto err;
425 }
426 ret = match_nor(nor, id, MAX_ID_LEN);
427 if (ret)
428 goto err;
429
430 if (nor->info->flag == 0)
431 nor->info->flag = SUPPORT_GENERAL;
432
433 nor->total_size = nor->info->total_size;
434 nor->addr_width = 3;
435 if (nor->total_size > SZ_16M) {
436 nor->addr_width = 4;
437 nor_set_4byte(true);
438 }
439
440 nor->page_size = NOR_PAGE_SIZE;
441 #ifdef CONFIG_DRIVERS_SPINOR_4K_SECTORS
442 nor->blk_size = SZ_4K;
443 #else
444 if (nor->info->flag & SUPPORT_64K_ERASE_BLK) {
445 nor->blk_size = NOR_BLK_SIZE;
446 } else if (nor->info->flag & SUPPORT_32K_ERASE_BLK) {
447 nor->blk_size = NOR_HALF_BLK_SIZE;
448 } else if (nor->info->flag & SUPPORT_4K_ERASE_BLK) {
449 nor->blk_size = NOR_PAGE_SIZE;
450 } else {
451 SPINOR_ERR("invalid blk size");
452 ret = -EINVAL;
453 goto err;
454 }
455 #endif
456
457 /* program property */
458 nor->w_cmd_slen = nor->addr_width == 4 ? 5 : 4;
459 nor->cmd_write = cmd_4bytes(NOR_CMD_PROG);
460 if (nor->info->flag & SUPPORT_QUAD_WRITE) {
461 nor->cmd_write = cmd_4bytes(NOR_CMD_QUAD_PROG);
462 if (nor->info->flag & USE_IO_PROG_X4) {
463 nor->cmd_write = cmd_4bytes(NOR_CMD_QUAD_IO_PROG);
464 nor->w_cmd_slen = 1;
465 }
466 }
467
468 /* read property */
469 nor->r_cmd_slen = nor->addr_width == 4 ? 6 : 5;
470 nor->cmd_read = cmd_4bytes(NOR_CMD_FAST_READ);
471 if (nor->info->flag & SUPPORT_QUAD_READ) {
472 nor->cmd_read = cmd_4bytes(NOR_CMD_QUAD_READ);
473 if (nor->info->flag & USE_IO_READ_X4) {
474 nor->cmd_read = cmd_4bytes(NOR_CMD_QUAD_IO_READ);
475 nor->r_cmd_slen = 1;
476 }
477 } else if (nor->info->flag & SUPPORT_DUAL_READ) {
478 nor->cmd_read = cmd_4bytes(NOR_CMD_DUAL_READ);
479 if (nor->info->flag & USE_IO_READ_X2) {
480 nor->cmd_read = cmd_4bytes(NOR_CMD_DUAL_IO_READ);
481 nor->r_cmd_slen = 1;
482 }
483 }
484
485 if (cmd_bit(nor->cmd_read) == 4 || cmd_bit(nor->cmd_write) == 4) {
486 ret = nor_set_quad_mode();
487 if (ret) {
488 SPINOR_ERR("enable quad mode failed");
489 goto err;
490 }
491 }
492
493 return 0;
494 err:
495 SPINOR_ERR("scan nor flash failed");
496 nor->info = NULL;
497 return ret;
498 }
499
nor_init(void)500 int nor_init(void)
501 {
502 int ret = -1;
503
504 if (nor->info)
505 return 0;
506
507 ret = nor_lock_init();
508 if (ret) {
509 SPINOR_ERR("create hal_sem lock for nor_flash failed");
510 goto out;
511 }
512
513 nor_lock();
514
515 ret = nor_spi_master_init(&nor->spim);
516 if (ret)
517 goto unlock;
518
519 ret = nor_reset();
520 if (ret)
521 goto unlock;
522
523 ret = nor_factory_register();
524 if (ret)
525 goto unlock;
526
527 ret = nor_scan();
528 if (ret)
529 goto unlock;
530
531 ret = nor_factory_init();
532 if (ret) {
533 SPINOR_ERR("factory init failed");
534 goto unlock;
535 }
536
537 SPINOR_INFO("Nor Flash %s size %uMB write %dbit read %dbit blk size %uKB",
538 nor->info->model, nor->total_size / 1024 / 1024,
539 cmd_bit(nor->cmd_write), cmd_bit(nor->cmd_read), nor->blk_size / 1024);
540 SPINOR_INFO("Nor Flash ID (hex): %02x %02x %02x", nor->info->id[0],
541 nor->info->id[1], nor->info->id[2]);
542
543 #ifdef CONFIG_DRIVERS_SPINOR_WRITE_LOCK
544 ret = nor_wr_lock_init(nor);
545 if (ret) {
546 SPINOR_ERR("write lock init failed");
547 goto unlock;
548 }
549
550 /* ensure all block is locked default */
551 ret = nor_wr_lock_all(nor);
552 if (ret) {
553 SPINOR_ERR("write lock all failed");
554 goto unlock;
555 }
556 #endif
557
558 #ifdef CONFIG_DRIVERS_SPINOR_CACHE
559 ret = nor_cache_init(nor);
560 if (ret) {
561 SPINOR_ERR("cache init failed");
562 goto unlock;
563 }
564 #endif
565
566 ret = 0;
567 unlock:
568 nor_unlock();
569 out:
570 if (ret)
571 SPINOR_ERR("init nor flash failed");
572 else
573 SPINOR_INFO("nor flash init ok");
574 return ret;
575 }
576
nor_deinit(void)577 int nor_deinit(void)
578 {
579 if (!nor->info)
580 return -EBUSY;
581
582 if (nor_lock()) {
583 SPINOR_ERR("deinit: lock nor failed");
584 return -EBUSY;
585 }
586
587 #ifdef CONFIG_DRIVERS_SPINOR_CACHE
588 nor_cache_exit();
589 #endif
590
591 #ifdef CONFIG_DRIVERS_SPINOR_WRITE_LOCK
592 nor_wr_unlock_all(nor);
593 #endif
594
595 if (nor->info) {
596 if (nor->addr_width == 4)
597 nor_set_4byte(0);
598 nor_spi_master_deinit(&nor->spim);
599 nor->info = NULL;
600 }
601
602 /* we do not unlock nor in case other task using nor after deinit */
603 return 0;
604 }
605
nor_erase_do(char cmd,unsigned int addr)606 static int nor_erase_do(char cmd, unsigned int addr)
607 {
608 int ret = -EBUSY;
609 char tbuf[5] = {0};
610 int cmdlen;
611
612 ret = nor_write_enable();
613 if (ret)
614 goto out;
615
616 tbuf[0] = cmd;
617 if (nor->addr_width == 4) {
618 tbuf[1] = addr >> 24;
619 tbuf[2] = addr >> 16;
620 tbuf[3] = addr >> 8;
621 tbuf[4] = addr & 0xFF;
622 cmdlen = 5;
623 } else {
624 tbuf[1] = addr >> 16;
625 tbuf[2] = addr >> 8;
626 tbuf[3] = addr & 0xFF;
627 cmdlen = 4;
628 }
629
630 ret = nor_transfer(cmdlen, tbuf, cmdlen, NULL, 0);
631 out:
632 if (ret)
633 SPINOR_ERR("erase address 0x%x with cmd 0x%x failed\n", addr, cmd);
634 return ret;
635 }
636
nor_erase_4k(unsigned int addr)637 static inline int nor_erase_4k(unsigned int addr)
638 {
639 int ret;
640
641 #ifdef CONFIG_DRIVERS_SPINOR_WRITE_LOCK
642 ret = nor_wr_unlock(nor, addr, SZ_4K);
643 if (ret)
644 return -1;
645 #endif
646
647 ret = nor_erase_do(cmd_4bytes(NOR_CMD_ERASE_BLK4K), addr);
648 if (ret)
649 goto out;
650
651 ret = nor_wait_ready(30, MAX_WAIT_LOOP);
652 out:
653 #ifdef CONFIG_DRIVERS_SPINOR_WRITE_LOCK
654 nor_wr_lock_all(nor);
655 #endif
656 return ret;
657 }
658
nor_erase_32k(unsigned int addr)659 static inline int nor_erase_32k(unsigned int addr)
660 {
661 int ret;
662
663 #ifdef CONFIG_DRIVERS_SPINOR_WRITE_LOCK
664 ret = nor_wr_unlock(nor, addr, SZ_32K);
665 if (ret)
666 return -1;
667 #endif
668
669 ret = nor_erase_do(cmd_4bytes(NOR_CMD_ERASE_BLK32K), addr);
670 if (ret)
671 goto out;
672
673 ret = nor_wait_ready(120, MAX_WAIT_LOOP);
674 out:
675 #ifdef CONFIG_DRIVERS_SPINOR_WRITE_LOCK
676 nor_wr_lock_all(nor);
677 #endif
678 return ret;
679 }
680
nor_erase_64k(unsigned int addr)681 static inline int nor_erase_64k(unsigned int addr)
682 {
683 int ret;
684
685 #ifdef CONFIG_DRIVERS_SPINOR_WRITE_LOCK
686 ret = nor_wr_unlock(nor, addr, SZ_64K);
687 if (ret)
688 return -1;
689 #endif
690
691 ret = nor_erase_do(cmd_4bytes(NOR_CMD_ERASE_BLK64K), addr);
692 if (ret)
693 goto out;
694
695 ret = nor_wait_ready(150, MAX_WAIT_LOOP);
696 out:
697 #ifdef CONFIG_DRIVERS_SPINOR_WRITE_LOCK
698 nor_wr_lock_all(nor);
699 #endif
700 return ret;
701 }
702
nor_erase_all(void)703 static inline int nor_erase_all(void)
704 {
705 int ret;
706
707 if (!nor->info)
708 return -EBUSY;
709
710 #ifdef CONFIG_DRIVERS_SPINOR_WRITE_LOCK
711 nor_wr_unlock_all(nor);
712 #endif
713
714 ret = nor_write_enable();
715 if (ret)
716 goto out;
717
718 ret = nor_send_cmd(NOR_CMD_ERASE_CHIP);
719 if (ret)
720 goto out;
721
722 ret = nor_wait_ready(26 * 1000, MAX_WAIT_LOOP);
723 out:
724 #ifdef CONFIG_DRIVERS_SPINOR_WRITE_LOCK
725 nor_wr_lock_all(nor);
726 #endif
727 return ret;
728 }
729
nor_erase(unsigned int addr,unsigned int size)730 int nor_erase(unsigned int addr, unsigned int size)
731 {
732 int ret;
733 struct nor_info *info = nor->info;
734
735 ret = nor_lock();
736 if (ret) {
737 SPINOR_ERR("erase: lock nor failed\n");
738 return ret;
739 }
740
741 ret = -EBUSY;
742 if (!nor->info)
743 goto unlock;
744
745 /*
746 * nor erase size can be 4k/32k/64k, driver should erase block size base
747 * on given size. Here must be align to 4k
748 */
749 if (size % SZ_4K) {
750 SPINOR_ERR("erase size 4k is not align to %u\n", size);
751 ret = -EINVAL;
752 goto unlock;
753 }
754
755 if (addr + size > nor->total_size) {
756 SPINOR_ERR("addr 0x%x with size %u over total size %u\n",
757 addr, size, nor->total_size);
758 ret = -EINVAL;
759 goto unlock;
760 }
761
762 SPINOR_DEBUG("try to erase addr 0x%x with size %u\n", addr, size);
763
764 if (addr == 0 && size == nor->total_size) {
765 ret = nor_erase_all();
766 goto unlock;
767 }
768
769 while (size) {
770
771 if ((size >= SZ_64K) &&
772 (addr % SZ_64K == 0) &&
773 (info->flag & SUPPORT_64K_ERASE_BLK) &&
774 !(info->flag & USE_4K_ERASE)) {
775 SPINOR_DEBUG("try to erase 64k from 0x%x\n", addr);
776 ret = nor_erase_64k(addr);
777 if (ret)
778 goto unlock;
779 addr += SZ_64K;
780 size -= SZ_64K;
781 continue;
782 }
783
784 if ((size >= SZ_32K) &&
785 (addr % SZ_32K == 0) &&
786 (info->flag & SUPPORT_32K_ERASE_BLK) &&
787 !(info->flag & USE_4K_ERASE)) {
788 SPINOR_DEBUG("try to erase 32k from 0x%x\n", addr);
789 ret = nor_erase_32k(addr);
790 if (ret)
791 goto unlock;
792 addr += SZ_32K;
793 size -= SZ_32K;
794 continue;
795 }
796
797 if ((size >= SZ_4K) &&
798 (addr % SZ_4K == 0) &&
799 (info->flag & SUPPORT_4K_ERASE_BLK)) {
800 SPINOR_DEBUG("try to erase 4k from 0x%x\n", addr);
801 ret = nor_erase_4k(addr);
802 if (ret)
803 goto unlock;
804 addr += SZ_4K;
805 size -= SZ_4K;
806 continue;
807 }
808
809 SPINOR_ERR("no erase cmd matched, addr 0x%x, size 0x%x flag:0x%x\n",
810 addr, size, info->flag);
811 break;
812 }
813
814 ret = size ? -EINVAL : 0;
815 unlock:
816 nor_unlock();
817 return ret;
818 }
819
nor_read_do(unsigned int addr,char * buf,unsigned int len)820 static int nor_read_do(unsigned int addr, char *buf, unsigned int len)
821 {
822 char cmd[5] = {0};
823 int cmdlen;
824
825 if (len > NOR_PAGE_SIZE)
826 return -EINVAL;
827
828 cmd[0] = nor->cmd_read;
829 if (nor->addr_width == 4) {
830 cmd[1] = addr >> 24;
831 cmd[2] = addr >> 16;
832 cmd[3] = addr >> 8;
833 cmd[4] = addr & 0xFF;
834 cmdlen = 5;
835 } else {
836 cmd[1] = addr >> 16;
837 cmd[2] = addr >> 8;
838 cmd[3] = addr & 0xFF;
839 cmdlen = 4;
840 }
841 return nor_transfer(nor->r_cmd_slen, cmd, cmdlen, buf, len);
842 }
843
nor_read(unsigned int addr,char * buf,unsigned int len)844 int nor_read(unsigned int addr, char *buf, unsigned int len)
845 {
846 int ret;
847
848 ret = nor_lock();
849 if (ret) {
850 SPINOR_ERR("read: lock nor failed\n");
851 goto out;
852 }
853
854 ret = -EBUSY;
855 if (!nor->info)
856 goto unlock;
857
858 // SPINOR_DEBUG("try to read addr 0x%x with len %u\n", addr, len);
859
860 if (nor_wait_ready(0, 500))
861 goto unlock;
862
863 while (len) {
864 unsigned int align_addr = ALIGN(addr + 1, NOR_PAGE_SIZE);
865 unsigned int rlen = MIN(align_addr - addr, len);
866
867 ret = nor_read_do(addr, buf, rlen);
868 if (ret)
869 goto unlock;
870
871 addr += rlen;
872 buf += rlen;
873 len -= rlen;
874 }
875
876 unlock:
877 nor_unlock();
878 out:
879 if (ret)
880 SPINOR_ERR("read address 0x%x with len %u failed\n", addr, len);
881 return ret;
882 }
883
nor_write_do(unsigned int addr,char * buf,unsigned int len)884 static int nor_write_do(unsigned int addr, char *buf, unsigned int len)
885 {
886 int ret = -EINVAL;
887 char tbuf[NOR_PAGE_SIZE + 5] = {0};
888 int cmdlen;
889
890 if (len > NOR_PAGE_SIZE)
891 return -EINVAL;
892
893 ret = nor_write_enable();
894 if (ret)
895 return ret;
896
897 if (nor->addr_width == 4) {
898 tbuf[0] = nor->cmd_write;
899 tbuf[1] = addr >> 24;
900 tbuf[2] = addr >> 16;
901 tbuf[3] = addr >> 8;
902 tbuf[4] = addr & 0xFF;
903 cmdlen = 5;
904 } else {
905 tbuf[0] = nor->cmd_write;
906 tbuf[1] = addr >> 16;
907 tbuf[2] = addr >> 8;
908 tbuf[3] = addr & 0xFF;
909 cmdlen = 4;
910 }
911
912 memcpy(tbuf + cmdlen, buf, MIN(len, (unsigned int)NOR_PAGE_SIZE));
913 ret = nor_transfer(nor->w_cmd_slen, tbuf, len + cmdlen, NULL, 0);
914 if (ret)
915 return ret;
916
917 return nor_wait_ready(0, 100 * 1000);
918 }
919
nor_write(unsigned int addr,char * buf,unsigned int len)920 int nor_write(unsigned int addr, char *buf, unsigned int len)
921 {
922 int ret;
923
924 ret = nor_lock();
925 if (ret) {
926 SPINOR_ERR("write: lock nor failed\n");
927 goto out;
928 }
929
930 ret = -EBUSY;
931 if (!nor->info)
932 goto unlock;
933
934 SPINOR_DEBUG("try to write addr 0x%x with len %u\n", addr, len);
935
936 if (nor_wait_ready(0, 500))
937 goto unlock;
938
939 while (len) {
940 unsigned int align_addr = ALIGN(addr + 1, NOR_PAGE_SIZE);
941 unsigned int wlen = MIN(align_addr - addr, len);
942
943 #ifdef CONFIG_DRIVERS_SPINOR_WRITE_LOCK
944 ret = nor_wr_unlock(nor, addr, len);
945 if (ret)
946 goto unlock;
947 #endif
948
949 ret = nor_write_do(addr, buf, wlen);
950 if (ret)
951 goto unlock;
952
953 #ifdef CONFIG_DRIVERS_SPINOR_WRITE_LOCK
954 ret = nor_wr_lock_all(nor);
955 if (ret)
956 goto unlock;
957 #endif
958
959 addr += wlen;
960 buf += wlen;
961 len -= wlen;
962 }
963
964 unlock:
965 nor_unlock();
966 out:
967 if (ret)
968 SPINOR_ERR("write address 0x%x with len %u failed\n", addr, len);
969 return ret;
970 }
971
get_nor_flash(void)972 struct nor_flash *get_nor_flash(void)
973 {
974 return nor;
975 }
976