initialize psram (doesn't get used yet)
This commit is contained in:
parent
94381019f4
commit
c4734c7fc7
2 changed files with 146 additions and 0 deletions
|
|
@ -10,6 +10,7 @@
|
|||
#define HAS_USBHOST 1
|
||||
#define HAS_USBPIO 1
|
||||
|
||||
#define PSRAM_CHIP_SELECT (47u)
|
||||
//#define ILI9341 1
|
||||
//#define ST7789 1
|
||||
//#define SWAP_JOYSTICK 1
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
#include "pico.h"
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/adc.h"
|
||||
#include "hardware/structs/qmi.h"
|
||||
#include "hardware/structs/xip.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
@ -1433,12 +1436,154 @@ static bool emu_eraseConfig(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
size_t _psram_size;
|
||||
static void __no_inline_not_in_flash_func(setup_psram)(void) {
|
||||
_psram_size = 0;
|
||||
#ifdef PSRAM_CHIP_SELECT
|
||||
gpio_set_function(PSRAM_CHIP_SELECT, GPIO_FUNC_XIP_CS1);
|
||||
uint32_t save = save_and_disable_interrupts();
|
||||
// Try and read the PSRAM ID via direct_csr.
|
||||
qmi_hw->direct_csr = 30 << QMI_DIRECT_CSR_CLKDIV_LSB |
|
||||
QMI_DIRECT_CSR_EN_BITS;
|
||||
// Need to poll for the cooldown on the last XIP transfer to expire
|
||||
// (via direct-mode BUSY flag) before it is safe to perform the first
|
||||
// direct-mode operation
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
|
||||
// Exit out of QMI in case we've inited already
|
||||
qmi_hw->direct_csr |= QMI_DIRECT_CSR_ASSERT_CS1N_BITS;
|
||||
// Transmit as quad.
|
||||
qmi_hw->direct_tx = QMI_DIRECT_TX_OE_BITS |
|
||||
QMI_DIRECT_TX_IWIDTH_VALUE_Q << QMI_DIRECT_TX_IWIDTH_LSB |
|
||||
0xf5;
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
(void)qmi_hw->direct_rx;
|
||||
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS);
|
||||
|
||||
// Read the id
|
||||
qmi_hw->direct_csr |= QMI_DIRECT_CSR_ASSERT_CS1N_BITS;
|
||||
uint8_t kgd = 0;
|
||||
uint8_t eid = 0;
|
||||
for (size_t i = 0; i < 7; i++) {
|
||||
if (i == 0) {
|
||||
qmi_hw->direct_tx = 0x9f;
|
||||
} else {
|
||||
qmi_hw->direct_tx = 0xff;
|
||||
}
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_TXEMPTY_BITS) == 0) {
|
||||
}
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
if (i == 5) {
|
||||
kgd = qmi_hw->direct_rx;
|
||||
} else if (i == 6) {
|
||||
eid = qmi_hw->direct_rx;
|
||||
} else {
|
||||
(void)qmi_hw->direct_rx;
|
||||
}
|
||||
}
|
||||
// Disable direct csr.
|
||||
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS | QMI_DIRECT_CSR_EN_BITS);
|
||||
|
||||
if (kgd != 0x5D) {
|
||||
restore_interrupts(save);
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable quad mode.
|
||||
qmi_hw->direct_csr = 30 << QMI_DIRECT_CSR_CLKDIV_LSB |
|
||||
QMI_DIRECT_CSR_EN_BITS;
|
||||
// Need to poll for the cooldown on the last XIP transfer to expire
|
||||
// (via direct-mode BUSY flag) before it is safe to perform the first
|
||||
// direct-mode operation
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
|
||||
// RESETEN, RESET and quad enable
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
qmi_hw->direct_csr |= QMI_DIRECT_CSR_ASSERT_CS1N_BITS;
|
||||
if (i == 0) {
|
||||
qmi_hw->direct_tx = 0x66;
|
||||
} else if (i == 1) {
|
||||
qmi_hw->direct_tx = 0x99;
|
||||
} else {
|
||||
qmi_hw->direct_tx = 0x35;
|
||||
}
|
||||
while ((qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) != 0) {
|
||||
}
|
||||
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS);
|
||||
for (size_t j = 0; j < 20; j++) {
|
||||
asm ("nop");
|
||||
}
|
||||
(void)qmi_hw->direct_rx;
|
||||
}
|
||||
// Disable direct csr.
|
||||
qmi_hw->direct_csr &= ~(QMI_DIRECT_CSR_ASSERT_CS1N_BITS | QMI_DIRECT_CSR_EN_BITS);
|
||||
|
||||
qmi_hw->m[1].timing =
|
||||
QMI_M0_TIMING_PAGEBREAK_VALUE_1024 << QMI_M0_TIMING_PAGEBREAK_LSB | // Break between pages.
|
||||
3 << QMI_M0_TIMING_SELECT_HOLD_LSB | // Delay releasing CS for 3 extra system cycles.
|
||||
1 << QMI_M0_TIMING_COOLDOWN_LSB |
|
||||
1 << QMI_M0_TIMING_RXDELAY_LSB |
|
||||
16 << QMI_M0_TIMING_MAX_SELECT_LSB | // In units of 64 system clock cycles. PSRAM says 8us max. 8 / 0.00752 / 64 = 16.62
|
||||
7 << QMI_M0_TIMING_MIN_DESELECT_LSB | // In units of system clock cycles. PSRAM says 50ns.50 / 7.52 = 6.64
|
||||
2 << QMI_M0_TIMING_CLKDIV_LSB;
|
||||
qmi_hw->m[1].rfmt = (QMI_M0_RFMT_PREFIX_WIDTH_VALUE_Q << QMI_M0_RFMT_PREFIX_WIDTH_LSB |
|
||||
QMI_M0_RFMT_ADDR_WIDTH_VALUE_Q << QMI_M0_RFMT_ADDR_WIDTH_LSB |
|
||||
QMI_M0_RFMT_SUFFIX_WIDTH_VALUE_Q << QMI_M0_RFMT_SUFFIX_WIDTH_LSB |
|
||||
QMI_M0_RFMT_DUMMY_WIDTH_VALUE_Q << QMI_M0_RFMT_DUMMY_WIDTH_LSB |
|
||||
QMI_M0_RFMT_DUMMY_LEN_VALUE_24 << QMI_M0_RFMT_DUMMY_LEN_LSB |
|
||||
QMI_M0_RFMT_DATA_WIDTH_VALUE_Q << QMI_M0_RFMT_DATA_WIDTH_LSB |
|
||||
QMI_M0_RFMT_PREFIX_LEN_VALUE_8 << QMI_M0_RFMT_PREFIX_LEN_LSB |
|
||||
QMI_M0_RFMT_SUFFIX_LEN_VALUE_NONE << QMI_M0_RFMT_SUFFIX_LEN_LSB);
|
||||
qmi_hw->m[1].rcmd = 0xeb << QMI_M0_RCMD_PREFIX_LSB |
|
||||
0 << QMI_M0_RCMD_SUFFIX_LSB;
|
||||
qmi_hw->m[1].wfmt = (QMI_M0_WFMT_PREFIX_WIDTH_VALUE_Q << QMI_M0_WFMT_PREFIX_WIDTH_LSB |
|
||||
QMI_M0_WFMT_ADDR_WIDTH_VALUE_Q << QMI_M0_WFMT_ADDR_WIDTH_LSB |
|
||||
QMI_M0_WFMT_SUFFIX_WIDTH_VALUE_Q << QMI_M0_WFMT_SUFFIX_WIDTH_LSB |
|
||||
QMI_M0_WFMT_DUMMY_WIDTH_VALUE_Q << QMI_M0_WFMT_DUMMY_WIDTH_LSB |
|
||||
QMI_M0_WFMT_DUMMY_LEN_VALUE_NONE << QMI_M0_WFMT_DUMMY_LEN_LSB |
|
||||
QMI_M0_WFMT_DATA_WIDTH_VALUE_Q << QMI_M0_WFMT_DATA_WIDTH_LSB |
|
||||
QMI_M0_WFMT_PREFIX_LEN_VALUE_8 << QMI_M0_WFMT_PREFIX_LEN_LSB |
|
||||
QMI_M0_WFMT_SUFFIX_LEN_VALUE_NONE << QMI_M0_WFMT_SUFFIX_LEN_LSB);
|
||||
qmi_hw->m[1].wcmd = 0x38 << QMI_M0_WCMD_PREFIX_LSB |
|
||||
0 << QMI_M0_WCMD_SUFFIX_LSB;
|
||||
|
||||
restore_interrupts(save);
|
||||
|
||||
_psram_size = 1024 * 1024; // 1 MiB
|
||||
uint8_t size_id = eid >> 5;
|
||||
if (eid == 0x26 || size_id == 2) {
|
||||
_psram_size *= 8;
|
||||
} else if (size_id == 0) {
|
||||
_psram_size *= 2;
|
||||
} else if (size_id == 1) {
|
||||
_psram_size *= 4;
|
||||
}
|
||||
|
||||
// Mark that we can write to PSRAM.
|
||||
xip_ctrl_hw->ctrl |= XIP_CTRL_WRITABLE_M1_BITS;
|
||||
|
||||
// Test write to the PSRAM.
|
||||
volatile uint32_t *psram_nocache = (volatile uint32_t *)0x15000000;
|
||||
psram_nocache[0] = 0x12345678;
|
||||
volatile uint32_t readback = psram_nocache[0];
|
||||
if (readback != 0x12345678) {
|
||||
_psram_size = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/********************************
|
||||
* Initialization
|
||||
********************************/
|
||||
void emu_init(void)
|
||||
{
|
||||
setup_psram();
|
||||
|
||||
//board_init();
|
||||
stdio_init_all();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue