flash/nor: Use proper data types in driver API
[fw/openocd] / src / flash / nor / at91sam4.c
index c37b1df20075e7aaaea614d6494b75ecdfb55409..26cde19bc335d435eedc5306a329d5692e2726b3 100644 (file)
@@ -9,19 +9,17 @@
  *   (at91sam3x* & at91sam4 support)*                                      *
  *                                                                         *
  *   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
@@ -67,8 +65,9 @@
 
 #define REG_NAME_WIDTH  (12)
 
-/* at91sam4s series (has always one flash bank)*/
+/* at91sam4s/at91sam4e/at91sam4c series (has always one flash bank)*/
 #define FLASH_BANK_BASE_S   0x00400000
+#define FLASH_BANK_BASE_C   0x01000000
 
 /* at91sam4sd series (two one flash banks), first bank address */
 #define FLASH_BANK0_BASE_SD FLASH_BANK_BASE_S
 /* at91sam4sd32x, second bank address */
 #define FLASH_BANK1_BASE_2048K_SD (FLASH_BANK0_BASE_SD+(2048*1024/2))
 
+/* at91sam4c32x, first and second bank address */
+#define FLASH_BANK0_BASE_C32 FLASH_BANK_BASE_C
+#define FLASH_BANK1_BASE_C32 (FLASH_BANK_BASE_C+(2048*1024/2))
+
 #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  offset_EFC_FSR   8
 #define  offset_EFC_FRR   12
 
-extern struct flash_driver at91sam4_flash;
+extern const struct flash_driver at91sam4_flash;
 
 static float _tomhz(uint32_t freq_hz)
 {
@@ -225,14 +228,14 @@ struct sam4_reg_list {
 
 static struct sam4_chip *all_sam4_chips;
 
-static struct sam4_chip *get_current_sam4(struct command_context *cmd_ctx)
+static struct sam4_chip *get_current_sam4(struct command_invocation *cmd)
 {
        struct target *t;
        static struct sam4_chip *p;
 
-       t = get_current_target(cmd_ctx);
+       t = get_current_target(cmd->ctx);
        if (!t) {
-               command_print(cmd_ctx, "No current target?");
+               command_print(cmd, "No current target?");
                return NULL;
        }
 
@@ -240,7 +243,7 @@ static struct sam4_chip *get_current_sam4(struct command_context *cmd_ctx)
        if (!p) {
                /* this should not happen */
                /* the command is not registered until the chip is created? */
-               command_print(cmd_ctx, "No SAM4 chips exist?");
+               command_print(cmd, "No SAM4 chips exist?");
                return NULL;
        }
 
@@ -249,7 +252,7 @@ static struct sam4_chip *get_current_sam4(struct command_context *cmd_ctx)
                        return p;
                p = p->next;
        }
-       command_print(cmd_ctx, "Cannot find SAM4 chip?");
+       command_print(cmd, "Cannot find SAM4 chip?");
        return NULL;
 }
 
@@ -260,11 +263,93 @@ static struct sam4_chip *get_current_sam4(struct command_context *cmd_ctx)
 
 /* these are used to *initialize* the "pChip->details" structure. */
 static const struct sam4_chip_details all_sam4_details[] = {
-       /* Start at91sam4s* series */
-       /*atsam4s16c - LQFP100/BGA100*/
+       /* Start at91sam4c* series */
+       /* at91sam4c32e - LQFP144 */
        {
-               .chipid_cidr    = 0x28AC0CE0,
-               .name           = "at91sam4s16c",
+               .chipid_cidr    = 0xA66D0EE0,
+               .name           = "at91sam4c32e",
+               .total_flash_size     = 2024 * 1024,
+               .total_sram_size      = 256 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+/*             .bank[0] = { */
+               {
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK0_BASE_C32,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 5,
+                               .present = 1,
+                               .size_bytes =  1024 * 1024,
+                               .nsectors   =  128,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
+/*             .bank[1] = { */
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 1,
+                               .base_address = FLASH_BANK1_BASE_C32,
+                               .controller_address = 0x400e0c00,
+                               .flash_wait_states = 5,
+                               .present = 1,
+                               .size_bytes =  1024 * 1024,
+                               .nsectors   =  128,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
+               },
+       },
+       /* at91sam4c32c - LQFP100 */
+       {
+               .chipid_cidr    = 0xA64D0EE0,
+               .name           = "at91sam4c32c",
+               .total_flash_size     = 2024 * 1024,
+               .total_sram_size      = 256 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+/*             .bank[0] = { */
+               {
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK0_BASE_C32,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 5,
+                               .present = 1,
+                               .size_bytes =  1024 * 1024,
+                               .nsectors   =  128,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
+/*             .bank[1] = { */
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 1,
+                               .base_address = FLASH_BANK1_BASE_C32,
+                               .controller_address = 0x400e0c00,
+                               .flash_wait_states = 5,
+                               .present = 1,
+                               .size_bytes =  1024 * 1024,
+                               .nsectors   =  128,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
+               },
+       },
+       /* at91sam4c16c - LQFP100 */
+       {
+               .chipid_cidr    = 0xA64C0CE0,
+               .name           = "at91sam4c16c",
                .total_flash_size     = 1024 * 1024,
                .total_sram_size      = 128 * 1024,
                .n_gpnvms       = 2,
@@ -276,9 +361,9 @@ static const struct sam4_chip_details all_sam4_details[] = {
                        .pChip  = NULL,
                        .pBank  = NULL,
                        .bank_number = 0,
-                       .base_address = FLASH_BANK_BASE_S,
+                       .base_address = FLASH_BANK_BASE_C,
                        .controller_address = 0x400e0a00,
-                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .flash_wait_states = 5,
                        .present = 1,
                        .size_bytes =  1024 * 1024,
                        .nsectors   =  128,
@@ -294,10 +379,78 @@ static const struct sam4_chip_details all_sam4_details[] = {
                  },
                },
        },
-       /*atsam4s16b - LQFP64/QFN64*/
+       /* at91sam4c8c - LQFP100 */
        {
-               .chipid_cidr    = 0x289C0CE0,
-               .name           = "at91sam4s16b",
+               .chipid_cidr    = 0xA64C0AE0,
+               .name           = "at91sam4c8c",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 128 * 1024,
+               .n_gpnvms       = 2,
+               .n_banks        = 1,
+               {
+/*             .bank[0] = {*/
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 0,
+                       .base_address = FLASH_BANK_BASE_C,
+                       .controller_address = 0x400e0a00,
+                       .flash_wait_states = 5,
+                       .present = 1,
+                       .size_bytes =  512 * 1024,
+                       .nsectors   =  64,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+       /* at91sam4c4c (rev B) - LQFP100 */
+       {
+               .chipid_cidr    = 0xA64C0CE5,
+               .name           = "at91sam4c4c",
+               .total_flash_size     = 256 * 1024,
+               .total_sram_size      = 128 * 1024,
+               .n_gpnvms       = 2,
+               .n_banks        = 1,
+               {
+/*             .bank[0] = {*/
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 0,
+                       .base_address = FLASH_BANK_BASE_C,
+                       .controller_address = 0x400e0a00,
+                       .flash_wait_states = 5,
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  32,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+
+       /* Start at91sam4e* series */
+       /*atsam4e16e - LQFP144/LFBGA144*/
+       {
+               .chipid_cidr    = 0xA3CC0CE0,
+               .name           = "at91sam4e16e",
                .total_flash_size     = 1024 * 1024,
                .total_sram_size      = 128 * 1024,
                .n_gpnvms       = 2,
@@ -311,7 +464,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_S,
                        .controller_address = 0x400e0a00,
-                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .flash_wait_states = 5,
                        .present = 1,
                        .size_bytes =  1024 * 1024,
                        .nsectors   =  128,
@@ -327,12 +480,113 @@ static const struct sam4_chip_details all_sam4_details[] = {
                  },
                },
        },
-       /*atsam4s16a - LQFP48/QFN48*/
+
+       /* Start at91sam4n* series */
+       /*atsam4n8a - LQFP48/QFN48*/
        {
-               .chipid_cidr    = 0x288C0CE0,
-               .name           = "at91sam4s16a",
+               .chipid_cidr    = 0x293B0AE0,
+               .name           = "at91sam4n8a",
+               .total_flash_size     = 512 * 1024,
+               .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 = 5,
+                       .present = 1,
+                       .size_bytes =  512 * 1024,
+                       .nsectors   =  64,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+       /*atsam4n8b - LQFP64/QFN64*/
+       {
+               .chipid_cidr    = 0x294B0AE0,
+               .name           = "at91sam4n8b",
+               .total_flash_size     = 512 * 1024,
+               .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 = 5,
+                       .present = 1,
+                       .size_bytes =  512 * 1024,
+                       .nsectors   =  64,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+       /*atsam4n8c - LQFP100/TFBGA100/VFBGA100*/
+       {
+               .chipid_cidr    = 0x295B0AE0,
+               .name           = "at91sam4n8c",
+               .total_flash_size     = 512 * 1024,
+               .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 = 5,
+                       .present = 1,
+                       .size_bytes =  512 * 1024,
+                       .nsectors   =  64,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+       /*atsam4n16b - LQFP64/QFN64*/
+       {
+               .chipid_cidr    = 0x29460CE0,
+               .name           = "at91sam4n16b",
                .total_flash_size     = 1024 * 1024,
-               .total_sram_size      = 128 * 1024,
+               .total_sram_size      = 80 * 1024,
                .n_gpnvms       = 2,
                .n_banks        = 1,
                {
@@ -344,7 +598,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
                        .bank_number = 0,
                        .base_address = FLASH_BANK_BASE_S,
                        .controller_address = 0x400e0a00,
-                       .flash_wait_states = 6, /* workaround silicon bug */
+                       .flash_wait_states = 5,
                        .present = 1,
                        .size_bytes =  1024 * 1024,
                        .nsectors   =  128,
@@ -360,96 +614,712 @@ static const struct sam4_chip_details all_sam4_details[] = {
                  },
                },
        },
-       /*atsam4s8c - LQFP100/BGA100*/
+       /*atsam4n16c - LQFP100/TFBGA100/VFBGA100*/
        {
-               .chipid_cidr    = 0x28AC0AE0,
-               .name           = "at91sam4s8c",
-               .total_flash_size     = 512 * 1024,
+               .chipid_cidr    = 0x29560CE0,
+               .name           = "at91sam4n16c",
+               .total_flash_size     = 1024 * 1024,
+               .total_sram_size      = 80 * 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 = 5,
+                       .present = 1,
+                       .size_bytes =  1024 * 1024,
+                       .nsectors   =  128,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+
+       /* Start at91sam4s* series */
+       /*atsam4s16c - LQFP100/BGA100*/
+       {
+               .chipid_cidr    = 0x28AC0CE0,
+               .name           = "at91sam4s16c",
+               .total_flash_size     = 1024 * 1024,
                .total_sram_size      = 128 * 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 =  512 * 1024,
-                       .nsectors   =  64,
-                       .sector_size = 8192,
-                       .page_size   = 512,
-                 },
-/*             .bank[1] = {*/
-                 {
-                       .present = 0,
-                       .probed = 0,
-                       .bank_number = 1,
+/*             .bank[0] = {*/
+                 {
+                       .probed = 0,
+                       .pChip  = NULL,
+                       .pBank  = NULL,
+                       .bank_number = 0,
+                       .base_address = FLASH_BANK_BASE_S,
+                       .controller_address = 0x400e0a00,
+                       .flash_wait_states = 5,
+                       .present = 1,
+                       .size_bytes =  1024 * 1024,
+                       .nsectors   =  128,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+       /*at91sam4sa16c - TFBGA100/VFBGA100/LQFP100*/
+       {
+               .chipid_cidr    = 0x28a70ce0,
+               .name           = "at91sam4sa16c",
+               .total_flash_size     = 1024 * 1024,
+               .total_sram_size      = 160 * 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 = 5,
+                       .present = 1,
+                       .size_bytes =  1024 * 1024,
+                       .nsectors   =  128,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+       /*atsam4s16b - LQFP64/QFN64/WLCSP64*/
+       {
+               .chipid_cidr    = 0x289C0CE0,
+               .name           = "at91sam4s16b",
+               .total_flash_size     = 1024 * 1024,
+               .total_sram_size      = 128 * 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 = 5,
+                       .present = 1,
+                       .size_bytes =  1024 * 1024,
+                       .nsectors   =  128,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+       /*atsam4sa16b - LQFP64/QFN64*/
+       {
+               .chipid_cidr    = 0x28970CE0,
+               .name           = "at91sam4sa16b",
+               .total_flash_size     = 1024 * 1024,
+               .total_sram_size      = 160 * 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 = 5,
+                       .present = 1,
+                       .size_bytes =  1024 * 1024,
+                       .nsectors   =  128,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+       /*atsam4s16a - LQFP48/QFN48*/
+       {
+               .chipid_cidr    = 0x288C0CE0,
+               .name           = "at91sam4s16a",
+               .total_flash_size     = 1024 * 1024,
+               .total_sram_size      = 128 * 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 = 5,
+                       .present = 1,
+                       .size_bytes =  1024 * 1024,
+                       .nsectors   =  128,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+       /*atsam4s8c - LQFP100/BGA100*/
+       {
+               .chipid_cidr    = 0x28AC0AE0,
+               .name           = "at91sam4s8c",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 128 * 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 = 5,
+                       .present = 1,
+                       .size_bytes =  512 * 1024,
+                       .nsectors   =  64,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+       /*atsam4s8b - LQFP64/QFN64/WLCSP64*/
+       {
+               .chipid_cidr    = 0x289C0AE0,
+               .name           = "at91sam4s8b",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 128 * 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 = 5,
+                       .present = 1,
+                       .size_bytes =  512 * 1024,
+                       .nsectors   =  64,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+       /*atsam4s8a - LQFP48/BGA48*/
+       {
+               .chipid_cidr    = 0x288C0AE0,
+               .name           = "at91sam4s8a",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 128 * 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 = 5,
+                       .present = 1,
+                       .size_bytes =  512 * 1024,
+                       .nsectors   =  64,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+
+       /*atsam4s4c - LQFP100/BGA100*/
+       {
+               .chipid_cidr    = 0x28ab09e0,
+               .name           = "at91sam4s4c",
+               .total_flash_size     = 256 * 1024,
+               .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 = 5,
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  32,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+
+       /*atsam4s4b - LQFP64/QFN64/WLCSP64*/
+       {
+               .chipid_cidr    = 0x289b09e0,
+               .name           = "at91sam4s4b",
+               .total_flash_size     = 256 * 1024,
+               .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 = 5,
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  32,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+
+       /*atsam4s4a - LQFP48/QFN48*/
+       {
+               .chipid_cidr    = 0x288b09e0,
+               .name           = "at91sam4s4a",
+               .total_flash_size     = 256 * 1024,
+               .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 = 5,
+                       .present = 1,
+                       .size_bytes =  256 * 1024,
+                       .nsectors   =  32,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+
+       /*atsam4s2c - LQFP100/BGA100*/
+       {
+               .chipid_cidr    = 0x28ab07e0,
+               .name           = "at91sam4s2c",
+               .total_flash_size     = 128 * 1024,
+               .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 = 5,
+                       .present = 1,
+                       .size_bytes =  128 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+
+       /*atsam4s2b - LQPF64/QFN64/WLCSP64*/
+       {
+               .chipid_cidr    = 0x289b07e0,
+               .name           = "at91sam4s2b",
+               .total_flash_size     = 128 * 1024,
+               .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 = 5,
+                       .present = 1,
+                       .size_bytes =  128 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+
+       /*atsam4s2a - LQFP48/QFN48*/
+       {
+               .chipid_cidr    = 0x288b07e0,
+               .name           = "at91sam4s2a",
+               .total_flash_size     = 128 * 1024,
+               .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 = 5,
+                       .present = 1,
+                       .size_bytes =  128 * 1024,
+                       .nsectors   =  16,
+                       .sector_size = 8192,
+                       .page_size   = 512,
+                 },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               },
+       },
+
+       /*at91sam4sd32c  - LQFP100/BGA100*/
+       {
+               .chipid_cidr    = 0x29a70ee0,
+               .name           = "at91sam4sd32c",
+               .total_flash_size     = 2048 * 1024,
+               .total_sram_size      = 160 * 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 = 5,
+                               .present = 1,
+                               .size_bytes =  1024 * 1024,
+                               .nsectors   =  128,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
+
+/*             .bank[1] = { */
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 1,
+                               .base_address = FLASH_BANK1_BASE_2048K_SD,
+                               .controller_address = 0x400e0c00,
+                               .flash_wait_states = 5,
+                               .present = 1,
+                               .size_bytes =  1024 * 1024,
+                               .nsectors   =  128,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
+               },
+       },
+
+       /*at91sam4sd32b  - LQFP64/BGA64*/
+       {
+               .chipid_cidr    = 0x29970ee0,
+               .name           = "at91sam4sd32b",
+               .total_flash_size     = 2048 * 1024,
+               .total_sram_size      = 160 * 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 = 5,
+                               .present = 1,
+                               .size_bytes =  1024 * 1024,
+                               .nsectors   =  128,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
+
+/*             .bank[1] = { */
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 1,
+                               .base_address = FLASH_BANK1_BASE_2048K_SD,
+                               .controller_address = 0x400e0c00,
+                               .flash_wait_states = 5,
+                               .present = 1,
+                               .size_bytes =  1024 * 1024,
+                               .nsectors   =  128,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
+               },
+       },
+
+       /*at91sam4sd16c - LQFP100/BGA100*/
+       {
+               .chipid_cidr    = 0x29a70ce0,
+               .name           = "at91sam4sd16c",
+               .total_flash_size     = 1024 * 1024,
+               .total_sram_size      = 160 * 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 = 5,
+                               .present = 1,
+                               .size_bytes =  512 * 1024,
+                               .nsectors   =  64,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
 
-                 },
+/*             .bank[1] = { */
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 1,
+                               .base_address = FLASH_BANK1_BASE_1024K_SD,
+                               .controller_address = 0x400e0c00,
+                               .flash_wait_states = 5,
+                               .present = 1,
+                               .size_bytes =  512 * 1024,
+                               .nsectors   =  64,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
                },
        },
-       /*atsam4s8b - LQFP64/BGA64*/
+
+       /*at91sam4sd16b - LQFP64/BGA64*/
        {
-               .chipid_cidr    = 0x289C0AE0,
-               .name           = "at91sam4s8b",
-               .total_flash_size     = 512 * 1024,
-               .total_sram_size      = 128 * 1024,
-               .n_gpnvms       = 2,
-               .n_banks        = 1,
+               .chipid_cidr    = 0x29970ce0,
+               .name           = "at91sam4sd16b",
+               .total_flash_size     = 1024 * 1024,
+               .total_sram_size      = 160 * 1024,
+               .n_gpnvms       = 3,
+               .n_banks        = 2,
+
+/*             .bank[0] = { */
                {
-/*             .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 =  512 * 1024,
-                       .nsectors   =  64,
-                       .sector_size = 8192,
-                       .page_size   = 512,
-                 },
-/*             .bank[1] = {*/
-                 {
-                       .present = 0,
-                       .probed = 0,
-                       .bank_number = 1,
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK0_BASE_SD,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 5,
+                               .present = 1,
+                               .size_bytes =  512 * 1024,
+                               .nsectors   =  64,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
 
-                 },
+/*             .bank[1] = { */
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 1,
+                               .base_address = FLASH_BANK1_BASE_1024K_SD,
+                               .controller_address = 0x400e0c00,
+                               .flash_wait_states = 5,
+                               .present = 1,
+                               .size_bytes =  512 * 1024,
+                               .nsectors   =  64,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
                },
        },
-       /*atsam4s8a - LQFP48/BGA48*/
+
+       /* atsamg53n19 */
        {
-               .chipid_cidr    = 0x288C0AE0,
-               .name           = "at91sam4s8a",
+               .chipid_cidr    = 0x247e0ae0,
+               .name           = "atsamg53n19",
                .total_flash_size     = 512 * 1024,
-               .total_sram_size      = 128 * 1024,
+               .total_sram_size      = 96 * 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 =  512 * 1024,
-                       .nsectors   =  64,
-                       .sector_size = 8192,
-                       .page_size   = 512,
-                 },
+               {
+                       {
+                               .probed = 0,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK_BASE_S,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 5,
+                               .present = 1,
+                               .size_bytes =  512 * 1024,
+                               .nsectors   =  64,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
 /*             .bank[1] = {*/
                  {
                        .present = 0,
@@ -457,51 +1327,75 @@ static const struct sam4_chip_details all_sam4_details[] = {
                        .bank_number = 1,
 
                  },
-               },
+               }
        },
 
-       /*at91sam4sd32c*/
+       /* atsamg55g19 */
        {
-               .chipid_cidr    = 0x29a70ee0,
-               .name           = "at91sam4sd32c",
-               .total_flash_size     = 2048 * 1024,
+               .chipid_cidr    = 0x24470ae0,
+               .name           = "atsamg55g19",
+               .total_flash_size     = 512 * 1024,
                .total_sram_size      = 160 * 1024,
-               .n_gpnvms       = 3,
-               .n_banks        = 2,
+               .n_gpnvms       = 2,
+               .n_banks        = 1,
 
-/*             .bank[0] = { */
                {
+/*                     .bank[0] = */
                        {
                                .probed = 0,
                                .pChip  = NULL,
                                .pBank  = NULL,
                                .bank_number = 0,
-                               .base_address = FLASH_BANK0_BASE_SD,
+                               .base_address = FLASH_BANK_BASE_S,
                                .controller_address = 0x400e0a00,
-                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .flash_wait_states = 5,
                                .present = 1,
-                               .size_bytes =  1024 * 1024,
-                               .nsectors   =  128,
+                               .size_bytes =  512 * 1024,
+                               .nsectors   =  64,
                                .sector_size = 8192,
                                .page_size   = 512,
                        },
+/*                     .bank[1] = */
+                       {
+                               .present = 0,
+                               .probed = 0,
+                               .bank_number = 1,
+                       },
+               }
+       },
 
-/*             .bank[1] = { */
+       /* atsamg55j19 */
+       {
+               .chipid_cidr    = 0x24570ae0,
+               .name           = "atsamg55j19",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 160 * 1024,
+               .n_gpnvms       = 2,
+               .n_banks        = 1,
+
+               {
+/*                     .bank[0] = */
                        {
                                .probed = 0,
                                .pChip  = NULL,
                                .pBank  = NULL,
-                               .bank_number = 1,
-                               .base_address = FLASH_BANK1_BASE_2048K_SD,
-                               .controller_address = 0x400e0c00,
-                               .flash_wait_states = 6, /* workaround silicon bug */
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK_BASE_S,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 5,
                                .present = 1,
-                               .size_bytes =  1024 * 1024,
-                               .nsectors   =  128,
+                               .size_bytes =  512 * 1024,
+                               .nsectors   =  64,
                                .sector_size = 8192,
                                .page_size   = 512,
                        },
-               },
+/*                     .bank[1] = */
+                       {
+                               .present = 0,
+                               .probed = 0,
+                               .bank_number = 1,
+                       },
+               }
        },
 
        /* terminate */
@@ -662,7 +1556,7 @@ static int EFC_PerformCommand(struct sam4_bank_private *pPrivate,
 
        int r;
        uint32_t v;
-       long long ms_now, ms_end;
+       int64_t ms_now, ms_end;
 
        /* default */
        if (status)
@@ -1002,7 +1896,7 @@ static uint32_t sam4_reg_fieldname(struct sam4_chip *pChip,
        }
 
        /* show the basics */
-       LOG_USER_N("\t%*s: %*d [0x%0*x] ",
+       LOG_USER_N("\t%*s: %*" PRId32 " [0x%0*" PRIx32 "] ",
                REG_NAME_WIDTH, regname,
                dwidth, v,
                hwidth, v);
@@ -1011,14 +1905,14 @@ static uint32_t sam4_reg_fieldname(struct sam4_chip *pChip,
 
 static const char _unknown[] = "unknown";
 static const char *const eproc_names[] = {
-       _unknown,                                       /* 0 */
+       "Cortex-M7",                            /* 0 */
        "arm946es",                                     /* 1 */
        "arm7tdmi",                                     /* 2 */
-       "cortex-m3",                            /* 3 */
+       "Cortex-M3",                            /* 3 */
        "arm920t",                                      /* 4 */
        "arm926ejs",                            /* 5 */
-       "cortex-a5",                            /* 6 */
-       "cortex-m4",                            /* 7 */
+       "Cortex-A5",                            /* 6 */
+       "Cortex-M4",                            /* 7 */
        _unknown,                                       /* 8 */
        _unknown,                                       /* 9 */
        _unknown,                                       /* 10 */
@@ -1039,7 +1933,7 @@ static const char *const nvpsize[] = {
        "64K bytes",                            /*  5 */
        _unknown,                                       /*  6 */
        "128K bytes",                           /*  7 */
-       _unknown,                                       /*  8 */
+       "160K bytes",                           /*  8 */
        "256K bytes",                           /*  9 */
        "512K bytes",                           /* 10 */
        _unknown,                                       /* 11 */
@@ -1076,12 +1970,21 @@ static const struct archnames { unsigned value; const char *name; } archnames[]
        { 0x37,  "CAP7 Series"                                                          },
        { 0x39,  "CAP9 Series"                                                          },
        { 0x3B,  "CAP11 Series"                                                         },
+       { 0x3C, "ATSAM4E"                                                               },
        { 0x40,  "AT91x40 Series"                                                       },
        { 0x42,  "AT91x42 Series"                                                       },
+       { 0x43,  "SAMG51 Series"
+       },
+       { 0x44,  "SAMG55 Series (49-pin WLCSP)"                                         },
+       { 0x45,  "SAMG55 Series (64-pin)"                                                        },
+       { 0x47,  "SAMG53 Series"
+       },
        { 0x55,  "AT91x55 Series"                                                       },
        { 0x60,  "AT91SAM7Axx Series"                                           },
        { 0x61,  "AT91SAM7AQxx Series"                                          },
        { 0x63,  "AT91x63 Series"                                                       },
+       { 0x64,  "SAM4CxxC (100-pin version)"                                           },
+       { 0x66,  "SAM4CxxE (144-pin version)"                                           },
        { 0x70,  "AT91SAM7Sxx Series"                                           },
        { 0x71,  "AT91SAM7XCxx Series"                                          },
        { 0x72,  "AT91SAM7SExx Series"                                          },
@@ -1227,10 +2130,10 @@ static void sam4_explain_ckgr_mcfr(struct sam4_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 sam4_explain_ckgr_plla(struct sam4_chip *pChip)
@@ -1246,8 +2149,8 @@ static void sam4_explain_ckgr_plla(struct sam4_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));
        }
@@ -1398,7 +2301,7 @@ static const struct sam4_reg_list sam4_all_regs[] = {
 
 static struct sam4_bank_private *get_sam4_bank_private(struct flash_bank *bank)
 {
-       return (struct sam4_bank_private *)(bank->driver_priv);
+       return bank->driver_priv;
 }
 
 /**
@@ -1473,13 +2376,18 @@ static int sam4_GetInfo(struct sam4_chip *pChip)
 {
        const struct sam4_reg_list *pReg;
        uint32_t regval;
+       int r;
+
+       r = sam4_ReadAllRegs(pChip);
+       if (r != ERROR_OK)
+               return r;
 
        pReg = &(sam4_all_regs[0]);
        while (pReg->name) {
                /* display all regs */
                LOG_DEBUG("Start: %s", pReg->name);
                regval = *sam4_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,
@@ -1495,7 +2403,7 @@ static int sam4_GetInfo(struct sam4_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],
@@ -1574,20 +2482,21 @@ FLASH_BANK_COMMAND_HANDLER(sam4_flash_bank_command)
                                ((unsigned int)(bank->base)),
                                ((unsigned int)(FLASH_BANK_BASE_S)));
                        return ERROR_FAIL;
-                       break;
 
                /* at91sam4s series only has bank 0*/
                /* at91sam4sd series has the same address for bank 0 (FLASH_BANK0_BASE_SD)*/
                case FLASH_BANK_BASE_S:
+               case FLASH_BANK_BASE_C:
                        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 at91sam4sd series */
+               /* Bank 1 of at91sam4sd/at91sam4c32 series */
                case FLASH_BANK1_BASE_1024K_SD:
                case FLASH_BANK1_BASE_2048K_SD:
+               case FLASH_BANK1_BASE_C32:
                        bank->driver_priv = &(pChip->details.bank[1]);
                        bank->bank_number = 1;
                        pChip->details.bank[1].pChip = pChip;
@@ -1599,6 +2508,22 @@ FLASH_BANK_COMMAND_HANDLER(sam4_flash_bank_command)
        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()
+ */
+static void sam4_free_driver_priv(struct flash_bank *bank)
+{
+       struct sam4_chip *chip = all_sam4_chips;
+       while (chip) {
+               struct sam4_chip *next = chip->next;
+               free(chip);
+               chip = next;
+       }
+       all_sam4_chips = NULL;
+}
+
 static int sam4_GetDetails(struct sam4_bank_private *pPrivate)
 {
        const struct sam4_chip_details *pDetails;
@@ -1619,10 +2544,12 @@ static int sam4_GetDetails(struct sam4_bank_private *pPrivate)
                LOG_ERROR("SAM4 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("SAM4 CHIPID_CIDR: 0x%08x decodes as follows",
+               LOG_INFO("SAM4 CHIPID_CIDR: 0x%08" PRIx32 " decodes as follows",
                        pPrivate->pChip->cfg.CHIPID_CIDR);
                sam4_explain_chipid_cidr(pPrivate->pChip);
                return ERROR_FAIL;
+       } else {
+               LOG_DEBUG("SAM4 Found chip %s, CIDR 0x%08x", pDetails->name, pDetails->chipid_cidr);
        }
 
        /* DANGER: THERE ARE DRAGONS HERE */
@@ -1658,14 +2585,34 @@ static int sam4_GetDetails(struct sam4_bank_private *pPrivate)
        return ERROR_OK;
 }
 
-static int _sam4_probe(struct flash_bank *bank, int noise)
+static int sam4_info(struct flash_bank *bank, char *buf, int buf_size)
+{
+       struct sam4_bank_private *pPrivate;
+       int k = bank->size / 1024;
+
+       pPrivate = get_sam4_bank_private(bank);
+       if (pPrivate == NULL) {
+               buf[0] = '\0';
+               return ERROR_FAIL;
+       }
+
+       snprintf(buf, buf_size,
+               "%s bank %d: %d kB at " TARGET_ADDR_FMT,
+               pPrivate->pChip->details.name,
+               pPrivate->bank_number,
+               k,
+               bank->base);
+
+       return ERROR_OK;
+}
+
+static int sam4_probe(struct flash_bank *bank)
 {
-       unsigned x;
        int r;
        struct sam4_bank_private *pPrivate;
 
 
-       LOG_DEBUG("Begin: Bank: %d, Noise: %d", bank->bank_number, noise);
+       LOG_DEBUG("Begin: Bank: %u", bank->bank_number);
        if (bank->target->state != TARGET_HALTED) {
                LOG_ERROR("Target not halted");
                return ERROR_TARGET_NOT_HALTED;
@@ -1690,9 +2637,12 @@ static int _sam4_probe(struct flash_bank *bank, int noise)
                return r;
 
        /* update the flash bank size */
-       for (x = 0; x < SAM4_MAX_FLASH_BANKS; x++) {
+       for (unsigned int x = 0; x < SAM4_MAX_FLASH_BANKS; x++) {
                if (bank->base == pPrivate->pChip->details.bank[x].base_address) {
                        bank->size = pPrivate->pChip->details.bank[x].size_bytes;
+                       LOG_DEBUG("SAM4 Set flash bank to " TARGET_ADDR_FMT " - "
+                                       TARGET_ADDR_FMT ", idx %d", bank->base,
+                                       bank->base + bank->size, x);
                        break;
                }
        }
@@ -1705,7 +2655,7 @@ static int _sam4_probe(struct flash_bank *bank, int noise)
                }
                bank->num_sectors = pPrivate->nsectors;
 
-               for (x = 0; ((int)(x)) < bank->num_sectors; x++) {
+               for (unsigned int x = 0; x < bank->num_sectors; x++) {
                        bank->sectors[x].size = pPrivate->sector_size;
                        bank->sectors[x].offset = x * (pPrivate->sector_size);
                        /* mark as unknown */
@@ -1731,21 +2681,22 @@ static int _sam4_probe(struct flash_bank *bank, int noise)
        return r;
 }
 
-static int sam4_probe(struct flash_bank *bank)
-{
-       return _sam4_probe(bank, 1);
-}
-
 static int sam4_auto_probe(struct flash_bank *bank)
 {
-       return _sam4_probe(bank, 0);
+       struct sam4_bank_private *pPrivate;
+
+       pPrivate = get_sam4_bank_private(bank);
+       if (pPrivate && pPrivate->probed)
+               return ERROR_OK;
+
+       return sam4_probe(bank);
 }
 
-static int sam4_erase(struct flash_bank *bank, int first, int last)
+static int sam4_erase(struct flash_bank *bank, unsigned int first,
+               unsigned int last)
 {
        struct sam4_bank_private *pPrivate;
        int r;
-       int i;
        int pageCount;
        /*16 pages equals 8KB - Same size as a lock region*/
        pageCount = 16;
@@ -1767,26 +2718,26 @@ static int sam4_erase(struct flash_bank *bank, int first, int last)
        if (!(pPrivate->probed))
                return ERROR_FLASH_BANK_NOT_PROBED;
 
-       if ((first == 0) && ((last + 1) == ((int)(pPrivate->nsectors)))) {
+       if ((first == 0) && ((last + 1) == pPrivate->nsectors)) {
                /* whole chip */
                LOG_DEBUG("Here");
                return FLASHD_EraseEntireBank(pPrivate);
        }
        LOG_INFO("sam4 does not auto-erase while programming (Erasing relevant sectors)");
-       LOG_INFO("sam4 First: 0x%08x Last: 0x%08x", (unsigned int)(first), (unsigned int)(last));
-       for (i = first; i <= last; i++) {
+       LOG_INFO("sam4 First: 0x%08x Last: 0x%08x", first, last);
+       for (unsigned int i = first; i <= last; i++) {
                /*16 pages equals 8KB - Same size as a lock region*/
                r = FLASHD_ErasePages(pPrivate, (i * pageCount), pageCount, &status);
-               LOG_INFO("Erasing sector: 0x%08x", (unsigned int)(i));
+               LOG_INFO("Erasing sector: 0x%08x", i);
                if (r != ERROR_OK)
-                       LOG_ERROR("SAM4: Error performing Erase page @ lock region number %d",
-                               (unsigned int)(i));
+                       LOG_ERROR("SAM4: Error performing Erase page @ lock region number %u",
+                               i);
                if (status & (1 << 2)) {
-                       LOG_ERROR("SAM4: Lock Region %d is locked", (unsigned int)(i));
+                       LOG_ERROR("SAM4: Lock Region %u is locked", i);
                        return ERROR_FAIL;
                }
                if (status & (1 << 1)) {
-                       LOG_ERROR("SAM4: Flash Command error @lock region %d", (unsigned int)(i));
+                       LOG_ERROR("SAM4: Flash Command error @lock region %u", i);
                        return ERROR_FAIL;
                }
        }
@@ -1794,7 +2745,8 @@ static int sam4_erase(struct flash_bank *bank, int first, int last)
        return ERROR_OK;
 }
 
-static int sam4_protect(struct flash_bank *bank, int set, int first, int last)
+static int sam4_protect(struct flash_bank *bank, int set, unsigned int first,
+               unsigned int last)
 {
        struct sam4_bank_private *pPrivate;
        int r;
@@ -1810,25 +2762,15 @@ static int sam4_protect(struct flash_bank *bank, int set, int first, int last)
                return ERROR_FLASH_BANK_NOT_PROBED;
 
        if (set)
-               r = FLASHD_Lock(pPrivate, (unsigned)(first), (unsigned)(last));
+               r = FLASHD_Lock(pPrivate, first, last);
        else
-               r = FLASHD_Unlock(pPrivate, (unsigned)(first), (unsigned)(last));
+               r = FLASHD_Unlock(pPrivate, first, last);
        LOG_DEBUG("End: r=%d", r);
 
        return r;
 
 }
 
-static int sam4_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 sam4_page_read(struct sam4_bank_private *pPrivate, unsigned pagenum, uint8_t *buf)
 {
        uint32_t adr;
@@ -1848,107 +2790,17 @@ static int sam4_page_read(struct sam4_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 sam4_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
-       sam4_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 sam4_page_write(struct sam4_bank_private *pPrivate, unsigned pagenum, uint8_t *buf)
+static int sam4_set_wait(struct sam4_bank_private *pPrivate)
 {
-       uint32_t adr;
-       uint32_t status;
        uint32_t fmr;   /* EEFC Flash Mode Register */
        int r;
 
-       adr = pagenum * pPrivate->page_size;
-       adr = (adr + pPrivate->base_address);
-
        /* Get flash mode register value */
        r = target_read_u32(pPrivate->pChip->target, pPrivate->controller_address, &fmr);
-       if (r != ERROR_OK)
-               LOG_DEBUG("Error Read failed: read flash mode register");
+       if (r != ERROR_OK) {
+               LOG_ERROR("Error Read failed: read flash mode register");
+               return r;
+       }
 
        /* Clear flash wait state field */
        fmr &= 0xfffff0ff;
@@ -1959,7 +2811,19 @@ static int sam4_page_write(struct sam4_bank_private *pPrivate, unsigned pagenum,
        LOG_DEBUG("Flash Mode: 0x%08x", ((unsigned int)(fmr)));
        r = target_write_u32(pPrivate->pBank->target, pPrivate->controller_address, fmr);
        if (r != ERROR_OK)
-               LOG_DEBUG("Error Write failed: set flash mode register");
+               LOG_ERROR("Error Write failed: set flash mode register");
+
+       return r;
+}
+
+static int sam4_page_write(struct sam4_bank_private *pPrivate, unsigned pagenum, const uint8_t *buf)
+{
+       uint32_t adr;
+       uint32_t status;
+       int r;
+
+       adr = pagenum * pPrivate->page_size;
+       adr = (adr + pPrivate->base_address);
 
        /* 1st sector 8kBytes - page 0 - 15*/
        /* 2nd sector 8kBytes - page 16 - 30*/
@@ -1997,7 +2861,7 @@ static int sam4_page_write(struct sam4_bank_private *pPrivate, unsigned pagenum,
 }
 
 static int sam4_write(struct flash_bank *bank,
-       uint8_t *buffer,
+       const uint8_t *buffer,
        uint32_t offset,
        uint32_t count)
 {
@@ -2047,6 +2911,10 @@ static int sam4_write(struct flash_bank *bank,
                goto done;
        }
 
+       r = sam4_set_wait(pPrivate);
+       if (r != ERROR_OK)
+               goto done;
+
        /* what page do we start & end in? */
        page_cur = offset / pPrivate->page_size;
        page_end = (offset + count - 1) / pPrivate->page_size;
@@ -2149,7 +3017,7 @@ done:
 COMMAND_HANDLER(sam4_handle_info_command)
 {
        struct sam4_chip *pChip;
-       pChip = get_current_sam4(CMD_CTX);
+       pChip = get_current_sam4(CMD);
        if (!pChip)
                return ERROR_OK;
 
@@ -2160,7 +3028,7 @@ COMMAND_HANDLER(sam4_handle_info_command)
        if (pChip->details.bank[0].pBank == NULL) {
                x = 0;
 need_define:
-               command_print(CMD_CTX,
+               command_print(CMD,
                        "Please define bank %d via command: flash bank %s ... ",
                        x,
                        at91sam4_flash.name);
@@ -2209,7 +3077,7 @@ COMMAND_HANDLER(sam4_handle_gpnvm_command)
        int r, who;
        struct sam4_chip *pChip;
 
-       pChip = get_current_sam4(CMD_CTX);
+       pChip = get_current_sam4(CMD);
        if (!pChip)
                return ERROR_OK;
 
@@ -2219,7 +3087,7 @@ COMMAND_HANDLER(sam4_handle_gpnvm_command)
        }
 
        if (pChip->details.bank[0].pBank == NULL) {
-               command_print(CMD_CTX, "Bank0 must be defined first via: flash bank %s ...",
+               command_print(CMD, "Bank0 must be defined first via: flash bank %s ...",
                        at91sam4_flash.name);
                return ERROR_FAIL;
        }
@@ -2232,10 +3100,8 @@ COMMAND_HANDLER(sam4_handle_gpnvm_command)
        switch (CMD_ARGC) {
                default:
                        return ERROR_COMMAND_SYNTAX_ERROR;
-                       break;
                case 0:
                        goto showall;
-                       break;
                case 1:
                        who = -1;
                        break;
@@ -2258,22 +3124,23 @@ showall:
                                r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), x, &v);
                                if (r != ERROR_OK)
                                        break;
-                               command_print(CMD_CTX, "sam4-gpnvm%u: %u", x, v);
+                               command_print(CMD, "sam4-gpnvm%u: %u", x, v);
                        }
                        return r;
                }
                if ((who >= 0) && (((unsigned)(who)) < pChip->details.n_gpnvms)) {
                        r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), who, &v);
-                       command_print(CMD_CTX, "sam4-gpnvm%u: %u", who, v);
+                       if (r == ERROR_OK)
+                               command_print(CMD, "sam4-gpnvm%u: %u", who, v);
                        return r;
                } else {
-                       command_print(CMD_CTX, "sam4-gpnvm invalid GPNVM: %u", who);
+                       command_print(CMD, "sam4-gpnvm invalid GPNVM: %u", who);
                        return ERROR_COMMAND_SYNTAX_ERROR;
                }
        }
 
        if (who == -1) {
-               command_print(CMD_CTX, "Missing GPNVM number");
+               command_print(CMD, "Missing GPNVM number");
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
@@ -2283,7 +3150,7 @@ showall:
                 (0 == strcmp("clear", CMD_ARGV[0])))                   /* quietly accept both */
                r = FLASHD_ClrGPNVM(&(pChip->details.bank[0]), who);
        else {
-               command_print(CMD_CTX, "Unknown command: %s", CMD_ARGV[0]);
+               command_print(CMD, "Unknown command: %s", CMD_ARGV[0]);
                r = ERROR_COMMAND_SYNTAX_ERROR;
        }
        return r;
@@ -2293,7 +3160,7 @@ COMMAND_HANDLER(sam4_handle_slowclk_command)
 {
        struct sam4_chip *pChip;
 
-       pChip = get_current_sam4(CMD_CTX);
+       pChip = get_current_sam4(CMD);
        if (!pChip)
                return ERROR_OK;
 
@@ -2308,7 +3175,7 @@ COMMAND_HANDLER(sam4_handle_slowclk_command)
                        COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], v);
                        if (v > 200000) {
                                /* absurd slow clock of 200Khz? */
-                               command_print(CMD_CTX, "Absurd/illegal slow clock freq: %d\n", (int)(v));
+                               command_print(CMD, "Absurd/illegal slow clock freq: %d\n", (int)(v));
                                return ERROR_COMMAND_SYNTAX_ERROR;
                        }
                        pChip->cfg.slow_freq = v;
@@ -2316,11 +3183,10 @@ COMMAND_HANDLER(sam4_handle_slowclk_command)
                }
                default:
                        /* error */
-                       command_print(CMD_CTX, "Too many parameters");
+                       command_print(CMD, "Too many parameters");
                        return ERROR_COMMAND_SYNTAX_ERROR;
-                       break;
        }
-       command_print(CMD_CTX, "Slowclk freq: %d.%03dkhz",
+       command_print(CMD, "Slowclk freq: %d.%03dkhz",
                (int)(pChip->cfg.slow_freq / 1000),
                (int)(pChip->cfg.slow_freq % 1000));
        return ERROR_OK;
@@ -2340,8 +3206,9 @@ static const struct command_registration at91sam4_exec_command_handlers[] = {
                .name = "info",
                .handler = sam4_handle_info_command,
                .mode = COMMAND_EXEC,
-               .help = "Print information about the current at91sam4 chip"
+               .help = "Print information about the current at91sam4 chip "
                        "and its flash configuration.",
+               .usage = "",
        },
        {
                .name = "slowclk",
@@ -2364,7 +3231,7 @@ static const struct command_registration at91sam4_command_handlers[] = {
        COMMAND_REGISTRATION_DONE
 };
 
-struct flash_driver at91sam4_flash = {
+const struct flash_driver at91sam4_flash = {
        .name = "at91sam4",
        .commands = at91sam4_command_handlers,
        .flash_bank_command = sam4_flash_bank_command,
@@ -2377,4 +3244,5 @@ struct flash_driver at91sam4_flash = {
        .erase_check = default_flash_blank_check,
        .protect_check = sam4_protect_check,
        .info = sam4_info,
+       .free_driver_priv = sam4_free_driver_priv,
 };