[openfirmware] [commit] r3743 - cpu/x86/pc/olpc/via/Notes
repository service
svn at openfirmware.info
Fri Oct 31 06:29:39 CET 2014
Author: quozl
Date: Fri Oct 31 06:29:38 2014
New Revision: 3743
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/3743
Log:
OLPC XO-4 - add EC recovery
Added:
cpu/x86/pc/olpc/via/Notes/fix-ec-4.fth
Added: cpu/x86/pc/olpc/via/Notes/fix-ec-4.fth
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ cpu/x86/pc/olpc/via/Notes/fix-ec-4.fth Fri Oct 31 06:29:38 2014 (r3743)
@@ -0,0 +1,542 @@
+purpose: Recover EC FLASH on XO-4 using cable from XO-1.5
+
+\ HOWTO USE THIS
+\ Put this file and an EC image (60416 bytes) on a USB stick, insert into XO-1.5
+\ Connect 6-pin programming cable from XO-1.5 recovery driver port (J3) to
+\ XO-4 EDI "REFLASH EC HEADER" (J2)
+\ Power on XO-1.5
+\ Power on XO-4
+\ ok fload u:\fix-ec-4.fth
+\ ok select /spi
+\ ok excavate-ec u:\old.bin
+\ ok recover-ec u:\new.bin
+
+dev /spi
+
+\ from cpu/arm/olpc/4.0/config.fth
+h# ec00 constant /ec-flash
+char 7 constant expected-ec-version
+h# eb80 constant ec-flags-offset
+
+: pio16mhz ( -- )
+ h# 01 h# 6c spi-b! \ 33/(2*1) MHz
+ h# 00 h# 6e spi-b! \ No special clocking
+ h# 08 h# 6d spi-b! \ Dynamic clock, PIO mode, command posted write off
+;
+: pio1.5mhz ( -- )
+ d# 11 h# 6c spi-b! \ 33/(2*11) = 1.5 MHz
+ h# 00 h# 6e spi-b! \ No special clocking
+ h# 08 h# 6d spi-b! \ Dynamic clock, PIO mode, command posted write off
+;
+
+: edi-go ( -- )
+ h# 802 spi-cmd! ( ) \ Set go bit
+ wait-done ( ) \ Wait for done bit
+ 0 spi-cmd! ( ) \ Clear go bit
+ \ The go bit must be cleared before clear-done, otherwise clear-done will not work
+ clear-done ( ) \ Clear done bit
+;
+
+variable access-count 0 access-count !
+variable out-ptr
+variable #in-bytes
+: spi-cs-on ( -- )
+\ access-count @ 1 = if pio8mhz 2 access-count ! then
+\ access-count @ 0= if pio1.5mhz 1 access-count ! then
+ 8 out-ptr ! 0 #in-bytes !
+;
+: spi-out ( b -- ) out-ptr @ spi-b! 1 out-ptr +! ;
+: spi-cs-off ( -- )
+ out-ptr @ 8 - ( #out-bytes )
+ dup 0= if drop exit then ( #out-bytes )
+ #in-bytes @ + 8 lshift 2 or spi-cmd!
+ wait-done
+ 0 spi-cmd!
+ clear-done
+;
+: spi-in ( -- b )
+ 1 #in-bytes !
+ spi-cs-off
+ out-ptr @ spi-b@
+ 8 out-ptr !
+;
+
+: edi-wait-b ( -- b )
+ 4 #in-bytes !
+ spi-cs-off
+ out-ptr @ #in-bytes @ bounds ?do
+ i spi-b@ h# 50 = if
+ i 1+ spi-b@ unloop exit
+ then
+ loop
+ true abort" Did not receive EDI data ready byte"
+;
+
+\ This cheats by assuming how long it takes for the data to return
+\ It's interesting as an example of how fast the hardware can go.
+: edi-really-fast-next-b@ ( -- b )
+ h# 33 8 spi-b!
+ h# 402 spi-cmd! wait-done
+ 0 spi-cmd!
+ clear-done
+ b spi-b@
+;
+
+
+\ *** Start of verbatim inclusion of edi.fth
+
+\ The following code depends on externally-provided low-level SPI bus
+\ access primitives that are defined in "bbedi.fth" for the "native"
+\ case (EC and CPU on the same machine). They can also be implemented
+\ for tethered programming from a different machine like an XO-1.5.
+\
+\ Low-level primitives:
+\ spi-start ( -- ) - Init SPI bus
+\ spi-cs-on ( -- ) - Assert SPI-bus CS#
+\ spi-cs-off ( -- ) - Deassert SPI-bus CS#
+\ spi-out ( byte -- ) - Send byte
+\ spi-in ( -- byte ) - Receive byte
+
+0 value edi-chip-id
+: kb9010? ( -- flag ) edi-chip-id 4 = ;
+
+: efcfg ( -- reg# ) kb9010? if h# fead else h# fea0 then ;
+: efcmd ( -- reg# ) kb9010? if h# feac else h# fea7 then ;
+: efdat ( -- reg# ) kb9010? if h# feab else h# feaa then ; \ io3731 has different read and write regs
+h# feab constant efdat-in
+: rst8051 ( -- reg# ) kb9010? if h# ff14 else h# f010 then ;
+: ecreboot ( -- reg# ) kb9010? if h# ff01 else h# f018 then ;
+\ Issues with .py code
+\ A14:A8 should be A15:A8 several places
+\ inconsistent use of handle vs gd.handle in edi_erase_chip
+
+\ KB9010 stuff...
+d# 59 d# 1024 * constant /kb9010-flash
+h# fe80 constant wdtcfg
+h# fe81 constant wdtpf
+h# fe82 constant wdt
+h# fea2 constant shccfg
+\ h# fea5 constant xbicfg \ Unused
+h# fea6 constant xbics
+\ h# feae constant efdatr \ Unused
+\ h# feaf constant emfburw
+h# feb2 constant xbiwp
+\ h# feb6 constant xbipump
+\ h# feb7 constant xbifm
+\ h# feb8 constant sbivr
+h# feb9 constant xbis
+h# ff0d constant clkcfg
+h# ff0f constant pllcfg
+h# ff1d constant ecsts
+h# ff1f constant pllcfg2
+h# ff14 constant pxcfg
+
+\ end KB9010 stuff...
+
+d# 128 constant /flash-page
+defer edi-progress ' 2drop to edi-progress ( offset size -- )
+
+: edi-cmd,adr ( offset cmd -- ) \ Send command plus 3 address bytes
+ spi-cs-on ( offset cmd )
+ spi-out ( offset )
+ lbsplit drop spi-out spi-out spi-out ( )
+;
+: edi-b! ( byte offset -- ) \ Write byte to address inside EC chip
+ h# 40 edi-cmd,adr spi-out spi-cs-off
+;
+[ifndef] edi-wait-b
+: edi-wait-b ( -- b ) \ Wait for and receive EC response byte
+ d# 100 0 do
+ spi-in ( d )
+ dup h# 5f <> if ( d )
+ dup h# 50 = if ( d )
+ drop
+ spi-in ( b )
+ spi-cs-off ( b )
+ unloop exit
+ then ( d )
+ spi-cs-off ( d )
+ \ The setup in the CL4 has can also report zeros when inactive.
+ 2dup h# ff = 00 = or abort" EDI byte in inactive"
+ ." Unknown EDI byte in response: " .h cr
+ true abort" EDI byte in confused"
+ then ( d )
+ drop
+ loop
+ spi-cs-off
+ true abort" EDI byte in timeout"
+;
+[then]
+: edi-b@ ( offset -- b ) \ Read byte from address inside EC chip
+ h# 30 edi-cmd,adr edi-wait-b
+;
+: edi-next-b@ ( -- b ) \ Read the next EC byte - auto-increment address
+ spi-cs-on h# 33 spi-out edi-wait-b
+;
+: edi-disable ( -- ) \ Turn off the EC EDI interface
+ spi-cs-on
+ h# f3 spi-out
+ spi-in ( b )
+ spi-cs-off
+ h# 8c <> if
+ ." Unexpected response from edi-disable" cr
+ then
+;
+
+0 [if]
+: edi-w@ ( offset -- w ) \ Read 16-bit word from address inside EC chip
+ dup 1+ edi-b@ ( offset b.low )
+ swap edi-b@ ( b.low b.high )
+ bwjoin
+;
+[else]
+: edi-w@ ( offset -- w ) \ Read 16-bit word from address inside EC chip
+ edi-b@ edi-next-b@ swap bwjoin
+;
+[then]
+: reset-8051 ( -- ) \ Reset 8-5
+ rst8051 edi-b@ 1 or rst8051 edi-b!
+;
+: unreset-8051 ( -- ) \ Reset 8-5
+ rst8051 edi-b@ 1 invert and rst8051 edi-b!
+ d# 2000 ms
+;
+
+\ 0 in bit 0 selects masked ROM as code source for 8051, 1 selects FLASH
+\ The 8051 should be in reset mode when changing that bit.
+
+: select-flash ( -- ) \ Setup for access to FLASH inside the EC
+ kb9010? if exit then
+ h# f011 edi-b@ 1 or h# f011 edi-b!
+;
+
+: edi-read-id ( -- id )
+ spi-cs-on h# 3e spi-out spi-in spi-cs-off
+;
+
+: probe-rdid ( -- found? ) \ Verify that the EC is the one we think it is
+ select-flash
+ h# f01c ['] edi-w@ catch if ( x )
+ drop false exit ( -- false )
+ then ( id )
+
+ 1 invert and h# 3730 =
+;
+
+: finished? ( b -- flag )
+ kb9010? if 2 and 0= else h# 80 and h# 80 = then
+;
+: wait-flash-busy ( -- ) \ Wait for an erase/programming operation to complete
+ get-msecs h# 1000 + ( limit )
+ begin ( limit )
+ efcfg edi-b@ ( limit b )
+ finished? if ( limit )
+ drop exit ( -- )
+ then ( limit )
+ dup get-msecs - 0<= ( limit timeout? )
+ until ( limit )
+ drop
+ true abort" EDI FLASH busy timeout"
+;
+
+: flash-cmd ( b -- ) efcmd edi-b! ;
+
+: set-offset ( offset -- )
+ lbsplit drop ( offset-low mid hi )
+ kb9010? if h# feaa edi-b! else drop then ( offset-low mid )
+ h# fea9 edi-b! h# fea8 edi-b! ( )
+;
+
+: erase-page ( offset -- )
+ wait-flash-busy ( offset )
+ set-offset ( )
+ h# 20 flash-cmd ( )
+;
+
+: erase-chip ( -- )
+ 0 set-offset \ New code does this (and does not wait-flash-busy)
+ wait-flash-busy h# 60 flash-cmd wait-flash-busy
+;
+
+: send-byte ( b offset -- ) set-offset efdat edi-b! 2 flash-cmd ;
+
+: edi-program-page ( adr offset -- )
+ \ Clear HVPL
+ wait-flash-busy h# 80 flash-cmd ( adr offset )
+
+ wait-flash-busy ( adr offset ) \ Necessary?
+
+ \ Fill the page buffer
+ swap /flash-page bounds do ( offset )
+ i c@ over send-byte ( offset )
+ 1+ ( offset' )
+ loop ( offset )
+ drop ( )
+
+ \ Commit the buffer to the FLASH memory
+ wait-flash-busy ( ) \ Redundant wait?
+ h# 70 flash-cmd ( ) \ Program page command
+ wait-flash-busy ( )
+;
+
+: edi-program-flash ( adr len offset -- )
+ cr ( adr len offset )
+ swap 0 ?do ( adr offset )
+ (cr i . ( adr offset )
+ dup i + ec-flags-offset <> if ( adr offset )
+ dup i + erase-page ( adr offset )
+ over i + over i + edi-program-page ( adr offset )
+ then ( adr offset )
+ i /ec-flash edi-progress ( adr offset )
+ /flash-page +loop ( adr offset )
+ 2drop ( )
+;
+: edi-read-flash ( adr len offset -- )
+ over 0= if 3drop exit then ( adr len offset )
+ edi-b@ ( adr len byte )
+ third c! ( adr len )
+ 1 /string bounds ?do ( )
+ edi-next-b@ i c! ( )
+ loop ( )
+;
+
+: trim@ ( offset -- b )
+ set-offset
+ h# 90 flash-cmd
+ wait-flash-busy
+ efdat-in edi-b@ \ reg: efdat
+;
+
+: trim-tune ( -- )
+\ firmware-id 0= if
+ \ Read trim data and write to register (for ENE macros)
+ h# 100 trim@ h# 5a = if
+ \ Low Voltage Detect TRIM register
+ h# f035 edi-b@ ( val )
+ h# 1f invert and ( val' )
+ h# 101 trim@ h# 1f and or ( val' )
+ h# f035 edi-b! ( )
+
+ \ Int Oscillator Control register - HKCOMOS32K
+ h# f02b edi-b@ ( val )
+ h# 0f invert and ( val' )
+ h# 102 trim@ h# 0f and or ( val' )
+ h# f02b edi-b! ( )
+ then
+
+ \ Read trim data and write to register (for HHNEC macros)
+ h# 1ff trim@ 0<> if
+ \ XBIMISC register - S[4:0]
+ h# fea6 edi-b@ ( val )
+ h# 1f invert and ( val' )
+ h# 1f0 trim@ h# 1f and or ( val' )
+ h# fea6 edi-b! ( )
+
+ \ XBI Pump IP register - Pdac[3:0] | Ndac[3:0]
+ h# 1f1 trim@ 4 lshift ( val )
+ h# 1f2 trim@ h# 0f and or ( val' )
+ h# fea3 edi-b! ( )
+
+ \ XBI Flash IP register - Bdac[3:0]
+ h# fea4 edi-b@ ( val )
+ h# 0f invert and ( val' )
+ h# 1f4 trim@ h# 0f and or ( val' )
+ h# fea4 edi-b! ( )
+
+ \ XB VR IP register - Tctrim[3:0] | Abstrim[3:0] (Vref temp coef and absolute value)
+ h# 1f5 trim@ 4 lshift ( val )
+ h# 1f6 trim@ h# 0f and or ( val' )
+ h# fea5 edi-b! ( )
+
+ \ XBI Flash IP register - Itim[3:0] - Must be last
+ h# fea4 edi-b@ ( val )
+ h# f0 invert and ( val' )
+ h# 1f4 trim@ 4 lshift or ( val' )
+ h# fea4 edi-b! ( )
+
+ 3 us \ Required after Itim[3:0] update
+
+ \ XBI Embedded Flash Configuration register
+ h# 10 h# fea0 edi-b! \ Set FLASH clock
+
+ h# fea0 edi-b@ h# d0 = if
+ ." Warning - XBIECFG is 0xd0" cr
+ then
+ then
+\ then
+;
+: set-chip-id ( -- )
+ ['] edi-read-id catch if ( )
+ edi-read-id ( id )
+ then ( id )
+ to edi-chip-id
+;
+: kb9010-init ( -- )
+ h# 00 xbics edi-b!
+ h# 00 xbiwp edi-b! \ Clear XBI write protection
+ h# ff wdt edi-b! \ Disable WDT
+ h# 00 wdtcfg edi-b!
+ h# 00 wdtpf edi-b!
+ h# 00 shccfg edi-b! \ Disable SHC
+ h# 0c clkcfg edi-b! \ Set the 8051 to 32Mhz
+ h# 08 efcfg edi-b! \ Enable the embedded flash cmd mode
+;
+base @ hex
+create special-row 1f0 w, 1f1 w, 1f2 w, 1f4 w, 1f5 w, 1f6 w, 1f3 w,
+create dest-regs feb9 w, feb6 w, feb6 w, feb7 w, feb8 w, feb8 w, feb7 w,
+create source-bits 1f c, 0f c, 0f c, 0f c, 07 c, 1f c, 0f c,
+create dest-bits 1f c, f0 c, 0f c, 0f c, e0 c, 1f c, f0 c,
+create shift-cnt 0 c, 4 c, 0 c, 0 c, 5 c, 0 c, 4 c,
+base !
+: kb9010-trimtune ( -- )
+ h# 1ff trim@ 0<> if
+ 7 0 do
+ special-row i wa+ w@ edi-b@ ( data )
+ source-bits i ca+ c@ or ( field )
+ shift-cnt i ca+ c@ lshift ( field' )
+ dest-regs i wa+ w@ edi-b@ ( field dest )
+ dest-bits i ca+ c@ invert and or ( dest' )
+ dest-regs i wa+ w@ edi-b! ( )
+ loop
+ wait-flash-busy
+ then
+ h# 80 trim@ h# 5a = if
+ ecsts edi-b@ ( old-ecsts )
+ dup 4 or ecsts edi-b! ( old-ecsts ) \ chipid is now pllcfg2
+
+ xbis edi-b@ h# 3f and ( old-ecsts xbis-bits )
+ h# 81 trim@ 3 and 6 lshift or ( old-ecsts xbis-value )
+ xbis edi-b! ( old-ecsts )
+
+ h# 82 trim@ h# f and 4 lshift ( old-ecsts pll-high )
+ h# 83 trim@ h# f0 and 4 rshift or ( old-ecsts pll-value )
+ pllcfg edi-b! ( old-ecsts )
+
+ pllcfg2 edi-b@ h# 3f and ( old-ecsts pll2-bits )
+ h# 82 trim@ h# 30 and 2 lshift or ( old-ecsts pll2-value )
+ pllcfg2 edi-b! ( old-ecsts )
+
+ ecsts edi-b! ( )
+ then
+;
+\ This is used to start EDI from routines where you do not want to
+\ put the EC into reset. ie the mfg tag reading routines
+: edi-open-active ( -- )
+ spi-start
+
+ \ Does a dummy ready and throws away the result.
+ \ required to get the EDI interface enabled
+ h# ff22 ['] edi-b@ catch 2drop
+
+ set-chip-id
+
+ select-flash
+;
+\ Full EDI startup sequece. Used when you want to reprogram the EC.
+: edi-open ( -- )
+ edi-open-active
+
+ reset-8051
+
+ kb9010? if
+ kb9010-init
+ kb9010-trimtune
+ else
+ trim-tune
+ then
+;
+
+\ *** End of verbatim inclusion of edi.fth
+
+\ *** Start of selective inclusion of cpu/arm/olpc/ecflash.fth
+
+: check-signature ( adr -- )
+ /ec-flash + h# 100 - ( adr' )
+ dup " XO-EC" comp abort" Bad signature in EC image" ( adr )
+ dup ." EC firmware version: " cscount type cr ( adr )
+ dup 6 + c@ expected-ec-version <> abort" Wrong EC version" ( adr )
+ drop
+;
+
+: ?ec-image-valid ( adr len -- )
+ dup /ec-flash <> abort" Image file is the wrong size" ( adr len )
+ over c@ h# 02 <> abort" Invalid EC image - must start with 02"
+ 2dup 0 -rot bounds ?do i l@ + /l +loop ( adr len checksum )
+ abort" Incorrect EC image checksum" ( adr len )
+ over check-signature ( adr len )
+ 2drop
+;
+
+0 value ec-file-loaded?
+: get-ec-file ( "name" -- )
+ safe-parse-word ." Reading " 2dup type cr
+ $read-open
+ load-base /ec-flash ifd @ fgets ( len )
+ ifd @ fclose ( len )
+ load-base swap ?ec-image-valid
+;
+
+\ Tells the EC to auto-restart after power cycling
+: set-ec-reboot ( -- ) 1 ecreboot edi-b! ;
+
+: ignore-ec-flags ( adr -- ) ec-flags-offset + /flash-page erase ;
+: reflash-ec ( -- )
+
+ pio1.5mhz
+ edi-open
+ ." Writing ..." load-base /ec-flash 0 edi-program-flash cr
+ ." Verifying ..."
+ load-base /ec-flash + /ec-flash 0 edi-read-flash
+
+ load-base ignore-ec-flags
+ load-base /ec-flash + ignore-ec-flags
+ load-base load-base /ec-flash + /ec-flash comp
+ abort" Miscompare!"
+ cr
+
+ ." Restarting EC" cr
+ set-ec-reboot
+ unreset-8051
+;
+: recover-ec ( "filename" -- ) get-ec-file reflash-ec ;
+
+: read-ec-flash ( -- )
+ pio1.5mhz
+ edi-open
+ flash-buf /ec-flash 0 edi-read-flash
+;
+: excavate-ec ( "name" -- )
+ safe-parse-word $new-file
+ read-ec-flash
+ load-base /ec-flash ofd @ fputs
+ ofd @ fclose
+;
+
+\ *** End of selective inclusion of cpu/arm/olpc/ecflash.fth
+
+dend
+
+
+\ LICENSE_BEGIN
+\ Copyright (c) 2014 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
More information about the openfirmware
mailing list