rp: Add rp_attach and rp_detach callbacks
Query JEDEC ID of flash chip on attach to be able to decode flash chip size.
This commit is contained in:
parent
354e37fbad
commit
f2cb13cf36
|
@ -43,11 +43,14 @@
|
||||||
#include "cortexm.h"
|
#include "cortexm.h"
|
||||||
|
|
||||||
#define RP_ID "Raspberry RP2040"
|
#define RP_ID "Raspberry RP2040"
|
||||||
|
#define RP_MAX_TABLE_SIZE 0x80
|
||||||
#define BOOTROM_MAGIC ('M' | ('u' << 8) | (0x01 << 16))
|
#define BOOTROM_MAGIC ('M' | ('u' << 8) | (0x01 << 16))
|
||||||
#define BOOTROM_MAGIC_ADDR 0x00000010
|
#define BOOTROM_MAGIC_ADDR 0x00000010
|
||||||
#define XIP_FLASH_START 0x10000000
|
#define XIP_FLASH_START 0x10000000
|
||||||
#define SRAM_START 0x20000000
|
#define SRAM_START 0x20000000
|
||||||
#define SRAM_SIZE 0x42000
|
#define SRAM_SIZE 0x42000
|
||||||
|
#define SSI_DR0_ADDR 0x18000060
|
||||||
|
#define QSPI_CTRL_ADDR 0x4001800c
|
||||||
|
|
||||||
#define FLASHSIZE_4K_SECTOR (4 * 1024)
|
#define FLASHSIZE_4K_SECTOR (4 * 1024)
|
||||||
#define FLASHSIZE_32K_BLOCK (32 * 1024)
|
#define FLASHSIZE_32K_BLOCK (32 * 1024)
|
||||||
|
@ -66,7 +69,7 @@
|
||||||
#define FLASHCMD_BLOCK32K_ERASE 0x52
|
#define FLASHCMD_BLOCK32K_ERASE 0x52
|
||||||
#define FLASHCMD_BLOCK64K_ERASE 0xd8
|
#define FLASHCMD_BLOCK64K_ERASE 0xd8
|
||||||
#define FLASHCMD_CHIP_ERASE 0x60
|
#define FLASHCMD_CHIP_ERASE 0x60
|
||||||
#define FLASHCMD_READ_ID 0x9F
|
#define FLASHCMD_READ_JEDEC_ID 0x9F
|
||||||
|
|
||||||
struct rp_priv_s {
|
struct rp_priv_s {
|
||||||
uint16_t _debug_trampoline;
|
uint16_t _debug_trampoline;
|
||||||
|
@ -391,6 +394,85 @@ static void rp_add_flash(target *t, uint32_t addr, size_t length)
|
||||||
target_add_flash(t, f);
|
target_add_flash(t, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rp_ssel_active(target *t, bool active)
|
||||||
|
{
|
||||||
|
const uint32_t qspi_ctrl_outover_low = 2UL << 8;
|
||||||
|
const uint32_t qspi_ctrl_outover_high = 3UL << 8;
|
||||||
|
uint32_t state = (active) ? qspi_ctrl_outover_low : qspi_ctrl_outover_high;
|
||||||
|
uint32_t val = target_mem_read32(t, QSPI_CTRL_ADDR);
|
||||||
|
val = (val & ~qspi_ctrl_outover_high) | state;
|
||||||
|
target_mem_write32(t, QSPI_CTRL_ADDR, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t rp_read_flash_chip(target *t, uint32_t cmd)
|
||||||
|
{
|
||||||
|
uint32_t value = 0;
|
||||||
|
|
||||||
|
rp_ssel_active(t, true);
|
||||||
|
|
||||||
|
/* write command into SPI peripheral's FIFO */
|
||||||
|
for (int count = 0; (count < 4); count++)
|
||||||
|
target_mem_write32(t, SSI_DR0_ADDR, cmd);
|
||||||
|
|
||||||
|
/* now we have an entry in the receive FIFO for each write */
|
||||||
|
for (int count = 0; (count < 4); count++) {
|
||||||
|
uint32_t status = target_mem_read32(t, SSI_DR0_ADDR);
|
||||||
|
value |= (status & 0xFF) << 24;
|
||||||
|
value >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
rp_ssel_active(t, false);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t rp_get_flash_length(target *t)
|
||||||
|
{
|
||||||
|
uint32_t size = MAX_FLASH;
|
||||||
|
uint32_t flash_id = rp_read_flash_chip(t, FLASHCMD_READ_JEDEC_ID);
|
||||||
|
|
||||||
|
DEBUG_INFO("Flash device ID: %08" PRIx32 "\n", flash_id);
|
||||||
|
|
||||||
|
uint8_t size_log2 = (flash_id & 0xff0000) >> 16;
|
||||||
|
if (size_log2 >= 8 || size_log2 <= 34)
|
||||||
|
size = 1 << size_log2;
|
||||||
|
|
||||||
|
DEBUG_INFO("Flash size: %d MB\n", (int)(size / 1024 / 1024));
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool rp_attach(target *t)
|
||||||
|
{
|
||||||
|
if (!cortexm_attach(t))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
|
||||||
|
uint16_t *table = alloca(RP_MAX_TABLE_SIZE);
|
||||||
|
uint16_t table_offset = target_mem_read32( t, BOOTROM_MAGIC_ADDR + 4);
|
||||||
|
if (!table || target_mem_read(t, table, table_offset, RP_MAX_TABLE_SIZE))
|
||||||
|
return false;
|
||||||
|
if (rp2040_fill_table(ps, table, RP_MAX_TABLE_SIZE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Free previously loaded memory map */
|
||||||
|
target_mem_map_free(t);
|
||||||
|
|
||||||
|
rp_flash_prepare(t);
|
||||||
|
uint32_t size = rp_get_flash_length(t);
|
||||||
|
rp_flash_resume(t);
|
||||||
|
|
||||||
|
rp_add_flash(t, XIP_FLASH_START, size);
|
||||||
|
target_add_ram(t, SRAM_START, SRAM_SIZE);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rp_detach(target *t)
|
||||||
|
{
|
||||||
|
cortexm_detach(t);
|
||||||
|
}
|
||||||
|
|
||||||
bool rp_probe(target *t)
|
bool rp_probe(target *t)
|
||||||
{
|
{
|
||||||
/* Check bootrom magic*/
|
/* Check bootrom magic*/
|
||||||
|
@ -403,26 +485,17 @@ bool rp_probe(target *t)
|
||||||
if ((boot_magic >> 24) == 1)
|
if ((boot_magic >> 24) == 1)
|
||||||
DEBUG_WARN("Old Bootrom Version 1!\n");
|
DEBUG_WARN("Old Bootrom Version 1!\n");
|
||||||
#endif
|
#endif
|
||||||
#define RP_MAX_TABLE_SIZE 0x80
|
|
||||||
uint16_t *table = alloca(RP_MAX_TABLE_SIZE);
|
|
||||||
uint16_t table_offset = target_mem_read32( t, BOOTROM_MAGIC_ADDR + 4);
|
|
||||||
if (!table || target_mem_read(t, table, table_offset, RP_MAX_TABLE_SIZE))
|
|
||||||
return false;
|
|
||||||
struct rp_priv_s *priv_storage = calloc(1, sizeof(struct rp_priv_s));
|
struct rp_priv_s *priv_storage = calloc(1, sizeof(struct rp_priv_s));
|
||||||
if (!priv_storage) { /* calloc failed: heap exhaustion */
|
if (!priv_storage) { /* calloc failed: heap exhaustion */
|
||||||
DEBUG_WARN("calloc: failed in %s\n", __func__);
|
DEBUG_WARN("calloc: failed in %s\n", __func__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (rp2040_fill_table(priv_storage, table, RP_MAX_TABLE_SIZE)) {
|
|
||||||
free(priv_storage);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
t->target_storage = (void*)priv_storage;
|
t->target_storage = (void*)priv_storage;
|
||||||
|
|
||||||
rp_add_flash(t, XIP_FLASH_START, MAX_FLASH);
|
|
||||||
t->driver = RP_ID;
|
t->driver = RP_ID;
|
||||||
t->target_options |= CORTEXM_TOPT_INHIBIT_SRST;
|
t->target_options |= CORTEXM_TOPT_INHIBIT_SRST;
|
||||||
target_add_ram(t, SRAM_START, SRAM_SIZE);
|
t->attach = rp_attach;
|
||||||
|
t->detach = rp_detach;
|
||||||
target_add_commands(t, rp_cmd_list, RP_ID);
|
target_add_commands(t, rp_cmd_list, RP_ID);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue