From 736e8bb77366ad556a5b59adb4ef5c09f4997aae Mon Sep 17 00:00:00 2001 From: Olivier Schonken Date: Tue, 6 Mar 2012 20:57:45 +0200 Subject: [PATCH] topic: Added support for the SAM3X/A variants Atmel introduced 7 new Cortex-M3 processors on 2012-02-28 SAM3X4C - 256KB flash SAM3X4E - 256KB flash SAM3X8C - 512KB flash SAM3X8E - 512KB flash SAM3X8H (Only on dev-kit - not in production...) - 512KB flash SAM3A4C - 256KB flash SAM3A8C - 256KB flash The SAM3X/A processors still suffer from the "6 waitstates needed to program device" errata. The CIDR address for the SAM3X/A processors are different from the other SAM3 processors. Unfortunately, the chip identification register is not at a constant address across all of the SAM3 series'. As a consequence, a simple heuristic is used to find where it's at... If the contents at the first address is zero, then we know that the second address is where the chip id register is. We can deduce this because for those SAM's that have the chip id @ 0x400e0940, the first address, 0x400e0740, is located in the memory map of the Power Management Controller (PMC). Furthermore, the address is not used by the PMC. So when read, the memory controller returns zero. Another interesting change is the flash bank address for flash bank 1. It is not fixed at 0x00100000 like the Sam3U. Bank 1 of the at91sam3a/x series starts at 0x00080000 + half the total flash size. Thus for the 256KB devices Bank 1 is located at 0x000A0000, and for the 512KB devices Bank 1 is located at 0x000C0000. The configuration files for the SAM3X/A processors will follow Change-Id: I6c3a707c00e05d993a2ad1d5a423f23b37ffd553 Signed-off-by: Olivier Schonken Reviewed-on: http://openocd.zylin.com/505 Tested-by: jenkins Reviewed-by: Spencer Oliver --- src/flash/nor/at91sam3.c | 385 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 369 insertions(+), 16 deletions(-) diff --git a/src/flash/nor/at91sam3.c b/src/flash/nor/at91sam3.c index 50f522f94..01c962413 100644 --- a/src/flash/nor/at91sam3.c +++ b/src/flash/nor/at91sam3.c @@ -4,8 +4,9 @@ * * * Copyright (C) 2010 by Olaf Lüke (at91sam3s* support) * * olaf@uni-paderborn.de * - * * - * * + * * + * Copyright (C) 2011 by Olivier Schonken (at91sam3x* support) * * + * and Jim Norris * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -75,6 +76,12 @@ /* at91sam3n series (has always one flash bank) */ #define FLASH_BANK_BASE_N 0x00400000 +/* at91sam3a/x series has two flash banks*/ +#define FLASH_BANK0_BASE_AX 0x00080000 +/*Bank 1 of the at91sam3a/x series starts at 0x00080000 + half flash size*/ +#define FLASH_BANK1_BASE_256K_AX 0x000A0000 +#define FLASH_BANK1_BASE_512K_AX 0x000C0000 + #define AT91C_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */ #define AT91C_EFC_FCMD_WP (0x1) /* (EFC) Write Page */ #define AT91C_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */ @@ -128,8 +135,13 @@ struct sam3_cfg { #define SAM3_CHIPID_CIDR (0x400E0740) uint32_t CHIPID_CIDR; +#define SAM3_CHIPID_CIDR2 (0x400E0940) /*SAM3X and SAM3A cidr at this address*/ + uint32_t CHIPID_CIDR2; #define SAM3_CHIPID_EXID (0x400E0744) uint32_t CHIPID_EXID; +#define SAM3_CHIPID_EXID2 (0x400E0944) /*SAM3X and SAM3A cidr at this address*/ + uint32_t CHIPID_EXID2; + #define SAM3_PMC_BASE (0x400E0400) #define SAM3_PMC_SCSR (SAM3_PMC_BASE + 0x0008) @@ -1286,6 +1298,327 @@ static const struct sam3_chip_details all_sam3_details[] = { }, }, + /* Start at91sam3a series*/ + /* System boots at address 0x0 */ + /* gpnvm[1] = selects boot code */ + /* if gpnvm[1] == 0 */ + /* boot is via "SAMBA" (rom) */ + /* else */ + /* boot is via FLASH */ + /* Selection is via gpnvm[2] */ + /* endif */ + /* */ + /* NOTE: banks 0 & 1 switch places */ + /* if gpnvm[2] == 0 */ + /* Bank0 is the boot rom */ + /* else */ + /* Bank1 is the boot rom */ + /* endif */ + + { + .chipid_cidr = 0x283E0A60, + .name = "at91sam3a8c", + .total_flash_size = 512 * 1024, + .total_sram_size = 96 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + { +/* .bank[0] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_AX, + .controller_address = 0x400e0a00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 16, + .sector_size = 16384, + .page_size = 256, + }, +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_512K_AX, + .controller_address = 0x400e0c00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 16, + .sector_size = 16384, + .page_size = 256, + + }, + }, + }, + { + .chipid_cidr = 0x283B0960, + .name = "at91sam3a4c", + .total_flash_size = 256 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + { +/* .bank[0] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_AX, + .controller_address = 0x400e0a00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 128 * 1024, + .nsectors = 8, + .sector_size = 16384, + .page_size = 256, + }, +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_256K_AX, + .controller_address = 0x400e0c00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 128 * 1024, + .nsectors = 8, + .sector_size = 16384, + .page_size = 256, + + }, + }, + }, + + /* Start at91sam3x* series */ + /* System boots at address 0x0 */ + /* gpnvm[1] = selects boot code */ + /* if gpnvm[1] == 0 */ + /* boot is via "SAMBA" (rom) */ + /* else */ + /* boot is via FLASH */ + /* Selection is via gpnvm[2] */ + /* endif */ + /* */ + /* NOTE: banks 0 & 1 switch places */ + /* if gpnvm[2] == 0 */ + /* Bank0 is the boot rom */ + /* else */ + /* Bank1 is the boot rom */ + /* endif */ + { + .chipid_cidr = 0x286E0A20, + .name = "at91sam3x8h", + .total_flash_size = 512 * 1024, + .total_sram_size = 96 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + { +/* .bank[0] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_AX, + .controller_address = 0x400e0a00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 16, + .sector_size = 16384, + .page_size = 256, + }, +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_512K_AX, + .controller_address = 0x400e0c00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 16, + .sector_size = 16384, + .page_size = 256, + + }, + }, + }, + { + .chipid_cidr = 0x285E0A60, + .name = "at91sam3x8e", + .total_flash_size = 512 * 1024, + .total_sram_size = 96 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + { +/* .bank[0] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_AX, + .controller_address = 0x400e0a00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 16, + .sector_size = 16384, + .page_size = 256, + }, +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_512K_AX, + .controller_address = 0x400e0c00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 16, + .sector_size = 16384, + .page_size = 256, + + }, + }, + }, + { + .chipid_cidr = 0x284E0A60, + .name = "at91sam3x8c", + .total_flash_size = 512 * 1024, + .total_sram_size = 96 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + { +/* .bank[0] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_AX, + .controller_address = 0x400e0a00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 16, + .sector_size = 16384, + .page_size = 256, + }, +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_512K_AX , + .controller_address = 0x400e0c00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 16, + .sector_size = 16384, + .page_size = 256, + + }, + }, + }, + { + .chipid_cidr = 0x285B0960, + .name = "at91sam3x4e", + .total_flash_size = 256 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + { +/* .bank[0] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_AX, + .controller_address = 0x400e0a00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 128 * 1024, + .nsectors = 8, + .sector_size = 16384, + .page_size = 256, + }, +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_256K_AX, + .controller_address = 0x400e0c00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 128 * 1024, + .nsectors = 8, + .sector_size = 16384, + .page_size = 256, + + }, + }, + }, + { + .chipid_cidr = 0x284B0960, + .name = "at91sam3x4c", + .total_flash_size = 256 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + { +/* .bank[0] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_AX, + .controller_address = 0x400e0a00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 128 * 1024, + .nsectors = 8, + .sector_size = 16384, + .page_size = 256, + }, +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_256K_AX, + .controller_address = 0x400e0c00, + .flash_wait_states = 6, /* workaround silicon bug */ + .present = 1, + .size_bytes = 128 * 1024, + .nsectors = 8, + .sector_size = 16384, + .page_size = 256, + + }, + }, + }, /* terminate */ { .chipid_cidr = 0, @@ -2125,8 +2458,9 @@ static const struct sam3_reg_list sam3_all_regs[] = { SAM3_ENTRY(PMC_SCSR, NULL), SAM3_ENTRY(PMC_SR, NULL), SAM3_ENTRY(CHIPID_CIDR, sam3_explain_chipid_cidr), + SAM3_ENTRY(CHIPID_CIDR2, sam3_explain_chipid_cidr), SAM3_ENTRY(CHIPID_EXID, NULL), - + SAM3_ENTRY(CHIPID_EXID2, NULL), /* TERMINATE THE LIST */ { .name = NULL } }; @@ -2199,10 +2533,28 @@ static int sam3_ReadAllRegs(struct sam3_chip *pChip) pReg->name, ((unsigned)(pReg->address)), r); return r; } - pReg++; } + /* Chip identification register + * + * Unfortunately, the chip identification register is not at + * a constant address across all of the SAM3 series'. As a + * consequence, a simple heuristic is used to find where it's + * at... + * + * If the contents at the first address is zero, then we know + * that the second address is where the chip id register is. + * We can deduce this because for those SAM's that have the + * chip id @ 0x400e0940, the first address, 0x400e0740, is + * located in the memory map of the Power Management Controller + * (PMC). Furthermore, the address is not used by the PMC. + * So when read, the memory controller returns zero.*/ + if (pChip->cfg.CHIPID_CIDR == 0) { + /*Put the correct CIDR and EXID values in the pChip structure */ + pChip->cfg.CHIPID_CIDR = pChip->cfg.CHIPID_CIDR2; + pChip->cfg.CHIPID_EXID = pChip->cfg.CHIPID_EXID2; + } return ERROR_OK; } @@ -2330,36 +2682,37 @@ FLASH_BANK_COMMAND_HANDLER(sam3_flash_bank_command) default: LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x or 0x%08x " "[at91sam3u series] or 0x%08x [at91sam3s series] or " - "0x%08x [at91sam3n series])", + "0x%08x [at91sam3n series] or 0x%08x or 0x%08x or 0x%08x[at91sam3ax series] )", ((unsigned int)(bank->base)), ((unsigned int)(FLASH_BANK0_BASE_U)), ((unsigned int)(FLASH_BANK1_BASE_U)), ((unsigned int)(FLASH_BANK_BASE_S)), - ((unsigned int)(FLASH_BANK_BASE_N))); + ((unsigned int)(FLASH_BANK_BASE_N)), + ((unsigned int)(FLASH_BANK0_BASE_AX)), + ((unsigned int)(FLASH_BANK1_BASE_256K_AX)), + ((unsigned int)(FLASH_BANK1_BASE_512K_AX))); return ERROR_FAIL; break; - /* at91sam3u series */ + /* at91sam3s and at91sam3n series only has bank 0*/ + /* at91sam3u and at91sam3ax series has the same address for bank 0*/ + case FLASH_BANK_BASE_S: case FLASH_BANK0_BASE_U: bank->driver_priv = &(pChip->details.bank[0]); bank->bank_number = 0; pChip->details.bank[0].pChip = pChip; pChip->details.bank[0].pBank = bank; break; + + /* Bank 1 of at91sam3u or at91sam3ax series */ case FLASH_BANK1_BASE_U: + case FLASH_BANK1_BASE_256K_AX: + case FLASH_BANK1_BASE_512K_AX: bank->driver_priv = &(pChip->details.bank[1]); bank->bank_number = 1; pChip->details.bank[1].pChip = pChip; pChip->details.bank[1].pBank = bank; break; - - /* at91sam3s and at91sam3n series */ - case FLASH_BANK_BASE_S: - bank->driver_priv = &(pChip->details.bank[0]); - bank->bank_number = 0; - pChip->details.bank[0].pChip = pChip; - pChip->details.bank[0].pBank = bank; - break; } /* we initialize after probing. */ @@ -2383,7 +2736,7 @@ static int sam3_GetDetails(struct sam3_bank_private *pPrivate) pDetails++; } if (pDetails->name == NULL) { - LOG_ERROR("SAM3 ChipID 0x%08x not found in table (perhaps you can this chip?)", + LOG_ERROR("SAM3 ChipID 0x%08x not found in table (perhaps you can ID this chip?)", (unsigned int)(pPrivate->pChip->cfg.CHIPID_CIDR)); /* Help the victim, print details about the chip */ LOG_INFO("SAM3 CHIPID_CIDR: 0x%08x decodes as follows",