flash/nor: use default_flash_blank_check() instead of dummy
[fw/openocd] / src / flash / nor / at91sam3.c
index b5074de7ca700c37a9c7081fa34a1503e3551a0f..711918862d95b4156e7bd2f301b12481faa0a5ec 100644 (file)
@@ -4,22 +4,21 @@
  *                                                                         *
  *   Copyright (C) 2010 by Olaf Lüke (at91sam3s* support)                  *
  *   olaf@uni-paderborn.de                                                 *
- *                                                                         *
- *                                                                         *
+ *                                                                                                                                                *
+ *   Copyright (C) 2011 by Olivier Schonken (at91sam3x* support)           *                                          *
+ *                     and Jim Norris                                      *
  *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General public License as published by  *
+ *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
  *   (at your option) any later version.                                   *
  *                                                                         *
  *   This program is distributed in the hope that it will be useful,       *
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE.  See the         *
- *   GNU General public License for more details.                          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
  *                                                                         *
- *   You should have received a copy of the GNU General public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
 ****************************************************************************/
 
 /* Some of the the lower level code was based on code supplied by
 /* at91sam3s series (has always one flash bank) */
 #define FLASH_BANK_BASE_S   0x00400000
 
+/* at91sam3sd series (has always two flash banks) */
+#define FLASH_BANK0_BASE_SD FLASH_BANK_BASE_S
+#define FLASH_BANK1_BASE_512K_SD (FLASH_BANK0_BASE_SD+(512*1024/2))
+
+
 /* at91sam3n series (has always one flash bank) */
 #define FLASH_BANK_BASE_N   0x00400000
 
+/* at91sam3a/x series has two flash banks*/
+#define        FLASH_BANK0_BASE_AX                     0x00080000
+/*Bank 1 of the at91sam3a/x series starts at 0x00080000 + half flash size*/
+#define        FLASH_BANK1_BASE_256K_AX        0x000A0000
+#define        FLASH_BANK1_BASE_512K_AX        0x000C0000
+
 #define         AT91C_EFC_FCMD_GETD                 (0x0)      /* (EFC) Get Flash Descriptor */
 #define         AT91C_EFC_FCMD_WP                   (0x1)      /* (EFC) Write Page */
 #define         AT91C_EFC_FCMD_WPL                  (0x2)      /* (EFC) Write Page and Lock */
 #define         AT91C_EFC_FCMD_EWP                  (0x3)      /* (EFC) Erase Page and Write Page */
-#define         AT91C_EFC_FCMD_EWPL                 (0x4)      /* (EFC) Erase Page and Write Page
-                                                                * then Lock */
+#define         AT91C_EFC_FCMD_EWPL                 (0x4)      /* (EFC) Erase Page and Write Page then Lock */
 #define         AT91C_EFC_FCMD_EA                   (0x5)      /* (EFC) Erase All */
-/* cmd6 is not present inhe at91sam3u4/2/1 data sheet table 17-2 */
+/* cmd6 is not present in the at91sam3u4/2/1 data sheet table 17-2 */
 /* #define      AT91C_EFC_FCMD_EPL                  (0x6) // (EFC) Erase plane? */
-/* cmd7 is not present inhe at91sam3u4/2/1 data sheet table 17-2 */
+/* cmd7 is not present in the at91sam3u4/2/1 data sheet table 17-2 */
 /* #define      AT91C_EFC_FCMD_EPA                  (0x7) // (EFC) Erase pages? */
 #define         AT91C_EFC_FCMD_SLB                  (0x8)      /* (EFC) Set Lock Bit */
 #define         AT91C_EFC_FCMD_CLB                  (0x9)      /* (EFC) Clear Lock Bit */
@@ -128,11 +137,13 @@ struct sam3_cfg {
 
 #define SAM3_CHIPID_CIDR          (0x400E0740)
        uint32_t CHIPID_CIDR;
+#define SAM3_CHIPID_CIDR2         (0x400E0940) /*SAM3X and SAM3A cidr at this address*/
+       uint32_t CHIPID_CIDR2;
 #define SAM3_CHIPID_EXID          (0x400E0744)
        uint32_t CHIPID_EXID;
+#define SAM3_CHIPID_EXID2         (0x400E0944) /*SAM3X and SAM3A cidr at this address*/
+       uint32_t CHIPID_EXID2;
 
-#define SAM3_SUPC_CR              (0x400E1210)
-       uint32_t SUPC_CR;
 
 #define SAM3_PMC_BASE             (0x400E0400)
 #define SAM3_PMC_SCSR             (SAM3_PMC_BASE + 0x0008)
@@ -185,7 +196,7 @@ struct sam3_bank_private {
 
        /* so we can find the chip we belong to */
        struct sam3_chip *pChip;
-       /* so we can find the orginal bank pointer */
+       /* so we can find the original bank pointer */
        struct flash_bank *pBank;
        unsigned bank_number;
        uint32_t controller_address;
@@ -201,7 +212,7 @@ struct sam3_bank_private {
 struct sam3_chip_details {
        /* THERE ARE DRAGONS HERE.. */
        /* note: If you add pointers here */
-       /* becareful about them as they */
+       /* be careful about them as they */
        /* may need to be updated inside */
        /* the function: "sam3_GetDetails() */
        /* which copy/overwrites the */
@@ -556,7 +567,7 @@ static const struct sam3_chip_details all_sam3_details[] = {
 
        /* Note: The preliminary at91sam3s datasheet says on page 302 */
        /* that the flash controller is at address 0x400E0800. */
-       /* This is _not_ the case, the controller resides at address 0x400e0a0. */
+       /* This is _not_ the case, the controller resides at address 0x400e0a00. */
        {
                .chipid_cidr    = 0x28A00960,
                .name           = "at91sam3s4c",
@@ -576,8 +587,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                                .flash_wait_states = 6, /* workaround silicon bug */
                                .present = 1,
                                .size_bytes = 256 * 1024,
-                               .nsectors   = 32,
-                               .sector_size = 8192,
+                               .nsectors   = 16,
+                               .sector_size = 16384,
                                .page_size   = 256,
                        },
 /*             .bank[1] = { */
@@ -609,8 +620,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                                .flash_wait_states = 6, /* workaround silicon bug */
                                .present = 1,
                                .size_bytes = 256 * 1024,
-                               .nsectors   = 32,
-                               .sector_size = 8192,
+                               .nsectors   = 16,
+                               .sector_size = 16384,
                                .page_size   = 256,
                        },
 /*             .bank[1] = { */
@@ -641,8 +652,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                                .flash_wait_states = 6, /* workaround silicon bug */
                                .present = 1,
                                .size_bytes = 256 * 1024,
-                               .nsectors   = 32,
-                               .sector_size = 8192,
+                               .nsectors   = 16,
+                               .sector_size = 16384,
                                .page_size   = 256,
                        },
 /*             .bank[1] = { */
@@ -673,8 +684,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                                .flash_wait_states = 6, /* workaround silicon bug */
                                .present = 1,
                                .size_bytes = 128 * 1024,
-                               .nsectors   = 16,
-                               .sector_size = 8192,
+                               .nsectors   = 8,
+                               .sector_size = 16384,
                                .page_size   = 256,
                        },
 /*             .bank[1] = { */
@@ -705,8 +716,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                                .flash_wait_states = 6, /* workaround silicon bug */
                                .present = 1,
                                .size_bytes = 128 * 1024,
-                               .nsectors   = 16,
-                               .sector_size = 8192,
+                               .nsectors   = 8,
+                               .sector_size = 16384,
                                .page_size   = 256,
                        },
 /*             .bank[1] = { */
@@ -718,6 +729,126 @@ static const struct sam3_chip_details all_sam3_details[] = {
                        },
                },
        },
+       {
+               .chipid_cidr    = 0x298B0A60,
+               .name           = "at91sam3sd8a",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 64 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+               {
+/*                     .bank[0] = { */
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK0_BASE_SD,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes =  256 * 1024,
+                               .nsectors   =  16,
+                               .sector_size = 32768,
+                               .page_size   = 256,
+                         },
+/*                     .bank[1] = { */
+                         {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 1,
+                               .base_address = FLASH_BANK1_BASE_512K_SD,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes =  256 * 1024,
+                               .nsectors   =  16,
+                               .sector_size = 32768,
+                               .page_size   = 256,
+                       },
+               },
+       },
+       {
+               .chipid_cidr    = 0x299B0A60,
+               .name           = "at91sam3sd8b",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 64 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+               {
+/*                     .bank[0] = { */
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK0_BASE_SD,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes =  256 * 1024,
+                               .nsectors   =  16,
+                               .sector_size = 32768,
+                               .page_size   = 256,
+                         },
+/*                     .bank[1] = { */
+                         {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 1,
+                               .base_address = FLASH_BANK1_BASE_512K_SD,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes =  256 * 1024,
+                               .nsectors   =  16,
+                               .sector_size = 32768,
+                               .page_size   = 256,
+                       },
+               },
+       },
+       {
+               .chipid_cidr    = 0x29ab0a60,
+               .name           = "at91sam3sd8c",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 64 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+               {
+/*                     .bank[0] = { */
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK0_BASE_SD,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes =  256 * 1024,
+                               .nsectors   =  16,
+                               .sector_size = 32768,
+                               .page_size   = 256,
+                         },
+/*                     .bank[1] = { */
+                         {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 1,
+                               .base_address = FLASH_BANK1_BASE_512K_SD,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes =  256 * 1024,
+                               .nsectors   =  16,
+                               .sector_size = 32768,
+                               .page_size   = 256,
+                       },
+               },
+       },
        {
                .chipid_cidr    = 0x288A0760,
                .name           = "at91sam3s2a",
@@ -737,8 +868,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                                .flash_wait_states = 6, /* workaround silicon bug */
                                .present = 1,
                                .size_bytes = 128 * 1024,
-                               .nsectors   = 16,
-                               .sector_size = 8192,
+                               .nsectors   = 8,
+                               .sector_size = 16384,
                                .page_size   = 256,
                        },
 /*             .bank[1] = { */
@@ -769,8 +900,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                                .flash_wait_states = 6, /* workaround silicon bug */
                                .present = 1,
                                .size_bytes = 64 * 1024,
-                               .nsectors   = 8,
-                               .sector_size = 8192,
+                               .nsectors   = 4,
+                               .sector_size = 16384,
                                .page_size   = 256,
                        },
 /*             .bank[1] = { */
@@ -801,8 +932,8 @@ static const struct sam3_chip_details all_sam3_details[] = {
                                .flash_wait_states = 6, /* workaround silicon bug */
                                .present = 1,
                                .size_bytes = 64 * 1024,
-                               .nsectors   = 8,
-                               .sector_size = 8192,
+                               .nsectors   = 4,
+                               .sector_size = 16384,
                                .page_size   = 256,
                        },
 /*             .bank[1] = { */
@@ -833,8 +964,104 @@ static const struct sam3_chip_details all_sam3_details[] = {
                                .flash_wait_states = 6, /* workaround silicon bug */
                                .present = 1,
                                .size_bytes = 64 * 1024,
-                               .nsectors   = 8,
-                               .sector_size = 8192,
+                               .nsectors   = 4,
+                               .sector_size = 16384,
+                               .page_size   = 256,
+                       },
+/*             .bank[1] = { */
+                       {
+                               .present = 0,
+                               .probed = 0,
+                               .bank_number = 1,
+
+                       },
+               },
+       },
+       {
+               .chipid_cidr    = 0x288B0A60,
+               .name           = "at91sam3s8a",
+               .total_flash_size     = 256 * 2048,
+               .total_sram_size      = 64 * 1024,
+               .n_gpnvms       = 2,
+               .n_banks        = 1,
+               {
+/*             .bank[0] = { */
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK_BASE_S,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes = 256 * 2048,
+                               .nsectors   = 16,
+                               .sector_size = 32768,
+                               .page_size   = 256,
+                       },
+/*             .bank[1] = { */
+                       {
+                               .present = 0,
+                               .probed = 0,
+                               .bank_number = 1,
+
+                       },
+               },
+       },
+       {
+               .chipid_cidr    = 0x289B0A60,
+               .name           = "at91sam3s8b",
+               .total_flash_size     = 256 * 2048,
+               .total_sram_size      = 64 * 1024,
+               .n_gpnvms       = 2,
+               .n_banks        = 1,
+               {
+/*             .bank[0] = { */
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK_BASE_S,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes = 256 * 2048,
+                               .nsectors   = 16,
+                               .sector_size = 32768,
+                               .page_size   = 256,
+                       },
+/*             .bank[1] = { */
+                       {
+                               .present = 0,
+                               .probed = 0,
+                               .bank_number = 1,
+
+                       },
+               },
+       },
+       {
+               .chipid_cidr    = 0x28AB0A60,
+               .name           = "at91sam3s8c",
+               .total_flash_size     = 256 * 2048,
+               .total_sram_size      = 64 * 1024,
+               .n_gpnvms       = 2,
+               .n_banks        = 1,
+               {
+/*             .bank[0] = { */
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK_BASE_S,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes = 256 * 2048,
+                               .nsectors   = 16,
+                               .sector_size = 32768,
                                .page_size   = 256,
                        },
 /*             .bank[1] = { */
@@ -1289,6 +1516,507 @@ static const struct sam3_chip_details all_sam3_details[] = {
                },
        },
 
+       {
+               .chipid_cidr    = 0x29480360,
+               .name           = "at91sam3n0b",
+               .total_flash_size     = 32 * 1024,
+               .total_sram_size      = 8 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 1,
+
+/*             .bank[0] = { */
+               {
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK_BASE_N,
+                               .controller_address = 0x400e0A00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes = 32 * 1024,
+                               .nsectors   = 2,
+                               .sector_size = 16384,
+                               .page_size   = 256,
+                       },
+
+/*             .bank[1] = { */
+                       {
+                               .present = 0,
+                               .probed = 0,
+                               .bank_number = 1,
+                       },
+               },
+       },
+
+       {
+               .chipid_cidr    = 0x29380360,
+               .name           = "at91sam3n0a",
+               .total_flash_size     = 32 * 1024,
+               .total_sram_size      = 8 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 1,
+
+/*             .bank[0] = { */
+               {
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK_BASE_N,
+                               .controller_address = 0x400e0A00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes = 32 * 1024,
+                               .nsectors   = 2,
+                               .sector_size = 16384,
+                               .page_size   = 256,
+                       },
+
+/*             .bank[1] = { */
+                       {
+                               .present = 0,
+                               .probed = 0,
+                               .bank_number = 1,
+                       },
+               },
+       },
+
+       {
+               .chipid_cidr    = 0x29450260,
+               .name           = "at91sam3n00b",
+               .total_flash_size     = 16 * 1024,
+               .total_sram_size      = 4 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 1,
+
+/*             .bank[0] = { */
+               {
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK_BASE_N,
+                               .controller_address = 0x400e0A00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes = 16 * 1024,
+                               .nsectors   = 1,
+                               .sector_size = 16384,
+                               .page_size   = 256,
+                       },
+
+/*             .bank[1] = { */
+                       {
+                               .present = 0,
+                               .probed = 0,
+                               .bank_number = 1,
+                       },
+               },
+       },
+
+       {
+               .chipid_cidr    = 0x29350260,
+               .name           = "at91sam3n00a",
+               .total_flash_size     = 16 * 1024,
+               .total_sram_size      = 4 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 1,
+
+/*             .bank[0] = { */
+               {
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK_BASE_N,
+                               .controller_address = 0x400e0A00,
+                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes = 16 * 1024,
+                               .nsectors   = 1,
+                               .sector_size = 16384,
+                               .page_size   = 256,
+                       },
+
+/*             .bank[1] = { */
+                       {
+                               .present = 0,
+                               .probed = 0,
+                               .bank_number = 1,
+                       },
+               },
+       },
+
+
+       /* Start at91sam3a series*/
+       /* System boots at address 0x0 */
+       /* gpnvm[1] = selects boot code */
+       /*     if gpnvm[1] == 0 */
+       /*         boot is via "SAMBA" (rom) */
+       /*     else */
+       /*         boot is via FLASH */
+       /*         Selection is via gpnvm[2] */
+       /*     endif */
+       /*  */
+       /* NOTE: banks 0 & 1 switch places */
+       /*     if gpnvm[2] == 0 */
+       /*         Bank0 is the boot rom */
+       /*      else */
+       /*         Bank1 is the boot rom */
+       /*      endif */
+
+       {
+               .chipid_cidr    = 0x283E0A60,
+               .name           = "at91sam3a8c",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 96 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+               {
+/*             .bank[0] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 0,
+                       .base_address = FLASH_BANK0_BASE_AX,
+                       .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+                 },
+/*             .bank[1] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 1,
+                       .base_address = FLASH_BANK1_BASE_512K_AX,
+                       .controller_address = 0x400e0c00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+
+                 },
+               },
+       },
+       {
+               .chipid_cidr    = 0x283B0960,
+               .name           = "at91sam3a4c",
+               .total_flash_size     = 256 * 1024,
+               .total_sram_size      = 64 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+               {
+/*             .bank[0] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 0,
+                       .base_address = FLASH_BANK0_BASE_AX,
+                       .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  128 * 1024,
+                       .nsectors   =  8,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+                 },
+/*             .bank[1] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 1,
+                       .base_address = FLASH_BANK1_BASE_256K_AX,
+                       .controller_address = 0x400e0c00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  128 * 1024,
+                       .nsectors   =  8,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+
+                 },
+               },
+       },
+
+       /* Start at91sam3x* series */
+       /* System boots at address 0x0 */
+       /* gpnvm[1] = selects boot code */
+       /*     if gpnvm[1] == 0 */
+       /*         boot is via "SAMBA" (rom) */
+       /*     else */
+       /*         boot is via FLASH */
+       /*         Selection is via gpnvm[2] */
+       /*     endif */
+       /*  */
+       /* NOTE: banks 0 & 1 switch places */
+       /*     if gpnvm[2] == 0 */
+       /*         Bank0 is the boot rom */
+       /*      else */
+       /*         Bank1 is the boot rom */
+       /*      endif */
+       /*at91sam3x8h - ES has an incorrect CIDR of 0x286E0A20*/
+       {
+               .chipid_cidr    = 0x286E0A20,
+               .name           = "at91sam3x8h - ES",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 96 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+               {
+/*             .bank[0] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 0,
+                       .base_address = FLASH_BANK0_BASE_AX,
+                       .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+                 },
+/*             .bank[1] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 1,
+                       .base_address = FLASH_BANK1_BASE_512K_AX,
+                       .controller_address = 0x400e0c00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+
+                 },
+               },
+       },
+       /*at91sam3x8h - ES2 and up uses the correct CIDR of 0x286E0A60*/
+       {
+               .chipid_cidr    = 0x286E0A60,
+               .name           = "at91sam3x8h",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 96 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+               {
+/*             .bank[0] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 0,
+                       .base_address = FLASH_BANK0_BASE_AX,
+                       .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+                 },
+/*             .bank[1] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 1,
+                       .base_address = FLASH_BANK1_BASE_512K_AX,
+                       .controller_address = 0x400e0c00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+
+                 },
+               },
+       },
+       {
+               .chipid_cidr    = 0x285E0A60,
+               .name           = "at91sam3x8e",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 96 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+               {
+/*             .bank[0] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 0,
+                       .base_address = FLASH_BANK0_BASE_AX,
+                       .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+                 },
+/*             .bank[1] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 1,
+                       .base_address = FLASH_BANK1_BASE_512K_AX,
+                       .controller_address = 0x400e0c00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+
+                 },
+               },
+       },
+       {
+               .chipid_cidr    = 0x284E0A60,
+               .name           = "at91sam3x8c",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 96 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+               {
+/*             .bank[0] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 0,
+                       .base_address = FLASH_BANK0_BASE_AX,
+                       .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+                 },
+/*             .bank[1] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 1,
+                       .base_address = FLASH_BANK1_BASE_512K_AX ,
+                       .controller_address = 0x400e0c00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+
+                 },
+               },
+       },
+       {
+               .chipid_cidr    = 0x285B0960,
+               .name           = "at91sam3x4e",
+               .total_flash_size     = 256 * 1024,
+               .total_sram_size      = 64 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+               {
+/*             .bank[0] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 0,
+                       .base_address = FLASH_BANK0_BASE_AX,
+                       .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  128 * 1024,
+                       .nsectors   =  8,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+                 },
+/*             .bank[1] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 1,
+                       .base_address = FLASH_BANK1_BASE_256K_AX,
+                       .controller_address = 0x400e0c00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  128 * 1024,
+                       .nsectors   =  8,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+
+                 },
+               },
+       },
+       {
+               .chipid_cidr    = 0x284B0960,
+               .name           = "at91sam3x4c",
+               .total_flash_size     = 256 * 1024,
+               .total_sram_size      = 64 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+               {
+/*             .bank[0] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 0,
+                       .base_address = FLASH_BANK0_BASE_AX,
+                       .controller_address = 0x400e0a00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  128 * 1024,
+                       .nsectors   =  8,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+                 },
+/*             .bank[1] = { */
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 1,
+                       .base_address = FLASH_BANK1_BASE_256K_AX,
+                       .controller_address = 0x400e0c00,
+                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .present = 1,
+                       .size_bytes =  128 * 1024,
+                       .nsectors   =  8,
+                       .sector_size = 16384,
+                       .page_size   = 256,
+
+                 },
+               },
+       },
        /* terminate */
        {
                .chipid_cidr    = 0,
@@ -1447,7 +2175,7 @@ static int EFC_PerformCommand(struct sam3_bank_private *pPrivate,
 
        int r;
        uint32_t v;
-       long long ms_now, ms_end;
+       int64_t ms_now, ms_end;
 
        /* default */
        if (status)
@@ -1740,7 +2468,7 @@ static uint32_t sam3_reg_fieldname(struct sam3_chip *pChip,
        }
 
        /* show the basics */
-       LOG_USER_N("\t%*s: %*d [0x%0*x] ",
+       LOG_USER_N("\t%*s: %*" PRIu32 " [0x%0*" PRIx32 "] ",
                REG_NAME_WIDTH, regname,
                dwidth, v,
                hwidth, v);
@@ -1752,7 +2480,7 @@ static const char *const eproc_names[] = {
        _unknown,                                       /* 0 */
        "arm946es",                                     /* 1 */
        "arm7tdmi",                                     /* 2 */
-       "cortex-m3",                            /* 3 */
+       "Cortex-M3",                            /* 3 */
        "arm920t",                                      /* 4 */
        "arm926ejs",                            /* 5 */
        _unknown,                                       /* 6 */
@@ -1836,6 +2564,13 @@ static const struct archnames { unsigned value; const char *name; } archnames[]
        { 0x89,  "ATSAM3SxB Series (64-pin version)"            },
        { 0x8A,  "ATSAM3SxC Series (100-pin version)"           },
        { 0x92,  "AT91x92 Series"                                                       },
+       { 0x93,  "ATSAM3NxA Series (48-pin version)"            },
+       { 0x94,  "ATSAM3NxB Series (64-pin version)"            },
+       { 0x95,  "ATSAM3NxC Series (100-pin version)"           },
+       { 0x98,  "ATSAM3SDxA Series (48-pin version)"           },
+       { 0x99,  "ATSAM3SDxB Series (64-pin version)"           },
+       { 0x9A,  "ATSAM3SDxC Series (100-pin version)"          },
+       { 0xA5,  "ATSAM5A"                                                              },
        { 0xF0,  "AT75Cxx Series"                                                       },
        { -1, NULL },
 };
@@ -1958,10 +2693,10 @@ static void sam3_explain_ckgr_mcfr(struct sam3_chip *pChip)
        v = (v * pChip->cfg.slow_freq) / 16;
        pChip->cfg.mainosc_freq = v;
 
-       LOG_USER("(%3.03f Mhz (%d.%03dkhz slowclk)",
+       LOG_USER("(%3.03f Mhz (%" PRIu32 ".%03" PRIu32 "khz slowclk)",
                _tomhz(v),
-               pChip->cfg.slow_freq / 1000,
-               pChip->cfg.slow_freq % 1000);
+               (uint32_t)(pChip->cfg.slow_freq / 1000),
+               (uint32_t)(pChip->cfg.slow_freq % 1000));
 }
 
 static void sam3_explain_ckgr_plla(struct sam3_chip *pChip)
@@ -1977,8 +2712,8 @@ static void sam3_explain_ckgr_plla(struct sam3_chip *pChip)
                LOG_USER("\tPLLA Freq: (Disabled,mula = 0)");
        else if (diva == 0)
                LOG_USER("\tPLLA Freq: (Disabled,diva = 0)");
-       else if (diva == 1) {
-               pChip->cfg.plla_freq = (pChip->cfg.mainosc_freq * (mula + 1));
+       else if (diva >= 1) {
+               pChip->cfg.plla_freq = (pChip->cfg.mainosc_freq * (mula + 1) / diva);
                LOG_USER("\tPLLA Freq: %3.03f MHz",
                        _tomhz(pChip->cfg.plla_freq));
        }
@@ -2121,9 +2856,9 @@ static const struct sam3_reg_list sam3_all_regs[] = {
        SAM3_ENTRY(PMC_SCSR, NULL),
        SAM3_ENTRY(PMC_SR, NULL),
        SAM3_ENTRY(CHIPID_CIDR, sam3_explain_chipid_cidr),
+       SAM3_ENTRY(CHIPID_CIDR2, sam3_explain_chipid_cidr),
        SAM3_ENTRY(CHIPID_EXID, NULL),
-       SAM3_ENTRY(SUPC_CR, NULL),
-
+       SAM3_ENTRY(CHIPID_EXID2, NULL),
        /* TERMINATE THE LIST */
        { .name = NULL }
 };
@@ -2131,7 +2866,7 @@ static const struct sam3_reg_list sam3_all_regs[] = {
 
 static struct sam3_bank_private *get_sam3_bank_private(struct flash_bank *bank)
 {
-       return (struct sam3_bank_private *)(bank->driver_priv);
+       return bank->driver_priv;
 }
 
 /**
@@ -2192,14 +2927,32 @@ static int sam3_ReadAllRegs(struct sam3_chip *pChip)
                r = sam3_ReadThisReg(pChip,
                                sam3_get_reg_ptr(&(pChip->cfg), pReg));
                if (r != ERROR_OK) {
-                       LOG_ERROR("Cannot read SAM3 registere: %s @ 0x%08x, Error: %d",
+                       LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08x, Error: %d",
                                pReg->name, ((unsigned)(pReg->address)), r);
                        return r;
                }
-
                pReg++;
        }
 
+       /* Chip identification register
+       *
+       * Unfortunately, the chip identification register is not at
+       * a constant address across all of the SAM3 series'. As a
+       * consequence, a simple heuristic is used to find where it's
+       * at...
+       *
+       * If the contents at the first address is zero, then we know
+       * that the second address is where the chip id register is.
+       * We can deduce this because for those SAM's that have the
+       * chip id @ 0x400e0940, the first address, 0x400e0740, is
+       * located in the memory map of the Power Management Controller
+       * (PMC). Furthermore, the address is not used by the PMC.
+       * So when read, the memory controller returns zero.*/
+       if (pChip->cfg.CHIPID_CIDR == 0)        {
+               /*Put the correct CIDR and EXID values in the pChip structure */
+               pChip->cfg.CHIPID_CIDR = pChip->cfg.CHIPID_CIDR2;
+               pChip->cfg.CHIPID_EXID = pChip->cfg.CHIPID_EXID2;
+       }
        return ERROR_OK;
 }
 
@@ -2213,7 +2966,7 @@ static int sam3_GetInfo(struct sam3_chip *pChip)
                /* display all regs */
                LOG_DEBUG("Start: %s", pReg->name);
                regval = *sam3_get_reg_ptr(&(pChip->cfg), pReg);
-               LOG_USER("%*s: [0x%08x] -> 0x%08x",
+               LOG_USER("%*s: [0x%08" PRIx32 "] -> 0x%08" PRIx32,
                        REG_NAME_WIDTH,
                        pReg->name,
                        pReg->address,
@@ -2229,7 +2982,7 @@ static int sam3_GetInfo(struct sam3_chip *pChip)
        LOG_USER(" cpu-freq: %3.03f MHz", _tomhz(pChip->cfg.cpu_freq));
        LOG_USER("mclk-freq: %3.03f MHz", _tomhz(pChip->cfg.mclk_freq));
 
-       LOG_USER(" UniqueId: 0x%08x 0x%08x 0x%08x 0x%08x",
+       LOG_USER(" UniqueId: 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32,
                pChip->cfg.unique_id[0],
                pChip->cfg.unique_id[1],
                pChip->cfg.unique_id[2],
@@ -2238,28 +2991,6 @@ static int sam3_GetInfo(struct sam3_chip *pChip)
        return ERROR_OK;
 }
 
-static int sam3_erase_check(struct flash_bank *bank)
-{
-       int x;
-
-       LOG_DEBUG("Here");
-       if (bank->target->state != TARGET_HALTED) {
-               LOG_ERROR("Target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-       if (0 == bank->num_sectors) {
-               LOG_ERROR("Target: not supported/not probed");
-               return ERROR_FAIL;
-       }
-
-       LOG_INFO("sam3 - supports auto-erase, erase_check ignored");
-       for (x = 0; x < bank->num_sectors; x++)
-               bank->sectors[x].is_erased = 1;
-
-       LOG_DEBUG("Done");
-       return ERROR_OK;
-}
-
 static int sam3_protect_check(struct flash_bank *bank)
 {
        int r;
@@ -2327,42 +3058,59 @@ FLASH_BANK_COMMAND_HANDLER(sam3_flash_bank_command)
                default:
                        LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x or 0x%08x "
                        "[at91sam3u series] or 0x%08x [at91sam3s series] or "
-                       "0x%08x [at91sam3n series])",
+                       "0x%08x [at91sam3n series] or 0x%08x or 0x%08x or 0x%08x[at91sam3ax series] )",
                        ((unsigned int)(bank->base)),
                        ((unsigned int)(FLASH_BANK0_BASE_U)),
                        ((unsigned int)(FLASH_BANK1_BASE_U)),
                        ((unsigned int)(FLASH_BANK_BASE_S)),
-                       ((unsigned int)(FLASH_BANK_BASE_N)));
+                       ((unsigned int)(FLASH_BANK_BASE_N)),
+                       ((unsigned int)(FLASH_BANK0_BASE_AX)),
+                   ((unsigned int)(FLASH_BANK1_BASE_256K_AX)),
+                   ((unsigned int)(FLASH_BANK1_BASE_512K_AX)));
                        return ERROR_FAIL;
                        break;
 
-               /* at91sam3u series */
+               /* at91sam3s and at91sam3n series only has bank 0*/
+               /* at91sam3u and at91sam3ax series has the same address for bank 0*/
+               case FLASH_BANK_BASE_S:
                case FLASH_BANK0_BASE_U:
                        bank->driver_priv = &(pChip->details.bank[0]);
                        bank->bank_number = 0;
                        pChip->details.bank[0].pChip = pChip;
                        pChip->details.bank[0].pBank = bank;
                        break;
+
+               /* Bank 1 of at91sam3u or at91sam3ax series */
                case FLASH_BANK1_BASE_U:
+               case FLASH_BANK1_BASE_256K_AX:
+               case FLASH_BANK1_BASE_512K_AX:
                        bank->driver_priv = &(pChip->details.bank[1]);
                        bank->bank_number = 1;
                        pChip->details.bank[1].pChip = pChip;
                        pChip->details.bank[1].pBank = bank;
                        break;
-
-               /* at91sam3s and at91sam3n series */
-               case FLASH_BANK_BASE_S:
-                       bank->driver_priv = &(pChip->details.bank[0]);
-                       bank->bank_number = 0;
-                       pChip->details.bank[0].pChip = pChip;
-                       pChip->details.bank[0].pBank = bank;
-                       break;
        }
 
        /* we initialize after probing. */
        return ERROR_OK;
 }
 
+/**
+ * Remove all chips from the internal list without distingushing which one
+ * is owned by this bank. This simplification works only for one shot
+ * deallocation like current flash_free_all_banks()
+ */
+void sam3_free_driver_priv(struct flash_bank *bank)
+{
+       struct sam3_chip *chip = all_sam3_chips;
+       while (chip) {
+               struct sam3_chip *next = chip->next;
+               free(chip);
+               chip = next;
+       }
+       all_sam3_chips = NULL;
+}
+
 static int sam3_GetDetails(struct sam3_bank_private *pPrivate)
 {
        const struct sam3_chip_details *pDetails;
@@ -2374,16 +3122,16 @@ static int sam3_GetDetails(struct sam3_bank_private *pPrivate)
        pDetails = all_sam3_details;
        while (pDetails->name) {
                /* Compare cidr without version bits */
-               if (pDetails->chipid_cidr == (pPrivate->pChip->cfg.CHIPID_CIDR & 0xFFFFFFE0))
+               if (((pDetails->chipid_cidr ^ pPrivate->pChip->cfg.CHIPID_CIDR) & 0xFFFFFFE0) == 0)
                        break;
                else
                        pDetails++;
        }
        if (pDetails->name == NULL) {
-               LOG_ERROR("SAM3 ChipID 0x%08x not found in table (perhaps you can this chip?)",
+               LOG_ERROR("SAM3 ChipID 0x%08x not found in table (perhaps you can ID this chip?)",
                        (unsigned int)(pPrivate->pChip->cfg.CHIPID_CIDR));
                /* Help the victim, print details about the chip */
-               LOG_INFO("SAM3 CHIPID_CIDR: 0x%08x decodes as follows",
+               LOG_INFO("SAM3 CHIPID_CIDR: 0x%08" PRIx32 " decodes as follows",
                        pPrivate->pChip->cfg.CHIPID_CIDR);
                sam3_explain_chipid_cidr(pPrivate->pChip);
                return ERROR_FAIL;
@@ -2531,7 +3279,7 @@ static int sam3_erase(struct flash_bank *bank, int first, int last)
                LOG_DEBUG("Here");
                return FLASHD_EraseEntireBank(pPrivate);
        }
-       LOG_INFO("sam3 auto-erases while programing (request ignored)");
+       LOG_INFO("sam3 auto-erases while programming (request ignored)");
        return ERROR_OK;
 }
 
@@ -2560,23 +3308,13 @@ static int sam3_protect(struct flash_bank *bank, int set, int first, int last)
 
 }
 
-static int sam3_info(struct flash_bank *bank, char *buf, int buf_size)
-{
-       if (bank->target->state != TARGET_HALTED) {
-               LOG_ERROR("Target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-       buf[0] = 0;
-       return ERROR_OK;
-}
-
 static int sam3_page_read(struct sam3_bank_private *pPrivate, unsigned pagenum, uint8_t *buf)
 {
        uint32_t adr;
        int r;
 
        adr = pagenum * pPrivate->page_size;
-       adr += adr + pPrivate->base_address;
+       adr += pPrivate->base_address;
 
        r = target_read_memory(pPrivate->pChip->target,
                        adr,
@@ -2589,94 +3327,7 @@ static int sam3_page_read(struct sam3_bank_private *pPrivate, unsigned pagenum,
        return r;
 }
 
-/* The code below is basically this: */
-/* compiled with */
-/* arm-none-eabi-gcc -mthumb -mcpu = cortex-m3 -O9 -S ./foobar.c -o foobar.s */
-/*  */
-/* Only the *CPU* can write to the flash buffer. */
-/* the DAP cannot... so - we download this 28byte thing */
-/* Run the algorithm - (below) */
-/* to program the device */
-/*  */
-/* ======================================== */
-/* #include <stdint.h> */
-/*  */
-/* struct foo { */
-/*   uint32_t *dst; */
-/*   const uint32_t *src; */
-/*   int   n; */
-/*   volatile uint32_t *base; */
-/*   uint32_t   cmd; */
-/* }; */
-/*  */
-/*  */
-/* uint32_t sam3_function(struct foo *p) */
-/* { */
-/*   volatile uint32_t *v; */
-/*   uint32_t *d; */
-/*   const uint32_t *s; */
-/*   int   n; */
-/*   uint32_t r; */
-/*  */
-/*   d = p->dst; */
-/*   s = p->src; */
-/*   n = p->n; */
-/*  */
-/*   do { */
-/*     *d++ = *s++; */
-/*   } while (--n) */
-/*     ; */
-/*  */
-/*   v = p->base; */
-/*  */
-/*   v[ 1 ] = p->cmd; */
-/*   do { */
-/*     r = v[8/4]; */
-/*   } while (!(r&1)) */
-/*     ; */
-/*   return r; */
-/* } */
-/* ======================================== */
-
-static const uint8_t
-       sam3_page_write_opcodes[] = {
-       /*  24 0000 0446                mov     r4, r0 */
-       0x04, 0x46,
-       /*  25 0002 6168                ldr     r1, [r4, #4] */
-       0x61, 0x68,
-       /*  26 0004 0068                ldr     r0, [r0, #0] */
-       0x00, 0x68,
-       /*  27 0006 A268                ldr     r2, [r4, #8] */
-       0xa2, 0x68,
-       /*  28                          @ lr needed for prologue */
-       /*  29                  .L2: */
-       /*  30 0008 51F8043B            ldr     r3, [r1], #4 */
-       0x51, 0xf8, 0x04, 0x3b,
-       /*  31 000c 12F1FF32            adds    r2, r2, #-1 */
-       0x12, 0xf1, 0xff, 0x32,
-       /*  32 0010 40F8043B            str     r3, [r0], #4 */
-       0x40, 0xf8, 0x04, 0x3b,
-       /*  33 0014 F8D1                bne     .L2 */
-       0xf8, 0xd1,
-       /*  34 0016 E268                ldr     r2, [r4, #12] */
-       0xe2, 0x68,
-       /*  35 0018 2369                ldr     r3, [r4, #16] */
-       0x23, 0x69,
-       /*  36 001a 5360                str     r3, [r2, #4] */
-       0x53, 0x60,
-       /*  37 001c 0832                adds    r2, r2, #8 */
-       0x08, 0x32,
-       /*  38                  .L4: */
-       /*  39 001e 1068                ldr     r0, [r2, #0] */
-       0x10, 0x68,
-       /*  40 0020 10F0010F            tst     r0, #1 */
-       0x10, 0xf0, 0x01, 0x0f,
-       /*  41 0024 FBD0                beq     .L4 */
-       0xfb, 0xd0,
-       0x00, 0xBE                              /* bkpt #0 */
-};
-
-static int sam3_page_write(struct sam3_bank_private *pPrivate, unsigned pagenum, uint8_t *buf)
+static int sam3_page_write(struct sam3_bank_private *pPrivate, unsigned pagenum, const uint8_t *buf)
 {
        uint32_t adr;
        uint32_t status;
@@ -2684,7 +3335,7 @@ static int sam3_page_write(struct sam3_bank_private *pPrivate, unsigned pagenum,
        int r;
 
        adr = pagenum * pPrivate->page_size;
-       adr += (adr + pPrivate->base_address);
+       adr += pPrivate->base_address;
 
        /* Get flash mode register value */
        r = target_read_u32(pPrivate->pChip->target, pPrivate->controller_address, &fmr);
@@ -2735,7 +3386,7 @@ static int sam3_page_write(struct sam3_bank_private *pPrivate, unsigned pagenum,
 }
 
 static int sam3_write(struct flash_bank *bank,
-       uint8_t *buffer,
+       const uint8_t *buffer,
        uint32_t offset,
        uint32_t count)
 {
@@ -2845,7 +3496,7 @@ static int sam3_write(struct flash_bank *bank,
 
        /* By checking that offset is correct here, we also
        fix a clang warning */
-       assert(offset == pPrivate->page_size);
+       assert(offset % pPrivate->page_size == 0);
 
        /* intermediate large pages */
        /* also - the final *terminal* */
@@ -2875,7 +3526,6 @@ static int sam3_write(struct flash_bank *bank,
                r = sam3_page_write(pPrivate, page_cur, pagebuffer);
                if (r != ERROR_OK)
                        goto done;
-               buffer += count;
        }
        LOG_DEBUG("Done!");
        r = ERROR_OK;
@@ -3113,7 +3763,7 @@ struct flash_driver at91sam3_flash = {
        .read = default_flash_read,
        .probe = sam3_probe,
        .auto_probe = sam3_auto_probe,
-       .erase_check = sam3_erase_check,
+       .erase_check = default_flash_blank_check,
        .protect_check = sam3_protect_check,
-       .info = sam3_info,
+       .free_driver_priv = sam3_free_driver_priv,
 };