flash/nor/at91sam4: add SAM4E16 support
[openocd.git] / src / flash / nor / at91sam4.c
index fd98b7f0da850370e77d91add82cb5ce4d0e78f4..8e873a6c7e76254796f0928c1e6533ae24688dea 100644 (file)
@@ -21,7 +21,7 @@
  *   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.             *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
 ****************************************************************************/
 
 /* Some of the the lower level code was based on code supplied by
 
 #define REG_NAME_WIDTH  (12)
 
-/* at91sam4s series (has always one flash bank)*/
+/* at91sam4s/at91sam4e series (has always one flash bank)*/
 #define FLASH_BANK_BASE_S   0x00400000
 
+/* 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))
+
 #define         AT91C_EFC_FCMD_GETD                 (0x0)      /* (EFC) Get Flash Descriptor */
 #define         AT91C_EFC_FCMD_WP                   (0x1)      /* (EFC) Write Page */
 #define         AT91C_EFC_FCMD_WPL                  (0x2)      /* (EFC) Write Page and Lock */
 #define         AT91C_EFC_FCMD_EWP                  (0x3)      /* (EFC) Erase Page and Write Page */
-#define         AT91C_EFC_FCMD_EWPL                 (0x4)      /* (EFC) Erase Page and Write Page
-                                                                * then Lock */
+#define         AT91C_EFC_FCMD_EWPL                 (0x4)      /* (EFC) Erase Page and Write Page then Lock */
 #define         AT91C_EFC_FCMD_EA                   (0x5)      /* (EFC) Erase All */
-/* cmd6 is not present inhe 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 */
@@ -166,7 +172,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 +188,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 */
@@ -248,12 +254,48 @@ static struct sam4_chip *get_current_sam4(struct command_context *cmd_ctx)
 }
 
 /*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. */
+/*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 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 = 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 =  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*/
        {
@@ -453,6 +495,86 @@ static const struct sam4_chip_details all_sam4_details[] = {
                  },
                },
        },
+
+       /*at91sam4sd32c*/
+       {
+               .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 = 6, /* workaround silicon bug */
+                               .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 = 6, /* workaround silicon bug */
+                               .present = 1,
+                               .size_bytes =  1024 * 1024,
+                               .nsectors   =  128,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
+               },
+       },
+
+       /* at91samg53n19 */
+       {
+               .chipid_cidr    = 0x247e0ae0,
+               .name           = "at91samg53n19",
+               .total_flash_size     = 512 * 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,
+                       },
+/*             .bank[1] = {*/
+                 {
+                       .present = 0,
+                       .probed = 0,
+                       .bank_number = 1,
+
+                 },
+               }
+       },
+
        /* terminate */
        {
                .chipid_cidr    = 0,
@@ -722,10 +844,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 +1073,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);
@@ -1018,8 +1147,13 @@ 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"
+       },
+       { 0x47,  "SAMG53 Series"
+       },
        { 0x55,  "AT91x55 Series"                                                       },
        { 0x60,  "AT91SAM7Axx Series"                                           },
        { 0x61,  "AT91SAM7AQxx Series"                                          },
@@ -1169,10 +1303,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 +1322,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 +1474,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 +1535,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;
                }
@@ -1421,7 +1555,7 @@ static int sam4_GetInfo(struct sam4_chip *pChip)
                /* 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 +1571,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],
@@ -1512,19 +1646,29 @@ FLASH_BANK_COMMAND_HANDLER(sam4_flash_bank_command)
        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:
                        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 */
+               case FLASH_BANK1_BASE_1024K_SD:
+               case FLASH_BANK1_BASE_2048K_SD:
+                       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. */
@@ -1551,7 +1695,7 @@ 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;
@@ -1704,7 +1848,7 @@ static int sam4_erase(struct flash_bank *bank, int first, int last)
                LOG_DEBUG("Here");
                return FLASHD_EraseEntireBank(pPrivate);
        }
-       LOG_INFO("sam4 does not auto-erase while programing (Erasing relevant sectors)");
+       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++) {
                /*16 pages equals 8KB - Same size as a lock region*/
@@ -1714,7 +1858,7 @@ static int sam4_erase(struct flash_bank *bank, int first, int last)
                        LOG_ERROR("SAM4: Error performing Erase page @ lock region number %d",
                                (unsigned int)(i));
                if (status & (1 << 2)) {
-                       LOG_ERROR("SAM4: Lock Reqion %d is locked", (unsigned int)(i));
+                       LOG_ERROR("SAM4: Lock Region %d is locked", (unsigned int)(i));
                        return ERROR_FAIL;
                }
                if (status & (1 << 1)) {
@@ -1751,16 +1895,6 @@ static int sam4_protect(struct flash_bank *bank, int set, int first, int last)
 
 }
 
-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;
@@ -1780,94 +1914,7 @@ 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_page_write(struct sam4_bank_private *pPrivate, unsigned pagenum, const uint8_t *buf)
 {
        uint32_t adr;
        uint32_t status;
@@ -1929,7 +1976,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)
 {
@@ -2308,5 +2355,4 @@ struct flash_driver at91sam4_flash = {
        .auto_probe = sam4_auto_probe,
        .erase_check = default_flash_blank_check,
        .protect_check = sam4_protect_check,
-       .info = sam4_info,
 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)