X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fat91sam4.c;h=3f9ea9bfa1fd228f0d1066265452634d333efc0c;hb=62329444abc89ad3b37fbb4ebc2edfd1dee23351;hp=c009a13998bae1c4d3f27fd49b09820ee7f728bf;hpb=908ee4dc9641bd3df2eb00264575501867da539d;p=openocd.git diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c index c009a13998..3f9ea9bfa1 100644 --- a/src/flash/nor/at91sam4.c +++ b/src/flash/nor/at91sam4.c @@ -9,22 +9,20 @@ * (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 . * ****************************************************************************/ -/* Some of the the lower level code was based on code supplied by +/* Some of the lower level code was based on code supplied by * ATMEL under this copyright. */ /* BEGIN ATMEL COPYRIGHT */ @@ -67,17 +65,28 @@ #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 +/* at91sam4sd16x, second bank address */ +#define FLASH_BANK1_BASE_1024K_SD (FLASH_BANK0_BASE_SD+(1024*1024/2)) +/* 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 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 int he at91sam4u4/2/1 data sheet table 19-2 */ +/* cmd6 is not present in the at91sam4u4/2/1 data sheet table 19-2 */ /* #define AT91C_EFC_FCMD_EPL (0x6) // (EFC) Erase plane? */ #define AT91C_EFC_FCMD_EPA (0x7) /* (EFC) Erase pages */ #define AT91C_EFC_FCMD_SLB (0x8) /* (EFC) Set Lock Bit */ @@ -94,7 +103,7 @@ #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) { @@ -157,7 +166,7 @@ struct sam4_cfg { }; struct sam4_bank_private { - int probed; + bool probed; /* DANGER: THERE ARE DRAGONS HERE.. */ /* NOTE: If you add more 'ghost' pointers */ /* be aware that you must *manually* update */ @@ -166,7 +175,7 @@ struct sam4_bank_private { /* so we can find the chip we belong to */ struct sam4_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; @@ -182,7 +191,7 @@ struct sam4_bank_private { struct sam4_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: "sam4_GetDetails() */ /* which copy/overwrites the */ @@ -203,7 +212,7 @@ struct sam4_chip_details { struct sam4_chip { struct sam4_chip *next; - int probed; + bool probed; /* this is "initialized" from the global const structure */ struct sam4_chip_details details; @@ -219,240 +228,1176 @@ 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; } - p = all_sam4_chips; - if (!p) { - /* this should not happen */ - /* the command is not registered until the chip is created? */ - command_print(cmd_ctx, "No SAM4 chips exist?"); - return NULL; - } + p = all_sam4_chips; + if (!p) { + /* this should not happen */ + /* the command is not registered until the chip is created? */ + command_print(cmd, "No SAM4 chips exist?"); + return NULL; + } + + while (p) { + if (p->target == t) + return p; + p = p->next; + } + command_print(cmd, "Cannot find SAM4 chip?"); + return NULL; +} + +/*The actual sector size of the SAM4S flash memory is 65536 bytes. 16 sectors for a 1024KB device*/ +/*The lockregions are 8KB per lock region, with a 1024KB device having 128 lock regions. */ +/*For the best results, nsectors are thus set to the amount of lock regions, and the sector_size*/ +/*set to the lock region size. Page erases are used to erase 8KB sections when programming*/ + +/* these are used to *initialize* the "pChip->details" structure. */ +static const struct sam4_chip_details all_sam4_details[] = { + /* Start at91sam4c* series */ + /* at91sam4c32e - LQFP144 */ + { + .chipid_cidr = 0xA66D0EE0, + .name = "at91sam4c32e", + .total_flash_size = 2024 * 1024, + .total_sram_size = 256 * 1024, + .n_gpnvms = 3, + .n_banks = 2, +/* .bank[0] = { */ + { + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_C32, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = { */ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_C32, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, + .present = true, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_C32, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = { */ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_C32, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, + .present = true, + .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, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_C, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .bank_number = 1, + + }, + }, + }, + /* at91sam4c8c - LQFP100 */ + { + .chipid_cidr = 0xA64C0AE0, + .name = "at91sam4c8c", + .total_flash_size = 512 * 1024, + .total_sram_size = 128 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_C, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_C, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 256 * 1024, + .nsectors = 32, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .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, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .bank_number = 1, + + }, + }, + }, + + /* Start at91sam4n* series */ + /*atsam4n8a - LQFP48/QFN48*/ + { + .chipid_cidr = 0x293B0AE0, + .name = "at91sam4n8a", + .total_flash_size = 512 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .bank_number = 1, + + }, + }, + }, + /*atsam4n16b - LQFP64/QFN64*/ + { + .chipid_cidr = 0x29460CE0, + .name = "at91sam4n16b", + .total_flash_size = 1024 * 1024, + .total_sram_size = 80 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .bank_number = 1, + + }, + }, + }, + /*atsam4n16c - LQFP100/TFBGA100/VFBGA100*/ + { + .chipid_cidr = 0x29560CE0, + .name = "at91sam4n16c", + .total_flash_size = 1024 * 1024, + .total_sram_size = 80 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .bank_number = 1, - while (p) { - if (p->target == t) - return p; - p = p->next; - } - command_print(cmd_ctx, "Cannot find SAM4 chip?"); - return NULL; -} + }, + }, + }, + /*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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .bank_number = 1, -/*The actual sector size of the SAM4S flash memory is 65536 bytes. 16 sectors for a 1024KB device*/ -/*The lockregions are 8KB per lock reqion, with a 1024KB device having 128 lock reqions. */ -/*For the best results, nsectors are thus set to the amount of lock regions, and the sector_size*/ -/*set to the lock region size. Page erases are used to erase 8KB sections when programming*/ + }, + }, + }, -/* these are used to *initialize* the "pChip->details" structure. */ -static const struct sam4_chip_details all_sam4_details[] = { - /* Start at91sam4s* series */ - /*atsam4s16c - LQFP100/BGA100*/ + /*atsam4s4c - LQFP100/BGA100*/ { - .chipid_cidr = 0x28AC0CE0, - .name = "at91sam4s16c", - .total_flash_size = 1024 * 1024, - .total_sram_size = 128 * 1024, + .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, + .probed = false, .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 = 1024 * 1024, - .nsectors = 128, + .flash_wait_states = 5, + .present = true, + .size_bytes = 256 * 1024, + .nsectors = 32, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { - .present = 0, - .probed = 0, + .present = false, + .probed = false, .bank_number = 1, }, }, }, - /*atsam4s16b - LQFP64/QFN64*/ + + /*atsam4s4b - LQFP64/QFN64/WLCSP64*/ { - .chipid_cidr = 0x289C0CE0, - .name = "at91sam4s16b", - .total_flash_size = 1024 * 1024, - .total_sram_size = 128 * 1024, + .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, + .probed = false, .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 = 1024 * 1024, - .nsectors = 128, + .flash_wait_states = 5, + .present = true, + .size_bytes = 256 * 1024, + .nsectors = 32, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { - .present = 0, - .probed = 0, + .present = false, + .probed = false, .bank_number = 1, }, }, }, - /*atsam4s16a - LQFP48/QFN48*/ + + /*atsam4s4a - LQFP48/QFN48*/ { - .chipid_cidr = 0x288C0CE0, - .name = "at91sam4s16a", - .total_flash_size = 1024 * 1024, - .total_sram_size = 128 * 1024, + .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, + .probed = false, .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 = 1024 * 1024, - .nsectors = 128, + .flash_wait_states = 5, + .present = true, + .size_bytes = 256 * 1024, + .nsectors = 32, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { - .present = 0, - .probed = 0, + .present = false, + .probed = false, .bank_number = 1, }, }, }, - /*atsam4s8c - LQFP100/BGA100*/ + + /*atsam4s2c - LQFP100/BGA100*/ { - .chipid_cidr = 0x28AC0AE0, - .name = "at91sam4s8c", - .total_flash_size = 512 * 1024, - .total_sram_size = 128 * 1024, + .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, + .probed = false, .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, + .flash_wait_states = 5, + .present = true, + .size_bytes = 128 * 1024, + .nsectors = 16, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { - .present = 0, - .probed = 0, + .present = false, + .probed = false, .bank_number = 1, }, }, }, - /*atsam4s8b - LQFP64/BGA64*/ + + /*atsam4s2b - LQPF64/QFN64/WLCSP64*/ { - .chipid_cidr = 0x289C0AE0, - .name = "at91sam4s8b", - .total_flash_size = 512 * 1024, - .total_sram_size = 128 * 1024, + .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, + .probed = false, .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, + .flash_wait_states = 5, + .present = true, + .size_bytes = 128 * 1024, + .nsectors = 16, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { - .present = 0, - .probed = 0, + .present = false, + .probed = false, .bank_number = 1, }, }, }, - /*atsam4s8a - LQFP48/BGA48*/ + + /*atsam4s2a - LQFP48/QFN48*/ { - .chipid_cidr = 0x288C0AE0, - .name = "at91sam4s8a", - .total_flash_size = 512 * 1024, - .total_sram_size = 128 * 1024, + .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, + .probed = false, .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, + .flash_wait_states = 5, + .present = true, + .size_bytes = 128 * 1024, + .nsectors = 16, .sector_size = 8192, .page_size = 512, }, /* .bank[1] = {*/ { - .present = 0, - .probed = 0, + .present = false, + .probed = false, .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_SD, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, + +/* .bank[1] = { */ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_2048K_SD, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, + .present = true, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_SD, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, + +/* .bank[1] = { */ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_2048K_SD, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, + .present = true, + .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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_SD, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, + +/* .bank[1] = { */ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_1024K_SD, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, + }, + }, + + /*at91sam4sd16b - LQFP64/BGA64*/ + { + .chipid_cidr = 0x29970ce0, + .name = "at91sam4sd16b", + .total_flash_size = 1024 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + +/* .bank[0] = { */ + { + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_SD, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, + +/* .bank[1] = { */ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_1024K_SD, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, + }, + }, + + /* atsamg53n19 */ + { + .chipid_cidr = 0x247e0ae0, + .name = "atsamg53n19", + .total_flash_size = 512 * 1024, + .total_sram_size = 96 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + +/* .bank[0] = {*/ + { + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = false, + .probed = false, + .bank_number = 1, + + }, + } + }, + + /* atsamg55g19 */ + { + .chipid_cidr = 0x24470ae0, + .name = "atsamg55g19", + .total_flash_size = 512 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + + { +/* .bank[0] = */ + { + .probed = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = */ + { + .present = false, + .probed = false, + .bank_number = 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 = false, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = true, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = */ + { + .present = false, + .probed = false, + .bank_number = 1, + }, + } + }, + /* terminate */ { .chipid_cidr = 0, @@ -611,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) @@ -722,10 +1667,17 @@ static int FLASHD_ErasePages(struct sam4_bank_private *pPrivate, break; } + /* AT91C_EFC_FCMD_EPA + * According to the datasheet FARG[15:2] defines the page from which + * the erase will start.This page must be modulo 4, 8, 16 or 32 + * according to the number of pages to erase. FARG[1:0] defines the + * number of pages to be erased. Previously (firstpage << 2) was used + * to conform to this, seems it should not be shifted... + */ return EFC_PerformCommand(pPrivate, /* send Erase Page */ AT91C_EFC_FCMD_EPA, - (firstPage << 2) | erasePages, + (firstPage) | erasePages, status); } @@ -944,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); @@ -953,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 */ @@ -981,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 */ @@ -1018,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" }, @@ -1169,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) @@ -1188,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)); } @@ -1340,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; } /** @@ -1401,7 +2362,7 @@ static int sam4_ReadAllRegs(struct sam4_chip *pChip) r = sam4_ReadThisReg(pChip, sam4_get_reg_ptr(&(pChip->cfg), pReg)); if (r != ERROR_OK) { - LOG_ERROR("Cannot read SAM4 registere: %s @ 0x%08x, Error: %d", + LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08x, Error: %d", pReg->name, ((unsigned)(pReg->address)), r); return r; } @@ -1415,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, @@ -1437,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], @@ -1506,31 +2472,58 @@ FLASH_BANK_COMMAND_HANDLER(sam4_flash_bank_command) pChip->target = bank->target; /* assumption is this runs at 32khz */ pChip->cfg.slow_freq = 32768; - pChip->probed = 0; + pChip->probed = false; } switch (bank->base) { default: LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x" - "[at91sam4s series] )", - ((unsigned int)(bank->base)), - ((unsigned int)(FLASH_BANK_BASE_S))); + "[at91sam4s series] )", + ((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/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; + pChip->details.bank[1].pBank = bank; + break; } /* we initialize after probing. */ return ERROR_OK; } +/** + * Remove all chips from the internal list without distinguishing 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; @@ -1551,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 */ @@ -1590,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; @@ -1622,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; } } @@ -1637,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 */ @@ -1646,7 +2664,7 @@ static int _sam4_probe(struct flash_bank *bank, int noise) } } - pPrivate->probed = 1; + pPrivate->probed = true; r = sam4_protect_check(bank); if (r != ERROR_OK) @@ -1663,21 +2681,25 @@ 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; uint32_t status; LOG_DEBUG("Here"); @@ -1696,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 programing (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 does not auto-erase while programming (Erasing relevant sectors)"); + 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, 16, &status); - LOG_INFO("Erasing sector: 0x%08x", (unsigned int)(i)); + r = FLASHD_ErasePages(pPrivate, (i * pageCount), pageCount, &status); + 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 Reqion %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; } } @@ -1723,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; @@ -1739,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; @@ -1777,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 */ -/* */ -/* 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; @@ -1888,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*/ @@ -1926,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) { @@ -1938,7 +2873,7 @@ static int sam4_write(struct flash_bank *bank, struct sam4_bank_private *pPrivate; uint8_t *pagebuffer; - /* incase we bail further below, set this to null */ + /* in case we bail further below, set this to null */ pagebuffer = NULL; /* ignore dumb requests */ @@ -1976,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; @@ -2070,15 +3009,14 @@ static int sam4_write(struct flash_bank *bank, LOG_DEBUG("Done!"); r = ERROR_OK; done: - if (pagebuffer) - free(pagebuffer); + free(pagebuffer); return r; } 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; @@ -2089,7 +3027,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); @@ -2138,7 +3076,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; @@ -2148,7 +3086,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; } @@ -2161,10 +3099,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; @@ -2187,22 +3123,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; } @@ -2212,7 +3149,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; @@ -2222,7 +3159,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; @@ -2237,7 +3174,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; @@ -2245,11 +3182,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; @@ -2269,8 +3205,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", @@ -2293,7 +3230,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, @@ -2306,4 +3243,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, };