diff --git a/arch/arm/src/rp23xx/rp23xx_psram.c b/arch/arm/src/rp23xx/rp23xx_psram.c index 9aa6837c8f8..1acc2a2e546 100644 --- a/arch/arm/src/rp23xx/rp23xx_psram.c +++ b/arch/arm/src/rp23xx/rp23xx_psram.c @@ -44,6 +44,8 @@ #include +#include + #include "arm_internal.h" #include "rp23xx_gpio.h" #include "rp23xx_psram.h" @@ -73,18 +75,51 @@ #define QMI_DIRECT_TX_IWIDTH_Q (2 << RP23XX_QMI_DIRECT_TX_IWIDTH_SHIFT) -/* Final QMI M1 register values for the APS6404 in quad mode. Computed from - * the field layout in the RP2350 datasheet to match the Pico SDK: +/* APS6404 limits, as in the Pico SDK: 133 MHz SCK, 8 us maximum chip + * select time (refresh), 18 ns minimum deselect time. + */ + +#define PSRAM_MAX_FREQ 133000000 +#define PSRAM_MAX_SELECT_NS 8000ull +#define PSRAM_MIN_DESELECT_NS 18ull + +/* QMI M1 timing for clk_sys, computed as the Pico SDK does. Do not use a + * divisor of 1 above 100 MHz, and add one RX delay step above 100 MHz SCK. + */ + +#define PSRAM_CLKDIV_MIN \ + ((BOARD_SYS_FREQ + PSRAM_MAX_FREQ - 1) / PSRAM_MAX_FREQ) +#define PSRAM_CLKDIV \ + (PSRAM_CLKDIV_MIN == 1 && BOARD_SYS_FREQ > 100000000 ? 2 : PSRAM_CLKDIV_MIN) +#define PSRAM_RXDELAY \ + (PSRAM_CLKDIV + (BOARD_SYS_FREQ / PSRAM_CLKDIV > 100000000 ? 1 : 0)) +#define PSRAM_MAX_SELECT \ + (PSRAM_MAX_SELECT_NS * BOARD_SYS_FREQ / (64 * 1000000000ull)) +#define PSRAM_MIN_DESELECT \ + ((PSRAM_MIN_DESELECT_NS * BOARD_SYS_FREQ + 999999999) / 1000000000 - \ + (PSRAM_CLKDIV + 1) / 2) + +#if PSRAM_CLKDIV > 255 || PSRAM_RXDELAY > 7 || PSRAM_MAX_SELECT > 63 || \ + PSRAM_MIN_DESELECT > 31 +# error "BOARD_SYS_FREQ is out of range for the PSRAM timing" +#endif + +/* Final QMI M1 register values for the APS6404 in quad mode: * - * TIMING: COOLDOWN=1, PAGEBREAK=1024, SELECT_HOLD=3, MAX_SELECT=16, - * MIN_DESELECT=7, RXDELAY=1, CLKDIV=2. + * TIMING: COOLDOWN=1, PAGEBREAK=1024, and the values above. * RFMT: quad prefix/addr/suffix/dummy/data, 8-bit prefix, 24 dummy bits. * RCMD: read prefix 0xeb. * WFMT: quad prefix/addr/suffix/dummy/data, 8-bit prefix, no dummy. * WCMD: write prefix 0x38. */ -#define RP23XX_PSRAM_M1_TIMING 0x61a07102 +#define RP23XX_PSRAM_M1_TIMING \ + ((1 << RP23XX_QMI_TIMING_COOLDOWN_SHIFT) | \ + (2 << RP23XX_QMI_TIMING_PAGEBREAK_SHIFT) | \ + ((uint32_t)PSRAM_MAX_SELECT << RP23XX_QMI_TIMING_MAX_SELECT_SHIFT) | \ + ((uint32_t)PSRAM_MIN_DESELECT << RP23XX_QMI_TIMING_MIN_DESELECT_SHIFT) | \ + (PSRAM_RXDELAY << RP23XX_QMI_TIMING_RXDELAY_SHIFT) | \ + PSRAM_CLKDIV) #define RP23XX_PSRAM_M1_RFMT 0x000612aa #define RP23XX_PSRAM_M1_RCMD 0x000000eb #define RP23XX_PSRAM_M1_WFMT 0x000012aa