diff --git a/config/examples/nxp-t1024.config b/config/examples/nxp-t1024.config index 211ead7a4..895f9f5b7 100644 --- a/config/examples/nxp-t1024.config +++ b/config/examples/nxp-t1024.config @@ -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 diff --git a/docs/Targets.md b/docs/Targets.md index 2fd3519a8..6a0b0e5d9 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -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 | | ----------------- | ---------- | ------------------- | diff --git a/hal/nxp_p1021.c b/hal/nxp_p1021.c index 7796a30a1..2cba23bc6 100644 --- a/hal/nxp_p1021.c +++ b/hal/nxp_p1021.c @@ -935,7 +935,7 @@ 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); @@ -943,7 +943,7 @@ static void hal_ddr_init(void) /* 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) { @@ -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); diff --git a/hal/nxp_ppc.h b/hal/nxp_ppc.h index 15f756d3e..4ad66c196 100644 --- a/hal/nxp_ppc.h +++ b/hal/nxp_ppc.h @@ -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__ diff --git a/hal/nxp_t1024.c b/hal/nxp_t1024.c index 95e7f2d55..63ca31f67 100644 --- a/hal/nxp_t1024.c +++ b/hal/nxp_t1024.c @@ -22,31 +22,35 @@ #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 @@ -54,6 +58,7 @@ #define USE_ERRATA_DDRA009663 #define USE_ERRATA_DDRA009942 +/* Foward declarations */ #if defined(ENABLE_DDR) && defined(TEST_DDR) static int test_ddr(void); #endif @@ -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 @@ -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 */ @@ -380,6 +386,26 @@ enum ifc_amask_sizes { #define AMD_STATUS_TOGGLE 0x40 #define AMD_STATUS_ERROR 0x20 +/* Flash unlock addresses */ +#if FLASH_CFI_WIDTH == 16 +#define FLASH_UNLOCK_ADDR1 0x555 +#define FLASH_UNLOCK_ADDR2 0x2AA +#else +#define FLASH_UNLOCK_ADDR1 0xAAA +#define FLASH_UNLOCK_ADDR2 0x555 +#endif + +/* 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)))) +#define FLASH_IO16_READ(sec, n) *((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 @@ -774,51 +800,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, FLASH_UNLOCK_ADDR1, 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) { @@ -941,16 +946,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 */ @@ -1331,7 +1336,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) { @@ -1447,29 +1452,143 @@ void hal_init(void) #endif } -int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) +/* wait for toggle to stop and status mask to be met within microsecond timeout */ +static int hal_flash_status_wait(uint32_t sector, uint16_t mask, uint32_t timeout_us) { - (void)address; - (void)data; - (void)len; - /* TODO: Implement NOR flash write using IFC */ + int ret = 0; + uint32_t timeout = 0; + uint16_t read1, read2; + + do { + /* detection of completion happens when reading status bits DQ6 and DQ2 stop toggling (0x44) */ + /* Only the */ + read1 = FLASH_IO8_READ(sector, 0); + if ((read1 & AMD_STATUS_TOGGLE) == 0) + read1 = FLASH_IO8_READ(sector, 0); + read2 = FLASH_IO8_READ(sector, 0); + if ((read2 & AMD_STATUS_TOGGLE) == 0) + read2 = FLASH_IO8_READ(sector, 0); + #ifdef DEBUG_FLASH + wolfBoot_printf("Wait toggle %x -> %x\n", read1, read2); + #endif + if (read1 == read2 && ((read1 & mask) == mask)) + break; + udelay(1); + } while (timeout++ < timeout_us); + if (timeout >= timeout_us) { + ret = -1; /* timeout */ + } +#ifdef DEBUG_FLASH + wolfBoot_printf("Wait done (%d tries): %x -> %x\n", + timeout, read1, read2); +#endif + return ret; +} + +int hal_flash_write(uint32_t address, const uint8_t *data, int len) +{ + uint32_t i, pos, sector, offset, xfer, nwords; + + /* 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; + nwords = 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); + #if FLASH_CFI_WIDTH == 16 + FLASH_IO16_WRITE(sector, offset, (nwords-1)); + #else + FLASH_IO8_WRITE(sector, offset, (nwords-1)); + #endif + + for (i=0; i= 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, Addr 0x%x, Len %d\n", + sector, address, len); + #endif + + hal_flash_unlock_sector(sector); + FLASH_IO8_WRITE(sector, FLASH_UNLOCK_ADDR1, AMD_CMD_ERASE_START); + hal_flash_unlock_sector(sector); + FLASH_IO8_WRITE(sector, 0, AMD_CMD_ERASE_SECTOR); + /* block erase timeout = 50us - for additional sectors */ + /* Typical is 200ms (max 1100ms) */ + + /* poll for erase completion - max 1.1 sec */ + hal_flash_status_wait(sector, 0x4C, 1100*1000); + + 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, FLASH_UNLOCK_ADDR1, AMD_CMD_UNLOCK_START); + FLASH_IO8_WRITE(sector, FLASH_UNLOCK_ADDR2, 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) { } @@ -1535,21 +1654,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 */ @@ -1560,6 +1681,9 @@ static int test_flash(void) wolfBoot_printf("Write Page: Ret %d\n", ret); #endif /* !TEST_FLASH_READONLY */ + /* invalidate cache */ + flush_cache((uint32_t)pagePtr, sizeof(pageData)); + wolfBoot_printf("Checking...\n"); ret = memcmp(pageData, pagePtr, sizeof(pageData)); if (ret != 0) { diff --git a/hal/nxp_t2080.c b/hal/nxp_t2080.c index dc344474d..adbdb302f 100644 --- a/hal/nxp_t2080.c +++ b/hal/nxp_t2080.c @@ -443,7 +443,7 @@ static void hal_ddr_init(void) /* Enable controller */ DDR_SDRAM_CFG |= DDR_SDRAM_CFG_MEM_EN; - asm volatile("sync;isync"); + __asm__ __volatile__("sync;isync"); /* Wait for data initialization is complete */ while ((DDR_SDRAM_CFG_2 & DDR_SDRAM_CFG_2_D_INIT)); diff --git a/src/boot_ppc.c b/src/boot_ppc.c index 6440daf80..1df610556 100644 --- a/src/boot_ppc.c +++ b/src/boot_ppc.c @@ -43,7 +43,7 @@ void write_tlb(uint32_t mas0, uint32_t mas1, uint32_t mas2, uint32_t mas3, mtspr(MAS2, mas2); mtspr(MAS3, mas3); mtspr(MAS7, mas7); - asm volatile("isync;msync;tlbwe;isync"); + __asm__ __volatile__("isync;msync;tlbwe;isync"); } void set_tlb(uint8_t tlb, uint8_t esel, uint32_t epn, uint32_t rpn, @@ -85,15 +85,16 @@ void invalidate_tlb(int tlb) void set_law(uint8_t idx, uint32_t addr_h, uint32_t addr_l, uint32_t trgt_id, uint32_t law_sz, int reset) { - if (reset) + if (reset) { set32(LAWAR(idx), 0); /* reset */ - #ifdef CORE_E500 - (void)addr_h; /* not used */ - set32(LAWBAR(idx), addr_l >> 12); - #else - set32(LAWBARH(idx), addr_h); - set32(LAWBARL(idx), addr_l); - #endif + } +#ifdef CORE_E500 + (void)addr_h; /* not used */ + set32(LAWBAR(idx), addr_l >> 12); +#else + set32(LAWBARH(idx), addr_h); + set32(LAWBARL(idx), addr_l); +#endif set32(LAWAR(idx), LAWAR_ENABLE | LAWAR_TRGT_ID(trgt_id) | law_sz); /* Read back so that we sync the writes */ @@ -143,18 +144,18 @@ void flush_cache(uint32_t start_addr, uint32_t size) for (addr = start; (addr <= end) && (addr >= start); addr += CACHE_LINE_SIZE) { - asm volatile("dcbst 0,%0" : : "r" (addr) : "memory"); + __asm__ __volatile__("dcbst 0,%0" : : "r" (addr) : "memory"); } /* wait for all dcbst to complete on bus */ - asm volatile("sync" : : : "memory"); + __asm__ __volatile__("sync" : : : "memory"); for (addr = start; (addr <= end) && (addr >= start); addr += CACHE_LINE_SIZE) { - asm volatile("icbi 0,%0" : : "r" (addr) : "memory"); + __asm__ __volatile__("icbi 0,%0" : : "r" (addr) : "memory"); } - asm volatile("sync" : : : "memory"); + __asm__ __volatile__("sync" : : : "memory"); /* flush prefetch queue */ - asm volatile("isync" : : : "memory"); + __asm__ __volatile__("isync" : : : "memory"); } #endif diff --git a/src/boot_ppc_start.S b/src/boot_ppc_start.S index 9ce6f2e45..9038566d8 100644 --- a/src/boot_ppc_start.S +++ b/src/boot_ppc_start.S @@ -462,11 +462,18 @@ flash_law: lwz r2, 8(r9) /* read back LAWAR (per 2.3.2 Configuring Local Access Windows) */ isync flash_tlb: - /* Flash: TLB 1, Entry 7, Super X/R/W, W, TS=0, 64/128M, IPROT */ + /* Flash: TLB 1, Entry 7, Super X/R/W, W/I/G, TS=0, 64/128M, IPROT */ /* Write is required for Write/Erase using CFI commands to base */ + #ifdef BUILD_LOADER_STAGE1 + /* Using XIP from this flash, so cannot use cache inhibit */ + #define FLASH_TLB_WING (MAS2_W | MAS2_G) + #else + /* IFC polling requires cache inhibit */ + #define FLASH_TLB_WING (MAS2_W | MAS2_I | MAS2_G) + #endif set_tlb(1, 7, FLASH_BASE_ADDR, FLASH_BASE_ADDR, FLASH_BASE_PHYS_HIGH, - MAS3_SX | MAS3_SW | MAS3_SR, MAS2_W | MAS2_G, 0, + MAS3_SX | MAS3_SW | MAS3_SR, FLASH_TLB_WING, 0, FLASH_TLB_PAGESZ, 1, r3); #else flash_tlb: