Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send release power-down (0xAB) instruction, to revive flash, that might be in power-down state #2130

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions src/rp2350/boot_stage2/boot2_generic_03h.S
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#error "RX delay greater than maximum"
#endif

#define CMD_RELEASE_POWERDOWN 0xAB
#define CMD_READ 0x03

// ----------------------------------------------------------------------------
Expand All @@ -60,6 +61,15 @@
// CLKDIV and RXDELAY, and no constraints on CS max assertion, CS min
// deassertion, or page boundary burst breaks.

// Need to use direct serial mode to send SR commands. Choose a
// conservative direct-mode divisor (5 MHz at 150 MHz clk_sys)
// since the XIP-mode divisor may be unsafe without an RX delay.
#define INIT_DIRECT_CSR (\
30 << QMI_DIRECT_CSR_CLKDIV_LSB | \
QMI_DIRECT_CSR_EN_BITS | \
QMI_DIRECT_CSR_AUTO_CS0N_BITS | \
0)

#define INIT_M0_TIMING (\
1 << QMI_M0_TIMING_COOLDOWN_LSB |\
PICO_FLASH_SPI_RXDELAY << QMI_M0_TIMING_RXDELAY_LSB |\
Expand Down Expand Up @@ -100,6 +110,25 @@ regular_func _stage2_boot
sw a0, QMI_M0_RCMD_OFFSET(a3)
li a0, INIT_M0_RFMT
sw a0, QMI_M0_RFMT_OFFSET(a3)

// Need to use direct serial mode to send commands.
li a1, INIT_DIRECT_CSR
sw a1, QMI_DIRECT_CSR_OFFSET(a3)
// Wait for cooldown on last XIP transfer to expire, by polling BUSY
1:
lw a1, QMI_DIRECT_CSR_OFFSET(a3)
andi a1, a1, QMI_DIRECT_CSR_BUSY_BITS
bnez a1, 1b

// Send release power-down command, discard RX
li a0, CMD_RELEASE_POWERDOWN
sw a0, QMI_DIRECT_TX_OFFSET(a3)
jal wait_qmi_ready
lw a0, QMI_DIRECT_RX_OFFSET(a3)

// Disable direct mode
andi a1, a1, ~QMI_DIRECT_CSR_EN_BITS
sw a1, QMI_DIRECT_CSR_OFFSET(a3)
#else
push {lr}
ldr r3, =XIP_QMI_BASE
Expand All @@ -109,11 +138,33 @@ regular_func _stage2_boot
str r0, [r3, #QMI_M0_RCMD_OFFSET]
ldr r0, =INIT_M0_RFMT
str r0, [r3, #QMI_M0_RFMT_OFFSET]

// Need to use direct serial mode to send commands.
ldr r1, =INIT_DIRECT_CSR
str r1, [r3, #QMI_DIRECT_CSR_OFFSET]
// Wait for cooldown on last XIP transfer to expire, by polling BUSY
1:
ldr r0, [r3, #QMI_DIRECT_CSR_OFFSET]
tst r0, #QMI_DIRECT_CSR_BUSY_BITS
bne 1b

// Send release power-down command, discard RX
movs r0, #CMD_RELEASE_POWERDOWN
str r0, [r3, #QMI_DIRECT_TX_OFFSET]
bl wait_qmi_ready
ldr r0, [r3, #QMI_DIRECT_RX_OFFSET]

// Disable direct mode
bics r1, #QMI_DIRECT_CSR_EN_BITS
str r1, [r3, #QMI_DIRECT_CSR_OFFSET]
#endif

// Pull in standard exit routine
#include "boot2_helpers/exit_from_boot2.S"

// Common functions
#include "boot2_helpers/wait_qmi_ready.S"

#ifndef __riscv
.global literals
literals:
Expand Down
13 changes: 13 additions & 0 deletions src/rp2350/boot_stage2/boot2_w25q080.S
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
// A better solution is to use a volatile SR write if your device supports it.
#define PROGRAM_STATUS_REG

#define CMD_RELEASE_POWERDOWN 0xAB
#define CMD_WRITE_ENABLE 0x06
#define CMD_READ_STATUS 0x05
#define CMD_READ_STATUS2 0x35
Expand Down Expand Up @@ -176,6 +177,12 @@ program_sregs:
lw a1, QMI_DIRECT_CSR_OFFSET(a3)
andi a1, a1, QMI_DIRECT_CSR_BUSY_BITS
bnez a1, 1b

// Send release power-down command, discard RX
li a0, CMD_RELEASE_POWERDOWN
sw a0, QMI_DIRECT_TX_OFFSET(a3)
jal wait_qmi_ready
lw a0, QMI_DIRECT_RX_OFFSET(a3)

// Check whether SR needs updating
li a0, CMD_READ_STATUS2
Expand Down Expand Up @@ -268,6 +275,12 @@ program_sregs:
ldr r0, [r3, #QMI_DIRECT_CSR_OFFSET]
tst r0, #QMI_DIRECT_CSR_BUSY_BITS
bne 1b

// Send release power-down command, discard RX
movs r0, #CMD_RELEASE_POWERDOWN
str r0, [r3, #QMI_DIRECT_TX_OFFSET]
bl wait_qmi_ready
ldr r0, [r3, #QMI_DIRECT_RX_OFFSET]

// Check whether SR needs updating
movs r0, #CMD_READ_STATUS2
Expand Down