[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