Skip to content

Commit a616d04

Browse files
committed
Peer review and debug cleanups
1 parent 0c1c3ba commit a616d04

3 files changed

Lines changed: 67 additions & 69 deletions

File tree

docs/Targets.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3393,6 +3393,56 @@ Executing Initialization File: /opt/Freescale/CodeWarrior_PA_10.5.1/PA/PA_Suppor
33933393
thread break: Stopped, 0x0, 0x0, cpuPowerPCBig, Connected (state, tid, pid, cpu, target)
33943394
```
33953395
3396+
### Known Issues and Workarounds (NXP T2080)
3397+
3398+
#### RAMFUNCTION and Flash XIP Constraints
3399+
3400+
The NAII 68PPC2 uses two S29GL01GS x8 NOR flash chips in parallel (16-bit bus)
3401+
on IFC CS0. wolfBoot executes in place (XIP) from this flash. AMD NOR flash
3402+
enters command mode (autoselect, program, erase) bank-wide, so instruction
3403+
fetch from flash during these operations returns status data instead of code.
3404+
3405+
All flash write/erase functions and their helpers must be marked `RAMFUNCTION`
3406+
to place them in the `.ramcode` section, which is copied to DDR and remapped
3407+
via TLB9. Key constraints:
3408+
3409+
- **No calls to flash-resident functions**: The linker generates trampolines
3410+
for cross-section calls that jump back to flash addresses. `ram_udelay()`
3411+
originally called `hal_get_plat_clk()` (in flash `.text`) via a trampoline,
3412+
causing crashes during flash command mode. Fixed by pre-computing the delay
3413+
ticks constant (`ram_delay_ticks`) in `hal_flash_init()`.
3414+
3415+
- **Inline TLB and cache operations**: `hal_flash_cache_disable()` and
3416+
`hal_flash_cache_enable()` use `ram_write_tlb()` (inline mtspr) and direct
3417+
L1CSR0/L1CSR1 manipulation instead of calling flash-resident `set_tlb()`,
3418+
`invalidate_dcache()`, or `invalidate_icache()`.
3419+
3420+
- **Write-to-Buffer-Abort-Reset**: After a WBP failure (DQ1 abort or timeout),
3421+
plain `AMD_CMD_RESET` (0xF0) is ignored. The S29GL01GS requires the full
3422+
unlock + reset sequence to exit the WBP-abort state.
3423+
3424+
#### Write-Buffer-Program Timing
3425+
3426+
The S29GL01GS write-buffer-program (WBP) command sequence (unlock, 0x25,
3427+
word count, data, 0x29 confirm) is timing-sensitive. The entire sequence from
3428+
unlock through confirm must execute without bus-stalling delays (e.g., UART
3429+
output via `ram_putchar`). Inserting delays of ~87us (one UART character at
3430+
115200 baud) between WBP steps triggers a DQ1 abort on the flash.
3431+
3432+
#### Multi-Core (ENABLE_MP)
3433+
3434+
The e6500 L2 cache is per-cluster (shared by all 4 cores). Secondary cores
3435+
must NOT perform L2 flash-invalidate (L2FI), as this discards all dirty L2
3436+
lines including the primary core's stack and code. The `boot_ppc_mp.S`
3437+
secondary core startup skips L2 init for e6500 (primary core already
3438+
initialized the shared L2). Secondary cores only set L1 stash ID via L1CSR2.
3439+
3440+
#### Cold Boot Stack
3441+
3442+
CPC SRAM is unreliable as early stack on cold power-on due to CoreNet bus
3443+
errors. The T2080 port uses L1 locked D-cache (16KB at `L1_CACHE_ADDR`) as
3444+
the initial stack, matching the U-Boot approach.
3445+
33963446
33973447
## NXP MCXA153
33983448

hal/nxp_ppc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ static inline void uart_putc_early(char c)
205205
volatile uint8_t *thr = (volatile uint8_t *)(CCSRBAR + 0x11C500UL);
206206
while (!(*lsr & 0x20)) {} /* poll THRE */
207207
*thr = (uint8_t)c;
208+
__asm__ __volatile__("eieio" : : : "memory");
208209
}
209210
#else
210211
static inline void uart_putc_early(char c) { (void)c; }

hal/nxp_t2080.c

Lines changed: 16 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ static uint32_t hal_get_bus_clk(void)
169169
#define DELAY_US (TIMEBASE_HZ / 1000000)
170170
static void udelay(uint32_t delay_us)
171171
{
172-
wait_ticks(delay_us * DELAY_US);
172+
wait_ticks((unsigned long long)delay_us * DELAY_US);
173173
}
174174

175175
/* Pre-computed DELAY_US value for ram_udelay() (RAMFUNCTION).
@@ -710,19 +710,6 @@ static void RAMFUNCTION ram_putchar(char c)
710710
;
711711
set8(UART_THR(UART_SEL), c);
712712
}
713-
static void RAMFUNCTION ram_puthex4(uint8_t val)
714-
{
715-
val &= 0xF;
716-
ram_putchar(val < 10 ? '0' + val : 'A' + val - 10);
717-
}
718-
static void RAMFUNCTION ram_puthex16(uint16_t val)
719-
{
720-
ram_puthex4(val >> 12);
721-
ram_puthex4(val >> 8);
722-
ram_puthex4(val >> 4);
723-
ram_puthex4(val);
724-
}
725-
726713
/* RAM-resident microsecond delay using inline timebase reads.
727714
* Uses pre-computed ram_delay_ticks (initialized before flash ops).
728715
* Cannot call DELAY_US macro — it expands to hal_get_plat_clk() in flash
@@ -814,8 +801,10 @@ static void RAMFUNCTION hal_flash_clear_wp(void)
814801
__asm__ __volatile__("sync; isync");
815802
/* Verify WP cleared */
816803
cspr = get32(IFC_CSPR(0));
804+
#ifdef DEBUG_UART
817805
wolfBoot_printf("WP clear: CSPR0=0x%x%s\n", cspr,
818806
(cspr & IFC_CSPR_WP) ? " (FAILED)" : " (OK)");
807+
#endif
819808
}
820809
}
821810

@@ -939,14 +928,6 @@ static int RAMFUNCTION hal_flash_status_wait(uint32_t sector, uint16_t mask,
939928
read1 = FLASH_IO8_READ(sector, 0);
940929
read2 = FLASH_IO8_READ(sector, 0);
941930
#endif
942-
/* Print first iteration reads for diagnostics */
943-
if (timeout == 0) {
944-
ram_putchar('[');
945-
ram_puthex16(read1);
946-
ram_putchar(':');
947-
ram_puthex16(read2);
948-
ram_putchar(']');
949-
}
950931
#ifdef DEBUG_FLASH
951932
wolfBoot_printf("Wait toggle %x -> %x\n", read1, read2);
952933
#endif
@@ -998,24 +979,13 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
998979
#endif
999980

1000981
/* Disable flash caching — AMD commands must reach the chip directly */
1001-
ram_putchar('w'); /* checkpoint: entering write */
1002982
hal_flash_cache_disable();
1003983
hal_flash_clear_wp();
1004984

1005985
/* Reset flash to read-array mode in case previous operation left it
1006986
* in command mode (e.g. after a timeout or incomplete operation) */
1007987
FLASH_IO8_WRITE(0, 0, AMD_CMD_RESET);
1008988
ram_udelay(50);
1009-
ram_putchar('r'); /* checkpoint: reset done */
1010-
1011-
/* Diagnostic: read erased data before write to verify both chips respond.
1012-
* Expected 0xFFFF after erase. If high byte != 0xFF, chip may be dead. */
1013-
{
1014-
uint16_t erased = FLASH_IO16_READ(address / FLASH_SECTOR_SIZE, 0);
1015-
ram_putchar('{');
1016-
ram_puthex16(erased);
1017-
ram_putchar('}');
1018-
}
1019989

1020990
pos = 0;
1021991
while (len > 0) {
@@ -1033,12 +1003,14 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
10331003
sector, offset, xfer, pos);
10341004
#endif
10351005

1006+
/* Write-Buffer-Program: the entire command sequence from unlock
1007+
* through confirm must execute without interruption. No UART
1008+
* output or other bus-stalling operations between steps —
1009+
* S29GL01GS has a write-buffer load timeout (~25-50us) that
1010+
* causes DQ1 abort if data or confirm arrives too late. */
10361011
hal_flash_unlock_sector(sector);
1037-
ram_putchar('u'); /* checkpoint: unlock done */
10381012
FLASH_IO8_WRITE(sector, offset, AMD_CMD_WRITE_TO_BUFFER);
10391013
FLASH_IO8_WRITE(sector, offset, (nwords-1));
1040-
ram_putchar('b'); /* checkpoint: buffer cmd + count sent */
1041-
10421014
for (i=0; i<nwords; i++) {
10431015
const uint8_t* ptr = &data[pos];
10441016
#if FLASH_CFI_WIDTH == 16
@@ -1048,57 +1020,28 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
10481020
#endif
10491021
pos += (FLASH_CFI_WIDTH/8);
10501022
}
1051-
ram_putchar('l'); /* checkpoint: data loaded */
10521023
/* Ensure all data stores reach IFC before confirm */
10531024
__asm__ __volatile__("sync" ::: "memory");
10541025
FLASH_IO8_WRITE(sector, offset, AMD_CMD_WRITE_BUFFER_CONFIRM);
1055-
/* Ensure confirm write reaches flash before polling */
1056-
__asm__ __volatile__("sync; isync" ::: "memory");
1057-
ram_putchar('c'); /* checkpoint: confirm sent */
10581026

10591027
/* poll for program completion - max 200ms (typical 410us) */
10601028
ret = hal_flash_status_wait(sector, 0x44, 200*1000);
1061-
if (ret == 0) {
1062-
ram_putchar('p'); /* pass */
1063-
} else if (ret == -2) {
1064-
ram_putchar('E'); /* DQ5 error */
1065-
} else {
1066-
ram_putchar('T'); /* timeout */
1067-
}
10681029
if (ret != 0) {
1069-
uint16_t readback;
10701030
/* Write-to-Buffer-Abort-Reset: plain AMD_CMD_RESET (0xF0) is
10711031
* IGNORED during an active WBP or WBP-abort state. Must use
10721032
* the unlock + reset sequence per S29GL01GS datasheet. */
10731033
hal_flash_unlock_sector(sector);
10741034
FLASH_IO8_WRITE(sector, 0, AMD_CMD_RESET);
10751035
ram_udelay(50);
1076-
/* Read back offset 0 to see if data was actually written */
1077-
readback = FLASH_IO16_READ(sector, 0);
1078-
ram_putchar('=');
1079-
ram_puthex16(readback);
1080-
/* Verify flash exited command mode (second read should match) */
1081-
{
1082-
uint16_t verify = FLASH_IO16_READ(sector, 0);
1083-
if (readback != verify) {
1084-
ram_putchar('!'); /* still in command mode */
1085-
/* Try one more reset */
1086-
hal_flash_unlock_sector(sector);
1087-
FLASH_IO8_WRITE(sector, 0, AMD_CMD_RESET);
1088-
ram_udelay(50);
1089-
}
1090-
}
1091-
wolfBoot_printf("\nFlash Write: %s at sector %d (ret %d)\n",
1092-
ret == -2 ? "DQ5 error" : "Timeout", sector, ret);
1036+
wolfBoot_printf("Flash Write: %s at sector %d\n",
1037+
ret == -2 ? "DQ5 error" : "Timeout", sector);
10931038
break;
10941039
}
1095-
ram_putchar('.'); /* checkpoint: page write OK */
10961040

10971041
address += xfer;
10981042
len -= xfer;
10991043
}
11001044

1101-
ram_putchar('d'); /* checkpoint: write loop done */
11021045
/* Restore flash caching — flash is back in read-array mode */
11031046
hal_flash_cache_enable();
11041047
return ret;
@@ -1370,8 +1313,12 @@ int hal_dts_fixup(void* dts_addr)
13701313
fdt_version(fdt), fdt_totalsize(fdt));
13711314

13721315
/* expand total size */
1373-
fdt->totalsize += 2048; /* expand by 2KB */
1374-
wolfBoot_printf("FDT: Expanded (2KB) to %d bytes\n", fdt->totalsize);
1316+
{
1317+
uint32_t new_size = (uint32_t)fdt_totalsize(fdt) + 2048U;
1318+
fdt_set_totalsize(fdt, new_size);
1319+
wolfBoot_printf("FDT: Expanded (2KB) to %d bytes\n",
1320+
fdt_totalsize(fdt));
1321+
}
13751322

13761323
/* fixup the memory region - single bank */
13771324
off = fdt_find_devtype(fdt, -1, "memory");

0 commit comments

Comments
 (0)