; --------------------------------------------------------------------------------
; @Title: OSPI FLASH Program script for the j7200-evm (DRA821)
; @Description:
; The S28HS512T (Cypress) is connected to the OSPI_CS0 controller
;
; SRAM:
; OSPI(controller) Base: 0x47040000
; OSPI memory mapped ADDRESS: 0x50000000
;
; Prerequisites: Switch Settings: CONFIG_SW[1] = OFF (SW3.1 on common board)
;
; @Chip: DRA821
; @Board: J7200-EVM
; @Author: CMO
; @Keywords: Cypress TD4*, Cypress DRA821, Cypress AM752X
; @Copyright: (C) 1989-2019 Lauterbach GmbH, licensed for use with TRACE32(R) only
; --------------------------------------------------------------------------------

;
;  FLASH SNOR hyperflash driver (not flashfile xspi)
;

LOCAL &OSPI_BASE &OSPI_MEMORY_BASE
&OSPI_BASE=0x47040000
&OSPI_MEMORY_BASE=0x50000000  ; flash contents memory mapped address

IF hardware.COMBIPROBE()||hardware.UTRACE()
  SYStem.CONFIG.CONNECTOR MIPI34 ; because of converter LA-3782

&use_pll2="yes"
&bare_metal="yes"              ; if R5 is not yet booted say yes
&iprobe="no"                   ; if TRACE32 logic analyzer hooked to r306 on SOM

IF "&iprobe"=="yes"
(
  NAME.RESet
  NAME.Set IProbe.00 FREQ
  IProbe.CSELect.IProbe FREQ     ; display ospi0_clk
  IProbe.Timing.IProbe.FREQ
  IProbe
  IProbe.OFF
)

IF "&bare_metal"=="yes"
(
  ; call out to bare metal CMMs to setup clocks
  TITLE "TRACE32 for ARM-CM3 - MASTER"
  DO "~~/cmm-ti/cmm-dra/cmm-dra821/x_gel_to_cmm_nda/J7VCL_m3.cmm"
  Register
  DO "~~/cmm-ti/cmm-dra/cmm-dra821/x_gel_to_cmm_nda/J7VCL_SI.cmm"
  WAIT 1s
)

; Disable CR5-MCU lockstep
Data.Set EZAXI:0x45A50040 %Long 0x00000000

; --------------------------------------------------------------------------------
; Connect to MCU-CR5 to program flash

SYStem.CPU DRA821-CR5-MCU
SYStem.CONFIG CORE 3. 1.
CORE.ASSIGN 1.
SYStem.Option ResBreak OFF
SYStem.Option EnReset OFF
SYStem.MemAccess DAP    ;Enable to use the dualport

SYStem.Option TRST OFF
SYStem.Attach
Break
AREA.CLEAR
AREA

; Enable GTC for debug timestamps, 0x3=freeze in debug halt
Data.Set EZAXI:0x00A90000 %LE %Long 0x1

SCREEN.OFF
GOSUB CACHE_MMU_INIT
GOSUB PIN_MUX
GOSUB CLK_INIT
GOSUB OSPI_INIT
SCREEN.ON

GOSUB WATCHDOG_DISABLE
WAIT 1.ms

Break.RESet
FLASH.RESet
FLASH.Create  1. &OSPI_MEMORY_BASE++0x03ffffff 0x40000 TARGET   Byte
FLASH.TARGET  0x41C00000   E:0x41C00000+0x2000    0x1000    ~~/demo/arm/flash/byte/snor_am752x.bin /DualPort

; Re-enable I cache
Data.Set C15:0x1 %Long (Data.Long(C15:0x1)|(0x1<<12.))  ; enable I cache

// Read FLASH Manufacturer and Device ID
SILENT.FLASH.SPI.CMD 1. 0x9F /READ 0x4 vm:0x0
IF (Data.Long(vm:0)&0xFFFF)==0x5B34 //S28HS512
(
  PRINT "spi flash is S28HS512"

  GOSUB SPI_4B_ADDRMODE_ENABLE
  SILENT.FLASH.SPI.CMD 1.  0x65 0x00 0x80 0x00 0x04 0x0 /READ 0x1 vm:0  ; Read Any Register to verify CFR3V
  IF (Data.Byte(vm:0)&0x08)==0x00 //0: hybrid
  (
    PRINT "detect the flash is the hybrid mode"
    FLASH.Delete 1.
    FLASH.Create 1. (&OSPI_MEMORY_BASE+0x00000000)++0x0001FFFF 0x01000 TARGET   Byte   ; 32 x 4K
    FLASH.Create 1. (&OSPI_MEMORY_BASE+0x00020000)++0x0001FFFF 0x20000 TARGET   Byte   ; 1 x 128k
    FLASH.Create 1. (&OSPI_MEMORY_BASE+0x00040000)++(0x03FFFFFF-0x40000) 0x40000 TARGET   Byte   ; rest x 256k
  )
)

DIALOG.YESNO "Program flash memory?"
LOCAL &progflash
ENTRY &progflash

IF &progflash
  GOSUB LOAD_IMAGE

FLASH.List

ENDDO

READ_ID_TEST:
(
  ; In case of errors you can try to read the ID via:
  ; GOSUB READ_ID_TEST
  ;
  ; Check the output of the AREA window.
  ; Expected output ID:
  ; 0x2C
  ; 0x5A (or 0x5B)
  ; 0x1A
  ; 0x10
  ; 0x41
  ; 0x00 (or 0x04)
  ; ...  (Unique ID code)

  LOCAL &rdata
  &CTRLREG=&OSPI_BASE+0x090
  &RXDATA0=&OSPI_BASE+0x0A0
  &RXDATA1=&OSPI_BASE+0x0A4

  &cmd=0x9f<<24.     //cmd
  &rd=0x1<<23.       //rd data enable
  &rd_num=0x7<<20.   //7+1==8bytes
  &cmd_exec=0x1      //cmd execution

  Data.Set EZAXI:&CTRLREG %LE %Long (&cmd|&cmd_exec|&rd_num|&rd)   ;write cmd + write data
  WAIT 100.ms

  &rdata=Data.Long(EZAXI:&RXDATA0)  ;read lower  , 8byte fifo
  PRINT "1st 0x" (&rdata)&0xFF " (Manufacture)"      ; //RXFIFO0
  PRINT "2nd 0x" (&rdata>>8.)&0xFF " (Device ID)"
  PRINT "3rd 0x" (&rdata>>16.)&0xFF
  PRINT "4th 0x" (&rdata>>24.)&0xFF
  &rdata=Data.Long(EZAXI:&RXDATA1)  ;read upper , 8byte fifo
  PRINT "5th 0x" (&rdata)&0xFF
  PRINT "6th 0x" (&rdata>>8.)&0xFF
  PRINT "7th 0x" (&rdata>>16.)&0xFF
  PRINT "8th 0x" (&rdata>>24.)&0xFF

  RETURN
)

OSPI_INIT:
(
  Data.Set EZAXI:&OSPI_BASE+0x0  %LE %Long 0x0
  Data.Set EZAXI:&OSPI_BASE+0x4  %LE %Long 0x00000013 ; 4B Addr Read
  Data.Set EZAXI:&OSPI_BASE+0x8  %LE %Long 0x00000012 ; 4B Addr Write

  Data.Set EZAXI:&OSPI_BASE+0x0  %LE %Long 0x80800000
  Data.Set EZAXI:&OSPI_BASE+0x14 %LE %Long 0x1003; 4B Address mode, 3B Addr: 0x1002
  Data.Set EZAXI:&OSPI_BASE+0x10 %LE %Long 0x21

  Data.Set EZAXI:&OSPI_BASE+0x1C %LE %Long 0xFFFFFFFF
  ;;Data.Set EZAXI:&OSPI_BASE+0xC  %LE %Long (0xFF<<16.)|(0xFF<<8.) ; !!!!! OSPI_DEV_DELAY_REG because of writing !!!!!
  Data.Set EZAXI:&OSPI_BASE+0x0  %LE %Long 0x00000081|(0x1<<19.)|(0xE<<10.) ; 0x1==baudrate_div4, enable usage of OSPI_CS0
  Data.Set EZAXI:&OSPI_BASE+0x1C %LE %Long 0x04000000 ;ospi_setdirectcutoff, end of the flash address

  IF "&use_pll2"=="yes"
    Data.Set EZAXI:&OSPI_BASE+0x0  %LE %Long 0x00000081|(0x2<<19.)|(0xE<<10.) ; pll2 divide, Enable using OSPI_CS0
  ELSE
    Data.Set EZAXI:&OSPI_BASE+0x0  %LE %Long 0x00000081|(0x5<<19.)|(0xE<<10.) ; pll1 divide, Enable using OSPI_CS0

  RETURN
)

PIN_MUX:
(
  ;MMR_unlock
  Data.Set EZAXI:0x4301D008 %Long 0x68EF3490  ;CTRLMMR_WKUP_LOCK7_KICK0
  Data.Set EZAXI:0x4301D00C %Long 0xD172BC5A

  ;WKUP_PADCONFIG0     0x00430C000
  ;                    0x0043000000
  Data.Set EZAXI:0x4301C000 %Long 0x00040000   ; B6: CTRLMMR_WKUP_PADCONFIG0 MCU_OSPI0_CLK
  Data.Set EZAXI:0x4301C004 %Long 0x00040000   ; C8: MCU_OSPI0_LBCLKO
  Data.Set EZAXI:0x4301C008 %Long 0x00040000   ; B7: MCU_OSPI0_DQS
  Data.Set EZAXI:0x4301C00C %Long 0x00040000   ; D8: MCU_OSPI0_D0
  Data.Set EZAXI:0x4301C010 %Long 0x00040000   ; C7: MCU_OSPI0_D1
  Data.Set EZAXI:0x4301C014 %Long 0x00040000   ; C5: MCU_OSPI0_D2
  Data.Set EZAXI:0x4301C018 %Long 0x00040000   ; A5: MCU_OSPI0_D3
  Data.Set EZAXI:0x4301C01C %Long 0x00040000   ; A6: MCU_OSPI0_D4
  Data.Set EZAXI:0x4301C020 %Long 0x00040000   ; B8: MCU_OSPI0_D5
  Data.Set EZAXI:0x4301C024 %Long 0x00040000   ; A8: MCU_OSPI0_D6
  Data.Set EZAXI:0x4301C028 %Long 0x00040000   ; A7: MCU_OSPI0_D7
  Data.Set EZAXI:0x4301C02C %Long 0x00040000   ; D6: MCU_OSPI0_CSn0
  Data.Set EZAXI:0x4301C030 %Long 0x00040000   ; D7: MCU_OSPI0_CSn1
  Data.Set EZAXI:0x4301C038 %Long 0x00040001   ; C6: MCU_OSPI0_CSn2
  Data.Set EZAXI:0x4301C03C %Long 0x00040001   ; D5: MCU_OSPI0_CSn3
  RETURN
)

CLK_INIT:
(
  Data.Set EZAXI:0x40F09008 %Long 0x68EF3490  ; CTRLMMR_MCU_LOCK2_KICK0
  Data.Set EZAXI:0x40F0900C %Long 0xD172BC5A

  Data.Set EZAXI:0x40d01010  %Long 0x68EF3490  ;MCU_PLL1_KICK0
  Data.Set EZAXI:0x40d01014  %Long 0xD172BC5A  ;MCU_PLL1_KICK1

  WAIT 1.ms

  IF "&use_pll2"=="yes"
  (
    Data.Set EZAXI:0x40D02090 %Long 0x0000800b  ; MCU_PLL2_HSDIV_CTRL4 --> 166MHz
    WAIT 1.ms
    Data.Set EZAXI:0x40F08030  %Long 0x1         ;CTRLMMR_MCU_OSPI0_CLKSEL, 2h - MCU_PLL2_HSDIV4_CLKOUT
  )
  ELSE
  (
    ;freq: PLL1 (2.4G) -> HSDIV4 (/5+1) -> 400Mhz --> BAUD/x
    Data.Set EZAXI:0x40D01090  %Long 0x8005      ;MCU_PLL1_HSDIV_CTRL4
    WAIT 1.ms
    Data.Set EZAXI:0x40F08030  %Long 0x0         ;CTRLMMR_MCU_OSPI0_CLKSEL, 0h - MCU_PLL1_HSDIV4_CLKOUT
  )
  WAIT 1.ms
  RETURN
)

WATCHDOG_DISABLE:
(
  //Fill in if >3min burn time needed
  RETURN
)

CACHE_MMU_INIT:
(
  PRIVATE &i &tmpReg

  ; Enable MPU and disable I and D caches
  &tmpReg=Data.Long(C15:0x1)
  &tmpReg=&tmpReg|0x1             ; enable MPU
  &tmpReg=(&tmpReg&(~(0x1<<2.)))  ; disable D cache
  &tmpReg=(&tmpReg&(~(0x1<<12.))) ; disable I cache
  Data.Set C15:0x1 %Long &tmpReg

  ; Configure small region setup for flash programming
  PER.Set.SaveIndex C15:0x026 %Long 0x0 C15:0x016 %Long 0x00000000 ; set default
  PER.Set.SaveIndex C15:0x026 %Long 0x0 C15:0x216 %Long 0x0000003F
  PER.Set.SaveIndex C15:0x026 %Long 0x0 C15:0x416 %Long 0x00001310
  PER.Set.SaveIndex C15:0x026 %Long 0x1 C15:0x016 %Long 0x50000000 ; setup flash window
  PER.Set.SaveIndex C15:0x026 %Long 0x1 C15:0x216 %Long 0x00000035
  PER.Set.SaveIndex C15:0x026 %Long 0x1 C15:0x416 %Long 0x00001301
  PER.Set.SaveIndex C15:0x026 %Long 0x2 C15:0x016 %Long 0x41C00000 ; setup buffer space
  PER.Set.SaveIndex C15:0x026 %Long 0x2 C15:0x216 %Long 0x00000027
  PER.Set.SaveIndex C15:0x026 %Long 0x2 C15:0x416 %Long 0x0000030C
  ; Reset all other MPU regions
  &i=3.
  WHILE &i<16.
  (
    PER.Set.SaveIndex C15:0x026 %Long &i C15:0x016 %Long 0x0
    PER.Set.SaveIndex C15:0x026 %Long &i C15:0x216 %Long 0x0
    PER.Set.SaveIndex C15:0x026 %Long &i C15:0x416 %Long 0x0
    &i=&i+1.
  )

  RETURN
)

LOAD_IMAGE:
(
  ; --------------------------------------------------------------------------------
  ; Start flash programming
  FLASH.ReProgram.ALL

  ; --------------------------------------------------------------------------------
  ; Load your code here, e.g. via Data.LOAD, Data.COPY, etc.
  ;     - J721E memory mapped OSPI range: 0x50000000--0x503fffff
  ;
  ; Example: Load test string to "base address + 0x100" of OSPI flash
  Data.Set VM:0x0 "#Flash test 1 2 3 4 5 6 7 8#"
  Data.COPY VM:0x0--0x1b EA:0x50000100

  ; <your code>
  ;data.copy eaxi:0x80000000++0xffff vm:0x10000
  ;data.copy vm:0x10000++0xffff EA:0x50010000

  ; --------------------------------------------------------------------------------
  ; Finalize flash programming
  FLASH.ReProgram.off

  ; --------------------------------------------------------------------------------
  ; Compare flashed data, e.g. by Data.LOAD <...> /ComPare, DataComPare, etc.
  ; Example:
  Data.ComPare VM:0--0x13 EA:0x50000100
  IF FOUND()
    PRINT %ERROR "Flash writing failed"
  ;Data.ComPare VM:0x10000++0xffff EA:0x50010000
  ;IF FOUND()
  ;	PRINT %ERROR "Flash writing failed"
)

END

// detect the flash address mode by the internal flash register (0x0080_0003)
// CR2V : should come 0x08(3B) or 0x88(4B)
SPI_4B_ADDRMODE_ENABLE:
(
  PRINT "switch 3B->4B mode"
  //3Byte mode
  SILENT.FLASH.SPI.CMD 1.  0x65 0x80 0x00 0x03 0x00       /READ 0x4 ;read CR2V
  SILENT.FLASH.SPI.CMD 1.  0x06
  SILENT.FLASH.SPI.CMD 1.  0x71 0x80 0x00 0x03 0x88         ; write  0x88 to CR2V , switch 3B->4B address mode
  //4Byte mode
  SILENT.FLASH.SPI.CMD 1.  0x65 0x00 0x80 0x00 0x03 0x0    /READ 0x4 ;read CR2V 4Bytes Address mode

  RETURN
)

// Addtional options
 //Disable flash ECC manually
  ; FLASH.SPI.CMD 1. 0x6  ;Write Enable
  ; FLASH.SPI.CMD 1. 0x71 00 0x80 0x00 0x05 0xa0  ;Write Any Register, CFR4V[3]:0 for the disable ECC
  ; FLASH.SPI.CMD 1. 0x65 00 0x80 0x00 0x05 /READ 0x2  ; Read Any Register to verify CFR4V  
  //Uniform sector mode - may need dummy data stuff
  ; FLASH.SPI.CMD 1. 0x06  ;Write Enable
  ; FLASH.SPI.CMD 1. 0x71 0x00 0x00 0x00 0x04 0x08   ;Write  0x08 to CFR3V, switch uniform mode
  ; FLASH.SPI.CMD 1. 0x65 0x00 0x80 0x00 0x04 /READ 0x1  ; Read Any Register to verify CFR3V
 )
