[openfirmware] [commit] r2432 - cpu/x86/pc/alex dev/intel dev/olpc/spiflash ofw/fs

repository service svn at openfirmware.info
Tue Aug 9 06:26:35 CEST 2011


Author: wmb
Date: Tue Aug  9 06:26:34 2011
New Revision: 2432
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2432

Log:
Alex - added SPI FLASH reprogramming.

Added:
   cpu/x86/pc/alex/spiui.fth
   dev/intel/spi.fth
Modified:
   cpu/x86/pc/alex/devices.fth
   dev/olpc/spiflash/spiflash.fth
   ofw/fs/cbfs.fth

Modified: cpu/x86/pc/alex/devices.fth
==============================================================================
--- cpu/x86/pc/alex/devices.fth	Tue Aug  9 06:25:40 2011	(r2431)
+++ cpu/x86/pc/alex/devices.fth	Tue Aug  9 06:26:34 2011	(r2432)
@@ -34,6 +34,14 @@
 h# 28 to vector-base1
 device-end
 
+fload ${BP}/dev/olpc/spiflash/flashif.fth   \ Generic FLASH interface
+
+fload ${BP}/dev/olpc/spiflash/memflash.fth  \ Memory-mapped FLASH read access
+
+warning @ warning off
+: stand-init-io  stand-init-io  h# ffc0.0000 to flash-base  ;
+warning !
+
 fload ${BP}/ofw/fs/cbfs.fth     \ Coreboot ROM filesystem
 
 \ Create the top-level device node to access the entire boot FLASH device
@@ -168,8 +176,16 @@
 
 fload ${BP}/ofw/core/muxdev.fth		\ I/O collection/distribution device
 
+fload ${BP}/dev/olpc/spiflash/spiif.fth     \ Generic low-level SPI bus access
+fload ${BP}/dev/intel/spi.fth               \ SPI FLASH programming
+
 fload ${BP}/cpu/x86/pc/reset.fth	\ reset-all
 
+: ?enough-power  ;                      \ Implement based on AC presence and battery status
+
+fload ${BP}/cpu/x86/pc/alex/spiui.fth   \ User interface for SPI FLASH programming
+: urom  ( -- )  " flash! u:\alex.rom" evaluate  ;
+
 \ LICENSE_BEGIN
 \ Copyright (c) 2011 FirmWorks
 \ 

Added: cpu/x86/pc/alex/spiui.fth
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ cpu/x86/pc/alex/spiui.fth	Tue Aug  9 06:26:34 2011	(r2432)
@@ -0,0 +1,177 @@
+\ See license at end of file
+purpose: User interface for reflashing SPI FLASH parts
+
+\ This code is concerned with the user interface for getting
+\ a new firmware image into memory and using it to program
+\ a FLASH device from that image.  The details of how to actually
+\ access the FLASH device are defined elsewhere.
+
+h# 4000 constant /chunk   \ Convenient sized piece for progress reports
+
+: write-flash-range  ( adr end-offset start-offset -- )
+   ." Writing" cr
+   ?do                ( adr )
+      \ Save time - don't write if the data is the same
+      i .x (cr                              ( adr )
+      spi-us d# 20 >=  if                   ( adr )
+         \ Just write if reading is slow
+         true                               ( adr must-write? )
+      else                                  ( adr )
+         dup  /flash-block  i  flash-verify ( adr must-write? )
+      then                                  ( adr must-write? )
+
+      if
+         i flash-erase-block
+         dup  /flash-block  i  flash-write  ( adr )
+      then
+      /flash-block +                        ( adr' )
+   /flash-block +loop                       ( adr )
+   cr  drop           ( )
+;
+
+: verify-flash-range  ( adr end-offset start-offset -- )
+   ." Verifying" cr
+   ?do                ( adr )
+      i .x (cr
+      dup   /flash-block  i  flash-verify   abort" Verify failed"
+      /flash-block +  ( adr' )
+   /flash-block +loop ( adr )
+   cr  drop           ( )
+;
+
+
+\ Perform a series of sanity checks on the new firmware image.
+
+[ifdef] load-base
+: flash-buf  load-base  ;
+[else]
+/flash buffer: flash-buf
+[then]
+
+0 value file-loaded?
+
+: -cbid  ( offset -- )  flash-buf /flash +  swap -  ;
+
+: check-id-string  ( offset expect$ -- )
+   rot -cbid @  -cbid cscount  ( expect$ got$ )
+   2over 2over $=  0=  if      ( expect$ got$ )
+      ." Expecting " 2swap type ." , got " type  cr
+      abort
+   then                        ( expect$ got$ )
+   4drop                       ( )
+;
+: ?coreboot-id  ( -- )
+   h# 14 -cbid @  /flash <>  abort" Coreboot flash size mismatch"
+   h# 1c " Samsung" check-id-string
+   h# 18 " Alex" check-id-string
+;
+: ?cbfs  ( -- )
+   flash-buf " LARCHIVE" comp  abort" Image file is not in CBFS format"
+   \ We could also check the integrity of the CBFS headers
+;
+
+: ?image-valid   ( len -- )
+   /flash <> abort" Image file is the wrong length"
+
+   ?cbfs
+   ?coreboot-id
+;
+
+: $get-file  ( "filename" -- )
+   $read-open
+   flash-buf  /flash  ifd @ fgets   ( len )
+   ifd @ fclose
+
+   ?image-valid
+
+   true to file-loaded?
+;
+
+: ?file  ( -- )
+   file-loaded?  0=  if
+      ." You must first load a valid FLASH image file with" cr
+      ."    get-file filename" cr
+      abort
+   then
+;
+
+: read-flash  ( "filename" -- )
+   writing
+   /flash  0  do
+      i .x (cr
+      flash-buf  i +  /chunk i  flash-read
+   /chunk +loop
+   flash-buf  /flash  ofd @ fputs
+   ofd @ fclose
+;
+
+: verify  ( -- )  ?file  flash-buf  /flash  0  verify-flash-range  ;
+
+: verify-firmware  ( -- )
+   flash-buf  /flash  0  verify-flash-range     \ Verify first part
+;
+
+: write-firmware   ( -- )
+   flash-buf  /flash 0  write-flash-range      \ Write first part
+;
+
+: reflash   ( -- )   \ Flash from data already in memory
+   ?file
+   flash-write-enable
+
+   write-firmware
+
+   ['] verify-firmware catch  if
+      ." Verify failed.  Retrying once"  cr
+      spi-identify
+      write-firmware
+      verify-firmware
+   then
+   flash-write-disable
+;
+
+defer fw-filename$  ' null$ to fw-filename$
+
+: get-file  ( ["filename"] -- )
+   parse-word   ( adr len )
+   dup 0=  if  2drop fw-filename$  then  ( adr len )
+   ." Reading " 2dup type cr                     ( adr len )
+   $get-file
+;
+
+: flash  ( ["filename"] -- )  get-file ?enough-power reflash  ;
+: flash! ( ["filename"] -- )  get-file reflash  ;
+
+: safe-flash-read  ( -- )
+   flash-buf  /flash  0 flash-read
+;
+
+dev /flash
+: selftest  ( -- error? )
+   .cbfs
+;
+device-end
+
+\ LICENSE_BEGIN
+\ Copyright (c) 2011 FirmWorks
+\ 
+\ Permission is hereby granted, free of charge, to any person obtaining
+\ a copy of this software and associated documentation files (the
+\ "Software"), to deal in the Software without restriction, including
+\ without limitation the rights to use, copy, modify, merge, publish,
+\ distribute, sublicense, and/or sell copies of the Software, and to
+\ permit persons to whom the Software is furnished to do so, subject to
+\ the following conditions:
+\ 
+\ The above copyright notice and this permission notice shall be
+\ included in all copies or substantial portions of the Software.
+\ 
+\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+\
+\ LICENSE_END

Added: dev/intel/spi.fth
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dev/intel/spi.fth	Tue Aug  9 06:26:34 2011	(r2432)
@@ -0,0 +1,258 @@
+\ See license at end of file
+purpose: Driver for SPI FLASH chips connected via Intel NM10 SPI interface
+
+h# fed1f020 value spi-base
+: spi-reg-b!  ( b offset -- )  spi-base + c!  ;
+: spi-reg-w!  ( w offset -- )  spi-base + w!  ;
+: spi-reg-l!  ( l offset -- )  spi-base + l!  ;
+: spi-reg-b@  ( offset -- b )  spi-base + c@  ;
+: spi-reg-w@  ( offset -- w )  spi-base + w@  ;
+: spi-reg-l@  ( offset -- l )  spi-base + l@  ;
+
+: spi-data     ( -- adr )  spi-base 8 +  ;
+
+: spi-stat@   ( -- w )  0 spi-reg-w@  ;
+: spi-stat!   ( w -- )  0 spi-reg-w!  ;
+: spi-ctrl!   ( w -- )  2 spi-reg-w!  ;
+: spi-addr!   ( l -- )  4 spi-reg-l!  ;
+: spi-prefix!  ( n -- )  h# 54 spi-reg-w!  ;
+: spi-type!  ( n -- )  h# 56 spi-reg-w!  ;
+: spi-opcode!  ( b opcode# -- )  h# 58 + spi-reg-b!  ;
+
+d# 64 constant max-spi-data
+
+
+\ Commands
+\ # t DCOA P Op 
+\ 0 0 4102    5 <no address> <1 data in>  read-status
+\ 1 2 4n12    3 <ADDR>       <N data in>  read
+\ 2 0 4322   9f <no address> <3 data in>  jedec-id
+\ 3 2 4232   90 <ADDR=0>     <2 data in>  90-id
+\ 4 2 4142   ab <ADDR=0>     <1 data in>  ab-id
+\ 5 1 4156 6  1 <no address> <1 data out> write-status
+\ 6 3 4n66 6  2 <ADDR>       <N data out> write
+\ 7 3 0076 6 d8 <ADDR>       <no data>    erase-block
+
+4 base ! 33122020 hex constant cycle-types
+: intel-spi-start  ( -- )
+   h# 0406 spi-prefix!  \ Prefix 0 is write-enable, 1 is write-disable
+   h# d80201ab h# 5c spi-reg-l!  \ opcodes 7-4
+   h# 909f0305 h# 58 spi-reg-l!  \ opcodes 3-0
+   cycle-types h# 56 spi-reg-w!
+   h# 0c spi-stat!
+;
+: spi-do-cmd  ( code -- )
+   begin  spi-stat@ 1 and  0=  until
+   spi-ctrl!
+   begin  spi-stat@ 4 and  until
+   4 spi-stat!
+;
+: spi-read-status  ( -- b )
+   h# 4002 spi-do-cmd
+   spi-data c@
+;
+: wait-write-done  ( -- )
+   d# 100000 0  do
+      spi-read-status 1 and 0=  if  unloop exit  then
+      d# 10 us
+   loop
+;
+: spi-read-n  ( adr len offset -- )
+   spi-addr!                               ( adr len )
+   dup 1- 8 lshift h# 4012 or  spi-do-cmd  ( adr len )
+   spi-data -rot move                      ( )
+;
+: jedec-id  ( -- b3b2b1 )
+   h# 4222 spi-do-cmd
+   spi-data w@  spi-data 2+ c@  wljoin
+;
+: 90-id  ( -- b2b1 )
+   0 spi-addr!
+   h# 4132 spi-do-cmd
+   spi-data w@
+;
+: ab-id  ( -- b1 )
+   0 spi-addr!
+   h# 4042 spi-do-cmd
+   spi-data c@
+;
+: spi-write-status  ( b -- )
+   spi-data c!         ( )
+   h# 4056 spi-do-cmd  ( )
+   wait-write-done     ( )
+;
+: spi-write-n  ( adr len offset -- )
+   spi-addr!            ( adr len )
+   tuck                 ( len adr len )
+   spi-data swap move   ( len )
+   1- 8 lshift h# 4066 or spi-do-cmd  ( )
+   wait-write-done                    ( )
+;
+: erase-spi-block  ( offset -- )
+   spi-addr!           ( )
+   h# 0076 spi-do-cmd  ( )
+   wait-write-done     ( )
+;
+
+\ Write within one SPI FLASH page.  Offset + len must not cross a page boundary
+
+: write-spi-page  ( adr len offset -- )
+   begin  over  while               ( adr len offset )
+      over max-spi-data min >r      ( adr len offset  r: this )
+      2 pick r@ 2 pick  spi-write-n ( adr len offset  r: this )
+      rot r@ +  rot r@ -  rot r> +  ( adr' len' offset' )
+   repeat                           ( adr len offset )
+   3drop                            ( )
+;
+
+: read-spi-flash  ( adr len offset -- )
+   begin  over  while               ( adr len offset )
+      over max-spi-data min >r      ( adr len offset  r: this )
+      2 pick r@ 2 pick  spi-read-n  ( adr len offset  r: this )
+      rot r@ +  rot r@ -  rot r> +  ( adr' len' offset' )
+   repeat                           ( adr len offset )
+   3drop                            ( )
+;
+
+\ Verify the contents of SPI FLASH starting at offset against
+\ the memory range adr,len .  Aborts with a message on mismatch.
+
+: verify-spi-flash  ( adr len offset -- mismatch? )
+   over alloc-mem >r                  ( adr len offset r: temp-adr )
+   r@  2 pick  rot                    ( adr len temp-adr len offset r: temp-adr )
+   flash-read                         ( adr len r: temp-adr )
+   tuck  r@ swap comp                 ( len mismatch? r: temp-adr )
+   r> rot free-mem                    ( mismatch? )
+;
+
+h# 10000 constant /spi-eblock   \ Smallest erase block common to all chips
+h#   100 constant /spi-page     \ Largest write for page-oriented chips
+
+\ Figures out how many bytes can be written in one transaction,
+\ subject to not crossing a 256-byte page boundary.
+
+: left-in-page  ( len offset -- len offset #left )
+   \ Determine how many bytes are left in the page containing offset
+   /spi-page  over /spi-page 1- and -      ( adr len offset left-in-page )
+
+   \ Determine the number of bytes to write in this transaction
+   2 pick  min                  ( adr len offset r: #to-write )
+;
+
+\ Adjust address, length, and write offset by the number of
+\ bytes transferred in the last action
+
+: adjust  ( adr len offset #transferred -- adr+ len- offset+ )
+   tuck +  >r  /string  r>
+;
+
+\ Determine if it's worthwhile to write; writing FF's is pointless
+: non-blank?  ( adr len -- non-blank? )  h# ff bskip 0<>  ;
+
+\ Write as many bytes as can be done in one operation, limited
+\ by page boundaries, and adjust the parameters to reflect the
+\ data that was written.  If the data that would be written is
+\ all FFs, save time by not actually writing it.
+
+: write-spi-some  ( adr len offset -- adr' len' offset' )
+   left-in-page                    ( adr len offset #to-write )
+
+   3 pick  over  non-blank?  if    ( adr len offset #to-write )
+      3 pick  over  3 pick         ( adr len offset #to-write  adr #to-write offset )
+      write-spi-page               ( adr len offset #to-write )
+   then                            ( adr len offset #to-write )
+
+   adjust                          ( adr' len' offset' )
+;
+
+\ Write data from the range adr,len to SPI FLASH beginning at offset
+\ Does not erase automatically; you have to do that beforehand.
+
+\ This version works for parts that support page writes with
+\ multiple data bytes after command 2
+
+: write-spi-flash  ( adr len offset -- )
+   begin  over  while    ( adr len offset )
+      write-spi-some     ( adr' len' offset' )
+   repeat                ( adr 0 offset )
+   3drop
+;
+
+\ Get the SPI FLASH ID and decode it to the extent that we need.
+\ There are several different commands to get ID information,
+\ and the various SPI FLASH chips support different subsets of
+\ those commands.  The AB command seems to be supported by all
+\ of them, so it's a good starting point.
+
+0 value spi-id#
+: spi-identify  ( -- )
+   ab-id to spi-id#
+   spi-id# case
+      h# 13  of  endof
+      h# 15  of  endof
+      h# 34  of  endof
+      ( default )  true abort" Unsupported SPI FLASH ID"
+   endcase
+   0 spi-write-status  \ Turn off write protect bits
+;
+
+\ Display a message telling what kind of part was found
+
+: .spi-id  ( -- )
+   ." SPI FLASH is "
+   spi-id#  case
+      h# 13  of  ." type 13 - Spansion, Winbond, or ST"  endof
+      h# 15  of  ." type 15 - Macronyx"  endof
+      h# 34  of  ." type 34 - Macronyx"  endof
+   endcase
+;
+
+: spi-flash-open  ( -- )
+   \ One retry
+   spi-start  ['] spi-identify catch  if
+      spi-start  spi-identify
+   then
+;
+: spi-flash-write-enable  ( -- )  flash-open  .spi-id cr  ;
+
+: use-spi-flash-read  ( -- )  ['] read-spi-flash to flash-read  ;
+
+\ Install the SPI FLASH versions as their implementations.
+: use-spi-flash  ( -- )
+   ['] spi-flash-open          to flash-open
+   ['] noop                    to flash-close
+   ['] spi-flash-write-enable  to flash-write-enable
+   ['] noop                    to flash-write-disable
+   ['] write-spi-flash         to flash-write
+   ['] verify-spi-flash        to flash-verify
+   ['] erase-spi-block         to flash-erase-block
+   use-mem-flash-read          \ Might be overridden
+   h# 40.0000  to /flash
+   /spi-eblock to /flash-block
+;
+use-spi-flash
+' intel-spi-start to spi-start
+
+\ LICENSE_BEGIN
+\ Copyright (c) 2011 FirmWorks
+\ 
+\ Permission is hereby granted, free of charge, to any person obtaining
+\ a copy of this software and associated documentation files (the
+\ "Software"), to deal in the Software without restriction, including
+\ without limitation the rights to use, copy, modify, merge, publish,
+\ distribute, sublicense, and/or sell copies of the Software, and to
+\ permit persons to whom the Software is furnished to do so, subject to
+\ the following conditions:
+\ 
+\ The above copyright notice and this permission notice shall be
+\ included in all copies or substantial portions of the Software.
+\ 
+\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+\
+\ LICENSE_END

Modified: dev/olpc/spiflash/spiflash.fth
==============================================================================
--- dev/olpc/spiflash/spiflash.fth	Tue Aug  9 06:25:40 2011	(r2431)
+++ dev/olpc/spiflash/spiflash.fth	Tue Aug  9 06:26:34 2011	(r2432)
@@ -64,7 +64,7 @@
 \ You have to wait after any command that modifies stuff
 \ inside the part - writes, erases, status register writes
 
-: wait-write-done  ( -- timeout? )
+: wait-write-done  ( -- )
    \ The Spansion part's datasheet claims that the only operation
    \ that takes longer than 500mS is bulk erase and we don't ever
    \ want to use that command
@@ -73,7 +73,6 @@
       spi-read-status 1 and 0=  if  unloop exit  then  \ Test WIP bit
       d# 10 us
    loop
-   -1
 ;
 
 \ Common start sequence for writes and erases - anything that

Modified: ofw/fs/cbfs.fth
==============================================================================
--- ofw/fs/cbfs.fth	Tue Aug  9 06:25:40 2011	(r2431)
+++ ofw/fs/cbfs.fth	Tue Aug  9 06:26:34 2011	(r2432)
@@ -1,7 +1,6 @@
 purpose: Coreboot filesystem ("CBFS") package
 \ See license at end of file
 
-h# ffc0.0000 value flash-base
 : .cbfs-type  ( type -- )
    case
       h#  10 of  ."        stage"  endof



More information about the openfirmware mailing list