[openfirmware] r881 - cpu/x86/pc/neptune dev

svn at openfirmware.info svn at openfirmware.info
Wed Aug 13 23:37:37 CEST 2008


Author: wmb
Date: 2008-08-13 23:37:36 +0200 (Wed, 13 Aug 2008)
New Revision: 881

Modified:
   cpu/x86/pc/neptune/addrs.fth
   cpu/x86/pc/neptune/config.fth
   cpu/x86/pc/neptune/devices.fth
   cpu/x86/pc/neptune/fw.bth
   cpu/x86/pc/neptune/romreset.bth
   dev/flashui.fth
   dev/flashwritepkg.fth
   dev/lpcflash.fth
Log:
Neptune - FLASH reprogramming user interface and enabled configuration variable saving.






Modified: cpu/x86/pc/neptune/addrs.fth
===================================================================
--- cpu/x86/pc/neptune/addrs.fth	2008-08-13 10:13:36 UTC (rev 880)
+++ cpu/x86/pc/neptune/addrs.fth	2008-08-13 21:37:36 UTC (rev 881)
@@ -4,12 +4,18 @@
 h# fff0.0000   constant rom-pa		\ Physical address of boot ROM
 h#   10.0000   constant /rom		\ Size of boot ROM
 
+h#    0.0000   constant config-vars-offset
 h#    8.0000   constant dropin-offset
 rom-pa dropin-offset +  constant dropin-base
 h#    8.0000   constant dropin-size
 
 dropin-base h# 20 +  constant ResetBase	\ Location of "reset" dropin in ROM
 
+\ Firmware reflash parameters
+h# 8.0000 constant fw-offset       \ Where to start reflashing
+h# 8.0000 constant /fw-reflash     \ Expected size of a reflash image
+h#    -30 constant fw-crc-offset   \ Location of firmware CRC (- is from end)
+
 h#  1c0.0000 constant fw-pa
 h#   20.0000 constant /fw-ram
 

Modified: cpu/x86/pc/neptune/config.fth
===================================================================
--- cpu/x86/pc/neptune/config.fth	2008-08-13 10:13:36 UTC (rev 880)
+++ cpu/x86/pc/neptune/config.fth	2008-08-13 21:37:36 UTC (rev 881)
@@ -51,8 +51,8 @@
 \ create use-ega
 \ create save-msrs
 
-create use-null-nvram  \ Don't store configuration variables
-\ create use-flash-nvram  \ Store configuration variables in firmware FLASH
+\ create use-null-nvram  \ Don't store configuration variables
+create use-flash-nvram  \ Store configuration variables in firmware FLASH
 
 fload ${BP}/cpu/x86/pc/neptune/addrs.fth
 

Modified: cpu/x86/pc/neptune/devices.fth
===================================================================
--- cpu/x86/pc/neptune/devices.fth	2008-08-13 10:13:36 UTC (rev 880)
+++ cpu/x86/pc/neptune/devices.fth	2008-08-13 21:37:36 UTC (rev 881)
@@ -79,16 +79,50 @@
 ;
 warning !
 
+\ Create the secondary FLASH node.  This device exists only when an external
+\ card is attached to the board.  It is used for initial programming of
+\ the primary FLASH, by swapping the ID selects for the internal and external
+\ FLASH chips.  The external FLASH appears as the primary boot FLASH (fff00000)
+\ and the internal one as the secondary (ffe00000).  In normal operation,
+\ the internal FLASH is primary (fff00000) and the secondary doesn't exist.
+
+\ We define the secondary node first so that "/flash" will refer to the primary
+\ (pathname matching finds the most recent match first).
+
+0 0  " ffe00000"  " /" begin-package
+   " flash" device-name
+
+   h# 10.0000 constant /device
+   h#  1.0000 constant /block
+   h#    1000 constant /sector
+   my-address my-space /device reg
+
+   h# 40.0000 negate  constant regs-offset
+
+   : write-enable  ( -- )
+      h# 1808 rdmsr  h# ff.ffff and  h# 2100.0000 or  h# 1808 wrmsr
+   ;
+   : write-disable  ( -- )
+      h# 1808 rdmsr  h# ff.ffff and  h# 2500.0000 or  h# 1808 wrmsr
+   ;
+
+   fload ${BP}/dev/flashpkg.fth
+   fload ${BP}/dev/lpcflash.fth
+   fload ${BP}/dev/flashwritepkg.fth
+end-package
+
 \ Create the top-level device node to access the entire boot FLASH device
 0 0  " fff00000"  " /" begin-package
    " flash" device-name
 
    h# 10.0000 value /device
+   my-address my-space /device reg
+
    h# 10.0000 constant /device-phys
-   my-address my-space /device-phys reg
+   h#  1.0000 constant /block
+   h#    1000 constant /sector
 
    h# 40.0000 negate constant regs-offset
-   h#  1.0000 value block-size
 
    : write-enable  ( -- )
       h# 1808 rdmsr  h# ff.ffff and  h# 2100.0000 or  h# 1808 wrmsr
@@ -106,7 +140,7 @@
 
 \ Create a node below the top-level FLASH node to accessing the portion
 \ containing the dropin modules
-0 0   dropin-offset <# u#s u#>   " /flash" begin-package
+0 0   dropin-offset <# u#s u#>   " flash" begin-package
    " dropins" device-name
 
    dropin-size constant /device
@@ -121,29 +155,6 @@
 \ This devalias lets us say, for example, "dir rom:"
 devalias rom     /dropin-fs
 
-\ Create the top-level device node to access the entire boot FLASH device
-0 0  " ffe00000"  " /" begin-package
-   " flash" device-name
-
-   h# 10.0000 value /device
-   h# 10.0000 constant /device-phys
-   my-address my-space /device-phys reg
-   h#  1.0000 value block-size
-
-   h# 40.0000 negate  constant regs-offset
-
-   : write-enable  ( -- )
-      h# 1808 rdmsr  h# ff.ffff and  h# 2100.0000 or  h# 1808 wrmsr
-   ;
-   : write-disable  ( -- )
-      h# 1808 rdmsr  h# ff.ffff and  h# 2500.0000 or  h# 1808 wrmsr
-   ;
-
-   fload ${BP}/dev/flashpkg.fth
-   fload ${BP}/dev/lpcflash.fth
-   fload ${BP}/dev/flashwritepkg.fth
-end-package
-
 fload ${BP}/cpu/x86/forthint.fth	\ Low-level interrupt handling code
 fload ${BP}/dev/isa/irq.fth		\ ISA interrupt dispatcher
 fload ${BP}/cpu/x86/pc/isatick.fth	        \ Use ISA timer as the alarm tick timer
@@ -218,10 +229,10 @@
 
 \ Create a node below the top-level FLASH node to access the portion
 \ containing the configuration variables.
-0 0  " d0000"  " /flash" begin-package
+0 0  config-vars-offset <# u#s u#>  " flash" begin-package
    " nvram" device-name
 
-   h# 10000 constant /device
+   h# 1000 constant /device      \ 4K - SST49LF080A sector size
    fload ${BP}/dev/subrange.fth
 end-package
 

Modified: cpu/x86/pc/neptune/fw.bth
===================================================================
--- cpu/x86/pc/neptune/fw.bth	2008-08-13 10:13:36 UTC (rev 880)
+++ cpu/x86/pc/neptune/fw.bth	2008-08-13 21:37:36 UTC (rev 881)
@@ -422,6 +422,28 @@
 
 fload ${BP}/dev/flashui.fth
 
+\ Copies internal flash to external - everything, including config vars
+: clone-flash  ( -- )
+   " /flash at fff00000" open-dev >r
+   load-base /rom  " read" r@  $call-method drop
+   r> close-dev
+
+   " devalias flash /flash at ffe00000" evaluate
+   load-base /rom  0  ($reflash)
+   " devalias flash /flash at fff00000" evaluate
+;
+
+: clone-firmware  ( -- )
+   " /flash at fff00000" open-dev >r
+   fw-offset u>d          " seek" r@  $call-method drop
+   load-base /fw-reflash  " read" r@  $call-method drop
+   r> close-dev
+
+   " devalias flash /flash at ffe00000" evaluate
+   load-base /fw-reflash  $reflash
+   " devalias flash /flash at fff00000" evaluate
+;
+
 : vme ( -- )
 	." Running Lattice programmer "
 	com1 io

Modified: cpu/x86/pc/neptune/romreset.bth
===================================================================
--- cpu/x86/pc/neptune/romreset.bth	2008-08-13 10:13:36 UTC (rev 880)
+++ cpu/x86/pc/neptune/romreset.bth	2008-08-13 21:37:36 UTC (rev 881)
@@ -97,8 +97,7 @@
    \ sdram_initialize,generic_sdram.c
    \ sdram_set_spdregisters(),auto.c
  
-   \ The LX devel board has only 512M ROM, but assigning 1M of address space is harmless
-   25fff002.10f80000.      1808 set-msr  \ 1M ROM at fff0.0000, system RAM limit at 0f80.0000
+   25ffe002.10f80000.      1808 set-msr  \ 2M ROM at ffe0.0000, system RAM limit at 0f80.0000
    20000000.000fff00.  10000020 set-msr  \ memory - 0..fffff
    2000000f.7ff00100.  10000028 set-msr  \ Top of memory at 0f7f.ffff
    212800fd.7fffd000.  10000029 set-msr  \ Range Offset - Frame buffer at PA fd00.0000 maps to RAM at 0f80.0000

Modified: dev/flashui.fth
===================================================================
--- dev/flashui.fth	2008-08-13 10:13:36 UTC (rev 880)
+++ dev/flashui.fth	2008-08-13 21:37:36 UTC (rev 881)
@@ -1,38 +1,29 @@
 purpose: Simple FLASH write user interface, calling flash node methods
 \ See license at end of file.
 
-[ifndef] reflash
-0 value flash-buf
-0 value /flash
-0 value /flash-block
-
-\ Simple UI for reflashing, assuming that you want to overwrite
-\ the entire FLASH contents.  That's not always a good assumption;
+\ Simple UI for reflashing.  That's not always a good assumption;
 \ some systems use certain FLASH blocks for persistent data like
 \ configuration variables or manufacturing data ("Vital Product Data").
 
-0 value file-loaded?
-
-: ?image-valid   ( len -- )
-   /flash <> abort" Image file is the wrong length"
-;
-
 0 value flash-ih
+0 value /flash-block
 
 : $call-flash  ( ??? -- ??? )  flash-ih $call-method  ;
 : close-flash  ( -- )
    flash-ih  if
       flash-ih close-dev
       0 to flash-ih
-      flash-buf /flash free-mem
    then
 ;
 
-: ?open-flash  ( -- )
+: open-flash  ( -- )
    flash-ih  if  exit  then
 
    " flash" open-dev to flash-ih
-   flash-ih 0=  abort" Can't open FLASH device"
+   flash-ih 0=  if
+      close-flash
+      true abort" Can't open FLASH device"
+   then
 
    " writable?"  $call-flash  0=  if
       close-flash
@@ -40,56 +31,88 @@
    then
 
    " block-size" $call-flash  to /flash-block
-   " size"       $call-flash  drop  to /flash
-   /flash alloc-mem to flash-buf
 ;
 
-: $get-flash-file  ( "filename" -- )
-   $read-open
-   flash-buf  /flash  ifd @ fgets   ( len )
-   ifd @ fclose
+: crc  ( adr len -- crc )  0 crctab  2swap ($crc)  ;
 
-   ?image-valid
+: ?crc  ( adr len -- )
+   fw-crc-offset -1 =  if  2drop exit  then   \ -1 means don't check
 
-   true to file-loaded?
+   ." Checking integrity ..." cr
+
+   \ Negative offsets are from the end
+   fw-crc-offset 0<  if  2dup +  else  over  then   ( adr len crc-base )
+   fw-crc-offset +                                  ( crc-adr )
+
+   dup l@  >r                        ( adr len crc-adr r: crc )
+   -1 over l!                        ( adr len crc-adr r: crc )
+
+   -rot  crc                         ( crc-adr calc-crc r: crc )
+   r@ rot l!                         ( calc-crc r: crc )
+   r> <>  if
+      true abort" Firmware image has bad internal CRC"
+   then
 ;
 
-: ?file  ( -- )
-   file-loaded?  0=  if
-      ." You must first load a valid FLASH image file with" cr
-      ."    get-file filename" cr
-      abort
+: ?image-valid   ( adr len -- )
+   dup /fw-reflash <>  if
+      true abort" Firmware image length is wrong"
    then
+   ?crc
 ;
 
-: reflash   ( -- )   \ Flash from data already in memory
-   ?open-flash
-   ?file
+\ No error checking so you can override the standard parameters
+: ($reflash)  ( adr len offset -- )
+   open-flash                                 ( adr len offset )
 
-   ." Writing" cr
+   tuck  u>d  " seek" $call-flash drop        ( adr offset len )
 
-   /flash  0  ?do
-      (cr i .
-      flash-buf i +  /flash-block  i  " flash-write" $call-flash  ( )
-   /flash-block +loop
+   ." Writing" cr                             ( adr offset len )
 
+   0  ?do                                     ( adr offset )
+      (cr dup i + .x                          ( adr offset )
+      over i +  /flash-block                  ( adr offset adr' len )
+      " write" $call-flash drop               ( adr offset )
+   /flash-block +loop                         ( adr offset )
+   2drop                                      ( )
+
    close-flash
 ;
 
-\ Set this defer word to return a string naming the default
-\ filename for firmware updates
-defer fw-filename$  ' null$ to fw-filename$
+: $reflash   ( adr len -- )   \ Flash from data already in memory
+   2dup ?image-valid
+   fw-offset ($reflash)
+;
 
-: get-flash-file  ( ["filename"] -- )
-   ?open-flash
-   parse-word   ( adr len )
-   dup 0=  if  2drop fw-filename$  then  ( adr len )
-   ." Reading " 2dup type cr                     ( adr len )
-   $get-flash-file
+0 value flash-buf
+
+: get-flash-file  ( "filename" -- adr len )
+   safe-parse-word                       ( filename$ )
+   ." Reading " 2dup type cr             ( filename$ )
+   $read-open                            ( )
+   ifd @ fsize  /fw-reflash <>  if       ( )
+      ifd @ fclose
+      true abort" Firmware image file size is wrong"
+   then                                  ( )
+
+   /fw-reflash alloc-mem to flash-buf    ( )
+
+   flash-buf  /fw-reflash  ifd @ fgets   ( len )
+   ifd @ fclose                          ( )
+   /fw-reflash <>  if
+      flash-buf /fw-reflash free-mem
+      true abort" Firmware image read failure"
+   then
+
+   flash-buf /fw-reflash                 ( adr len )
 ;
 
-: flash  ( ["filename"] -- )  get-flash-file reflash  ;
-[then]
+: flash  ( "filename" -- )
+   get-flash-file                  ( adr len )
+   ['] $reflash catch              ( false | x x throw-code )
+   flash-buf /fw-reflash free-mem  ( false | x x throw-code )
+   throw
+;
 
 
 \ LICENSE_BEGIN

Modified: dev/flashwritepkg.fth
===================================================================
--- dev/flashwritepkg.fth	2008-08-13 10:13:36 UTC (rev 880)
+++ dev/flashwritepkg.fth	2008-08-13 21:37:36 UTC (rev 881)
@@ -23,9 +23,27 @@
 \   Otherwise, copy the existing contents of the erase unit to a buffer,
 \   merge in the new data, erase, then write back the buffer.
 
-: left-in-block  ( len offset -- #left )
+0 instance value /chunk
+
+: set-chunk-size  ( len -- )
+   dup /device =  if                           ( len )
+      seek-ptr 0=  if  to /chunk  exit  then   ( len )
+   then                                        ( len )
+   /block >=  if  /block  else  /sector  then  to /chunk
+;
+
+: erase-chunk  ( offset -- )
+   /chunk case                  ( offset )
+      /sector  of  erase-sector     endof
+      /block   of  erase-block      endof
+      /device  of  drop erase-chip  endof
+      true abort" flashwritepkg: Internal error - bad value for /chunk"
+   endcase
+;
+
+: left-in-chunk  ( len offset -- #left )
    \ Determine how many bytes are left in the page containing offset
-   block-size  swap block-size 1- and -  ( len left-in-page )
+   /chunk  swap /chunk 1- and -  ( len left-in-page )
    min                                   ( #left )
 ;
 
@@ -42,37 +60,37 @@
 ;
 
 : erase+write  ( adr len -- )
-   dup block-size =  if
+   dup /chunk =  if                         ( adr len )
       \ If we are going to overwrite the entire block, there's no need to
       \ preserve the old data.  This can only happen if we are already
       \ aligned on an erase block boundary.
-      seek-ptr erase-block           ( adr len )
-      seek-ptr flash-write                 ( )
+      seek-ptr erase-chunk                  ( adr len )
+      seek-ptr flash-write                  ( )
    else
       \ Allocate a buffer to save the old block contents
-      block-size alloc-mem  >r                  ( adr len )
+      /chunk alloc-mem  >r                  ( adr len )
 
-      seek-ptr block-size round-down            ( adr len block-start )
+      seek-ptr /chunk round-down            ( adr len block-start )
 
       \ Copy existing data from FLASH block to the buffer
-      dup device-base +  r@  block-size lmove   ( adr len block-start )
+      dup device-base +  r@  /chunk lmove   ( adr len block-start )
 
       \ Merge new bytes into the buffer
-      -rot                                      ( block-start adr len )
-      seek-ptr block-size mod                   ( block-start adr len buf-offset )
-      r@ +  swap move                           ( block-start )
+      -rot                                  ( block-start adr len )
+      seek-ptr /chunk mod                   ( block-start adr len buf-offset )
+      r@ +  swap move                       ( block-start )
 
       \ Erase the block and rewrite it from the buffer
-      dup  erase-block                          ( block-start )
-      r@  block-size  rot  flash-write          ( )
+      dup  erase-chunk                      ( block-start )
+      r@  /chunk  rot  flash-write          ( )
 
       \ Release the buffer
-      r> block-size free-mem
+      r> /chunk free-mem
    then
 ;
 
 : handle-block  ( adr len -- adr' len' )
-   dup seek-ptr left-in-block         ( adr len #left )
+   dup seek-ptr left-in-chunk         ( adr len #left )
    >r                                 ( adr len r: #left )
    over r@ must-erase?  if            ( adr len r: #left )
       over r@ erase+write             ( adr len r: #left )
@@ -85,6 +103,7 @@
 
 : write  ( adr len -- #written )
    writable?  0=  if  2drop 0 exit  then
+   dup set-chunk-size                         ( adr len )
    tuck                                       ( len adr len )
    begin  dup  while  handle-block  repeat    ( len adr' remain' )
    2drop                                      ( len )

Modified: dev/lpcflash.fth
===================================================================
--- dev/lpcflash.fth	2008-08-13 10:13:36 UTC (rev 880)
+++ dev/lpcflash.fth	2008-08-13 21:37:36 UTC (rev 881)
@@ -1,11 +1,20 @@
 purpose: LPC/FWH FLASH low-level write words for use inside a device node
 \ See license at end of file.
 
-\ write-enable and write-disable need to be defined externally
-\ Typically you load flashpkg.fth before and flashwritepkg.fth after this
+\ Typically this file is loaded between flashpkg.fth and flashwritepkg.fth
 
 0 instance value regs-adr
 
+\ The "register space" for an LPC FLASH device is a different address bank,
+\ typically differing by the value of A22.  In some devices there are only
+\ two registers (chip ID and GPIO), while other devices have write lock
+\ registers scattered throughout a large (e.g. 1 MB) address space.
+
+: map-regs  ( -- )
+   regs-adr  if  exit  then
+   my-address my-space regs-offset +  /device  " map-in" $call-parent  to regs-adr
+;
+
 : unmap-regs  ( -- )
    regs-adr  if
       regs-adr /device " map-out" $call-parent
@@ -14,13 +23,45 @@
    then
 ;
 
+\ This tests for the presence of an LPC/FWH FLASH device by trying to
+\ read its ID register.  You can't tell by reading the FLASH data because
+\ an erased device is indistinguishable from a device that's not there.
+\ ROM emulators that can't be written via the LPC bus will show up as
+\ "not present" (unless they emulate the ID register).
+
+: (present?)  ( -- flag )
+   regs-adr h# c.0000 +  c@  ( id0 )
+
+   dup 0<>  swap h# ff <>  and   ( id-present? )
+;
+
+\ Test for device presence, leaving register space in the same state
+\ (mapped or not) as before.  This is intended for use as an "early
+\ probe" to see if the device is there.
+
+: present?  ( -- flag )
+   regs-adr  if
+      (present?)
+   else
+      map-regs  (present?)  unmap-regs
+   then   
+;
+
+\ Test for device presence (and thus the ability to write), leaving
+\ register space mapped and the device write-enabled if the device is
+\ indeed present.  This intended for use in preparation for a sequence
+\ of write operations.  When the sequence is finished, closing the
+\ device instance will unmap the registers and write-disable .
+
 : writable?  ( -- flag )
+   \ This is an optimization so writable? can be called multiple times
+   \ quickly.  Theres is no point in leaving register space mapped if
+   \ there are no registers.
    regs-adr  if  true exit  then
 
-   my-address my-space regs-offset +  /device  " map-in" $call-parent  to regs-adr
-   regs-adr h# c.0000 +  c@  ( id0 )
+   map-regs
 
-   dup 0<>  swap h# ff <>  and   ( writable? )
+   (present?)
 
    dup  if  write-enable  else  unmap-regs  then
 ;
@@ -32,7 +73,11 @@
 : >lpc-adr  ( offset -- )  device-base +  ;
 : jedec!  ( byte -- )  h# 5555 >lpc-adr  c!  ;
 
-\ The write enable for the block at fffx.0000 is at ffbx.0002
+\ Some, but not all, devices have block-granularity software locking via
+\ register-space addresses.  For example, SST49LF008A (FWH version) has
+\ software locking, while SST47LF080A (LPC version) does not.  Writing
+\ the lock register addresses is innocuous on the ones without locking.
+
 : write-enable-block  ( offset -- )
    h# ffff invert and  2  or         ( we-offset )
    regs-adr +   0 swap c!
@@ -53,10 +98,21 @@
    begin  device-base c@ tuck  =  until  ( value )
    drop
 ;
+: erase-sector  ( offset -- )
+   dup write-enable-block
+   write-setup   h# 80 jedec!
+   write-setup   h# 30 swap >lpc-adr c!
+   wait-toggle
+;
 : erase-block  ( offset -- )
    dup write-enable-block
    write-setup   h# 80 jedec!
    write-setup   h# 50 swap >lpc-adr c!
+   wait-toggle 
+;
+: erase-chip  ( -- )
+   write-setup   h# 80 jedec!
+   write-setup   h# 10 jedec!
    wait-toggle
 ;
 
@@ -78,6 +134,7 @@
    dup erase-block       ( adr len offset )
    flash-write
 ;
+: block-size  ( -- u )  /block  ;
 
 \ LICENSE_BEGIN
 \ Copyright (c) 2008 FirmWorks




More information about the openfirmware mailing list