diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 11159bf3c2..4538a9d98a 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -207,9 +207,24 @@ jobs: nxp_t2080_test: uses: ./.github/workflows/test-build-powerpc.yml + # T2080 RDB DDR register values are not yet populated (placeholders in + # nxp_t2080.h), so CI must select a board with complete DDR config. + nxp_t2080_test_naii_68ppc2: + uses: ./.github/workflows/test-build-powerpc.yml + with: + arch: ppc + config-file: ./config/examples/nxp-t2080.config + make-args: CFLAGS_EXTRA=-DBOARD_NAII_68PPC2 + + # VPX3-152 compile test: validates board-specific code paths build cleanly. + # Uses default config addresses (128MB layout); real hardware needs the + # VPX3-152 address overrides uncommented in .config. + nxp_t2080_vpx3152_test: + uses: ./.github/workflows/test-build-powerpc.yml with: arch: ppc config-file: ./config/examples/nxp-t2080.config + make-args: CFLAGS_EXTRA=-DBOARD_CW_VPX3152 nxp_ls1028a_test: uses: ./.github/workflows/test-build.yml diff --git a/docs/Targets.md b/docs/Targets.md index fbc02e6181..54614ec42a 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -4009,16 +4009,28 @@ Flash factory_custom.bin to NOR base 0xE800_0000 ## NXP QorIQ T2080 PPC -The NXP QorIQ T2080 is a PPC e6500 based processor (four cores). Support has been tested with the NAII 68PPC2. +The NXP QorIQ T2080 is a PPC e6500 based processor (four cores). Three board +variants are supported: + +| Board | Config Define | Oscillator | DDR | NOR Flash | +|-------|---------------|-----------|-----|-----------| +| T2080 RDB (default) | _(none)_ | 66.66 MHz | DDR3L SODIMM | 128 MB @ `0xE8000000` | +| Curtiss-Wright VPX3-152 | `BOARD_CW_VPX3152` | 66.667 MHz | 4 GB DDR3L | 256 MB @ `0xF0000000` | +| NAII 68PPC2 | `BOARD_NAII_68PPC2` | 100 MHz | 8 GB DDR3 | 128 MB @ `0xE8000000` | + +> **Note:** The T2080 RDB DDR register values are placeholder stubs (all zeros +> with TODO comments in `hal/nxp_t2080.h`). DDR initialization will not succeed +> until you populate them from a U-Boot register dump. The NAII 68PPC2 and +> CW VPX3-152 DDR configs are populated and tested. Example configuration: [/config/examples/nxp-t2080.config](/config/examples/nxp-t2080.config). -Stock layout is default; for NAII 68PPC2, uncomment the "# NAII 68PPC2:" lines and comment the stock lines. +See [Board Selection](#board-selection) below for per-board setup. ### Design NXP T2080 PPC -The QorIQ requires a Reset Configuration Word (RCW) to define the boot parameters, which resides at the start of the flash (0xE8000000). +The QorIQ requires a Reset Configuration Word (RCW) to define the boot parameters, which resides at the start of the flash (`0xE8000000` for 128 MB boards, `0xF0000000` for the 256 MB CW VPX3-152). -The flash boot entry point is `0xEFFFFFFC`, which is an offset jump to wolfBoot initialization boot code. Initially the PowerPC core enables only a 4KB region to execute from. The initialization code (`src/boot_ppc_start.S`) sets the required CCSR and TLB for memory addressing and jumps to wolfBoot `main()`. +The flash boot entry point is the last 4 bytes of the NOR flash region (`0xEFFFFFFC` for 128 MB flash, `0xFFFFFFFC` for 256 MB flash), which is an offset jump to wolfBoot initialization boot code. Initially the PowerPC core enables only a 4KB region to execute from. The initialization code (`src/boot_ppc_start.S`) sets the required CCSR and TLB for memory addressing and jumps to wolfBoot `main()`. #### Boot Sequence and Hardware Constraints @@ -4041,7 +4053,7 @@ CPC SRAM is unreliable for stores on cold power-on — L1 dirty-line evictions through CoreNet to CPC cause bus errors (silent CPU checkstop with `MSR[ME]=0`). The fix (matching U-Boot) uses L1 locked D-cache as the initial 16KB stack: `dcbz` allocates cache lines without bus reads, `dcbtls` locks them so they -are never evicted. The locked lines at `L1_CACHE_ADDR` (0xF8E00000) are +are never evicted. The locked lines at `L1_CACHE_ADDR` (`0xF8E00000`; `0xEE800000` on VPX3-152) are entirely core-local. After DDR init in `hal_init()`, the stack relocates to DDR and the CPC switches from SRAM to L3 cache mode. @@ -4052,9 +4064,16 @@ boot, allowing L1 I-cache to cache instruction fetches while preventing speculative prefetch to the IFC. C code switches to `MAS2_I | MAS2_G` during flash write/erase (command mode), then `MAS2_M` for full caching afterward. +**CCSRBAR Relocation (CW VPX3-152 only)** + +The default CCSRBAR at `0xFE000000` (16 MB) falls within the VPX3-152's 256 MB +flash VA range (`0xF0000000`–`0xFFFFFFFF`). The startup assembly relocates +CCSRBAR to `0xEF000000` (just below flash). The CPC SRAM and L1 cache addresses +are also relocated to `0xEE900000`/`0xEE800000` to avoid overlap. + **RAMFUNCTION Constraints** -The NAII 68PPC2 NOR flash (two S29GL01GS x8 in parallel, 16-bit bus) enters +The NOR flash (two S29GL01GS x8 in parallel, 16-bit bus) enters command mode bank-wide — instruction fetches during program/erase return status data instead of code. All flash write/erase functions are marked `RAMFUNCTION`, placed in `.ramcode`, copied to DDR, and remapped via TLB9. Key rules: @@ -4094,30 +4113,38 @@ machine check (exceptions instead of checkstop), debug, and recoverable interrupt enable. Branch prediction (BUCSR) is deferred to `hal_init()` after DDR stack relocation. -**UART Debug Checkpoints (`DEBUG_UART=1`)** +### Building wolfBoot for NXP T2080 PPC + +By default wolfBoot will use `powerpc-linux-gnu-` cross-compiler prefix. These tools can be installed with the Debian package `gcc-powerpc-linux-gnu` (`sudo apt install gcc-powerpc-linux-gnu`). + +#### Board Selection -Assembly startup emits characters to UART0 (0xFE11C500, 115200 baud): +Copy the example config and select your board: +**T2080 RDB (default):** ``` -1 - CPC invalidate start A - L2 cluster enable start -2 - CPC invalidate done B - L2 cluster enabled -3 - CPC SRAM configured E - L1 cache setup -4 - SRAM LAW configured F - L1 I-cache enabled -5 - Flash TLB configured G - L1 D-cache enabled -6 - CCSRBAR TLB configured D - Stack ready (L1 locked cache) -7 - SRAM TLB configured Z - About to jump to C code -8 - CPC enabled +cp ./config/examples/nxp-t2080.config .config ``` -### Building wolfBoot for NXP T2080 PPC +**Curtiss-Wright VPX3-152:** +``` +cp ./config/examples/nxp-t2080.config .config +``` +Then in `.config`, uncomment `CFLAGS_EXTRA+=-DBOARD_CW_VPX3152` and all lines +marked with `# CW VPX3-152` (flash offset, SRAM address, origin, partition addresses, +DTS addresses). -By default wolfBoot will use `powerpc-linux-gnu-` cross-compiler prefix. These tools can be installed with the Debian package `gcc-powerpc-linux-gnu` (`sudo apt install gcc-powerpc-linux-gnu`). +**NAII 68PPC2:** +``` +cp ./config/examples/nxp-t2080.config .config +``` +Then in `.config`, uncomment `CFLAGS_EXTRA+=-DBOARD_NAII_68PPC2`. + +#### Build -The `make` creates a `factory.bin` image that can be programmed at `0xE8080000` -(For NAII 68PPC2, first edit `nxp-t2080.config` to uncomment the NAII 68PPC2 lines.) +The `make` creates a `factory.bin` image that can be programmed to the application partition address. ``` -cp ./config/examples/nxp-t2080.config .config make clean make keytools make @@ -4146,19 +4173,31 @@ CROSS_COMPILE_PATH=/opt/fsl-qoriq/2.0/sysroots/ppce6500-fsl-linux/usr ### Programming NXP T2080 PPC -NOR Flash Region: `0xE8000000 - 0xEFFFFFFF` (128 MB) +NOR Flash Regions: +- **T2080 RDB / NAII 68PPC2**: `0xE8000000 - 0xEFFFFFFF` (128 MB) +- **CW VPX3-152**: `0xF0000000 - 0xFFFFFFFF` (256 MB) -Flash Layout (with files): +Flash Layout (T2080 RDB / NAII 68PPC2, 128 MB flash): | Description | File | Address | | ----------- | ---- | ------- | -| Reset Configuration Word (RCW) | `68PPC2_RCW_v0p7.bin` | `0xE8000000` | +| Reset Configuration Word (RCW) | _(board-specific)_ | `0xE8000000` | | Frame Manager Microcode | `fsl_fman_ucode_t2080_r1.0.bin` | `0xE8020000` | | Signed Application | `test-app/image_v1_signed.bin` | `0xE8080000` | -| wolfBoot | `wolfboot.bin` | `0xEFF40000` | -| Boot Entry Point (with offset jump to init code) | | `0xEFFFFFFC` | +| wolfBoot | `wolfboot.bin` | `0xEFFE0000` | +| Boot Entry Point (offset jump to init code) | | `0xEFFFFFFC` | + +Flash Layout (CW VPX3-152, 256 MB flash): + +| Description | File | Address | +| ----------- | ---- | ------- | +| Reset Configuration Word (RCW) | _(board-specific)_ | `0xF0000000` | +| Frame Manager Microcode | `fsl_fman_ucode_t2080_r1.0.bin` | `0xF0020000` | +| Signed Application | `test-app/image_v1_signed.bin` | `0xF0080000` | +| wolfBoot | `wolfboot.bin` | `0xFFFE0000` | +| Boot Entry Point (offset jump to init code) | | `0xFFFFFFFC` | -Or program the `factory.bin` to `0xE8080000` +Or program the `factory.bin` to the application partition address. Example Boot Debug Output (with `DEBUG_UART=1`): @@ -4197,11 +4236,11 @@ See these TRACE32 demo script files: ``` DO flash_cfi.cmm -FLASH.ReProgram 0xEFF40000--0xEFFFFFFF /Erase -Data.LOAD.binary wolfboot.bin 0xEFF40000 +FLASH.ReProgram 0xEFFE0000--0xEFFFFFFF /Erase +Data.LOAD.binary wolfboot.bin 0xEFFE0000 FLASH.ReProgram.off -Data.LOAD.binary wolfboot.bin 0xEFF40000 /Verify +Data.LOAD.binary wolfboot.bin 0xEFFE0000 /Verify ``` Note: To disable the flash protection bits use: @@ -4219,7 +4258,11 @@ Data.Set 0xE8000000 %W 0x9090 Data.Set 0xE8000000 %W 0x0000 ``` -#### Flash Programming with CodeWarrior TAP +#### Flash Programming with CodeWarrior TAP (Experimental) + +> **Note:** CodeWarrior TAP debugging has not been validated for this target. +> Lauterbach TRACE32 is the recommended debug probe. The following steps are +> provided for reference only. In CodeWarrior use the `Flash Programmer` tool (see under Commander View -> Miscellaneous) * Connection: "CodeWarrior TAP Connection" @@ -4231,11 +4274,11 @@ In CodeWarrior use the `Flash Programmer` tool (see under Commander View -> Misc ``` tftp 1000000 wolfboot.bin -protect off eff40000 +C0000 -erase eff40000 +C0000 -cp.b 1000000 eff40000 C0000 -protect on eff40000 +C0000 -cmp.b 1000000 eff40000 C0000 +protect off effe0000 +20000 +erase effe0000 +20000 +cp.b 1000000 effe0000 20000 +protect on effe0000 +20000 +cmp.b 1000000 effe0000 20000 ``` ### Debugging NXP T2080 PPC @@ -4265,9 +4308,11 @@ sYmbol.SourcePATH.SetBaseDir ~/wolfBoot Data.LOAD.Elf wolfboot.elf /NoCODE /StripPART "/home/username/wolfBoot/" ``` -#### CodeWarrior TAP +#### CodeWarrior TAP (Experimental) -This is an example for debugging the T2080 with CodeWarrior TAP, however we were not successful using it. The Lauterbach is what we ended up using to debug. +> **Note:** CodeWarrior TAP debugging has not been validated for this target. +> Lauterbach TRACE32 is the recommended debug probe. The following steps are +> provided for reference only. Start GDB Proxy: diff --git a/hal/nxp_t2080.c b/hal/nxp_t2080.c index 27980b240e..473651673b 100644 --- a/hal/nxp_t2080.c +++ b/hal/nxp_t2080.c @@ -300,6 +300,9 @@ static void hal_reconfigure_cpc_as_cache(void) *dst++ = *src++; } + /* Ensure all stores have drained before flushing cache lines */ + __asm__ __volatile__("sync" ::: "memory"); + /* Flush D-cache and invalidate I-cache for the DDR copy */ flush_cache(DDR_RAMCODE_ADDR, ramcode_size); @@ -663,6 +666,13 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) int ret = 0; uint32_t i, sector, offset, nwords; const uint32_t width_bytes = FLASH_CFI_WIDTH / 8; + uint32_t addr_off = address; + + /* Bounds check */ + if (addr_off >= FLASH_BASE_ADDR) + addr_off -= FLASH_BASE_ADDR; + if (addr_off + (uint32_t)len > FLASH_BANK_SIZE) + return -1; /* Enforce alignment to flash bus width */ if ((address % width_bytes) != 0 || (len % width_bytes) != 0) { @@ -741,6 +751,13 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) { int ret = 0; uint32_t sector; + uint32_t addr_off = address; + + /* Bounds check */ + if (addr_off >= FLASH_BASE_ADDR) + addr_off -= FLASH_BASE_ADDR; + if (addr_off + (uint32_t)len > FLASH_BANK_SIZE) + return -1; /* adjust for flash base */ if (address >= FLASH_BASE_ADDR) @@ -848,7 +865,7 @@ extern uint32_t _bootpg_addr; static void hal_mp_up(uint32_t bootpg, uint32_t spin_table_ddr) { uint32_t all_cores, active_cores, whoami; - int timeout = 50, i; + int timeout = 10000, i; /* 10000 * 100us = 1s, matches U-Boot convention */ whoami = get32(PIC_WHOAMI); /* Get current running core number */ all_cores = ((1 << CPU_NUMCORES) - 1); /* mask of all cores */ @@ -990,7 +1007,8 @@ static void hal_mp_init(void) void hal_prepare_boot(void) { - + /* Intentionally empty: pre-boot cleanup (cache flush, interrupt disable) + * is handled by boot_ppc.c:do_boot(). */ } #ifdef MMU diff --git a/hal/nxp_t2080.h b/hal/nxp_t2080.h index 5428b7c60b..4c68489245 100644 --- a/hal/nxp_t2080.h +++ b/hal/nxp_t2080.h @@ -395,7 +395,12 @@ enum ifc_amask_sizes { #define DDR_ERR_INT_EN_VAL 0x0000001D #define DDR_ERR_SBE_VAL 0x00010000 #else -/* T2080 RDB: DDR register values */ +/* T2080 RDB DDR register values are not yet populated. + * To complete this, boot U-Boot on T2080 RDB and run the register dump + * commands below, then replace the 0x00000000 placeholders with actual values. */ +#ifdef ENABLE_DDR +#error "T2080 RDB DDR register values not populated. See TODO comments in nxp_t2080.h. Define BOARD_CW_VPX3152 or BOARD_NAII_68PPC2, or fill in DDR values from a U-Boot register dump." +#endif /* TODO: Fill ALL values from Phase 1 U-Boot register dump: * md.l 0xfe008000 4; md.l 0xfe008010 4 (CS BNDS) * md.l 0xfe008080 4; md.l 0xfe0080c0 4 (CS CONFIG) diff --git a/src/boot_ppc_mp.S b/src/boot_ppc_mp.S index 7dc74698a1..cdf81fe48f 100644 --- a/src/boot_ppc_mp.S +++ b/src/boot_ppc_mp.S @@ -119,7 +119,7 @@ branch_prediction: mr r4, r0 mr r5, r4 #endif - slwi r8, r5, 6 /* spin table is padded to 64 bytes */ + slwi r8, r5, 6 /* multiply by ENTRY_SIZE (64 bytes) */ /* use r10 for the spin table base address */ add r10, r3, r8 @@ -268,7 +268,7 @@ _second_half_boot_page: li r8, 3 stw r8, ENTRY_ADDR_LOWER(r10) - /* mask branch address (64MB) to setup tlb */ + /* Align branch address to 64MB boundary for TLB mapping below */ rlwinm r12, r4, 0, 0, 5 /* setup registers before jump */ @@ -280,7 +280,7 @@ _second_half_boot_page: li r4, 0 li r5, 0 li r6, 0 - lis r7, (64 * 1024 * 1024)@h + lis r7, (64 * 1024 * 1024)@h /* r7 = IMA size (64MB per ePAPR) */ li r8, 0 li r9, 0 @@ -309,7 +309,7 @@ _second_half_boot_page: rfi /* Reserve space for spin table entries */ - .align 6 /* 64-bytes */ + .align 6 /* 64-byte alignment for spin table entries (ENTRY_SIZE) */ .globl _spin_table _spin_table: .space CPU_NUMCORES * ENTRY_SIZE diff --git a/src/boot_ppc_start.S b/src/boot_ppc_start.S index 9b0609fc66..9c86a437b8 100644 --- a/src/boot_ppc_start.S +++ b/src/boot_ppc_start.S @@ -341,14 +341,26 @@ setup_interrupts: ori r9, r9, (CCSRBAR + 0x1000)@l create_temp_ccsr: - /* Create a temporary TLB entry for new and old location */ - /* CCSRBAR: TLB 0, Entry 0, Supervisor R/W, IG, TS=0, 4KB */ + /* Create temporary TLB0 entries for CCSRBAR relocation. + * + * TLB0 on e6500 is 4-way set-associative (2048 entries, 512 sets). + * The "esel" parameter selects the WAY within a set; the SET is + * determined by the virtual address (EPN). These two entries map + * different EPNs (CCSRBAR vs CCSRBAR+0x1000), so they fall in + * different TLB0 sets and do not overwrite each other. + * + * We use different ways (0 and 1) for visual clarity. Both entries + * are cleaned up by the TLB0 flash-invalidate (MMUCSR0) after + * relocation completes. */ + + /* CCSRBAR new location: TLB0 Way 0, Supervisor R/W, IG, TS=0, 4KB */ set_tlb(0, 0, CCSRBAR, CCSRBAR, CCSRBAR_PHYS_HIGH, MAS3_SR | MAS3_SW, MAS2_I | MAS2_G, 0, BOOKE_PAGESZ_4K, 0, r3); - set_tlb(0, 0, + /* CCSRBAR old location: TLB0 Way 1, Supervisor R/W, IG, TS=0, 4KB */ + set_tlb(0, 1, CCSRBAR + 0x1000, CCSRBAR_DEF, 0, MAS3_SR | MAS3_SW, MAS2_I | MAS2_G, 0, BOOKE_PAGESZ_4K, 0, r3);