Skip to content

Commit

Permalink
Added NXP IFC NOR Flash erase/write.
Browse files Browse the repository at this point in the history
  • Loading branch information
dgarske committed Oct 3, 2023
1 parent 63c5688 commit ed15a28
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 86 deletions.
4 changes: 2 additions & 2 deletions config/examples/nxp-t1024.config
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ DEBUG_ELF=0
# NOR Base Address
ARCH_FLASH_OFFSET?=0xEC000000

# Flash Sector Size
WOLFBOOT_SECTOR_SIZE=0x10000
# Flash Sector Size (128KB)
WOLFBOOT_SECTOR_SIZE=0x20000

# wolfBoot start address
WOLFBOOT_ORIGIN=0xEFF40000
Expand Down
2 changes: 1 addition & 1 deletion docs/Targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -1265,7 +1265,7 @@ Reset Configuration Word (RCW):

Flash is NOR on IFC CS0 (0x0_EC00_0000) 64MB (default).

Default NOR Flash Memory Layout (64MB):
Default NOR Flash Memory Layout (64MB) (128KB block, 1K page)

| Description | Address | Size |
| ----------------- | ---------- | ------------------- |
Expand Down
6 changes: 3 additions & 3 deletions hal/nxp_p1021.c
Original file line number Diff line number Diff line change
Expand Up @@ -935,15 +935,15 @@ static void hal_ddr_init(void)

/* Set values, but do not enable the DDR yet */
set32(DDR_SDRAM_CFG, ((DDR_SDRAM_CFG_VAL & ~DDR_SDRAM_CFG_MEM_EN)));
asm volatile("sync;isync");
__asm__ __volatile__("sync;isync");

/* busy wait for ~500us */
udelay(500);

/* Enable controller */
reg = get32(DDR_SDRAM_CFG) & ~DDR_SDRAM_CFG_BI;
set32(DDR_SDRAM_CFG, reg | DDR_SDRAM_CFG_MEM_EN);
asm volatile("sync;isync");
__asm__ __volatile__("sync;isync");

/* Wait for data initialization to complete */
while (get32(DDR_SDRAM_CFG_2) & DDR_SDRAM_CFG_2_D_INIT) {
Expand Down Expand Up @@ -1438,7 +1438,7 @@ static void hal_mp_up(uint32_t bootpg)
bpcr = get32(ECM_EEBPCR);
bpcr |= ECM_EEBPCR_CPU_EN(up);
set32(ECM_EEBPCR, bpcr);
asm volatile("sync; isync; msync");
__asm__ __volatile__("sync; isync; msync");

/* wait for other core to start */
cpu_up_mask = (1 << whoami);
Expand Down
6 changes: 3 additions & 3 deletions hal/nxp_ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -545,13 +545,13 @@
#define WC_STRINGIFY(str) _WC_STRINGIFY_L2(str)
#endif

#define mtspr(rn, v) asm volatile("mtspr " WC_STRINGIFY(rn) ",%0" : : "r" (v))
#define mtspr(rn, v) __asm__ __volatile__("mtspr " WC_STRINGIFY(rn) ",%0" : : "r" (v))

#define mfmsr() ({ \
unsigned int rval; \
asm volatile("mfmsr %0" : "=r" (rval)); rval; \
__asm__ __volatile__("mfmsr %0" : "=r" (rval)); rval; \
})
#define mtmsr(v) asm volatile("mtmsr %0" : : "r" (v))
#define mtmsr(v) __asm__ __volatile__("mtmsr %0" : : "r" (v))


#ifndef __ASSEMBLER__
Expand Down
204 changes: 142 additions & 62 deletions hal/nxp_t1024.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,43 @@
#include "target.h"
#include "printf.h"
#include "string.h"
#include "image.h" /* for RAMFUNCTION */
#include "hal.h"
#include "nxp_ppc.h"

/* Tested on T1024E Rev 1.0, e5500 core 2.1, PVR 8024_1021 and SVR 8548_0010 */
/* IFC: CS0 NOR, CS1 MRAM, CS2 CPLD, CS3, MPU CPLD */
/* DDR: DDR4 w/ECC (5 chips MT40A256M16GE-083EIT) - SPD on I2C1 at Addr 0x51 */

/* Tests */
#if 1
//#define TEST_DDR
//#define TEST_FLASH
//#define TEST_TPM
#endif
/* Debugging */
/* #define DEBUG_FLASH */
/* #define DEBUG_ESPI 1 */

#define ENABLE_DDR
#define ENABLE_BUS_CLK_CALC
#define ENABLE_IFC
#ifndef BUILD_LOADER_STAGE1
#define ENABLE_CPLD
//#define ENABLE_CPLD
#define ENABLE_QE /* QUICC Engine */
//#define ENABLE_FMAN
//#define ENABLE_MP /* multi-core support */
#if defined(WOLFBOOT_TPM) || defined(TEST_TPM)
#define ENABLE_ESPI /* SPI for TPM */
#endif

/* Tests */
#if 1
//#define TEST_DDR
//#define TEST_FLASH
//#define TEST_TPM
#endif
#endif

#define USE_ERRATA_DDRA008378
#define USE_ERRATA_DDRA008109
#define USE_ERRATA_DDRA009663
#define USE_ERRATA_DDRA009942

/* Foward declarations */
#if defined(ENABLE_DDR) && defined(TEST_DDR)
static int test_ddr(void);
#endif
Expand All @@ -64,6 +69,8 @@ static int test_flash(void);
static int test_tpm(void);
#endif

static void hal_flash_unlock_sector(uint32_t sector);

#ifdef ENABLE_ESPI
#include "spi_drv.h" /* for transfer flags */
#endif
Expand Down Expand Up @@ -321,7 +328,6 @@ enum ifc_amask_sizes {
IFC_AMASK_4GB = 0x0000,
};


/* NOR Flash */
#define FLASH_BANK_SIZE (64*1024*1024)
#define FLASH_PAGE_SIZE (1024) /* program buffer */
Expand Down Expand Up @@ -380,6 +386,16 @@ enum ifc_amask_sizes {
#define AMD_STATUS_TOGGLE 0x40
#define AMD_STATUS_ERROR 0x20

/* Flash IO Helpers */
#if FLASH_CFI_WIDTH == 16
#define FLASH_IO8_WRITE(sec, n, val) *((volatile uint16_t*)(FLASH_BASE_ADDR + (FLASH_SECTOR_SIZE * (sec)) + ((n) * 2))) = (((val) << 8) | (val))
#define FLASH_IO16_WRITE(sec, n, val) *((volatile uint16_t*)(FLASH_BASE_ADDR + (FLASH_SECTOR_SIZE * (sec)) + ((n) * 2))) = (val)
#define FLASH_IO8_READ(sec, n) (uint8_t)(*((volatile uint16_t*)(FLASH_BASE_ADDR + (FLASH_SECTOR_SIZE * (sec)) + ((n) * 2))))
#else
#define FLASH_IO8_WRITE(sec, n, val) *((volatile uint8_t*)(FLASH_BASE_ADDR + (FLASH_SECTOR_SIZE * (sec)) + (n))) = (val)
#define FLASH_IO8_READ(sec, n) *((volatile uint8_t*)(FLASH_BASE_ADDR + (FLASH_SECTOR_SIZE * (sec)) + (n)))
#endif


/* CPLD */
#define CPLD_BASE 0xFFDF0000
Expand Down Expand Up @@ -774,51 +790,30 @@ void uart_write(const char* buf, uint32_t sz)
}
#endif /* DEBUG_UART */

#if FLASH_CFI_WIDTH == 16
#define FLASH_IO8_WRITE(n, val) *((volatile uint16_t*)(FLASH_BASE_ADDR + (n))) = (((val) << 8) | (val))
#define FLASH_IO8_READ(n) (uint8_t)(*((volatile uint16_t*)(FLASH_BASE_ADDR + (n))) >> 8)
#else
#define FLASH_IO8_WRITE(n, val) *((volatile uint8_t*)(FLASH_BASE_ADDR + (n))) = (val)
#define FLASH_IO8_READ(n) *((volatile uint8_t*)(FLASH_BASE_ADDR + (n)))
#endif

#ifndef BUILD_LOADER_STAGE1
static int RAMFUNCTION hal_flash_getid(void)
#if defined(ENABLE_IFC) && !defined(BUILD_LOADER_STAGE1)
static int hal_flash_getid(void)
{
#ifdef ENABLE_IFC
int i;
uint8_t manfid[4];

/* Get Manufacture ID */

#if 0
/* Unlock sequence */
FLASH_IO8_WRITE(0xAAA, AMD_CMD_UNLOCK_START);
FLASH_IO8_WRITE(0x555, AMD_CMD_UNLOCK_ACK);
#endif

/* Reset */
//FLASH_IO8_WRITE(0, AMD_CMD_RESET);
//udelay(1);

/* Read CFI */
FLASH_IO8_WRITE(0xAAA, FLASH_CMD_CFI);
hal_flash_unlock_sector(0);
FLASH_IO8_WRITE(0, 0x555, FLASH_CMD_READ_ID);
udelay(1000);

for (i=0; i<(int)sizeof(manfid); i++) {
manfid[i] = FLASH_IO8_READ(i);
}
manfid[0] = FLASH_IO8_READ(0, 0); /* Manufacture Code */
manfid[1] = FLASH_IO8_READ(0, 1); /* Device Code 1 */
manfid[2] = FLASH_IO8_READ(0, 14); /* Device Code 2 */
manfid[3] = FLASH_IO8_READ(0, 15); /* Device Code 3 */

/* Leave READ CFI */
FLASH_IO8_WRITE(0, AMD_CMD_RESET);
/* Exit read info */
FLASH_IO8_WRITE(0, 0, AMD_CMD_RESET);
udelay(1);

wolfBoot_printf("Flash ID: 0x%x 0x%x 0x%x 0x%x\n",
wolfBoot_printf("Flash: Mfg 0x%x, Device Code 0x%x/0x%x/0x%x\n",
manfid[0], manfid[1], manfid[2], manfid[3]);
#endif /* ENABLE_IFC */

return 0;
}
#endif /* BUILD_LOADER_STAGE1 */
#endif /* ENABLE_IFC && !BUILD_LOADER_STAGE1 */

static void hal_flash_init(void)
{
Expand Down Expand Up @@ -941,16 +936,16 @@ static void hal_ddr_init(void)

/* Set values, but do not enable the DDR yet */
set32(DDR_SDRAM_CFG, DDR_SDRAM_CFG_VAL & ~DDR_SDRAM_CFG_MEM_EN);
asm volatile("sync;isync");
__asm__ __volatile__("sync;isync");

/* busy wait for ~500us */
udelay(500);
asm volatile("sync;isync");
__asm__ __volatile__("sync;isync");

/* Enable controller */
reg = get32(DDR_SDRAM_CFG) & ~DDR_SDRAM_CFG_BI;
set32(DDR_SDRAM_CFG, reg | DDR_SDRAM_CFG_MEM_EN);
asm volatile("sync;isync");
__asm__ __volatile__("sync;isync");

#ifdef USE_ERRATA_DDRA008378
/* Errata A-008378: training in DDR4 mode */
Expand Down Expand Up @@ -1331,7 +1326,7 @@ static void hal_mp_up(uint32_t bootpg)

/* Release the CPU core(s) */
set32(DCFG_BRR, all_cores);
asm volatile("sync; isync; msync");
__asm__ __volatile__("sync; isync; msync");

/* wait for other core to start */
while (timeout) {
Expand Down Expand Up @@ -1447,29 +1442,112 @@ void hal_init(void)
#endif
}

int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
static int hal_flash_is_busy(uint32_t sector)
{
(void)address;
(void)data;
(void)len;
/* TODO: Implement NOR flash write using IFC */
uint8_t read1, read2;
FLASH_IO8_WRITE(sector, 0, AMD_STATUS_TOGGLE);
read1 = FLASH_IO8_READ(sector, 0);
read2 = FLASH_IO8_READ(sector, 0);
return (read1 == read2); /* watch for state change */
}

int hal_flash_write(uint32_t address, const uint8_t *data, int len)
{
uint32_t pos, i, sector, offset, xfer;

/* adjust for flash base */
if (address >= FLASH_BASE_ADDR)
address -= FLASH_BASE_ADDR;

#ifdef DEBUG_FLASH
wolfBoot_printf("Flash Write: Ptr %p -> Addr 0x%x (len %d)\n",
data, address, len);
#endif

pos = 0;
while (len > 0) {
/* dertermine sector address */
sector = (address / FLASH_SECTOR_SIZE);
offset = address - (sector * FLASH_SECTOR_SIZE);
offset /= (FLASH_CFI_WIDTH/8);
xfer = len;
if (xfer > FLASH_PAGE_SIZE)
xfer = FLASH_PAGE_SIZE;
xfer /= (FLASH_CFI_WIDTH/8);

#ifdef DEBUG_FLASH
wolfBoot_printf("Flash Write: Sector %d, Offset %d, Len %d, Pos %d\n",
sector, offset, xfer, pos);
#endif

hal_flash_unlock_sector(sector);
FLASH_IO8_WRITE(sector, offset, AMD_CMD_WRITE_TO_BUFFER);
FLASH_IO8_WRITE(sector, offset, xfer);

for (i=0; i<xfer; i+=(FLASH_CFI_WIDTH/8)) {
const uint8_t* ptr = &data[pos + i];
#if FLASH_CFI_WIDTH == 16
FLASH_IO16_WRITE(sector, offset + i, *((const uint16_t*)ptr));
#else
FLASH_IO8_WRITE(sector, offset + i, *ptr);
#endif
}
FLASH_IO8_WRITE(sector, offset, AMD_CMD_WRITE_BUFFER_CONFIRM);

/* poll for program completion */
while (hal_flash_is_busy(sector));

address += xfer;
len -= xfer;
pos += xfer;
}
return 0;
}

int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
int hal_flash_erase(uint32_t address, int len)
{
(void)address;
(void)len;
/* TODO: Implement NOR flash erase using IFC */
uint32_t sector;

/* adjust for flash base */
if (address >= FLASH_BASE_ADDR)
address -= FLASH_BASE_ADDR;

while (len > 0) {
/* dertermine sector address */
sector = (address / FLASH_SECTOR_SIZE);

#ifdef DEBUG_FLASH
wolfBoot_printf("Flash Erase: Sector %d, Address 0x%x, Len %d\n",
sector, address, len);
#endif

hal_flash_unlock_sector(sector);
FLASH_IO8_WRITE(sector, 0x555, AMD_CMD_ERASE_START);
hal_flash_unlock_sector(sector);
FLASH_IO8_WRITE(sector, 0, AMD_CMD_ERASE_SECTOR);

/* poll for erase completion */
while (hal_flash_is_busy(sector));

address += FLASH_SECTOR_SIZE;
len -= FLASH_SECTOR_SIZE;
}
return 0;
}

void RAMFUNCTION hal_flash_unlock(void)
static void hal_flash_unlock_sector(uint32_t sector)
{
/* Unlock sequence */
FLASH_IO8_WRITE(sector, 0x555, AMD_CMD_UNLOCK_START);
FLASH_IO8_WRITE(sector, 0x2AA, AMD_CMD_UNLOCK_ACK);
}

void hal_flash_unlock(void)
{
hal_flash_unlock_sector(0);
}

void RAMFUNCTION hal_flash_lock(void)
void hal_flash_lock(void)
{

}
Expand Down Expand Up @@ -1535,21 +1613,23 @@ static int test_ddr(void)
#if defined(ENABLE_IFC) && defined(TEST_FLASH)

#ifndef TEST_ADDRESS
#define TEST_ADDRESS (2 * 0x100000) /* 2MB */
/* 0xEC100000 (1MB offset) */
#define TEST_ADDRESS (FLASH_BASE_ADDR + (1 * 0x100000))
#endif

/* #define TEST_FLASH_READONLY */

static uint32_t pageData[WOLFBOOT_SECTOR_SIZE/4]; /* force 32-bit alignment */
static uint32_t pageData[FLASH_PAGE_SIZE/sizeof(uint32_t)]; /* force 32-bit alignment */

static int test_flash(void)
{
int ret;
uint32_t i;
uint8_t* pagePtr = (uint8_t*)FLASH_BASE_ADDR + TEST_ADDRESS;
uint8_t* pagePtr = (uint8_t*)TEST_ADDRESS;

#ifndef TEST_FLASH_READONLY
/* Erase sector */
ret = hal_flash_erase(TEST_ADDRESS, WOLFBOOT_SECTOR_SIZE);
ret = hal_flash_erase(TEST_ADDRESS, sizeof(pageData));
wolfBoot_printf("Erase Sector: Ret %d\n", ret);

/* Write Pages */
Expand Down
Loading

0 comments on commit ed15a28

Please sign in to comment.