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

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

Merged
merged 2 commits into from
Nov 21, 2024

Conversation

Wren6991
Copy link
Contributor

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).
@Wren6991 Wren6991 added this to the 2.1.0 milestone Nov 21, 2024
@Wren6991 Wren6991 self-assigned this Nov 21, 2024
@Wren6991 Wren6991 linked an issue Nov 21, 2024 that may be closed by this pull request
Copy link
Contributor

@kilograham kilograham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sweet

@kilograham kilograham merged commit 7b07b0b into develop Nov 21, 2024
8 checks passed
@kilograham kilograham deleted the qmi-save branch November 21, 2024 22:52
@will-v-pi
Copy link
Contributor

will-v-pi commented Nov 29, 2024

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);
}

will-v-pi added a commit to will-v-pi/pico-sdk that referenced this pull request Nov 29, 2024
Fixes bug introduced by raspberrypi#2082 where flash_devinfo_get_cs_size would use rom_data_lookup from flash during a __no_inline_not_in_flash_func
kilograham pushed a commit that referenced this pull request Dec 2, 2024
* Move rom_data_lookup code into rom_data_lookup_inline

Allows ROM data lookup from FLASH/RAM sensitive code

* Use rom_data_lookup_inline in flash_devinfo_ptr

Fixes bug introduced by #2082 where flash_devinfo_get_cs_size would use rom_data_lookup from flash during a __no_inline_not_in_flash_func
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Flash operations overwrite PSRAM QMI configuration registers
3 participants