Skip to content

Commit cce1825

Browse files
committed
Fixes for T2080 flash driver
1 parent b79351b commit cce1825

File tree

2 files changed

+179
-27
lines changed

2 files changed

+179
-27
lines changed

hal/nxp_t2080.c

Lines changed: 178 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,46 @@
2828
/* generic shared NXP QorIQ driver code */
2929
#include "nxp_ppc.c"
3030

31+
/* AMD CFI Commands (Spansion/Cypress) */
32+
#define AMD_CMD_RESET 0xF0
33+
#define AMD_CMD_WRITE 0xA0
34+
#define AMD_CMD_ERASE_START 0x80
35+
#define AMD_CMD_ERASE_SECTOR 0x30
36+
#define AMD_CMD_UNLOCK_START 0xAA
37+
#define AMD_CMD_UNLOCK_ACK 0x55
38+
#define AMD_CMD_WRITE_TO_BUFFER 0x25
39+
#define AMD_CMD_WRITE_BUFFER_CONFIRM 0x29
40+
#define AMD_CMD_SET_PPB_ENTRY 0xC0
41+
#define AMD_CMD_SET_PPB_EXIT_BC1 0x90
42+
#define AMD_CMD_SET_PPB_EXIT_BC2 0x00
43+
#define AMD_CMD_PPB_UNLOCK_BC1 0x80
44+
#define AMD_CMD_PPB_UNLOCK_BC2 0x30
45+
#define AMD_CMD_PPB_LOCK_BC1 0xA0
46+
#define AMD_CMD_PPB_LOCK_BC2 0x00
47+
48+
#define AMD_STATUS_TOGGLE 0x40
49+
#define AMD_STATUS_ERROR 0x20
50+
51+
/* Flash unlock addresses */
52+
#if FLASH_CFI_WIDTH == 16
53+
#define FLASH_UNLOCK_ADDR1 0x555
54+
#define FLASH_UNLOCK_ADDR2 0x2AA
55+
#else
56+
#define FLASH_UNLOCK_ADDR1 0xAAA
57+
#define FLASH_UNLOCK_ADDR2 0x555
58+
#endif
59+
60+
/* Flash IO Helpers */
61+
#if FLASH_CFI_WIDTH == 16
62+
#define FLASH_IO8_WRITE(sec, n, val) *((volatile uint16_t*)(FLASH_BASE_ADDR + (FLASH_SECTOR_SIZE * (sec)) + ((n) * 2))) = (((val) << 8) | (val))
63+
#define FLASH_IO16_WRITE(sec, n, val) *((volatile uint16_t*)(FLASH_BASE_ADDR + (FLASH_SECTOR_SIZE * (sec)) + ((n) * 2))) = (val)
64+
#define FLASH_IO8_READ(sec, n) (uint8_t)(*((volatile uint16_t*)(FLASH_BASE_ADDR + (FLASH_SECTOR_SIZE * (sec)) + ((n) * 2))))
65+
#define FLASH_IO16_READ(sec, n) *((volatile uint16_t*)(FLASH_BASE_ADDR + (FLASH_SECTOR_SIZE * (sec)) + ((n) * 2)))
66+
#else
67+
#define FLASH_IO8_WRITE(sec, n, val) *((volatile uint8_t*)(FLASH_BASE_ADDR + (FLASH_SECTOR_SIZE * (sec)) + (n))) = (val)
68+
#define FLASH_IO8_READ(sec, n) *((volatile uint8_t*)(FLASH_BASE_ADDR + (FLASH_SECTOR_SIZE * (sec)) + (n)))
69+
#endif
70+
3171

3272
#ifdef DEBUG_UART
3373
void uart_init(void)
@@ -87,7 +127,7 @@ static void hal_flash_init(void)
87127
{
88128
/* IFC - NOR Flash */
89129
/* LAW is also set in boot_ppc_start.S:flash_law */
90-
set_law(1, FLASH_BASE_PHYS_HIGH, FLASH_BASE, LAW_TRGT_IFC, LAW_SIZE_128MB, 1);
130+
set_law(1, FLASH_BASE_PHYS_HIGH, FLASH_BASE_ADDR, LAW_TRGT_IFC, LAW_SIZE_128MB, 1);
91131

92132
/* NOR IFC Flash Timing Parameters */
93133
set32(IFC_FTIM0(0), (IFC_FTIM0_NOR_TACSE(4) |
@@ -103,7 +143,7 @@ static void hal_flash_init(void)
103143
set32(IFC_FTIM3(0), 0);
104144
/* NOR IFC Definitions (CS0) */
105145
set32(IFC_CSPR_EXT(0), 0xF);
106-
set32(IFC_CSPR(0), (IFC_CSPR_PHYS_ADDR(FLASH_BASE) |
146+
set32(IFC_CSPR(0), (IFC_CSPR_PHYS_ADDR(FLASH_BASE_ADDR) |
107147
IFC_CSPR_PORT_SIZE_16 |
108148
IFC_CSPR_MSEL_NOR |
109149
IFC_CSPR_V));
@@ -289,51 +329,166 @@ void hal_init(void)
289329
#endif /* ENABLE_CPLD */
290330
}
291331

332+
static void hal_flash_unlock_sector(uint32_t sector)
333+
{
334+
/* AMD unlock sequence */
335+
FLASH_IO8_WRITE(sector, FLASH_UNLOCK_ADDR1, AMD_CMD_UNLOCK_START);
336+
FLASH_IO8_WRITE(sector, FLASH_UNLOCK_ADDR2, AMD_CMD_UNLOCK_ACK);
337+
}
338+
339+
/* wait for toggle to stop and status mask to be met within microsecond timeout */
340+
static int hal_flash_status_wait(uint32_t sector, uint16_t mask,
341+
uint32_t timeout_us)
342+
{
343+
int ret = 0;
344+
uint32_t timeout = 0;
345+
uint16_t read1, read2;
346+
347+
do {
348+
/* detection of completion happens when reading status bits
349+
* DQ6 and DQ2 stop toggling (0x44) */
350+
read1 = FLASH_IO8_READ(sector, 0);
351+
if ((read1 & AMD_STATUS_TOGGLE) == 0)
352+
read1 = FLASH_IO8_READ(sector, 0);
353+
read2 = FLASH_IO8_READ(sector, 0);
354+
if ((read2 & AMD_STATUS_TOGGLE) == 0)
355+
read2 = FLASH_IO8_READ(sector, 0);
356+
#ifdef DEBUG_FLASH
357+
wolfBoot_printf("Wait toggle %x -> %x\n", read1, read2);
358+
#endif
359+
if (read1 == read2 && ((read1 & mask) == mask))
360+
break;
361+
udelay(1);
362+
} while (timeout++ < timeout_us);
363+
if (timeout >= timeout_us) {
364+
ret = -1; /* timeout */
365+
}
366+
#ifdef DEBUG_FLASH
367+
wolfBoot_printf("Wait done (%d tries): %x -> %x\n",
368+
timeout, read1, read2);
369+
#endif
370+
return ret;
371+
}
372+
292373
int hal_flash_write(uint32_t address, const uint8_t *data, int len)
293374
{
294-
(void)address;
295-
(void)data;
296-
(void)len;
297-
/* TODO: Implement NOR flash write using IFC */
375+
uint32_t i, pos, sector, offset, xfer, nwords;
376+
377+
/* adjust for flash base */
378+
if (address >= FLASH_BASE_ADDR)
379+
address -= FLASH_BASE_ADDR;
380+
381+
#ifdef DEBUG_FLASH
382+
wolfBoot_printf("Flash Write: Ptr %p -> Addr 0x%x (len %d)\n",
383+
data, address, len);
384+
#endif
385+
386+
pos = 0;
387+
while (len > 0) {
388+
/* determine sector address */
389+
sector = (address / FLASH_SECTOR_SIZE);
390+
offset = address - (sector * FLASH_SECTOR_SIZE);
391+
offset /= (FLASH_CFI_WIDTH/8);
392+
xfer = len;
393+
if (xfer > FLASH_PAGE_SIZE)
394+
xfer = FLASH_PAGE_SIZE;
395+
nwords = xfer / (FLASH_CFI_WIDTH/8);
396+
397+
#ifdef DEBUG_FLASH
398+
wolfBoot_printf("Flash Write: Sector %d, Offset %d, Len %d, Pos %d\n",
399+
sector, offset, xfer, pos);
400+
#endif
401+
402+
hal_flash_unlock_sector(sector);
403+
FLASH_IO8_WRITE(sector, offset, AMD_CMD_WRITE_TO_BUFFER);
404+
#if FLASH_CFI_WIDTH == 16
405+
FLASH_IO16_WRITE(sector, offset, (nwords-1));
406+
#else
407+
FLASH_IO8_WRITE(sector, offset, (nwords-1));
408+
#endif
409+
410+
for (i=0; i<nwords; i++) {
411+
const uint8_t* ptr = &data[pos];
412+
#if FLASH_CFI_WIDTH == 16
413+
FLASH_IO16_WRITE(sector, i, *((const uint16_t*)ptr));
414+
#else
415+
FLASH_IO8_WRITE(sector, i, *ptr);
416+
#endif
417+
pos += (FLASH_CFI_WIDTH/8);
418+
}
419+
FLASH_IO8_WRITE(sector, offset, AMD_CMD_WRITE_BUFFER_CONFIRM);
420+
/* Typical 410us */
421+
422+
/* poll for program completion - max 200ms */
423+
hal_flash_status_wait(sector, 0x44, 200*1000);
424+
425+
address += xfer;
426+
len -= xfer;
427+
}
298428
return 0;
299429
}
300430

301431
int hal_flash_erase(uint32_t address, int len)
302432
{
303-
(void)address;
304-
(void)len;
305-
/* TODO: Implement NOR flash erase using IFC */
433+
uint32_t sector;
434+
435+
/* adjust for flash base */
436+
if (address >= FLASH_BASE_ADDR)
437+
address -= FLASH_BASE_ADDR;
438+
439+
while (len > 0) {
440+
/* determine sector address */
441+
sector = (address / FLASH_SECTOR_SIZE);
442+
443+
#ifdef DEBUG_FLASH
444+
wolfBoot_printf("Flash Erase: Sector %d, Addr 0x%x, Len %d\n",
445+
sector, address, len);
446+
#endif
447+
448+
hal_flash_unlock_sector(sector);
449+
FLASH_IO8_WRITE(sector, FLASH_UNLOCK_ADDR1, AMD_CMD_ERASE_START);
450+
hal_flash_unlock_sector(sector);
451+
FLASH_IO8_WRITE(sector, 0, AMD_CMD_ERASE_SECTOR);
452+
/* block erase timeout = 50us - for additional sectors */
453+
/* Typical is 200ms (max 1100ms) */
454+
455+
/* poll for erase completion - max 1.1 sec */
456+
hal_flash_status_wait(sector, 0x4C, 1100*1000);
457+
458+
address += FLASH_SECTOR_SIZE;
459+
len -= FLASH_SECTOR_SIZE;
460+
}
306461
return 0;
307462
}
308463

309464
void hal_flash_unlock(void)
310465
{
311466
/* Disable all flash protection bits */
312467
/* enter Non-volatile protection mode (C0h) */
313-
*((volatile uint16_t*)(FLASH_BASE + 0xAAA)) = 0xAAAA;
314-
*((volatile uint16_t*)(FLASH_BASE + 0x554)) = 0x5555;
315-
*((volatile uint16_t*)(FLASH_BASE + 0xAAA)) = 0xC0C0;
468+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0xAAA)) = 0xAAAA;
469+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0x554)) = 0x5555;
470+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0xAAA)) = 0xC0C0;
316471
/* clear all protection bit (80h/30h) */
317-
*((volatile uint16_t*)(FLASH_BASE + 0x000)) = 0x8080;
318-
*((volatile uint16_t*)(FLASH_BASE + 0x000)) = 0x3030;
472+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0x000)) = 0x8080;
473+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0x000)) = 0x3030;
319474
/* exit Non-volatile protection mode (90h/00h) */
320-
*((volatile uint16_t*)(FLASH_BASE + 0x000)) = 0x9090;
321-
*((volatile uint16_t*)(FLASH_BASE + 0x000)) = 0x0000;
475+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0x000)) = 0x9090;
476+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0x000)) = 0x0000;
322477
}
323478

324479
void hal_flash_lock(void)
325480
{
326481
/* Enable all flash protection bits */
327482
/* enter Non-volatile protection mode (C0h) */
328-
*((volatile uint16_t*)(FLASH_BASE + 0xAAA)) = 0xAAAA;
329-
*((volatile uint16_t*)(FLASH_BASE + 0x554)) = 0x5555;
330-
*((volatile uint16_t*)(FLASH_BASE + 0xAAA)) = 0xC0C0;
483+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0xAAA)) = 0xAAAA;
484+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0x554)) = 0x5555;
485+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0xAAA)) = 0xC0C0;
331486
/* set all protection bit (A0h/00h) */
332-
*((volatile uint16_t*)(FLASH_BASE + 0x000)) = 0xA0A0;
333-
*((volatile uint16_t*)(FLASH_BASE + 0x000)) = 0x0000;
487+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0x000)) = 0xA0A0;
488+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0x000)) = 0x0000;
334489
/* exit Non-volatile protection mode (90h/00h) */
335-
*((volatile uint16_t*)(FLASH_BASE + 0x000)) = 0x9090;
336-
*((volatile uint16_t*)(FLASH_BASE + 0x000)) = 0x0000;
490+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0x000)) = 0x9090;
491+
*((volatile uint16_t*)(FLASH_BASE_ADDR + 0x000)) = 0x0000;
337492
}
338493

339494
void hal_prepare_boot(void)

hal/nxp_t2080.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,11 @@ enum ifc_amask_sizes {
127127

128128

129129
/* ---- NOR Flash ---- */
130-
#define FLASH_BASE 0xE8000000
131-
132130
#define FLASH_BANK_SIZE (128*1024*1024)
133131
#define FLASH_PAGE_SIZE (1024) /* program buffer */
134132
#define FLASH_SECTOR_SIZE (128*1024)
135133
#define FLASH_SECTORS (FLASH_BANK_SIZE / FLASH_SECTOR_SIZE)
136-
#define FLASH_CFI_16BIT 0x02 /* word */
137-
#define FLASH_CFI_WIDTH FLASH_CFI_16BIT
134+
#define FLASH_CFI_WIDTH 16 /* 8 or 16 */
138135

139136
#define FLASH_ERASE_TOUT 60000 /* Flash Erase Timeout (ms) */
140137
#define FLASH_WRITE_TOUT 500 /* Flash Write Timeout (ms) */

0 commit comments

Comments
 (0)