[OpenBIOS] r336 - dev/olpc/cafenand
svn at openbios.org
svn at openbios.org
Sun Apr 29 21:32:48 CEST 2007
Author: wmb
Date: 2007-04-29 21:32:48 +0200 (Sun, 29 Apr 2007)
New Revision: 336
Modified:
dev/olpc/cafenand/badblock.fth
dev/olpc/cafenand/cafenand.fth
dev/olpc/cafenand/configure.fth
dev/olpc/cafenand/methods.fth
dev/olpc/cafenand/test.fth
Log:
OLPC CaFe NAND driver - added support for two-NAND-chip packages. trac #1374
Modified: dev/olpc/cafenand/badblock.fth
===================================================================
--- dev/olpc/cafenand/badblock.fth 2007-04-27 22:25:44 UTC (rev 335)
+++ dev/olpc/cafenand/badblock.fth 2007-04-29 19:32:48 UTC (rev 336)
@@ -8,7 +8,7 @@
: round-up ( n boundary -- n' ) over 1- + over / * ;
: /bbt ( -- bytes ) \ Bytes per bad block table
- pages/chip pages/eblock / 3 + 4 / ( bytes )
+ total-pages pages/eblock / 3 + 4 / ( bytes )
/page round-up
;
@@ -70,8 +70,8 @@
\ Page range to search for a bad block table
: bbtbounds ( low-page high-page -- )
0 to bbt0 0 to bbt1
- pages/chip #bbtsearch pages/eblock * -
- pages/chip pages/eblock -
+ total-pages #bbtsearch pages/eblock * -
+ total-pages pages/eblock -
;
\ Look for existing bad block tables, setting bbt0 and bbt1 if found
@@ -118,7 +118,7 @@
\ Scan the device and record the factory bad-block info in a table
: initial-badblock-scan ( -- )
- pages/chip 0 do
+ total-pages 0 do
i initial-block-bad? if
i .bad
else
@@ -214,7 +214,7 @@
exit
then
bbt1 if bbt1 exit then
- pages/chip
+ total-pages
;
: map-resblock ( page# #pages -- page#' #pages )
@@ -275,7 +275,7 @@
\ This is fairly severe, not recommended except in exceptional situations
: scrub ( -- )
release-bbt
- pages/chip 0 ?do
+ total-pages 0 ?do
(cr i .
i erase-block
pages/eblock +loop
@@ -301,7 +301,7 @@
;
: show-bbt ( -- )
get-bbt
- pages/chip 0 ?do
+ total-pages 0 ?do
i block-reserved? if ." Reserved " i .page-byte cr else
i block-bad? if ." Bad block" i .page-byte cr then
then
Modified: dev/olpc/cafenand/cafenand.fth
===================================================================
--- dev/olpc/cafenand/cafenand.fth 2007-04-27 22:25:44 UTC (rev 335)
+++ dev/olpc/cafenand/cafenand.fth 2007-04-29 19:32:48 UTC (rev 336)
@@ -15,7 +15,6 @@
" reg" property
-
: my-w@ ( offset -- w ) my-space + " config-w@" $call-parent ;
: my-w! ( w offset -- ) my-space + " config-w!" $call-parent ;
@@ -64,12 +63,29 @@
\ Wait not busy - XXX need timeout
: ctrl-wait ( -- ) begin h# c cl@ h# 8000.0000 and 0= until ;
-\ Think of col as the offset within a disk block, and row as the block#
-: set-address ( row col -- ) h# 1c cl! h# 20 cl! ;
+\ Bit 19 in the command (0) register is reserved according to the
+\ version of the CaFe chip spec that we have, but Jerry Zheng says
+\ that it chooses the chip select - 0 for CS0, 1 for CS1.
+1 instance value chip-boundary \ Boundary between chip 0 and chip 1
+0 instance value cs-mask \ Chip-select bit for command 0 register
+: chip0 ( -- ) 0 to cs-mask ;
+: chip1 ( -- ) h# 80000 to cs-mask ;
+
+: set-chip ( page# -- page#' )
+ dup chip-boundary >= if chip-boundary - chip1 else chip0 then
+;
+
+\ For erase-block, the address that is sent to the chip is formatted
+\ differently than for reads and writes.
+: set-erase-page ( page# -- ) set-chip lwsplit h# 20 cl! h# 1c cl! ;
+
+: set-page ( page# offset -- ) h# 1c cl! set-chip h# 20 cl! ;
+
: >cmd ( cmd# #nonmem #address-bytes -- cmdval )
dup if 1- d# 27 lshift h# 4000.0000 or then ( cmd# #nm adr-field )
- swap 7 and d# 22 lshift or ( cmd# nm,adr )
+ over 1 and d# 20 lshift or \ #nm[0] ( cmd# #nm adr+nm0 )
+ swap e and d# 21 lshift or \ #nm[3:1] ( cmd# adr+nm )
or h# 8000.0000 or
;
@@ -80,29 +96,26 @@
h# 0420.0000 0 5 >cmd constant read-cmd
h# 0220.0080 0 5 >cmd constant write-cmd
-: wait-dma-done ( -- )
- begin
- h# 10 cl@ h# 1000.0000 and
- until
- h# 1000.0000 h# 10 cl! \ Clear DMA done
+: wait-mask ( bitmask -- )
+ begin dup h# 10 cl@ and until ( bitmask )
+ h# 10 cl! \ Clear status bit
;
+: wait-dma ( -- ) h# 1000.0000 wait-mask ;
+: wait-cmd ( -- ) h# 8000.0000 wait-mask ;
-: wait-done ( -- )
- begin
- h# 10 cl@ h# 8000.0000 and
- until
- h# 8000.0000 h# 10 cl! \ Clear done
-;
-
\ Control3 - no reset, no BAR write protect
: write-disable ( -- ) 0 8 cl! ;
: write-enable ( -- ) h# 4000.0000 8 cl! ;
-: cmd ( n -- ) 0 cl! wait-done ;
-: cmd2 ( n -- ) 4 cl! ;
+: cmd ( cmd cmd2 -- )
+ /page d# 10 rshift 3 and d# 28 lshift or 4 cl! ( cmd )
+ cs-mask or 0 cl! ( )
+;
+
: datalen ( n -- ) h# 18 cl! ;
-: read-status ( -- b ) read-status-cmd cmd h# 30 cl@ h# ff and ;
-\ : read-id ( -- ) 0 0 set-address read-id-cmd cmd h# 30 cl@ ;
+
+: read-status ( -- b ) read-status-cmd 0 cmd wait-cmd h# 30 cl@ h# ff and ;
+\ : read-id ( -- ) 0 0 set-page read-id-cmd 0 cmd wait-cmd h# 30 cl@ ;
: dma-off ( -- ) 0 h# 40 cl! ;
: wait-write-done ( -- )
@@ -118,10 +131,10 @@
\ Assumes that the range doesn't straddle a page boundary
: generic-read ( len page# offset cmd cmd2 -- chip-adr )
- cmd2 >r ( len page# offset r: cmd )
- set-address dma-off ( len r: cmd )
- datalen ( r: cmd )
- r> cmd ( )
+ >r >r ( len page# offset r: cmd cmd2 )
+ set-page dma-off ( len r: cmd cmd2 )
+ datalen ( r: cmd cmd2 )
+ r> r> cmd wait-cmd ( )
chip h# 1000 + ( adr )
;
: pio-read ( adr len page# offset -- )
@@ -132,19 +145,19 @@
: pio-write-raw ( adr len page# offset -- )
write-enable
- dma-off set-address dup datalen ( adr len )
- chip h# 2000 + swap move ( )
- h# 2000.0110 cmd2 write-cmd cmd ( ) \ 2000. 2K page, (No Auto ECC)
+ dma-off set-page dup datalen ( adr len )
+ chip h# 2000 + swap move ( )
+ write-cmd h# 0000.0110 cmd wait-cmd ( ) No Auto ECC
wait-write-done
write-disable
;
: pio-write-page ( adr page# -- )
- write-enable dma-off ( adr page# )
- 0 set-address ( adr )
- /page h# e + dup datalen ( adr len )
- chip h# 2000 + swap move ( )
- h# 6800.0110 cmd2 write-cmd cmd ( ) \ 4000. Auto ECC, 2000. 2K page, 0800 R/S ECC
+ write-enable dma-off ( adr page# )
+ 0 set-page ( adr )
+ /page h# e + dup datalen ( adr len )
+ chip h# 2000 + swap move ( )
+ write-cmd h# 4800.0110 cmd wait-cmd ( ) \ 4000. Auto ECC, 0800. R/S ECC
wait-write-done
write-disable
;
@@ -153,7 +166,7 @@
/oob swap h# 800 read-cmd h# 130 generic-read
;
-: read-rst ( -- ) h# 8000.0000 h# c cl! ;
+: read-rst ( -- ) h# 8000.0000 h# c cl! ;
0 instance value dma-vadr
0 instance value dma-padr
@@ -176,13 +189,10 @@
;
: slow-dma-read ( adr len page# offset -- )
- set-address
- dup true dma-setup ( )
- h# 130 cmd2 read-cmd 0 cl! ( adr chip-adr r: len )
- \ XXX put a 90 us delay here so we don't start hitting the register
- \ until almost done.
- wait-dma-done \ For DMA reads we wait for DMA completion instead of cmd
- dma-release ( )
+ set-page
+ dup true dma-setup ( )
+ read-cmd h# 0800.0130 cmd wait-dma ( adr chip-adr r: len )
+ dma-release ( )
;
: /dma-buf ( -- n ) /page /oob + ;
@@ -192,34 +202,33 @@
\ XXX should check ECC
: read-page ( adr page# -- )
- h# 20 cl! 0 h# 1c cl!
+ 0 set-page ( adr )
/page ( /oob + ) h# 18 cl! ( adr )
dma-buf-pa h# 44 cl! ( adr )
0 h# 48 cl! ( adr )
/page h# a000.0000 or h# 40 cl! ( adr )
- h# 130 4 cl! read-cmd 0 cl! ( adr )
- wait-dma-done \ For DMA reads we wait for DMA completion instead of cmd
+ read-cmd h# 0800.0130 cmd wait-dma ( adr )
dma-buf-va swap /page do-lmove ( )
;
: dma-write-raw ( adr len page# offset -- )
- write-enable ( adr len page# offset )
- set-address ( adr len )
- dup false dma-setup ( )
- h# 2000.0110 cmd2 write-cmd cmd ( )
- wait-write-done
- dma-release
- write-disable
+ write-enable ( adr len page# offset )
+ set-page ( adr len )
+ dup false dma-setup ( )
+ write-cmd h# 110 cmd wait-cmd ( )
+ wait-write-done ( )
+ dma-release ( )
+ write-disable ( )
;
: dma-write-page ( adr page# -- ) \ Size is fixed
write-enable ( adr page# )
- 0 set-address ( adr )
+ 0 set-page ( adr )
h# 800 h# 80e false dma-setup ( )
- h# 6800.0110 cmd2 write-cmd cmd ( ) \ Auto-ECC, 2KB, RS, write cmd
- wait-write-done
+ write-cmd h# 4800.0110 cmd wait-cmd ( ) \ Auto-ECC, RS, write cmd
+ wait-write-done ( )
\ dma-release
- write-disable
+ write-disable ( )
;
\ : read-page ( adr page# -- ) dma-read-page ;
@@ -229,9 +238,8 @@
3 value #erase-adr-bytes \ Chip dependent
: erase-block ( page# -- )
write-enable
- lwsplit swap set-address \ Fiddle the block number
- h# 1d0 cmd2
- h# 20.0060 0 #erase-adr-bytes >cmd cmd
+ set-erase-page
+ h# 20.0060 0 #erase-adr-bytes >cmd h# 1d0 cmd
wait-write-done
write-disable
;
@@ -240,12 +248,10 @@
: send-reset-cmd ( -- )
ctrl-wait
- h# 8000.00ff cmd \ NAND Reset command
+ h# 8000.00ff 0 cmd wait-cmd \ NAND Reset command
;
: init ( -- )
- 0 0 cl! \ Clear command register
- h# 2000.0000 4 cl! \ Page 2KB
write-disable
send-reset-cmd
Modified: dev/olpc/cafenand/configure.fth
===================================================================
--- dev/olpc/cafenand/configure.fth 2007-04-27 22:25:44 UTC (rev 335)
+++ dev/olpc/cafenand/configure.fth 2007-04-29 19:32:48 UTC (rev 336)
@@ -1,8 +1,9 @@
\ See license at end of file
purpose: Common code for NAND FLASH access
-h# 4.0000 instance value pages/chip
-h# 40 instance value pages/eblock
+h# 0 instance value total-pages \ Start with 0 and add chips
+h# 0 instance value pages/chip
+h# 40 instance value pages/eblock
\ This uses byte 4 to work out the plane parameters
\ The Samsung part has this byte, but the Hynix part doesn't
@@ -10,7 +11,7 @@
dup 4 + c@ ( adr plane-data )
h# 1000 over 4 rshift 7 and lshift ( adr plane-data pages/plane )
1 rot 2 rshift 3 and lshift ( adr kbytes/plane #planes )
- * to pages/chip ( adr )
+ * to pages/chip ( adr )
;
\ This uses byte 3 to work out the page and erase block sizes
@@ -55,6 +56,7 @@
: configure ( -- okay? )
read-id ( adr )
['] configure-auto catch 0= nip
+ pages/chip total-pages + to total-pages
;
\ LICENSE_BEGIN
Modified: dev/olpc/cafenand/methods.fth
===================================================================
--- dev/olpc/cafenand/methods.fth 2007-04-27 22:25:44 UTC (rev 335)
+++ dev/olpc/cafenand/methods.fth 2007-04-29 19:32:48 UTC (rev 336)
@@ -6,6 +6,24 @@
comp 0=
;
+: configure-all ( -- error? )
+ 0 to total-pages
+
+ \ Set boundary to 0 to look for chip on CE1#
+ \ If one is found, the number of pages will be added to total-pages
+ 0 to chip-boundary configure drop
+
+ \ Set boundary to 1 to look for chip on CE0# (configure uses page# 0)
+ 1 to chip-boundary configure if
+ pages/chip \ Chip present at CE0#, set boundary above it
+ else
+ 0 \ No chip at CE0, set boundary at 0 to use CE1# chip
+ then
+ to chip-boundary
+
+ total-pages 0= \ Error if there are no chips
+;
+
external
: dma-alloc ( len -- adr ) " dma-alloc" $call-parent ;
@@ -27,7 +45,7 @@
resmap if
#reserved-eblocks /eblock
else
- pages/chip /page
+ total-pages /page
then
um*
;
@@ -35,7 +53,7 @@
: open ( -- okay? )
map-regs
init
- configure 0= if false exit then
+ configure-all if false exit then
/dma-buf dma-alloc to dma-buf-va
dma-buf-va /dma-buf false " dma-map-in" $call-parent to dma-buf-pa
Modified: dev/olpc/cafenand/test.fth
===================================================================
--- dev/olpc/cafenand/test.fth 2007-04-27 22:25:44 UTC (rev 335)
+++ dev/olpc/cafenand/test.fth 2007-04-29 19:32:48 UTC (rev 336)
@@ -59,7 +59,7 @@
;
: test-all ( -- )
- pages/chip 0 do
+ total-pages 0 do
(cr i .
i test-eb
key? ?leave
@@ -68,7 +68,7 @@
\ XXX skip mfg bad blocks
: erase-all ( -- )
- pages/chip 0 do
+ total-pages 0 do
(cr i .
i erase-block
key? ?leave
@@ -84,7 +84,7 @@
: scan-all
cr
- pages/chip 0 do
+ total-pages 0 do
i ?.
ib /full-page i 0 pio-read
mismatch? if i . .where then
@@ -104,7 +104,7 @@
;
: .bad ( page# -- ) .x ." bad" cr ;
: initial-badblock-scan ( -- )
- pages/chip 0 do
+ total-pages 0 do
i block-bad? if
i .bad
else
@@ -147,11 +147,12 @@
[then]
: scan-bad ( -- )
- pages/chip 0 do
+ total-pages 0 do
bbbuf 4 i h# 800 pio-read i .bad
bbbuf 4 i 1+ h# 800 pio-read i 1+ .bad
pages/eblock +loop
;
+
\ LICENSE_BEGIN
\ Copyright (c) 2006 FirmWorks
\
More information about the OpenBIOS
mailing list