# Nintendo Game & Watch: Super Mario Bros. and Zelda set OCTOSPI1 1 set OCTOSPI2 0 source [find target/stm32h7x.cfg] # HXA-001 QSPI initialization # Based on https://forums.pimoroni.com/t/accessing-external-flash-from-openocd/12558 # With contributions by https://github.com/jan2642 and https://github.com/GMMan proc hxa-001_qspi_init { } { echo "Initializing Octo-SPI interface" # PB01: OCTOSPIM_P1_IO0, PD12: OCTOSPIM_P1_IO1, PE02: OCTOSPIM_P1_IO2, # PA01: OCTOSPIM_P1_IO3, PB02: OCTOSPIM_P1_CLK, PE11: OCTOSPIM_P1_NCS, # PD01: 1.8V power # Enable GPIO clocks mmw 0x58024540 0x0000001b 0x00000000 ;# RCC_AHB4ENR |= GPIOAEN | GPIOBEN | GPIODEN | GPIOEEN # Enable Octo-SPI clocks mmw 0x58024534 0x00204000 0x00000000 ;# RCC_AHB3ENR |= OCTOSPI1EN | OCTOSPIMEN (enable clocks) sleep 1 ;# Wait for clock startup # Set GPIO ports (push-pull, no pull) # Port A: PA01:AF09:V mmw 0x58020000 0x00000000 0x00000004 ;# GPIOA_MODER mmw 0x58020008 0x0000000c 0x00000000 ;# GPIOA_OSPEEDR mmw 0x58020020 0x00000090 0x00000000 ;# GPIOA_AFRL # Port B: PB01:AF11:V PB02:AF09:V mmw 0x58020400 0x00000000 0x00000014 ;# GPIOB_MODER mmw 0x58020408 0x0000003c 0x00000000 ;# GPIOB_OSPEEDR mmw 0x58020420 0x000009b0 0x00000000 ;# GPIOB_AFRL # Port D: PD01:OP:L PD12:AF09:V mmw 0x58020c00 0x00000000 0x01000008 ;# GPIOD_MODER mmw 0x58020c08 0x03000000 0x00000000 ;# GPIOD_OSPEEDR mmw 0x58020c24 0x00090000 0x00000000 ;# GPIOD_AFRH # Port E: PE02:AF09:V PE11:AF11:V mmw 0x58021000 0x00000000 0x00400010 ;# GPIOE_MODER mmw 0x58021008 0x00c00030 0x00000000 ;# GPIOE_OSPEEDR mmw 0x58021020 0x00000900 0x00000000 ;# GPIOE_AFRL mmw 0x58021024 0x0000b000 0x00000000 ;# GPIOE_AFRH # Reset Octo-SPI mmw 0x5802447c 0x00204000 0x00000000 ;# RCC_AHB3RSTR |= OCTOSPIMRST | OCTOSPI1RST # Take Octo-SPI out of reset mmw 0x5802447c 0x00000000 0x00204000 ;# RCC_AHB3RSTR &= ~(OCTOSPIMRST | OCTOSPI1RST) # Turn on 1.8v power mww 0x58020c18 0x00010000 ;# GPIOD_BSRR |= BR1 # Set up Octo-SPI interface mww 0x52005000 0x00000400 ;# OCTOSPI_CR: FMODE=0x0, FTHRES=0x04 mww 0x52005008 0x011B0208 ;# OCTOSPI_DCR1: MTYP=0x1, DEVSIZE=0x1B, CSHT=0x2, DLYBYP=0x1 mww 0x5200500c 0x00000002 ;# OCTOSPI_DCR2: PRESCALER=0x02 mmw 0x52005000 0x00000001 0x00000000 ;# OCTOSPI_CR: EN=0x1 # reset the Macronix flash mww 0x52005100 0x00000001 ;# OCTOSPI_CCR: no data, no address, no alternate bytes, instruction on a single line # indirect write mode without data, address and alternate bytes causes the following commands to be sent immediately mww 0x52005110 0x00000066 ;# OCTOSPI_IR: Reset-Enable (RSTEN) sleep 1 mww 0x52005110 0x00000099 ;# OCTOSPI_IR: Reset (RST) sleep 20 ;# wait for the flash to come out of reset mmw 0x52005000 0x30000000 0x00000001 ;# OCTOSPI_CR |= FMODE=0x3, &= ~EN if { [env LARGE_FLASH] == 0 } { # OCTOSPI1: memory-mapped 1-line read mode with 3-byte addresses mww 0x52005100 0x01002101 ;# OCTOSPI_CCR: DMODE=0x1, ABMODE=0x0, ADSIZE=0x2, ADMODE=0x1, ISIZE=0x0, IMODE=0x1 } else { # OCTOSPI1: memory-mapped 1-line read mode with 4-byte addresses mww 0x52005100 0x01003101 ;# OCTOSPI_CCR: DMODE=0x1, ABMODE=0x0, ADSIZE=0x3, ADMODE=0x1, ISIZE=0x0, IMODE=0x1 } mww 0x52005110 0x00000003 ;# OCTOSPI_IR: INSTR=READ mmw 0x52005000 0x00000001 0x00000000 ;# OCTOSPI_CR |= EN flash probe 1 ;# load configuration from CR, TCR, CCR, IR register values } $_CHIPNAME.cpu0 configure -event reset-end { flash probe 0 hxa-001_qspi_init }