@@ -7,6 +7,7 @@ struct spinor_info_t {
77 uint32_t blksz ;
88 uint32_t read_granularity ;
99 uint32_t write_granularity ;
10+ uint32_t write_pagesz ;
1011 uint8_t address_length ;
1112 uint8_t opcode_read ;
1213 uint8_t opcode_write ;
@@ -70,10 +71,11 @@ struct sfdp_t {
7071};
7172
7273static const struct spinor_info_t spinor_infos [] = {
73- { "W25X40" , 0xef3013 , 512 * 1024 , 4096 , 1 , 256 , 3 , OPCODE_READ , OPCODE_PROG , OPCODE_WREN , OPCODE_E4K , 0 , OPCODE_E64K , 0 },
74- { "W25Q128JVEIQ" , 0xefc018 , 16 * 1024 * 1024 , 4096 , 1 , 256 , 3 , OPCODE_READ , OPCODE_PROG , OPCODE_WREN , OPCODE_E4K , OPCODE_E32K , OPCODE_E64K , 0 },
75- { "W25Q256JVEIQ" , 0xef4019 , 32 * 1024 * 1024 , 4096 , 1 , 256 , 4 , OPCODE_READ , OPCODE_PROG , OPCODE_WREN , OPCODE_E4K , OPCODE_E32K , OPCODE_E64K , 0 },
76- { "GD25D10B" , 0xc84011 , 128 * 1024 , 4096 , 1 , 256 , 3 , OPCODE_READ , OPCODE_PROG , OPCODE_WREN , OPCODE_E4K , OPCODE_E32K , OPCODE_E64K , 0 },
74+ { "W25X40" , 0xef3013 , 512 * 1024 , 4096 , 1 , 256 , 256 , 3 , OPCODE_READ , OPCODE_PROG , OPCODE_WREN , OPCODE_E4K , 0 , OPCODE_E64K , 0 },
75+ { "SST25VF016B" , 0xbf2541 , 2 * 1024 * 1024 , 4096 , 1 , 1 , 1 , 3 , OPCODE_READ , OPCODE_PROG , OPCODE_WREN , OPCODE_E4K , OPCODE_E32K , OPCODE_E64K , 0 },
76+ { "W25Q128JVEIQ" , 0xefc018 , 16 * 1024 * 1024 , 4096 , 1 , 256 , 256 , 3 , OPCODE_READ , OPCODE_PROG , OPCODE_WREN , OPCODE_E4K , OPCODE_E32K , OPCODE_E64K , 0 },
77+ { "W25Q256JVEIQ" , 0xef4019 , 32 * 1024 * 1024 , 4096 , 1 , 256 , 256 , 4 , OPCODE_READ , OPCODE_PROG , OPCODE_WREN , OPCODE_E4K , OPCODE_E32K , OPCODE_E64K , 0 },
78+ { "GD25D10B" , 0xc84011 , 128 * 1024 , 4096 , 1 , 256 , 256 , 3 , OPCODE_READ , OPCODE_PROG , OPCODE_WREN , OPCODE_E4K , OPCODE_E32K , OPCODE_E64K , 0 },
7779};
7880
7981static inline int spinor_read_sfdp (struct xfel_ctx_t * ctx , uint32_t swapbuf , uint32_t swaplen , uint32_t cmdlen , struct sfdp_t * sfdp )
@@ -255,6 +257,7 @@ static inline int spinor_info(struct xfel_ctx_t * ctx, struct spinor_pdata_t * p
255257 pdat -> info .opcode_write_enable = OPCODE_WREN ;
256258 pdat -> info .read_granularity = 1 ;
257259 pdat -> info .opcode_read = OPCODE_READ ;
260+ pdat -> info .write_pagesz = 256 ;
258261 if ((sfdp .bt .major == 1 ) && (sfdp .bt .minor < 5 ))
259262 {
260263 /* Basic flash parameter table 1th dword */
@@ -269,6 +272,7 @@ static inline int spinor_info(struct xfel_ctx_t * ctx, struct spinor_pdata_t * p
269272 /* Basic flash parameter table 11th dword */
270273 v = (sfdp .bt .table [43 ] << 24 ) | (sfdp .bt .table [42 ] << 16 ) | (sfdp .bt .table [41 ] << 8 ) | (sfdp .bt .table [40 ] << 0 );
271274 pdat -> info .write_granularity = 1 << ((v >> 4 ) & 0xf );
275+ pdat -> info .write_pagesz = pdat -> info .write_granularity ;
272276 }
273277 pdat -> info .opcode_write = OPCODE_PROG ;
274278 return 1 ;
@@ -730,6 +734,8 @@ static void spinor_helper_write(struct xfel_ctx_t * ctx, struct spinor_pdata_t *
730734 granularity = (count < 0x40000000 ) ? count : 0x40000000 ;
731735 else
732736 granularity = pdat -> info .write_granularity ;
737+ if (pdat -> info .write_pagesz > 0 )
738+ granularity = granularity > (int32_t )pdat -> info .write_pagesz ? (int32_t )pdat -> info .write_pagesz : granularity ;
733739 granularity = granularity > (pdat -> swaplen - 5 ) ? (pdat -> swaplen - 5 ) : granularity ;
734740
735741 switch (pdat -> info .address_length )
@@ -927,9 +933,20 @@ int spinor_write(struct xfel_ctx_t * ctx, uint64_t addr, void * buf, uint64_t le
927933 uint64_t base , n ;
928934 int64_t cnt ;
929935 uint32_t esize , emask ;
936+ uint64_t waddr , wlen ;
937+ uint8_t * wbuf ;
938+ uint8_t * vbuf ;
939+ uint8_t * expbuf ;
940+ uint64_t vbase , vcnt ;
941+ uint64_t start , end ;
942+ uint32_t i ;
943+ int attempt ;
930944
931945 if (spinor_helper_init (ctx , & pdat ))
932946 {
947+ waddr = addr ;
948+ wlen = len ;
949+ wbuf = buf ;
933950 if (pdat .info .opcode_erase_4k != 0 )
934951 esize = 4096 ;
935952 else if (pdat .info .opcode_erase_32k != 0 )
@@ -955,6 +972,16 @@ int spinor_write(struct xfel_ctx_t * ctx, uint64_t addr, void * buf, uint64_t le
955972 }
956973 base = addr ;
957974 cnt = len ;
975+ vbuf = malloc (esize );
976+ expbuf = malloc (esize );
977+ if (!vbuf || !expbuf )
978+ {
979+ if (vbuf )
980+ free (vbuf );
981+ if (expbuf )
982+ free (expbuf );
983+ return 0 ;
984+ }
958985 progress_start (& p , cnt );
959986 while (cnt > 0 )
960987 {
@@ -966,6 +993,70 @@ int spinor_write(struct xfel_ctx_t * ctx, uint64_t addr, void * buf, uint64_t le
966993 progress_update (& p , n );
967994 }
968995 progress_stop (& p );
996+ vbase = waddr & ~emask ;
997+ vcnt = (waddr & emask ) + wlen ;
998+ vcnt = (vcnt + ((vcnt & emask ) ? esize : 0 )) & ~emask ;
999+ while (vcnt > 0 )
1000+ {
1001+ memset (expbuf , 0xff , esize );
1002+ start = vbase > waddr ? vbase : waddr ;
1003+ end = (vbase + esize ) < (waddr + wlen ) ? (vbase + esize ) : (waddr + wlen );
1004+ if (start < end )
1005+ memcpy (expbuf + (start - vbase ), wbuf + (start - waddr ), end - start );
1006+ for (attempt = 0 ; attempt < 3 ; attempt ++ )
1007+ {
1008+ int need_erase = 0 ;
1009+ int need_prog = 0 ;
1010+ spinor_helper_read (ctx , & pdat , vbase , vbuf , esize );
1011+ for (i = 0 ; i < esize ; i ++ )
1012+ {
1013+ uint8_t exp = expbuf [i ];
1014+ uint8_t got = vbuf [i ];
1015+ if ((exp & ~got ) != 0 )
1016+ need_erase = 1 ;
1017+ if ((~exp & got ) != 0 )
1018+ need_prog = 1 ;
1019+ if (need_erase && need_prog )
1020+ break ;
1021+ }
1022+ if (!need_erase && !need_prog )
1023+ break ;
1024+ printf ("spinor: verify mismatch at 0x%llx (attempt %d), %s%s\r\n" ,
1025+ (unsigned long long )vbase , attempt + 1 ,
1026+ need_erase ? "need-erase" : "" ,
1027+ need_prog ? (need_erase ? "+need-prog" : "need-prog" ) : "" );
1028+ if (need_erase )
1029+ {
1030+ uint64_t off ;
1031+ spinor_helper_erase (ctx , & pdat , vbase , esize );
1032+ for (off = 0 ; off < esize ; off += n )
1033+ {
1034+ n = (esize - off ) > 65536 ? 65536 : (esize - off );
1035+ spinor_helper_write (ctx , & pdat , vbase + off , expbuf + off , n );
1036+ }
1037+ }
1038+ else if (need_prog )
1039+ {
1040+ for (i = 0 ; i < esize ; i ++ )
1041+ {
1042+ if (vbuf [i ] != expbuf [i ])
1043+ spinor_helper_write (ctx , & pdat , vbase + i , expbuf + i , 1 );
1044+ }
1045+ }
1046+ }
1047+ if (attempt == 3 )
1048+ {
1049+ printf ("spinor: verify failed at 0x%llx after retries\r\n" ,
1050+ (unsigned long long )vbase );
1051+ free (vbuf );
1052+ free (expbuf );
1053+ return 0 ;
1054+ }
1055+ vbase += esize ;
1056+ vcnt -= esize ;
1057+ }
1058+ free (vbuf );
1059+ free (expbuf );
9691060 return 1 ;
9701061 }
9711062 return 0 ;
0 commit comments