]> git.kernelconcepts.de Git - karo-tx-redboot.git/blobdiff - packages/devs/flash/amd/am29xxxxx/v2_0/include/flash_am29xxxxx.inl
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / devs / flash / amd / am29xxxxx / v2_0 / include / flash_am29xxxxx.inl
index 53869044d9d16d813ba43b2002e9b1a01e0d2838..2c2fd3eb09b249fe6aaefd6fa5097b5c14223ecd 100644 (file)
@@ -97,7 +97,8 @@
 #define _16AS8 CYGNUM_FLASH_16AS8
 #endif
 
-#if (_16AS8 == 0)
+
+# if (_16AS8 == 0)||CYGHWR_DEVS_FLASH_ST_M29W320D
 # define FLASH_Setup_Addr1              (0x555)
 # define FLASH_Setup_Addr2              (0x2AA)
 # define FLASH_VendorID_Addr            (0)
 # define FLASH_DeviceID_Addr3           (0x1e)
 # define FLASH_WP_Addr                  (4)
 #endif
+
 #define FLASH_Setup_Code1               FLASHWORD( 0xAA )
 #define FLASH_Setup_Code2               FLASHWORD( 0x55 )
 #define FLASH_Setup_Erase               FLASHWORD( 0x80 )
@@ -480,6 +482,7 @@ norflash_program_buf(void* addr, void* data, int len)
     const CYG_ADDRWORD mask  =
         flash_dev_info->bufsiz * sizeof (flash_data_t) - 1;
     unsigned long rem_sect_size;
+    int remain;
 
     // check the address is suitably aligned
     if ((unsigned long)addr & (CYGNUM_FLASH_INTERLEAVE * CYGNUM_FLASH_WIDTH / 8 - 1))
@@ -492,6 +495,7 @@ norflash_program_buf(void* addr, void* data, int len)
     f_s1 = FLASH_P2V(BANK + FLASH_Setup_Addr1);
     f_s2 = FLASH_P2V(BANK + FLASH_Setup_Addr2);
     rem_sect_size = 0;
+    remain = len % sizeof (flash_data_t);
     len /= sizeof (flash_data_t);
 
     while (len > 0) {
@@ -565,6 +569,51 @@ norflash_program_buf(void* addr, void* data, int len)
         len -= nwords;
     }
 
+    // Program remaining bytes if len not a multiple of flash word size
+    if ((FLASH_ERR_OK == res) && remain)
+    {
+        // construct final word to be programmed with 0xff in the
+        // remaining bytes
+        flash_data_t final = (flash_data_t)-1;
+        unsigned char *src = (unsigned char *) data_ptr;
+        unsigned char *dst = (unsigned char *) &final;
+
+        while (remain--)
+            *dst++ = *src++;
+
+        addr_v = FLASH_P2V(addr_p);
+
+        // Program data [byte] - 4 step sequence
+        *f_s1 = FLASH_Setup_Code1;
+        *f_s2 = FLASH_Setup_Code2;
+        *f_s1 = FLASH_Program;
+        *addr_v = final;
+
+        timeout = CYGNUM_FLASH_TIMEOUT_PROGRAM;
+        while (true) {
+            flash_data_t state = *addr_v;
+            if (final == state) {
+                break;
+            }
+
+            // Can't check for FLASH_Err since it'll fail in parallel
+            // configurations.
+
+            if (--timeout == 0) {
+                res = FLASH_ERR_DRV_TIMEOUT;
+                break;
+            }
+        }
+
+        if (FLASH_ERR_OK != res)
+            *FLASH_P2V(ROM) = FLASH_Reset;
+
+        if (*addr_v != final) {
+            // Only update return value if write operation was OK
+            if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;
+        }
+    }
+
     // Ideally, we'd want to return not only the failure code, but also
     // the address/device that reported the error.
     return res;
@@ -604,23 +653,21 @@ find_sector(volatile flash_data_t * addr, unsigned long *remain_size)
     if (flash_dev_info->bootblock) {
         cyg_uint32 * bootblocks = flash_dev_info->bootblocks;
         while (*bootblocks != _LAST_BOOTBLOCK) {
-            int ls = flash_dev_info->block_size;
-
-            if (*bootblocks++ == (res - base)) {
-                while (res + *bootblocks < a) {
+            if (*bootblocks++ == (res - base)) { /* Matching offset marker */
+                while (res + *bootblocks <= a) {
                     res += *bootblocks++;
                 }
+                *remain_size = *bootblocks - (a - res);
+                break;
             } else {
+                int ls = flash_dev_info->block_size;
                 // Skip over segment
                 while ((ls -= *bootblocks++) > 0) ;
             }
         }
-
-        if (*bootblocks != _LAST_BOOTBLOCK)   
-            *remain_size = *bootblocks - (a - res);
     }
     
     return (flash_data_t *) res;
 }
 
-#endif // CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL
+#endif // CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL
\ No newline at end of file