Save/restore QMI window 1 registers across calls to flash_exit_xip(). #2082

Merged
Wren6991 merged 2 commits from qmi-save into develop 2024-11-21 16:52:34 -06:00
Wren6991 commented 2024-11-21 06:34:40 -06:00 (Migrated from github.com)

This works around the RP2350 ROM reinitialising window 1 even when it does not actually issue an XIP exit sequence to that QSPI device. If no exit sequence is issued, then the original configuration still applies.

This is not valid in the case where the ROM does issue an XIP exit sequence to the second chip select, because the original mode is no longer valid once the device is in the serial command state. The ROM does this when FLASH_DEVINFO (loaded from OTP, stored in boot RAM) has a nonzero size for chip select 1. To distinguish the two cases, this patch adds getters/setters for FLASH_DEVINFO.

If chip select 1 has a nonzero size in FLASH_DEVINFO then the ROM's register changes for window 1 are not reverted, and instead the hardware_flash code makes additional changes to ensure writes also work (as the ROM only reinitialises for reads).

This means that, in the case you have opted into ROM support for the second chip select by setting a nonzero CS1 size in FLASH_DEVINFO, the device on chip select 1 will continue to function correctly, but full performance won't be restored until it is reinitialised. The best way to handle this is initialising both chip select devices in your XIP setup function (your boot2).

This works around the RP2350 ROM reinitialising window 1 even when it does not actually issue an XIP exit sequence to that QSPI device. If no exit sequence is issued, then the original configuration still applies. This is not valid in the case where the ROM *does* issue an XIP exit sequence to the second chip select, because the original mode is no longer valid once the device is in the serial command state. The ROM does this when FLASH_DEVINFO (loaded from OTP, stored in boot RAM) has a nonzero size for chip select 1. To distinguish the two cases, this patch adds getters/setters for FLASH_DEVINFO. If chip select 1 has a nonzero size in FLASH_DEVINFO then the ROM's register changes for window 1 are not reverted, and instead the hardware_flash code makes additional changes to ensure writes also work (as the ROM only reinitialises for reads). This means that, in the case you have opted into ROM support for the second chip select by setting a nonzero CS1 size in FLASH_DEVINFO, the device on chip select 1 will continue to function correctly, but full performance won't be restored until it is reinitialised. The best way to handle this is initialising both chip select devices in your XIP setup function (your boot2).
lurch (Migrated from github.com) reviewed 2024-11-21 06:34:40 -06:00
will-v-pi (Migrated from github.com) reviewed 2024-11-21 06:34:40 -06:00
kilograham (Migrated from github.com) requested changes 2024-11-21 10:28:19 -06:00
@ -124,0 +136,4 @@
FLASH_DEVINFO_SIZE_4M = 0xa,
FLASH_DEVINFO_SIZE_8M = 0xb,
FLASH_DEVINFO_SIZE_16M = 0xc,
FLASH_DEVINFO_SIZE_MAX = 0xc
kilograham (Migrated from github.com) commented 2024-11-21 10:28:12 -06:00

ughh.. this file is using TABs not 4 spaces

ughh.. this file is using TABs not 4 spaces
Wren6991 (Migrated from github.com) reviewed 2024-11-21 10:37:27 -06:00
@ -124,0 +136,4 @@
FLASH_DEVINFO_SIZE_4M = 0xa,
FLASH_DEVINFO_SIZE_8M = 0xb,
FLASH_DEVINFO_SIZE_16M = 0xc,
FLASH_DEVINFO_SIZE_MAX = 0xc
Wren6991 (Migrated from github.com) commented 2024-11-21 10:37:27 -06:00

oh, yeah. My editor is set up to guess from the file, but there were no indented lines in here.

oh, yeah. My editor is set up to guess from the file, but there were no indented lines in here.
kilograham (Migrated from github.com) approved these changes 2024-11-21 10:56:26 -06:00
kilograham (Migrated from github.com) left a comment

sweet

sweet
will-v-pi commented 2024-11-29 09:16:37 -06:00 (Migrated from github.com)

I was having a play with powering down flash, and this PR appears to have broken that on RP2350? I have the following function, which works on RP2040 with 2.0.0 and 2.1.0, but on RP2350 only works on 2.0.0, or 2.1.0 with this PR reverted. On 2.1.0 with this PR included it hits a hardfault during the first flash_do_cmd.

From looking at the .dis, it appears that when flash_devinfo_get_cs_size uses flash_devinfo_ptr, it calls the rom_data_lookup stored in flash which is currently powered down, hence the hardfault.

I guess the fix would be to add a rom_data_lookup_inline function and use that instead? I've opened #2116 to do this

void __no_inline_not_in_flash_func(test_flash_powercycle)() {
    // Disable Flash
    uint8_t txbuf[1] = {0xB9};
    uint8_t rxbuf[1] = {0x00};

    uint32_t intrs = save_and_disable_interrupts();
    flash_do_cmd(txbuf, rxbuf, 1);

    busy_wait_at_least_cycles(125000000);

    // Won't do anything as flash is powered down
    flash_range_erase(0, 4096);

    // Enable flash
    txbuf[0] = 0xAB;

    flash_do_cmd(txbuf, rxbuf, 1);

    busy_wait_at_least_cycles(125000000);
    restore_interrupts_from_disabled(intrs);
}
I was having a play with powering down flash, and this PR appears to have broken that on RP2350? I have the following function, which works on RP2040 with 2.0.0 and 2.1.0, but on RP2350 only works on 2.0.0, or 2.1.0 with this PR reverted. On 2.1.0 with this PR included it hits a hardfault during the first `flash_do_cmd`. From looking at the `.dis`, it appears that when `flash_devinfo_get_cs_size` uses `flash_devinfo_ptr`, it calls the `rom_data_lookup` stored in flash which is currently powered down, hence the hardfault. I guess the fix would be to add a `rom_data_lookup_inline` function and use that instead? I've opened #2116 to do this ```c void __no_inline_not_in_flash_func(test_flash_powercycle)() { // Disable Flash uint8_t txbuf[1] = {0xB9}; uint8_t rxbuf[1] = {0x00}; uint32_t intrs = save_and_disable_interrupts(); flash_do_cmd(txbuf, rxbuf, 1); busy_wait_at_least_cycles(125000000); // Won't do anything as flash is powered down flash_range_erase(0, 4096); // Enable flash txbuf[0] = 0xAB; flash_do_cmd(txbuf, rxbuf, 1); busy_wait_at_least_cycles(125000000); restore_interrupts_from_disabled(intrs); } ```
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-raspberrypi/pico-sdk!2082
No description provided.