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
3373void 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+
292373int 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
301431int 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
309464void 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
324479void 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
339494void hal_prepare_boot (void )
0 commit comments