@@ -217,9 +217,10 @@ static void hal_flash_init(void)
217217 wolfBoot_printf ("IFC CSPR0: 0x%x%s\n" , cspr ,
218218 (cspr & IFC_CSPR_WP ) ? " (WP set)" : "" );
219219#endif
220- if (cspr & IFC_CSPR_WP ) {
221- set32 (IFC_CSPR (0 ), cspr & ~IFC_CSPR_WP );
222- }
220+ /* WP clearing is done in hal_flash_clear_wp() from RAMFUNCTION code.
221+ * T2080RM requires V=0 before modifying IFC_CSPR, which is not safe
222+ * during XIP. The RAMFUNCTION code runs from DDR with flash TLB
223+ * guarded, so it can safely toggle V=0 -> modify -> V=1. */
223224
224225 /* Note: hal_flash_getid() is disabled because AMD Autoselect mode
225226 * affects the entire flash bank. Since wolfBoot runs XIP from the same
@@ -715,6 +716,25 @@ static void RAMFUNCTION hal_flash_cache_enable(void)
715716 invalidate_icache ();
716717}
717718
719+ /* Clear IFC write-protect. T2080RM says IFC_CSPR should only be written
720+ * when V=0. Must be called from RAMFUNCTION (DDR) with flash TLB set to
721+ * guarded (MAS2_G) so no speculative access occurs while V is briefly 0. */
722+ static void RAMFUNCTION hal_flash_clear_wp (void )
723+ {
724+ uint32_t cspr = get32 (IFC_CSPR (0 ));
725+ if (cspr & IFC_CSPR_WP ) {
726+ /* Clear V first, then modify WP, then re-enable V */
727+ set32 (IFC_CSPR (0 ), cspr & ~(IFC_CSPR_WP | IFC_CSPR_V ));
728+ __asm__ __volatile__("sync; isync" );
729+ set32 (IFC_CSPR (0 ), (cspr & ~IFC_CSPR_WP ) | IFC_CSPR_V );
730+ __asm__ __volatile__("sync; isync" );
731+ /* Verify WP cleared */
732+ cspr = get32 (IFC_CSPR (0 ));
733+ wolfBoot_printf ("WP clear: CSPR0=0x%x%s\n" , cspr ,
734+ (cspr & IFC_CSPR_WP ) ? " (FAILED)" : " (OK)" );
735+ }
736+ }
737+
718738static void RAMFUNCTION hal_flash_unlock_sector (uint32_t sector )
719739{
720740 /* AMD unlock sequence */
@@ -773,6 +793,12 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
773793
774794 /* Disable flash caching — AMD commands must reach the chip directly */
775795 hal_flash_cache_disable ();
796+ hal_flash_clear_wp ();
797+
798+ /* Reset flash to read-array mode in case previous operation left it
799+ * in command mode (e.g. after a timeout or incomplete operation) */
800+ FLASH_IO8_WRITE (0 , 0 , AMD_CMD_RESET );
801+ ram_udelay (50 );
776802
777803 pos = 0 ;
778804 while (len > 0 ) {
@@ -792,18 +818,15 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
792818
793819 hal_flash_unlock_sector (sector );
794820 FLASH_IO8_WRITE (sector , offset , AMD_CMD_WRITE_TO_BUFFER );
795- #if FLASH_CFI_WIDTH == 16
796- FLASH_IO16_WRITE (sector , offset , (nwords - 1 ));
797- #else
821+ /* Word count (N-1) must be replicated to both chips */
798822 FLASH_IO8_WRITE (sector , offset , (nwords - 1 ));
799- #endif
800823
801824 for (i = 0 ; i < nwords ; i ++ ) {
802825 const uint8_t * ptr = & data [pos ];
803826 #if FLASH_CFI_WIDTH == 16
804- FLASH_IO16_WRITE (sector , i , * ((const uint16_t * )ptr ));
827+ FLASH_IO16_WRITE (sector , offset + i , * ((const uint16_t * )ptr ));
805828 #else
806- FLASH_IO8_WRITE (sector , i , * ptr );
829+ FLASH_IO8_WRITE (sector , offset + i , * ptr );
807830 #endif
808831 pos += (FLASH_CFI_WIDTH /8 );
809832 }
@@ -814,6 +837,7 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
814837 ret = hal_flash_status_wait (sector , 0x44 , 200 * 1000 );
815838 if (ret != 0 ) {
816839 wolfBoot_printf ("Flash Write: Timeout at sector %d\n" , sector );
840+ FLASH_IO8_WRITE (sector , 0 , AMD_CMD_RESET );
817841 break ;
818842 }
819843
@@ -837,6 +861,12 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
837861
838862 /* Disable flash caching — AMD commands must reach the chip directly */
839863 hal_flash_cache_disable ();
864+ hal_flash_clear_wp ();
865+
866+ /* Reset flash to read-array mode in case previous operation left it
867+ * in command mode (e.g. after a timeout or incomplete operation) */
868+ FLASH_IO8_WRITE (0 , 0 , AMD_CMD_RESET );
869+ ram_udelay (50 );
840870
841871 while (len > 0 ) {
842872 /* determine sector address */
@@ -854,10 +884,21 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
854884 /* block erase timeout = 50us - for additional sectors */
855885 /* Typical is 200ms (max 1100ms) */
856886
887+ /* Debug: check if flash entered erase mode (DQ6 should toggle) */
888+ {
889+ uint16_t r1 = FLASH_IO8_READ (sector , 0 );
890+ uint16_t r2 = FLASH_IO8_READ (sector , 0 );
891+ wolfBoot_printf ("Erase cmd sent: read 0x%x, 0x%x %s\n" ,
892+ r1 , r2 , (r1 != r2 ) ? "(toggling)" : "(NOT toggling)" );
893+ }
894+
857895 /* poll for erase completion - max 1.1 sec */
858896 ret = hal_flash_status_wait (sector , 0x4C , 1100 * 1000 );
859897 if (ret != 0 ) {
860- wolfBoot_printf ("Flash Erase: Timeout at sector %d\n" , sector );
898+ uint16_t r1 = FLASH_IO8_READ (sector , 0 );
899+ wolfBoot_printf ("Flash Erase: Timeout at sector %d (status 0x%x)\n" ,
900+ sector , r1 );
901+ FLASH_IO8_WRITE (sector , 0 , AMD_CMD_RESET );
861902 break ;
862903 }
863904
0 commit comments