2 * Broadcom NAND core interface
4 * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved.
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29 #include <nand_core.h>
34 #define NANDFL_MSG(args) printf args
36 #define NANDFL_MSG(args)
39 #define NANDF_RETRIES 1000000
41 #define NANDF_SMALL_BADBLOCK_POS 5
42 #define NANDF_LARGE_BADBLOCK_POS 0
44 /* Private global state */
45 static hndnand_t nandcore
;
48 static int nandcore_poll(si_t
*sih
, nandregs_t
*nc
);
50 hndnand_t
*nandcore_init(si_t
*sih
);
51 static int nandcore_read(hndnand_t
*nfl
, uint64 offset
, uint len
, uchar
*buf
);
52 static int nandcore_write(hndnand_t
*nfl
, uint64 offset
, uint len
, const uchar
*buf
);
53 static int nandcore_erase(hndnand_t
*nfl
, uint64 offset
);
54 static int nandcore_checkbadb(hndnand_t
*nfl
, uint64 offset
);
55 static int nandcore_mark_badb(hndnand_t
*nfl
, uint64 offset
);
57 static int nandcore_read_oob(hndnand_t
*nfl
, uint64 addr
, uint8
*oob
);
59 static int nandcore_dev_ready(hndnand_t
*nfl
);
60 static int nandcore_select_chip(hndnand_t
*nfl
, int chip
);
61 static int nandcore_cmdfunc(hndnand_t
*nfl
, uint64 addr
, int cmd
);
62 static int nandcore_waitfunc(hndnand_t
*nfl
, int *status
);
63 static int nandcore_write_oob(hndnand_t
*nfl
, uint64 addr
, uint8
*oob
);
64 static int nandcore_read_page(hndnand_t
*nfl
, uint64 addr
, uint8
*buf
, uint8
*oob
, bool ecc
,
65 uint32
*herr
, uint32
*serr
);
66 static int nandcore_write_page(hndnand_t
*nfl
, uint64 addr
, const uint8
*buf
, uint8
*oob
, bool ecc
);
67 static int nandcore_cmd_read_byte(hndnand_t
*nfl
, int cmd
, int arg
);
70 /* Issue a nand flash command */
72 nandcore_cmd(osl_t
*osh
, nandregs_t
*nc
, uint opcode
)
74 W_REG(osh
, &nc
->cmd_start
, opcode
);
83 for (j
= 0; j
< 32; j
++)
90 _nandcore_buf_erased(const void *buf
, unsigned len
)
93 const uint32
*p
= buf
;
95 for (i
= 0; i
< (len
>> 2); i
++) {
96 if (p
[i
] != 0xffffffff)
104 _nandcore_read_page(hndnand_t
*nfl
, uint64 offset
, uint8
*buf
, uint8
*oob
, bool ecc
,
105 uint32
*herr
, uint32
*serr
)
108 nandregs_t
*nc
= (nandregs_t
*)nfl
->core
;
109 aidmp_t
*ai
= (aidmp_t
*)nfl
->wrap
;
111 unsigned spare_per_sec
;
113 unsigned hard_err_count
= 0;
114 uint32 mask
, reg
, *to
;
115 uint32 err_soft_reg
, err_hard_reg
;
116 int i
, ret
, sectorsize_shift
, sec_per_page_shift
;
120 mask
= nfl
->pagesize
- 1;
121 /* Check offset and length */
122 if ((offset
& mask
) != 0)
125 if ((((offset
+ nfl
->pagesize
) >> 20) > nfl
->size
) ||
126 ((((offset
+ nfl
->pagesize
) >> 20) == nfl
->size
) &&
127 (((offset
+ nfl
->pagesize
) & ((1 << 20) - 1)) != 0)))
130 osh
= si_osh(nfl
->sih
);
132 /* Reset ECC error stats */
133 err_hard_reg
= R_REG(osh
, &nc
->uncorr_error_count
);
134 err_soft_reg
= R_REG(osh
, &nc
->read_error_count
);
137 sectorsize_shift
= _nandcore_ffs(nfl
->sectorsize
) - 1;
138 sec_per_page_shift
= _nandcore_ffs(nfl
->pagesize
) - 1 - sectorsize_shift
;
140 spare_per_sec
= nfl
->oobsize
>> sec_per_page_shift
;
142 /* Set the page address for the following commands */
143 reg
= (R_REG(osh
, &nc
->cmd_ext_address
) & ~NANDCMD_EXT_ADDR_MASK
);
144 W_REG(osh
, &nc
->cmd_ext_address
, (reg
| (offset
>> 32)));
146 /* Enable ECC validation for ecc page reads */
148 OR_REG(osh
, nfl
->chipidx
? &nc
->acc_control_cs1
: &nc
->acc_control_cs0
,
149 NANDAC_CS0_RD_ECC_EN
);
151 AND_REG(osh
, nfl
->chipidx
? &nc
->acc_control_cs1
: &nc
->acc_control_cs0
,
152 ~NANDAC_CS0_RD_ECC_EN
);
154 /* Loop all sectors in page */
155 for (sector
= 0; sector
< (1 << sec_per_page_shift
); sector
++) {
158 /* Copy partial sectors sized by cache reg */
159 while (data_bytes
< (1 << sectorsize_shift
)) {
162 col
= data_bytes
+ (sector
<< sectorsize_shift
);
164 W_REG(osh
, &nc
->cmd_address
, offset
+ col
);
166 /* Issue command to read partial page */
167 nandcore_cmd(osh
, nc
, NANDCMD_PAGE_RD
);
169 /* Wait for the command to complete */
170 if ((ret
= nandcore_poll(nfl
->sih
, nc
)) < 0)
173 /* Set controller to Little Endian mode for copying */
174 OR_REG(osh
, &ai
->ioctrl
, NAND_APB_LITTLE_ENDIAN
);
176 if (data_bytes
== 0 && oob
) {
177 to
= (uint32
*)(oob
+ sector
* spare_per_sec
);
178 for (i
= 0; i
< spare_per_sec
; i
+= 4, to
++)
179 *to
= R_REG(osh
, &nc
->spare_area_read_ofs
[i
/4]);
183 to
= (uint32
*)(buf
+ col
);
184 for (i
= 0; i
< NFL_SECTOR_SIZE
; i
+= 4, to
++)
185 *to
= R_REG(osh
, &nc
->flash_cache
[i
/4]);
187 data_bytes
+= NFL_SECTOR_SIZE
;
189 /* Return to Big Endian mode for commands etc */
190 AND_REG(osh
, &ai
->ioctrl
, ~NAND_APB_LITTLE_ENDIAN
);
192 /* capture hard errors for each partial */
193 if (err_hard_reg
!= R_REG(osh
, &nc
->uncorr_error_count
)) {
194 int era
= (R_REG(osh
, &nc
->intfc_status
) & NANDIST_ERASED
);
195 if ((!era
) && (!_nandcore_buf_erased(buf
+col
, NFL_SECTOR_SIZE
)))
198 err_hard_reg
= R_REG(osh
, &nc
->uncorr_error_count
);
200 } /* while FlashCache buffer */
206 /* Report hard ECC errors */
208 *herr
= hard_err_count
;
210 /* Get ECC soft error stats */
212 *serr
= R_REG(osh
, &nc
->read_error_count
) - err_soft_reg
;
218 _nandcore_write_page(hndnand_t
*nfl
, uint64 offset
, const uint8
*buf
, uint8
*oob
, bool ecc
)
221 nandregs_t
*nc
= (nandregs_t
*)nfl
->core
;
222 aidmp_t
*ai
= (aidmp_t
*)nfl
->wrap
;
223 unsigned data_bytes
, spare_bytes
;
224 unsigned spare_per_sec
, sector
, num_sec
;
225 uint32 mask
, reg
, *from
;
226 int i
, ret
= 0, sectorsize_shift
, sec_per_page_shift
;
230 mask
= nfl
->pagesize
- 1;
231 /* Check offset and length */
232 if ((offset
& mask
) != 0)
235 if ((((offset
+ nfl
->pagesize
) >> 20) > nfl
->size
) ||
236 ((((offset
+ nfl
->pagesize
) >> 20) == nfl
->size
) &&
237 (((offset
+ nfl
->pagesize
) & ((1 << 20) - 1)) != 0)))
240 osh
= si_osh(nfl
->sih
);
243 sectorsize_shift
= _nandcore_ffs(nfl
->sectorsize
) - 1;
244 sec_per_page_shift
= _nandcore_ffs(nfl
->pagesize
) - 1 - sectorsize_shift
;
246 spare_per_sec
= nfl
->oobsize
>> sec_per_page_shift
;
249 AND_REG(osh
, &nc
->cs_nand_select
, ~NANDCSEL_NAND_WP
);
251 /* Set the page address for the following commands */
252 reg
= (R_REG(osh
, &nc
->cmd_ext_address
) & ~NANDCMD_EXT_ADDR_MASK
);
253 W_REG(osh
, &nc
->cmd_ext_address
, (reg
| (offset
>> 32)));
255 /* Enable ECC generation for ecc page write, if requested */
257 OR_REG(osh
, nfl
->chipidx
? &nc
->acc_control_cs1
: &nc
->acc_control_cs0
,
258 NANDAC_CS0_WR_ECC_EN
);
260 AND_REG(osh
, nfl
->chipidx
? &nc
->acc_control_cs1
: &nc
->acc_control_cs0
,
261 ~NANDAC_CS0_WR_ECC_EN
);
264 num_sec
= 1 << sec_per_page_shift
;
266 /* Loop all sectors in page */
267 for (sector
= 0; sector
< num_sec
; sector
++) {
270 /* Copy partial sectors sized by cache reg */
271 while (data_bytes
< (1 << sectorsize_shift
)) {
274 col
= data_bytes
+ (sector
<< sectorsize_shift
);
276 /* Set address of 512-byte sub-page */
277 W_REG(osh
, &nc
->cmd_address
, offset
+ col
);
279 /* Set controller to Little Endian mode for copying */
280 OR_REG(osh
, &ai
->ioctrl
, NAND_APB_LITTLE_ENDIAN
);
282 /* Set spare area is written at each sector start */
283 if (data_bytes
== 0) {
285 from
= (uint32
*)(oob
+ spare_bytes
);
286 for (i
= 0; i
< spare_per_sec
; i
+= 4, from
++)
287 W_REG(osh
, &nc
->spare_area_write_ofs
[i
/4], *from
);
290 /* Write 0xffffffff to spare_area_write_ofs register
291 * to prevent old spare_area_write_ofs vale write
292 * when we issue NANDCMD_PAGE_PROG.
294 for (i
= 0; i
< spare_per_sec
; i
+= 4)
295 W_REG(osh
, &nc
->spare_area_write_ofs
[i
/4],
299 spare_bytes
+= spare_per_sec
;
302 /* Copy sub-page data */
303 from
= (uint32
*)(buf
+ col
);
304 for (i
= 0; i
< NFL_SECTOR_SIZE
; i
+= 4, from
++)
305 W_REG(osh
, &nc
->flash_cache
[i
/4], *from
);
307 data_bytes
+= NFL_SECTOR_SIZE
;
309 /* Return to Big Endian mode for commands etc */
310 AND_REG(osh
, &ai
->ioctrl
, ~NAND_APB_LITTLE_ENDIAN
);
312 /* Push data into internal cache */
313 nandcore_cmd(osh
, nc
, NANDCMD_PAGE_PROG
);
315 ret
= nandcore_poll(nfl
->sih
, nc
);
323 OR_REG(osh
, &nc
->cs_nand_select
, NANDCSEL_NAND_WP
);
328 static bool firsttime
= TRUE
;
331 nandcore_check_id(uint8
*id
)
339 case NFL_VENDOR_NUMONYX
:
342 case NFL_VENDOR_MICRON
:
345 case NFL_VENDOR_TOSHIBA
:
348 case NFL_VENDOR_HYNIX
:
351 case NFL_VENDOR_SAMSUNG
:
354 case NFL_VENDOR_ESMT
:
357 case NFL_VENDOR_MXIC
:
360 case NFL_VENDOR_ZENTEL
:
364 printf("No NAND flash type found\n");
371 /* Initialize nand flash access */
373 nandcore_init(si_t
*sih
)
386 /* Only support chipcommon revision == 42 for now */
387 if (sih
->ccrev
!= 42)
390 if ((nc
= (nandregs_t
*)si_setcore(sih
, NS_NAND_CORE_ID
, 0)) == NULL
)
393 if (R_REG(NULL
, &nc
->flash_device_id
) == 0)
396 if (!firsttime
&& nandcore
.size
)
400 bzero(&nandcore
, sizeof(nandcore
));
403 nandcore
.core
= (void *)nc
;
404 nandcore
.wrap
= si_wrapperregs(sih
);
405 nandcore
.read
= nandcore_read
;
406 nandcore
.write
= nandcore_write
;
407 nandcore
.erase
= nandcore_erase
;
408 nandcore
.checkbadb
= nandcore_checkbadb
;
409 nandcore
.markbadb
= nandcore_mark_badb
;
411 nandcore
.read_oob
= nandcore_read_oob
;
413 nandcore
.dev_ready
= nandcore_dev_ready
;
414 nandcore
.select_chip
= nandcore_select_chip
;
415 nandcore
.cmdfunc
= nandcore_cmdfunc
;
416 nandcore
.waitfunc
= nandcore_waitfunc
;
417 nandcore
.write_oob
= nandcore_write_oob
;
418 nandcore
.read_page
= nandcore_read_page
;
419 nandcore
.write_page
= nandcore_write_page
;
420 nandcore
.cmd_read_byte
= nandcore_cmd_read_byte
;
423 nandcore_cmd(osh
, nc
, NANDCMD_ID_RD
);
424 if (nandcore_poll(sih
, nc
) < 0) {
428 ai
= (aidmp_t
*)nandcore
.wrap
;
430 /* Toggle as little endian */
431 OR_REG(osh
, &ai
->ioctrl
, NAND_APB_LITTLE_ENDIAN
);
433 id
= R_REG(osh
, &nc
->flash_device_id
);
434 id2
= R_REG(osh
, &nc
->flash_device_id_ext
);
436 /* Toggle as big endian */
437 AND_REG(osh
, &ai
->ioctrl
, ~NAND_APB_LITTLE_ENDIAN
);
439 for (i
= 0; i
< 5; i
++) {
441 nandcore
.id
[i
] = (id
>> (8*i
)) & 0xff;
443 nandcore
.id
[i
] = id2
& 0xff;
446 name
= nandcore_check_id(nandcore
.id
);
449 nandcore
.type
= nandcore
.id
[0];
451 ncf
= R_REG(osh
, &nc
->config_cs0
);
452 /* Page size (# of bytes) */
453 val
= (ncf
& NANDCF_CS0_PAGE_SIZE_MASK
) >> NANDCF_CS0_PAGE_SIZE_SHIFT
;
456 nandcore
.pagesize
= 512;
459 nandcore
.pagesize
= (1 << 10) * 2;
462 nandcore
.pagesize
= (1 << 10) * 4;
465 nandcore
.pagesize
= (1 << 10) * 8;
468 /* Block size (# of bytes) */
469 val
= (ncf
& NANDCF_CS0_BLOCK_SIZE_MASK
) >> NANDCF_CS0_BLOCK_SIZE_SHIFT
;
472 nandcore
.blocksize
= (1 << 10) * 8;
475 nandcore
.blocksize
= (1 << 10) * 16;
478 nandcore
.blocksize
= (1 << 10) * 128;
481 nandcore
.blocksize
= (1 << 10) * 256;
484 nandcore
.blocksize
= (1 << 10) * 512;
487 nandcore
.blocksize
= (1 << 10) * 1024;
490 nandcore
.blocksize
= (1 << 10) * 2048;
493 printf("Unknown block size\n");
496 /* NAND flash size in MBytes */
497 val
= (ncf
& NANDCF_CS0_DEVICE_SIZE_MASK
) >> NANDCF_CS0_DEVICE_SIZE_SHIFT
;
498 nandcore
.size
= (1 << val
) * 4;
500 /* Get Device I/O data bus width */
501 if (ncf
& NANDCF_CS0_DEVICE_WIDTH
)
504 /* Spare size and Spare per sector (# of bytes) */
505 acc_control
= R_REG(osh
, &nc
->acc_control_cs0
);
506 if (acc_control
& NANDAC_CS0_SECTOR_SIZE_1K
) {
507 printf("Pin strapping error. Sector size 1K hasn't supported yet\n");
511 /* Check conflict between 1K sector and page size */
512 if (acc_control
& NANDAC_CS0_SECTOR_SIZE_1K
) {
513 /* NOTE: 1K sector is not yet supported. */
514 nandcore
.sectorsize
= 1024;
517 nandcore
.sectorsize
= 512;
519 if (nandcore
.sectorsize
== 1024 && nandcore
.pagesize
== 512) {
520 printf("Pin strapping error. Page size is 512, but sector size is 1024\n");
525 nandcore
.sparesize
= acc_control
& NANDAC_CS0_SPARE_AREA_SIZE
;
528 nandcore
.oobsize
= nandcore
.sparesize
* (nandcore
.pagesize
/ NFL_SECTOR_SIZE
);
531 nandcore
.ecclevel
= (acc_control
& NANDAC_CS0_ECC_LEVEL_MASK
) >> NANDAC_CS0_ECC_LEVEL_SHIFT
;
532 if (nandcore
.sectorsize
== 1024)
533 nandcore
.ecclevel
*= 2;
535 nandcore
.numblocks
= (nandcore
.size
* (1 << 10)) / (nandcore
.blocksize
>> 10);
537 printf("Found a %s NAND flash:\n", name
);
538 printf("Total size: %uMB\n", nandcore
.size
);
539 printf("Block size: %uKB\n", (nandcore
.blocksize
>> 10));
540 printf("Page Size: %uB\n", nandcore
.pagesize
);
541 printf("OOB Size: %uB\n", nandcore
.oobsize
);
542 printf("Sector size: %uB\n", nandcore
.sectorsize
);
543 printf("Spare size: %uB\n", nandcore
.sparesize
);
544 printf("ECC level: %u-bit\n", nandcore
.ecclevel
);
545 printf("Device ID: 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x\n",
546 nandcore
.id
[0], nandcore
.id
[1], nandcore
.id
[2],
547 nandcore
.id
[3], nandcore
.id
[4]);
552 nandcore
.phybase
= SI_NS_NANDFLASH
;
553 nandcore
.base
= (uint32
)REG_MAP(SI_NS_NANDFLASH
, SI_FLASH_WINDOW
);
556 /* Configuration readback */
557 printf("R_REG(cs_nand_select) = 0x%08x\n", R_REG(osh
, &nc
->cs_nand_select
));
558 printf("R_REG(config_cs0) = 0x%08x\n", R_REG(osh
, &nc
->config_cs0
));
559 printf("R_REG(acc_control_cs0) = 0x%08x\n", R_REG(osh
, &nc
->acc_control_cs0
));
562 return nandcore
.size
? &nandcore
: NULL
;
565 /* Read len bytes starting at offset into buf. Returns number of bytes read. */
567 nandcore_read(hndnand_t
*nfl
, uint64 offset
, uint len
, uchar
*buf
)
572 uint32 herr
= 0, serr
= 0;
575 osh
= si_osh(nfl
->sih
);
581 _nandcore_read_page(nfl
, offset
, to
, NULL
, TRUE
, &herr
, &serr
);
583 res
-= nfl
->pagesize
;
584 offset
+= nfl
->pagesize
;
591 /* Poll for command completion. Returns zero when complete. */
593 nandcore_poll(si_t
*sih
, nandregs_t
*nc
)
602 pollmask
= NANDIST_CTRL_READY
| NANDIST_FLASH_READY
;
603 for (i
= 0; i
< NANDF_RETRIES
; i
++) {
604 if ((R_REG(osh
, &nc
->intfc_status
) & pollmask
) == pollmask
) {
609 printf("%s: not ready\n", __FUNCTION__
);
613 /* Write len bytes starting at offset into buf. Returns number of bytes
617 nandcore_write(hndnand_t
*nfl
, uint64 offset
, uint len
, const uchar
*buf
)
625 osh
= si_osh(nfl
->sih
);
631 ret
= _nandcore_write_page(nfl
, offset
, from
, NULL
, TRUE
);
635 res
-= nfl
->pagesize
;
636 offset
+= nfl
->pagesize
;
637 from
+= nfl
->pagesize
;
646 /* Erase a region. Returns number of bytes scheduled for erasure.
647 * Caller should poll for completion.
650 nandcore_erase(hndnand_t
*nfl
, uint64 offset
)
652 si_t
*sih
= nfl
->sih
;
653 nandregs_t
*nc
= (nandregs_t
*)nfl
->core
;
662 if ((offset
>> 20) >= nfl
->size
)
664 if ((offset
& (nfl
->blocksize
- 1)) != 0) {
669 AND_REG(osh
, &nc
->cs_nand_select
, ~NANDCSEL_NAND_WP
);
671 /* Set the block address for the following commands */
672 reg
= (R_REG(osh
, &nc
->cmd_ext_address
) & ~NANDCMD_EXT_ADDR_MASK
);
673 W_REG(osh
, &nc
->cmd_ext_address
, (reg
| (offset
>> 32)));
675 W_REG(osh
, &nc
->cmd_address
, offset
);
676 nandcore_cmd(osh
, nc
, NANDCMD_BLOCK_ERASE
);
677 if (nandcore_poll(sih
, nc
) < 0)
681 W_REG(osh
, &nc
->cmd_start
, NANDCMD_STATUS_RD
);
682 if (nandcore_poll(sih
, nc
) < 0)
685 status
= R_REG(osh
, &nc
->intfc_status
) & NANDIST_STATUS
;
692 OR_REG(osh
, &nc
->cs_nand_select
, NANDCSEL_NAND_WP
);
698 nandcore_checkbadb(hndnand_t
*nfl
, uint64 offset
)
700 si_t
*sih
= nfl
->sih
;
701 nandregs_t
*nc
= (nandregs_t
*)nfl
->core
;
702 aidmp_t
*ai
= (aidmp_t
*)nfl
->wrap
;
706 uint32 nand_intfc_status
;
713 if ((offset
>> 20) >= nfl
->size
)
715 if ((offset
& (nfl
->blocksize
- 1)) != 0) {
719 /* Set the block address for the following commands */
720 reg
= (R_REG(osh
, &nc
->cmd_ext_address
) & ~NANDCMD_EXT_ADDR_MASK
);
721 W_REG(osh
, &nc
->cmd_ext_address
, (reg
| (offset
>> 32)));
723 for (i
= 0; i
< 2; i
++) {
724 off
= offset
+ (nfl
->pagesize
* i
);
725 W_REG(osh
, &nc
->cmd_address
, off
);
726 nandcore_cmd(osh
, nc
, NANDCMD_SPARE_RD
);
727 if (nandcore_poll(sih
, nc
) < 0) {
731 nand_intfc_status
= R_REG(osh
, &nc
->intfc_status
) & NANDIST_SPARE_VALID
;
732 if (nand_intfc_status
!= NANDIST_SPARE_VALID
) {
735 printf("%s: Spare is not valid\n", __FUNCTION__
);
740 /* Toggle as little endian */
741 OR_REG(osh
, &ai
->ioctrl
, NAND_APB_LITTLE_ENDIAN
);
743 if ((R_REG(osh
, &nc
->spare_area_read_ofs
[0]) & 0xff) != 0xff) {
746 printf("%s: Bad Block (0x%llx)\n", __FUNCTION__
, offset
);
750 /* Toggle as big endian */
751 AND_REG(osh
, &ai
->ioctrl
, ~NAND_APB_LITTLE_ENDIAN
);
762 nandcore_mark_badb(hndnand_t
*nfl
, uint64 offset
)
764 si_t
*sih
= nfl
->sih
;
765 nandregs_t
*nc
= (nandregs_t
*)nfl
->core
;
766 aidmp_t
*ai
= (aidmp_t
*)nfl
->wrap
;
775 if ((offset
>> 20) >= nfl
->size
)
777 if ((offset
& (nfl
->blocksize
- 1)) != 0) {
782 AND_REG(osh
, &nc
->cs_nand_select
, ~NANDCSEL_NAND_WP
);
784 /* Set the block address for the following commands */
785 reg
= (R_REG(osh
, &nc
->cmd_ext_address
) & ~NANDCMD_EXT_ADDR_MASK
);
786 W_REG(osh
, &nc
->cmd_ext_address
, (reg
| (offset
>> 32)));
789 W_REG(osh
, &nc
->cmd_address
, offset
);
790 nandcore_cmd(osh
, nc
, NANDCMD_BLOCK_ERASE
);
791 if (nandcore_poll(sih
, nc
) < 0) {
793 /* Still go through the spare area write */
798 * Enable partial page programming and disable ECC checkbit generation
799 * for PROGRAM_SPARE_AREA
801 reg
= R_REG(osh
, &nc
->acc_control_cs0
);
802 reg
|= NANDAC_CS0_PARTIAL_PAGE_EN
;
803 reg
|= NANDAC_CS0_FAST_PGM_RDIN
;
804 reg
&= ~NANDAC_CS0_WR_ECC_EN
;
805 W_REG(osh
, &nc
->acc_control_cs0
, reg
);
807 for (i
= 0; i
< 2; i
++) {
808 off
= offset
+ (nfl
->pagesize
* i
);
809 W_REG(osh
, &nc
->cmd_address
, off
);
811 /* Toggle as little endian */
812 OR_REG(osh
, &ai
->ioctrl
, NAND_APB_LITTLE_ENDIAN
);
814 W_REG(osh
, &nc
->spare_area_write_ofs
[0], 0);
815 W_REG(osh
, &nc
->spare_area_write_ofs
[1], 0);
816 W_REG(osh
, &nc
->spare_area_write_ofs
[2], 0);
817 W_REG(osh
, &nc
->spare_area_write_ofs
[3], 0);
819 /* Toggle as big endian */
820 AND_REG(osh
, &ai
->ioctrl
, ~NAND_APB_LITTLE_ENDIAN
);
822 nandcore_cmd(osh
, nc
, NANDCMD_SPARE_PROG
);
823 if (nandcore_poll(sih
, nc
) < 0) {
826 printf("%s: Spare program is not ready\n", __FUNCTION__
);
833 /* Restore the default value for spare area write registers */
834 W_REG(osh
, &nc
->spare_area_write_ofs
[0], 0xffffffff);
835 W_REG(osh
, &nc
->spare_area_write_ofs
[1], 0xffffffff);
836 W_REG(osh
, &nc
->spare_area_write_ofs
[2], 0xffffffff);
837 W_REG(osh
, &nc
->spare_area_write_ofs
[3], 0xffffffff);
840 * Disable partial page programming and enable ECC checkbit generation
841 * for PROGRAM_SPARE_AREA
843 reg
= R_REG(osh
, &nc
->acc_control_cs0
);
844 reg
&= ~NANDAC_CS0_PARTIAL_PAGE_EN
;
845 reg
&= ~NANDAC_CS0_FAST_PGM_RDIN
;
846 reg
|= NANDAC_CS0_WR_ECC_EN
;
847 W_REG(osh
, &nc
->acc_control_cs0
, reg
);
850 OR_REG(osh
, &nc
->cs_nand_select
, NANDCSEL_NAND_WP
);
857 /* Functions support brcmnand driver */
859 _nandcore_set_cmd_address(hndnand_t
*nfl
, uint64 addr
)
863 si_t
*sih
= nfl
->sih
;
864 nandregs_t
*nc
= (nandregs_t
*)nfl
->core
;
869 reg
= (R_REG(osh
, &nc
->cmd_ext_address
) & ~NANDCMD_EXT_ADDR_MASK
);
870 W_REG(osh
, &nc
->cmd_ext_address
, (reg
| (addr
>> 32)));
871 W_REG(osh
, &nc
->cmd_address
, addr
);
875 nandcore_dev_ready(hndnand_t
*nfl
)
877 aidmp_t
*ai
= (aidmp_t
*)nfl
->wrap
;
881 return (R_REG(si_osh(nfl
->sih
), &ai
->iostatus
) & NAND_RO_CTRL_READY
);
885 nandcore_select_chip(hndnand_t
*nfl
, int chip
)
889 si_t
*sih
= nfl
->sih
;
890 nandregs_t
*nc
= (nandregs_t
*)nfl
->core
;
895 reg
= R_REG(osh
, &nc
->cmd_ext_address
);
896 reg
&= ~NANDCMD_CS_SEL_MASK
;
897 reg
|= (chip
<< NANDCMD_CS_SEL_SHIFT
);
898 W_REG(osh
, &nc
->cmd_ext_address
, reg
);
900 /* Set active chip index */
907 nandcore_cmdfunc(hndnand_t
*nfl
, uint64 addr
, int cmd
)
911 nandregs_t
*nc
= (nandregs_t
*)nfl
->core
;
914 osh
= si_osh(nfl
->sih
);
918 _nandcore_set_cmd_address(nfl
, addr
);
922 AND_REG(osh
, &nc
->cs_nand_select
, ~NANDCSEL_NAND_WP
);
923 nandcore_cmd(osh
, nc
, NANDCMD_BLOCK_ERASE
);
924 ret
= nandcore_waitfunc(nfl
, NULL
);
926 OR_REG(osh
, &nc
->cs_nand_select
, NANDCSEL_NAND_WP
);
929 _nandcore_set_cmd_address(nfl
, addr
);
932 _nandcore_set_cmd_address(nfl
, addr
);
933 nandcore_cmd(osh
, nc
, NANDCMD_PAGE_RD
);
934 ret
= nandcore_waitfunc(nfl
, NULL
);
937 nandcore_cmd(osh
, nc
, NANDCMD_FLASH_RESET
);
938 ret
= nandcore_waitfunc(nfl
, NULL
);
941 nandcore_cmd(osh
, nc
, NANDCMD_ID_RD
);
942 ret
= nandcore_waitfunc(nfl
, NULL
);
946 AND_REG(osh
, &nc
->cs_nand_select
, ~NANDCSEL_NAND_WP
);
947 nandcore_cmd(osh
, nc
, NANDCMD_STATUS_RD
);
948 ret
= nandcore_waitfunc(nfl
, NULL
);
950 OR_REG(osh
, &nc
->cs_nand_select
, NANDCSEL_NAND_WP
);
952 case CMDFUNC_READOOB
:
956 printf("%s: Unknow command 0x%x\n", __FUNCTION__
, cmd
);
965 /* Return intfc_status FLASH_STATUS if CTRL/FLASH is ready otherwise -1 */
967 nandcore_waitfunc(hndnand_t
*nfl
, int *status
)
971 nandregs_t
*nc
= (nandregs_t
*)nfl
->core
;
974 osh
= si_osh(nfl
->sih
);
976 ret
= nandcore_poll(nfl
->sih
, nc
);
977 if (ret
== 0 && status
)
978 *status
= R_REG(osh
, &nc
->intfc_status
) & NANDIST_STATUS
;
992 for (j
= 0; j
< 32; j
++)
1000 nandcore_read_oob(hndnand_t
*nfl
, uint64 addr
, uint8
*oob
)
1003 si_t
*sih
= nfl
->sih
;
1004 nandregs_t
*nc
= (nandregs_t
*)nfl
->core
;
1005 aidmp_t
*ai
= (aidmp_t
*)nfl
->wrap
;
1007 unsigned spare_per_sec
, sector
;
1008 int i
, sectorsize_shift
, sec_per_page_shift
;
1013 /* Set the page address for the following commands */
1014 reg
= (R_REG(osh
, &nc
->cmd_ext_address
) & ~NANDCMD_EXT_ADDR_MASK
);
1015 W_REG(osh
, &nc
->cmd_ext_address
, (reg
| (addr
>> 32)));
1018 sectorsize_shift
= ffs(nfl
->sectorsize
) - 1;
1019 sec_per_page_shift
= ffs(nfl
->pagesize
) - 1 - sectorsize_shift
;
1021 spare_per_sec
= nfl
->oobsize
>> sec_per_page_shift
;
1023 /* Disable ECC validation for spare area reads */
1024 AND_REG(osh
, nfl
->chipidx
? &nc
->acc_control_cs1
: &nc
->acc_control_cs0
,
1025 ~NANDAC_CS0_RD_ECC_EN
);
1027 /* Loop all sectors in page */
1028 for (sector
= 0; sector
< (1 << sec_per_page_shift
); sector
++) {
1031 col
= (sector
<< sectorsize_shift
);
1033 /* Issue command to read partial page */
1034 W_REG(osh
, &nc
->cmd_address
, addr
+ col
);
1036 nandcore_cmd(osh
, nc
, NANDCMD_SPARE_RD
);
1038 /* Wait for the command to complete */
1039 if (nandcore_poll(sih
, nc
))
1042 if (!(R_REG(osh
, &nc
->intfc_status
) & NANDIST_SPARE_VALID
)) {
1043 printf("%s: data not valid\n", __FUNCTION__
);
1047 /* Set controller to Little Endian mode for copying */
1048 OR_REG(osh
, &ai
->ioctrl
, NAND_APB_LITTLE_ENDIAN
);
1050 to
= (uint32
*)(oob
+ sector
* spare_per_sec
);
1051 for (i
= 0; i
< spare_per_sec
; i
+= 4, to
++)
1052 *to
= R_REG(osh
, &nc
->spare_area_read_ofs
[i
/4]);
1054 /* Return to Big Endian mode for commands etc */
1055 AND_REG(osh
, &ai
->ioctrl
, ~NAND_APB_LITTLE_ENDIAN
);
1063 nandcore_write_oob(hndnand_t
*nfl
, uint64 addr
, uint8
*oob
)
1066 si_t
*sih
= nfl
->sih
;
1067 nandregs_t
*nc
= (nandregs_t
*)nfl
->core
;
1068 aidmp_t
*ai
= (aidmp_t
*)nfl
->wrap
;
1070 unsigned spare_per_sec
, sector
, num_sec
;
1071 int i
, sectorsize_shift
, sec_per_page_shift
;
1078 AND_REG(osh
, &nc
->cs_nand_select
, ~NANDCSEL_NAND_WP
);
1081 * Enable partial page programming and disable ECC checkbit generation
1082 * for PROGRAM_SPARE_AREA
1084 reg
= R_REG(osh
, nfl
->chipidx
? &nc
->acc_control_cs1
: &nc
->acc_control_cs0
);
1085 reg
|= NANDAC_CS0_PARTIAL_PAGE_EN
;
1086 reg
|= NANDAC_CS0_FAST_PGM_RDIN
;
1087 reg
&= ~NANDAC_CS0_WR_ECC_EN
;
1088 W_REG(osh
, nfl
->chipidx
? &nc
->acc_control_cs1
: &nc
->acc_control_cs0
, reg
);
1091 sectorsize_shift
= _nandcore_ffs(nfl
->sectorsize
) - 1;
1092 sec_per_page_shift
= _nandcore_ffs(nfl
->pagesize
) - 1 - sectorsize_shift
;
1094 spare_per_sec
= nfl
->oobsize
>> sec_per_page_shift
;
1096 /* Set the page address for the following commands */
1097 reg
= (R_REG(osh
, &nc
->cmd_ext_address
) & ~NANDCMD_EXT_ADDR_MASK
);
1098 W_REG(osh
, &nc
->cmd_ext_address
, (reg
| (addr
>> 32)));
1100 num_sec
= 1 << sec_per_page_shift
;
1102 /* Loop all sectors in page */
1103 for (sector
= 0; sector
< num_sec
; sector
++) {
1106 /* Spare area accessed by the data sector offset */
1107 col
= (sector
<< sectorsize_shift
);
1109 W_REG(osh
, &nc
->cmd_address
, addr
+ col
);
1111 /* Set controller to Little Endian mode for copying */
1112 OR_REG(osh
, &ai
->ioctrl
, NAND_APB_LITTLE_ENDIAN
);
1114 from
= (uint32
*)(oob
+ sector
* spare_per_sec
);
1115 for (i
= 0; i
< spare_per_sec
; i
+= 4, from
++)
1116 W_REG(osh
, &nc
->spare_area_write_ofs
[i
/4], *from
);
1118 /* Return to Big Endian mode for commands etc */
1119 AND_REG(osh
, &ai
->ioctrl
, ~NAND_APB_LITTLE_ENDIAN
);
1121 /* Push spare bytes into internal buffer, last goes to flash */
1122 nandcore_cmd(osh
, nc
, NANDCMD_SPARE_PROG
);
1124 if (nandcore_poll(sih
, nc
)) {
1132 * Disable partial page programming and enable ECC checkbit generation
1133 * for PROGRAM_SPARE_AREA
1135 reg
= R_REG(osh
, nfl
->chipidx
? &nc
->acc_control_cs1
: &nc
->acc_control_cs0
);
1136 reg
&= ~NANDAC_CS0_PARTIAL_PAGE_EN
;
1137 reg
&= ~NANDAC_CS0_FAST_PGM_RDIN
;
1138 reg
|= NANDAC_CS0_WR_ECC_EN
;
1139 W_REG(osh
, nfl
->chipidx
? &nc
->acc_control_cs1
: &nc
->acc_control_cs0
, reg
);
1142 OR_REG(osh
, &nc
->cs_nand_select
, NANDCSEL_NAND_WP
);
1148 nandcore_read_page(hndnand_t
*nfl
, uint64 addr
, uint8
*buf
, uint8
*oob
, bool ecc
,
1149 uint32
*herr
, uint32
*serr
)
1151 return _nandcore_read_page(nfl
, addr
, buf
, oob
, ecc
, herr
, serr
);
1155 nandcore_write_page(hndnand_t
*nfl
, uint64 addr
, const uint8
*buf
, uint8
*oob
, bool ecc
)
1157 return _nandcore_write_page(nfl
, addr
, buf
, oob
, ecc
);
1161 nandcore_cmd_read_byte(hndnand_t
*nfl
, int cmd
, int arg
)
1165 nandregs_t
*nc
= (nandregs_t
*)nfl
->core
;
1168 osh
= si_osh(nfl
->sih
);
1171 case CMDFUNC_READID
:
1172 return R_REG(osh
, id_ext
? &nc
->flash_device_id_ext
: &nc
->flash_device_id
);
1173 case CMDFUNC_STATUS
:
1174 return (R_REG(osh
, &nc
->intfc_status
) & NANDIST_STATUS
);
1177 printf("%s: Unknow command 0x%x\n", __FUNCTION__
, cmd
);