; --------------------------------------------------------------------------------
; @Title:  Example script for programming of MPC560xS internal and external QSPI FLASH.
; @Description: 
;
; Internal Flash algorithm may depend on processor revision:
;   MPC560xS all revisions       c90fl560xs.bin or higher
;
; External QuadSPI Flash algorithm may depend on processor revision:
;   MPC560xS Cut 2     quadspi_c2.bin
;   MPC560xS Cut 3     quadspi_c3.bin
;
; NOTES:
; 
; PLL Init assumes 8MHz XTAL. Settings will require changing for other values.
;
; @Keywords: SPI 
; @Author: JIM
; @Chip: MPC560?S
; @Copyright: (C) 1989-2014 Lauterbach GmbH, licensed for use with TRACE32(R) only
; --------------------------------------------------------------------------------
; $Id: jpc560s_quadspi.cmm 5942 2018-08-14 14:54:59Z jjeong $

LOCAL &arg1
ENTRY &arg1
&arg1=STRing.UPpeR("&arg1")  // for example "PREPAREONLY"


;setup internal Flash variables
LOCAL &flashbase_int &shadowbase_int &flashsize_int &flashdriver_int &newflashconfig
&flashbase_int=0x00000000
&shadowbase_int=0x00200000
&flashsize_int=0x080000
&flashdriver_int="c90fl560xs.bin"
&newflashconfig=0

;setup QuadSPI Flash variables
LOCAL &flashbase_qspi &flashsize_qspi &sectorsize_qspi &flashdriver_qspi
&flashbase_qspi=0x80000000  ; TODO: check flash base address (QSPI_AMBA_BASE)
&flashsize_qspi=0x01000000  ; TODO: set flash size here (16Mb)
&sectorsize_qspi=0x00010000 ; TODO: set sector size (64k)
&flashdriver_qspi="tbd.bin"

LOCAL &rambase &quadread_enable
&rambase=0x40000000
&quadread_enable=0  ;set to 1 for quad reads, 0 for single

; --------------------------------------------------------------------------------
; CPU setup
; --------------------------------------------------------------------------------

SYStem.RESet
SYStem.BdmClock 4.0MHz
;select automatic CPU detection
SYStem.DETECT.CPU
SYStem.Option.WATCHDOG OFF
SYStem.Up

;check processor version
LOCAL &NPC_DID
&NPC_DID=Data.Long(DBG:0x80)
IF (&NPC_DID&0x0FFFF000)==0x0AE60000
(
  PRINT %ERROR "Processor revision cut 1 not supported."
  &newflashconfig=0
  ENDDO
)
ELSE IF (&NPC_DID&0x0FFFF000)==0x0AE61000
(
  &flashdriver_qspi="jpc560s_c2_quadspi.bin"
  &newflashconfig=1
)
ELSE
(
  &flashdriver_qspi="jpc560s_c3_quadspi.bin"
  &newflashconfig=1
)

;enable all peripherals and enter DRUN mode
Data.Set ANC:0xC3FE037C %Long 0x80808080 ;enable all perip clocks
Data.Set ANC:0xC3FDC080 %Long 0x000000FE ;Peripheral ON in every mode
Data.Set ANC:0xC3FE0374 %Long 0x00000000 ;Select Fast IRC (16 MHz)
;Re-enter in DRUN mode to update
Data.Set ANC:0xC3FDC004 %Long 0x30005AF0 
Data.Set ANC:0xC3FDC004 %Long 0x3000A50F 

GOSUB Setup_PLL
GOSUB Setup_QSPI
  
;protect from accessing unimplemented memory (open Data.List/Dump windows)
MAP.DenyAccess 0x20000000--0x3FFFFFFF

; initialize internal SRAM
Data.Set EA:0x40000000--0x4000bfff %Quad 0

; --------------------------------------------------------------------------------
; External Flash declaration and load
; --------------------------------------------------------------------------------

; get user to select file
LOCAL &filename
DIALOG.File *
ENTRY %LINE &filename

FLASH.RESet
FLASH.Create 1. &flashbase_qspi++(&flashsize_qspi-1) &sectorsize_qspi TARGET Byte
FLASH.TARGET E:&rambase E:&rambase+0x2000 0x1000 "~~/demo/powerpc/flash/byte/&flashdriver_qspi" /STACKSIZE 0x0200
FLASH.ReProgram.off &flashbase_qspi++(&flashsize_qspi-1)
Data.LOAD.auto "&filename" &flashbase_qspi++(&flashsize_qspi-1)
FLASH.ReProgram.off 

; Internal Flash declaration and load

FLASH.RESet
FLASH.Create 1. (&flashbase_int+0x00000000)++0x07fff TARGET Quad 0. ; L0
FLASH.Create 1. (&flashbase_int+0x00008000)++0x03fff TARGET Quad 1. ; L1 
FLASH.Create 1. (&flashbase_int+0x0000c000)++0x03fff TARGET Quad 2. ; L2 
FLASH.Create 1. (&flashbase_int+0x00010000)++0x07fff TARGET Quad 3. ; L3
FLASH.Create 1. (&flashbase_int+0x00018000)++0x07fff TARGET Quad 4. ; L4
FLASH.Create 1. (&flashbase_int+0x00020000)++0x1ffff TARGET Quad 5. ; L5
FLASH.Create 2. (&flashbase_int+0x00040000)++0x1ffff TARGET Quad 0. ; M0
FLASH.Create 2. (&flashbase_int+0x00060000)++0x1ffff TARGET Quad 1. ; M1

IF &newflashconfig==1
(
  FLASH.Create 3. (&flashbase_int+0x00080000+0x00000000)++0x1ffff TARGET Quad 0. ; L0
  FLASH.Create 3. (&flashbase_int+0x00080000+0x00020000)++0x1ffff TARGET Quad 1. ; L1 
)
ELSE
(
  ; Flash bank 1
  FLASH.Create 3. (&flashbase_int+0x00080000+0x00000000)++0x07fff TARGET Quad 0. ; L0
  FLASH.Create 3. (&flashbase_int+0x00080000+0x00008000)++0x03fff TARGET Quad 1. ; L1 
  FLASH.Create 3. (&flashbase_int+0x00080000+0x0000c000)++0x03fff TARGET Quad 2. ; L2 
  FLASH.Create 3. (&flashbase_int+0x00080000+0x00010000)++0x07fff TARGET Quad 3. ; L3
  FLASH.Create 3. (&flashbase_int+0x00080000+0x00018000)++0x07fff TARGET Quad 4. ; L4
  FLASH.Create 3. (&flashbase_int+0x00080000+0x00020000)++0x1ffff TARGET Quad 5. ; L5
)
FLASH.Create 4. (&flashbase_int+0x00080000+0x00040000)++0x1ffff TARGET Quad 0. ; M0
FLASH.Create 4. (&flashbase_int+0x00080000+0x00060000)++0x1ffff TARGET Quad 1. ; M1

; Shadow row
FLASH.Create 9. (&shadowbase_int+0x00000000)++0x3fff NOP Quad
; Data flash
FLASH.Create 10. (&flashbase_int+0x00800000)++0x3fff TARGET Quad 0.
FLASH.Create 10. (&flashbase_int+0x00804000)++0x3fff TARGET Quad 1.
FLASH.Create 10. (&flashbase_int+0x00808000)++0x3fff TARGET Quad 2.
FLASH.Create 10. (&flashbase_int+0x0080c000)++0x3fff TARGET Quad 3.

FLASH.TARGET E:&rambase E:&rambase+0x2000 0x1000 ~~/demo/powerpc/flash/quad/&flashdriver_int

//End of the test prepareonly
IF "&arg1"=="PREPAREONLY"
ENDDO


FLASH.ReProgram ALL
Data.LOAD.auto "&filename" E:0x00--(&flashsize_int-1)
FLASH.ReProgram.off 

;optional: compare data with QSPI memory to ensure load has been successful
;Data.LOAD "&filename" &flashbase_qspi++(&flashsize_qspi-1) /ComPare

ENDDO



; --------------------------------------------------------------------------------
;setup PLL - Assumes 8MHz Source
; --------------------------------------------------------------------------------
Setup_PLL:
  Data.Set ANC:0xC3FDC02C %Long (Data.Long(ANC:0xC3FDC02C)|0x00000020);switch on external osc
  Data.Set ANC:0xC3FDC02C %Long (Data.Long(ANC:0xC3FDC02C)|0x00000002);Select external osc
  ;enter DRUN
  Data.Set ANC:0xC3FDC004 %Long 0x30005AF0 
  Data.Set ANC:0xC3FDC004 %Long 0x3000A50F 
  WAIT ((Data.Long(ANC:0xC3FDC000))&0x00000020)!=0x0 ;Wait for external osc to stabilize
  WAIT ((Data.Long(ANC:0xC3FDC000))&0x08000000)!=0x08000000 ;Wait for mode entry to complete 
  WAIT ((Data.Long(ANC:0xC3FDC000))&0xF0000000)==0x30000000 ;Check DRUN mode has been entered 

  ;set divider values
  Data.Set ANC:0xC3FE00A0 %Byte (Data.Byte(ANC:0xC3FE00A0)&0xC3) ;IDF- div by 1
  Data.Set ANC:0xC3FE00A0 %Byte ((Data.Byte(ANC:0xC3FE00A0)&0xFC)|0x02) ;ODF - div by 8
  Data.Set ANC:0xC3FE00A1 %Byte (Data.Byte(ANC:0xC3FE00A1)|0x40) ;NDIV - div by 64 for 64MHz PLL
  Data.Set ANC:0xC3FDC02C %Long (Data.Long(ANC:0xC3FDC02C)|0x00000040) ;PLL on

  ;re-enter the drun mode, to update the configuration
  Data.Set ANC:0xC3FDC004 %Long 0x30005AF0 
  Data.Set ANC:0xC3FDC004 %Long 0x3000A50F 
  WAIT ((Data.Long(ANC:0xC3FDC000))&0x08000000)!=0x08000000 ;Wait for mode entry to complete 
  WAIT ((Data.Long(ANC:0xC3FDC000))&0xF0000000)==0x30000000 ;Check DRUN mode has been entered 
  WAIT ((Data.Long(ANC:0xC3FE00A0))&0x00000008)!=0x00000000 ;Wait til PLL is locked
    
  Data.Set ANC:0xC3FDC02C %Long (Data.Long(ANC:0xC3FDC02C)|0x04) ;Select external osc;system clock is PLL
  Data.Set ANC:0xC3FDC004 %Long 0x30005AF0 
  Data.Set ANC:0xC3FDC004 %Long 0x3000A50F 
  WAIT ((Data.Long(ANC:0xC3FDC000))&0x08000000)!=0x08000000 ;Wait for mode entry to complete 
  WAIT ((Data.Long(ANC:0xC3FDC000))&0xF0000000)==0x30000000 ;Check DRUN mode has been entered 
  WAIT ((Data.Long(ANC:0xC3FDC000))&0x0000000F)==0x00000004 ;ensure we rnow running from PLL 
RETURN


; --------------------------------------------------------------------------------
; set up QuadSPI
; setup pins in SIU
; --------------------------------------------------------------------------------
Setup_QSPI:
  Data.Set ANC:0xC3F900E0 %Word 0x0A02
  Data.Set ANC:0xC3F900E2 %Word 0x0B03
  Data.Set ANC:0xC3F900E4 %Word 0x0B03
  Data.Set ANC:0xC3F900E6 %Word 0x0703
  Data.Set ANC:0xC3F900E8 %Word 0x0703
  Data.Set ANC:0xC3F900EA %Word 0x0603

  Data.Set ANC:0xC3FE0398 %Long 0x01000000 ;set QSPI clock as sysclk/2
  Data.Set ANC:0xFFFA8000 %Long 0x00000088 ;Enable QuadSPI mode

  IF &quadread_enable==1
  (
    Data.Set ANC:0xFFFA8104 %Long 0x000000a3 ;enable high performance mode (winbond only, cmd is ignored by spansion)
    WAIT ((Data.Long(ANC:0xFFFA815c))&0x00000001)!=0x00000001   ;wait for command to be sent
    Data.Set ANC:0xFFFA8158 %Long 0x000040eb ; Use Quad I/O reads - Command: 0xEB, Read Size:64bytes
  )
RETURN
