This is an automated email from Gerrit.

Rick Foos ([email protected]) just uploaded a new patch set to Gerrit, which 
you can find at http://openocd.zylin.com/3230

-- gerrit

commit 0b79a8f84692cac93e2c8c5cc189e7b24c5e7006
Author: Rick Foos <[email protected]>
Date:   Mon Feb 8 15:19:30 2016 -0600

    Add support for Ambiq Micro EVK.
    
    Change-Id: Iae92d869369c6827244f0071f9cb522d8d91fed8
    Signed-off-by: Rick Foos <[email protected]>

diff --git a/contrib/99-openocd.rules b/contrib/99-openocd.rules
index 344b933..bc9aae7 100644
--- a/contrib/99-openocd.rules
+++ b/contrib/99-openocd.rules
@@ -119,6 +119,10 @@ ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", 
MODE="664", GROUP="plugdev"
 # TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board
 ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="664", GROUP="plugdev"
 
+# Ambiq Micro EVK's.
+SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="2aec", 
ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev", RUN+="/sbin/modprobe 
ftdi_sio" RUN+="/bin/sh -c 'echo 2aec 6010 > 
/sys/bus/usb-serial/drivers/ftdi_sio/new_id'"
+SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="2aec", 
ATTRS{idProduct}=="6011", MODE="664", GROUP="plugdev", RUN+="/sbin/modprobe 
ftdi_sio" RUN+="/bin/sh -c 'echo 2aec 6011 > 
/sys/bus/usb-serial/drivers/ftdi_sio/new_id'"
+
 # Marvell Sheevaplug
 ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="664", GROUP="plugdev"
 
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index 834e4d4..8a8122f 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -10,6 +10,7 @@ libocdflashnor_la_SOURCES = \
 NOR_DRIVERS = \
        aduc702x.c \
        aducm360.c \
+       ambiqmicro.c \
        at91sam4.c \
        at91sam4l.c \
        at91samd.c \
diff --git a/src/flash/nor/ambiqmicro.c b/src/flash/nor/ambiqmicro.c
new file mode 100644
index 0000000..37ab29b
--- /dev/null
+++ b/src/flash/nor/ambiqmicro.c
@@ -0,0 +1,1018 @@
+/******************************************************************************
+ *
+ * @file ambiqmicro.c
+ *
+ * @brief Ambiq Micro flash driver.
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ * Copyright (c) 2015, David Racine <dracine at ambiqmicro.com>
+ *
+ * Copyright (c) 2016, Rick Foos <rfoos at solengtech.com>
+ *
+ * Copyright (c) 2016, Ambiq Micro, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "jtag/interface.h"
+#include "imp.h"
+#include "target/algorithm.h"
+#include "target/armv7m.h"
+#include "target/cortex_m.h"
+
+/*
+ * Address and Key defines
+ */
+#define PROGRAM_KEY      (0x12344321)
+#define OTP_PROGRAM_KEY  (0x87655678)
+
+#define FLASH_PROGRAM_MAIN_FROM_SRAM                0x0800005d
+#define FLASH_PROGRAM_OTP_FROM_SRAM                 0x08000061
+#define FLASH_ERASE_LIST_MAIN_PAGES_FROM_SRAM       0x08000065
+#define FLASH_MASS_ERASE_MAIN_PAGES_FROM_SRAM       0x08000069
+
+
+/****************************************************************************
+ *
+ * MCUCTRL device structure
+ *
+ *****************************************************************************/
+typedef struct {
+       /*
+        * Device part number. (BCD format)
+        */
+       uint32_t ui32ChipPN;
+
+       /*
+        * Flash Size.
+        */
+       uint32_t ui32FlashSize;
+
+       /*
+        * SRAM Size.
+        */
+       uint32_t ui32SRAMSize;
+}
+am_hal_mcuctrl_device_t;
+
+const uint32_t apollo_flash_size[] = {
+       1 << 15,
+       1 << 16,
+       1 << 17,
+       1 << 18,
+       1 << 19,
+       1 << 20,
+       1 << 21
+};
+
+const uint32_t apollo_sram_size[] = {
+       1 << 15,
+       1 << 16,
+       1 << 17,
+       1 << 18,
+       1 << 19,
+       1 << 20,
+       1 << 21
+};
+
+struct ambiqmicro_flash_bank {
+       /* chip id register */
+
+       uint32_t probed;
+
+       const char *target_name;
+       uint8_t target_class;
+
+       uint32_t sramsiz;
+       uint32_t flshsiz;
+
+       /* flash geometry */
+       uint32_t num_pages;
+       uint32_t pagesize;
+       uint32_t pages_in_lockregion;
+
+       /* nv memory bits */
+       uint16_t num_lockbits;
+
+       /* main clock status */
+       uint32_t rcc;
+       uint32_t rcc2;
+       uint8_t mck_valid;
+       uint8_t xtal_mask;
+       uint32_t iosc_freq;
+       uint32_t mck_freq;
+       const char *iosc_desc;
+       const char *mck_desc;
+};
+
+static struct {
+       uint8_t class;
+       uint8_t partno;
+       const char *partname;
+} ambiqmicroParts[] = {
+       {0xFF, 0x00, "Unknown Part"},
+       {0x01, 0x00, "Apollo"},
+       {0xFF, 0x00, "Unknown Part"}
+};
+
+static char *ambiqmicroClassname[1] = {
+       "Apollo"
+};
+
+uint32_t source[256];
+uint32_t result[256];
+uint32_t *presult;
+
+uint32_t *pSrc = source;
+volatile uint32_t *pDst = (volatile uint32_t *) 0;
+
+/*
+ * Return Code.
+ */
+int rc;
+
+/***************************************************************************
+*      openocd command interface                                              *
+***************************************************************************/
+
+/* flash_bank ambiqmicro <base> <size> 0 0 <target#>
+ */
+FLASH_BANK_COMMAND_HANDLER(ambiqmicro_flash_bank_command)
+{
+       struct ambiqmicro_flash_bank *ambiqmicro_info;
+
+       if (CMD_ARGC < 6)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       ambiqmicro_info = calloc(sizeof(struct ambiqmicro_flash_bank), 1);
+
+       bank->driver_priv = ambiqmicro_info;
+
+       ambiqmicro_info->target_name = "Unknown target";
+
+       /* part wasn't probed yet */
+       ambiqmicro_info->probed = 0;
+
+       return ERROR_OK;
+}
+
+static int get_ambiqmicro_info(struct flash_bank *bank, char *buf, int 
buf_size)
+{
+       struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv;
+
+       if (ambiqmicro_info->probed == 0) {
+               LOG_ERROR("Target not probed");
+               return ERROR_FLASH_BANK_NOT_PROBED;
+       }
+
+       snprintf(buf,
+               buf_size,
+               "\nAmbiq Micro information: Chip is "
+               "class %i (%s) %s\n",
+               ambiqmicro_info->target_class,
+               ambiqmicroClassname[ambiqmicro_info->target_class],
+               ambiqmicro_info->target_name);
+
+       return ERROR_OK;
+}
+
+/***************************************************************************
+*      chip identification and status                                         *
+***************************************************************************/
+
+/* Fill in driver info structure */
+static int ambiqmicro_read_part_info(struct flash_bank *bank)
+{
+       struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv;
+       struct target *target = bank->target;
+       uint32_t ui32PartNum = 0;
+
+       /*
+        * Read Part Number.
+        */
+       target_read_u32(target, 0x40020000, &ui32PartNum);
+       LOG_DEBUG("Part number: %d", ui32PartNum);
+
+       /*
+        * Determine device class.
+        */
+       ambiqmicro_info->target_class = (ui32PartNum & 0xFF000000) >> 24;
+
+       switch (ambiqmicro_info->target_class) {
+               case 1:                         /* 1 - Apollo */
+               case 5:         /* 5 - Apollo Secure */
+                       bank->base = bank->bank_number * 0x40000;
+                       ambiqmicro_info->pagesize = 2048;
+                       ambiqmicro_info->flshsiz =
+                       apollo_flash_size[(ui32PartNum & 0x00F00000) >> 20];
+                       ambiqmicro_info->sramsiz =
+                       apollo_sram_size[(ui32PartNum & 0x000F0000) >> 16];
+                       ambiqmicro_info->num_pages = ambiqmicro_info->flshsiz /
+                       ambiqmicro_info->pagesize;
+                       if (ambiqmicro_info->num_pages > 128) {
+                               ambiqmicro_info->num_pages = 128;
+                               ambiqmicro_info->flshsiz = 1024 * 256;
+                       }
+                       break;
+
+               default:
+                       LOG_INFO("Unknown Class. Using Apollo-64 as default.");
+
+                       bank->base = bank->bank_number * 0x40000;
+                       ambiqmicro_info->pagesize = 2048;
+                       ambiqmicro_info->flshsiz = apollo_flash_size[1];
+                       ambiqmicro_info->sramsiz = apollo_sram_size[0];
+                       ambiqmicro_info->num_pages = ambiqmicro_info->flshsiz /
+                       ambiqmicro_info->pagesize;
+                       if (ambiqmicro_info->num_pages > 128) {
+                               ambiqmicro_info->num_pages = 128;
+                               ambiqmicro_info->flshsiz = 1024 * 256;
+                       }
+                       break;
+
+       }
+
+       ambiqmicro_info->target_name =
+               ambiqmicroParts[ambiqmicro_info->target_class].partname;
+
+       LOG_DEBUG("num_pages: %d, pagesize: %d, flash: %d, sram: %d",
+               ambiqmicro_info->num_pages,
+               ambiqmicro_info->pagesize,
+               ambiqmicro_info->flshsiz,
+               ambiqmicro_info->sramsiz);
+
+       return ERROR_OK;
+}
+
+/***************************************************************************
+*      flash operations                                                       *
+***************************************************************************/
+
+static int ambiqmicro_protect_check(struct flash_bank *bank)
+{
+       struct ambiqmicro_flash_bank *ambiqmicro = bank->driver_priv;
+       int status = ERROR_OK;
+       uint32_t i;
+
+
+       if (ambiqmicro->probed == 0) {
+               LOG_ERROR("Target not probed");
+               return ERROR_FLASH_BANK_NOT_PROBED;
+       }
+
+       for (i = 0; i < (unsigned) bank->num_sectors; i++)
+               bank->sectors[i].is_protected = -1;
+
+       return status;
+}
+
+static int ambiqmicro_mass_erase(struct flash_bank *bank)
+{
+       struct target *target = NULL;
+       struct ambiqmicro_flash_bank *ambiqmicro_info = NULL;
+       uint32_t retval = ERROR_OK;
+
+       ambiqmicro_info = bank->driver_priv;
+       target = bank->target;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (ambiqmicro_info->probed == 0) {
+               LOG_ERROR("Target not probed");
+               return ERROR_FLASH_BANK_NOT_PROBED;
+       }
+
+       /*
+        * Clear Bootloader bit.
+        */
+       retval = target_write_u32(target, 0x400201a0, 0x0);
+
+       /*
+        * Set up the SRAM.
+        */
+
+       /*
+        * Bank.
+        */
+       retval = target_write_u32(target, 0x10000000, bank->bank_number);
+
+       /*
+        * Write Key.
+        */
+       retval = target_write_u32(target, 0x10000004, PROGRAM_KEY);
+
+       /*
+        * Breakpoint.
+        */
+       retval = target_write_u32(target, 0x10000008, 0xfffffffe);
+
+       /*
+        * Erase the main array.
+        */
+       LOG_INFO("Mass erase on bank %d", bank->bank_number);
+
+       /*
+        * passed pc, addr = ROM function, handle breakpoints, not debugging.
+        */
+       retval = target_resume(
+               target,
+               false,
+               FLASH_MASS_ERASE_MAIN_PAGES_FROM_SRAM,
+               true,
+               true);
+
+       if (retval != ERROR_OK)
+               LOG_ERROR("error executing ambiqmicro flash mass erase 
algorithm");
+
+       /*
+        * Wait for halt.
+        */
+       for (;; ) {
+               target_poll(target);
+               if (target->state == TARGET_HALTED)
+                       break;
+               else if (target->state == TARGET_RUNNING ||
+                       target->state == TARGET_DEBUG_RUNNING) {
+                       /*
+                        * Keep polling until target halts.
+                        */
+                       target_poll(target);
+                       alive_sleep(100);
+                       LOG_DEBUG("state = %d", target->state);
+               } else {
+                       LOG_ERROR("Target not halted or running %d", 
target->state);
+                       retval = ERROR_OK;
+                       break;
+               }
+       }
+
+       /*
+        * Read return value.
+        */
+       target_read_u32(target, 0x10000008, &retval);
+
+       if (retval != 0) {
+               LOG_ERROR("Flash not happy %d", retval);
+               return -1;
+       }
+
+       /*
+        * Set Bootloader bit.
+        */
+       retval = target_write_u32(target, 0x400201a0, 0x1);
+
+       if (retval != ERROR_OK)
+               LOG_ERROR("error setting bootloader bit");
+
+       return ERROR_OK;
+}
+
+
+static int ambiqmicro_erase(struct flash_bank *bank, int first, int last)
+{
+       struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv;
+       struct target *target = bank->target;
+       uint32_t retval = ERROR_OK;
+
+       if (bank->target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (ambiqmicro_info->probed == 0) {
+               LOG_ERROR("Target not probed");
+               return ERROR_FLASH_BANK_NOT_PROBED;
+       }
+
+       /*
+        * Check pages.
+        * Fix num_pages for the device.
+        */
+       if ((first < 0) || (last < first) || (last >= 
(int)ambiqmicro_info->num_pages))
+               return ERROR_FLASH_SECTOR_INVALID;
+
+       /*
+        * Just Mass Erase if all pages are given.
+        * TODO: Fix num_pages for the device
+        */
+       if ((first == 0) && (last == ((int)ambiqmicro_info->num_pages-1)))
+               return ambiqmicro_mass_erase(bank);
+
+       /*
+        * Clear Bootloader bit.
+        */
+       retval = target_write_u32(target, 0x400201a0, 0x0);
+
+       /*
+        * Set up the SRAM.
+        */
+
+       /*
+        * Bank.
+        */
+       retval = target_write_u32(target, 0x10000000, bank->bank_number);
+
+       /*
+        * Number of pages to erase.
+        */
+       retval = target_write_u32(target, 0x10000004, 1 + (last-first));
+
+       /*
+        * Write Key.
+        */
+       retval = target_write_u32(target, 0x10000008, PROGRAM_KEY);
+
+       /*
+        * Breakpoint.
+        */
+       retval = target_write_u32(target, 0x1000000c, 0xfffffffe);
+
+       /*
+        * Pointer to flash address.
+        */
+       retval = target_write_u32(target, 0x10000010, first);
+
+       /*
+        * Erase the pages.
+        */
+       LOG_INFO("Erasing pages %d to %d on bank %d", first, last, 
bank->bank_number);
+
+       /*
+        * passed pc, addr = ROM function, handle breakpoints, not debugging.
+        */
+       retval = target_resume(
+               target,
+               false,
+               FLASH_ERASE_LIST_MAIN_PAGES_FROM_SRAM,
+               true,
+               true);
+
+       if (retval != ERROR_OK)
+               LOG_ERROR("error executing ambiqmicro flash mass erase 
algorithm");
+
+       /*
+        * Wait for halt.
+        */
+       for (;; ) {
+               target_poll(target);
+               if (target->state == TARGET_HALTED)
+                       break;
+               else if (target->state == TARGET_RUNNING ||
+                       target->state == TARGET_DEBUG_RUNNING) {
+                       /*
+                        * Keep polling until target halts.
+                        */
+                       target_poll(target);
+                       alive_sleep(100);
+                       LOG_DEBUG("state = %d", target->state);
+               } else {
+                       LOG_ERROR("Target not halted or running %d", 
target->state);
+                       retval = ERROR_OK;
+                       break;
+               }
+       }
+
+       LOG_INFO("%d pages erased!", 1+(last-first));
+
+       if (first == 0) {
+               /*
+                * Set Bootloader bit.
+                */
+               retval = target_write_u32(target, 0x400201a0, 0x1);
+       }
+
+       /*
+        * Read return value.
+        */
+       target_read_u32(target, 0x1000000c, &retval);
+
+       if (retval != 0) {
+               LOG_ERROR("Flash not happy %d", retval);
+               return -1;
+       }
+
+       return ERROR_OK;
+}
+
+static int ambiqmicro_protect(struct flash_bank *bank, int set, int first, int 
last)
+{
+       /* struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv;
+        * struct target *target = bank->target; */
+
+       /*
+        * TODO
+        */
+       LOG_INFO("Not yet implemented");
+
+       if (bank->target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       return ERROR_OK;
+}
+
+static int ambiqmicro_write_block(struct flash_bank *bank,
+       const uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+       /* struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv; */
+       struct target *target = bank->target;
+       uint32_t address = bank->base + offset;
+       uint32_t ui32buffer_pointer = 0x10000010;
+       uint32_t ui32maxbuffer;
+       uint32_t thisrun_count;
+       uint32_t retval = ERROR_OK;
+
+       if (((count%4) != 0) || ((offset%4) != 0)) {
+               LOG_ERROR("write block must be multiple of 4 bytes in offset & 
length");
+               return ERROR_FAIL;
+       }
+
+       /*
+        * Max buffer size for this device.
+        * Hard code 6kB for the buffer.
+        */
+       ui32maxbuffer = 0x1800;
+
+       LOG_INFO("Flashing main array");
+
+       while (count > 0) {
+               if (count > ui32maxbuffer)
+                       thisrun_count = ui32maxbuffer;
+               else
+                       thisrun_count = count;
+
+               /*
+                * Set up the SRAM.
+                */
+
+               /*
+                * Pointer to flash.
+                */
+               retval = target_write_u32(target, 0x10000000, address);
+
+               /*
+                * Number of 32-bit words to program.
+                */
+               retval = target_write_u32(target, 0x10000004, thisrun_count/4);
+
+               /*
+                * Write Key.
+                */
+               retval = target_write_u32(target, 0x10000008, PROGRAM_KEY);
+
+               /*
+                * Breakpoint.
+                */
+               retval = target_write_u32(target, 0x1000000c, 0xfffffffe);
+
+               /*
+                * Write Buffer.
+                */
+               retval = target_write_buffer(target, ui32buffer_pointer, 
thisrun_count, buffer);
+
+               if (retval != ERROR_OK)
+                       break;
+
+               LOG_DEBUG("address = 0x%08x", address);
+
+               retval = target_resume(
+                       target,
+                       false,
+                       FLASH_PROGRAM_MAIN_FROM_SRAM,
+                       true,
+                       true);
+
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("error executing ambiqmicro flash write 
algorithm");
+                       break;
+               }
+
+               /*
+                * Wait for halt.
+                */
+               for (;; ) {
+                       target_poll(target);
+                       if (target->state == TARGET_HALTED)
+                               break;
+                       else if (target->state == TARGET_RUNNING ||
+                               target->state == TARGET_DEBUG_RUNNING) {
+                               /*
+                                * Keep polling until target halts.
+                                */
+                               target_poll(target);
+                               alive_sleep(100);
+                               LOG_DEBUG("state = %d", target->state);
+                       } else {
+                               LOG_ERROR("Target not halted or running %d", 
target->state);
+                               retval = ERROR_OK;
+                               break;
+                       }
+               }
+
+               /*
+                * Read return value.
+                */
+               target_read_u32(target, 0x1000000c, &retval);
+
+               if (retval != 0) {
+                       LOG_ERROR("Flash not happy %d", retval);
+                       return -1;
+               }
+
+               buffer += thisrun_count;
+               address += thisrun_count;
+               count -= thisrun_count;
+       }
+
+
+       LOG_INFO("Main array flashed");
+
+       /*
+        * Clear Bootloader bit.
+        */
+       retval = target_write_u32(target, 0x400201a0, 0x0);
+
+       if (retval != ERROR_OK)
+               LOG_ERROR("error clearing bootloader bit");
+
+       return retval;
+}
+
+static int ambiqmicro_write(struct flash_bank *bank, const uint8_t *buffer,
+       uint32_t offset, uint32_t count)
+{
+       uint32_t retval;
+
+       /* try using a block write */
+       retval = ambiqmicro_write_block(bank, buffer, offset, count);
+       if (retval != ERROR_OK)
+               LOG_ERROR("write failed");
+
+       return retval;
+}
+
+static int ambiqmicro_probe(struct flash_bank *bank)
+{
+       struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv;
+       uint32_t retval;
+
+       /* If this is a ambiqmicro chip, it has flash; probe() is just
+        * to figure out how much is present.  Only do it once.
+        */
+       if (ambiqmicro_info->probed == 1) {
+               LOG_INFO("Target already probed");
+               return ERROR_OK;
+       }
+
+       /* ambiqmicro_read_part_info() already handled error checking and
+        * reporting.  Note that it doesn't write, so we don't care about
+        * whether the target is halted or not.
+        */
+       retval = ambiqmicro_read_part_info(bank);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (bank->sectors) {
+               free(bank->sectors);
+               bank->sectors = NULL;
+       }
+
+       /* provide this for the benefit of the NOR flash framework */
+       bank->size = ambiqmicro_info->pagesize * ambiqmicro_info->num_pages;
+       bank->num_sectors = ambiqmicro_info->num_pages;
+       bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
+       for (int i = 0; i < bank->num_sectors; i++) {
+               bank->sectors[i].offset = i * ambiqmicro_info->pagesize;
+               bank->sectors[i].size = ambiqmicro_info->pagesize;
+               bank->sectors[i].is_erased = -1;
+               bank->sectors[i].is_protected = -1;
+       }
+
+       /*
+        * Part has been probed.
+        */
+       ambiqmicro_info->probed = 1;
+
+       return retval;
+}
+
+static int ambiqmicro_otp_program(struct flash_bank *bank,
+       uint32_t offset, uint32_t count)
+{
+       struct target *target = NULL;
+       struct ambiqmicro_flash_bank *ambiqmicro_info = NULL;
+       uint32_t retval = ERROR_OK;
+
+       ambiqmicro_info = bank->driver_priv;
+       target = bank->target;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (ambiqmicro_info->probed == 0) {
+               LOG_ERROR("Target not probed");
+               return ERROR_FLASH_BANK_NOT_PROBED;
+       }
+
+       if (count > 256) {
+               LOG_ERROR("Count must be < 256");
+               return -1;
+       }
+
+       /*
+        * Clear Bootloader bit.
+        */
+       retval = target_write_u32(target, 0x400201a0, 0x0);
+
+       /*
+        * Set up the SRAM.
+        */
+
+       /*
+        * Bank.
+        */
+       retval = target_write_u32(target, 0x10000000, offset);
+
+       /*
+        * Num of words to program.
+        */
+       retval = target_write_u32(target, 0x10000004, count);
+
+       /*
+        * Write Key.
+        */
+       retval = target_write_u32(target, 0x10000008, OTP_PROGRAM_KEY);
+
+       /*
+        * Breakpoint.
+        */
+       retval = target_write_u32(target, 0x1000000c, 0xfffffffe);
+
+       /*
+        * Program OTP.
+        */
+       LOG_INFO("Programming OTP offset 0x%08x", offset);
+
+       /*
+        * passed pc, addr = ROM function, handle breakpoints, not debugging.
+        */
+       retval = target_resume(
+               target,
+               false,
+               FLASH_PROGRAM_OTP_FROM_SRAM,
+               true,
+               true);
+
+       if (retval != ERROR_OK)
+               LOG_ERROR("error executing ambiqmicro otp program algorithm");
+
+       /*
+        * Wait for halt.
+        */
+       for (;; ) {
+               target_poll(target);
+               if (target->state == TARGET_HALTED)
+                       break;
+               else if (target->state == TARGET_RUNNING ||
+                       target->state == TARGET_DEBUG_RUNNING) {
+                       /*
+                        * Keep polling until target halts.
+                        */
+                       target_poll(target);
+                       alive_sleep(100);
+                       LOG_DEBUG("state = %d", target->state);
+               } else {
+                       LOG_ERROR("Target not halted or running %d", 
target->state);
+                       retval = ERROR_OK;
+                       break;
+               }
+       }
+
+       /*
+        * Read return value.
+        */
+       target_read_u32(target, 0x1000000c, &retval);
+
+       if (retval != 0) {
+               LOG_ERROR("Flash not happy %d", retval);
+               return -1;
+       }
+
+       LOG_INFO("Programming OTP finished");
+
+       return ERROR_OK;
+}
+
+#if 0
+static int ambiqmicro_auto_probe(struct flash_bank *bank)
+{
+       struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv;
+       if (ambiqmicro_info->probed)
+               return ERROR_OK;
+       return ambiqmicro_probe(bank);
+}
+#endif
+
+
+COMMAND_HANDLER(ambiqmicro_handle_mass_erase_command)
+{
+       int i;
+
+       if (CMD_ARGC < 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       struct flash_bank *bank;
+       uint32_t retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, 
&bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       if (ambiqmicro_mass_erase(bank) == ERROR_OK) {
+               /* set all sectors as erased */
+               for (i = 0; i < bank->num_sectors; i++)
+                       bank->sectors[i].is_erased = 1;
+
+               command_print(CMD_CTX, "ambiqmicro mass erase complete");
+       } else
+               command_print(CMD_CTX, "ambiqmicro mass erase failed");
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(ambiqmicro_handle_page_erase_command)
+{
+       struct flash_bank *bank;
+       uint32_t first, last;
+       uint32_t retval;
+
+       if (CMD_ARGC < 3)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
+
+       retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       if (ambiqmicro_erase(bank, first, last) == ERROR_OK)
+               command_print(CMD_CTX, "ambiqmicro page erase complete");
+       else
+               command_print(CMD_CTX, "ambiqmicro page erase failed");
+
+       return ERROR_OK;
+}
+
+
+/**
+ * Enable/Disable fault regs.
+ */
+COMMAND_HANDLER(ambiqmicro_handle_fault_capture_command)
+{
+       struct flash_bank *bank;
+       uint32_t enable;
+       uint32_t retval;
+
+       if (CMD_ARGC < 2)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], enable);
+       enable = enable >= 1;
+
+       command_print(CMD_CTX, "enable=%d", enable);
+
+       retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       /*
+        * TODO
+        */
+       LOG_INFO("Not yet implemented");
+
+       return ERROR_OK;
+}
+
+/**
+ * Program the otp block.
+ */
+COMMAND_HANDLER(ambiqmicro_handle_program_otp_command)
+{
+       struct flash_bank *bank;
+       uint32_t offset, count;
+       uint32_t retval;
+
+       if (CMD_ARGC < 3)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], offset);
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
+
+       command_print(CMD_CTX, "offset=0x%08x count=%d", offset, count);
+
+       CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+
+       retval = ambiqmicro_otp_program(bank, offset, count);
+
+       if (retval != ERROR_OK)
+               LOG_ERROR("error check log");
+
+       return ERROR_OK;
+}
+
+
+
+static const struct command_registration ambiqmicro_exec_command_handlers[] = {
+       {
+               .name = "mass_erase",
+               .usage = "<bank>",
+               .handler = ambiqmicro_handle_mass_erase_command,
+               .mode = COMMAND_EXEC,
+               .help = "Erase entire device",
+       },
+       {
+               .name = "page_erase",
+               .usage = "<bank> <first> <last>",
+               .handler = ambiqmicro_handle_page_erase_command,
+               .mode = COMMAND_EXEC,
+               .help = "Erase device pages",
+       },
+       {
+               .name = "fault_capture",
+               .usage = "<bank> <enable>",
+               .handler = ambiqmicro_handle_fault_capture_command,
+               .mode = COMMAND_EXEC,
+               .help = "Enable/disable the fault capture registers",
+       },
+       {
+               .name = "program_otp",
+               .handler = ambiqmicro_handle_program_otp_command,
+               .mode = COMMAND_EXEC,
+               .usage = "<bank> <offset> <count>",
+               .help =
+                       "Program OTP (assumes you have already written array 
starting at 0x10000010)",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+static const struct command_registration ambiqmicro_command_handlers[] = {
+       {
+               .name = "ambiqmicro",
+               .mode = COMMAND_EXEC,
+               .help = "ambiqmicro flash command group",
+               .usage = "",
+               .chain = ambiqmicro_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+struct flash_driver ambiqmicro_flash = {
+       .name = "ambiqmicro",
+       .commands = ambiqmicro_command_handlers,
+       .flash_bank_command = ambiqmicro_flash_bank_command,
+       .erase = ambiqmicro_erase,
+       .protect = ambiqmicro_protect,
+       .write = ambiqmicro_write,
+       .read = default_flash_read,
+       .probe = ambiqmicro_probe,
+       .auto_probe = ambiqmicro_probe,
+       .erase_check = default_flash_blank_check,
+       .protect_check = ambiqmicro_protect_check,
+       .info = get_ambiqmicro_info,
+};
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index 48d584e..7a69c74 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -27,6 +27,7 @@ extern struct flash_driver lpc288x_flash;
 extern struct flash_driver lpc2900_flash;
 extern struct flash_driver lpcspifi_flash;
 extern struct flash_driver cfi_flash;
+extern struct flash_driver ambiqmicro_flash;
 extern struct flash_driver at91sam3_flash;
 extern struct flash_driver at91sam4_flash;
 extern struct flash_driver at91sam4l_flash;
@@ -75,6 +76,7 @@ static struct flash_driver *flash_drivers[] = {
        &lpc2900_flash,
        &lpcspifi_flash,
        &cfi_flash,
+       &ambiqmicro_flash,
        &at91sam7_flash,
        &at91sam3_flash,
        &at91sam4_flash,
diff --git a/tcl/board/am-apollo_evk.cfg b/tcl/board/am-apollo_evk.cfg
new file mode 100644
index 0000000..10dd9d8
--- /dev/null
+++ b/tcl/board/am-apollo_evk.cfg
@@ -0,0 +1,6 @@
+#
+# Ambiq Micro - Apollo EVK Board.
+#
+
+source [find interface/am-ft4232.cfg]
+source [find target/am-apollo.cfg]
diff --git a/tcl/interface/am-ft4232.cfg b/tcl/interface/am-ft4232.cfg
new file mode 100644
index 0000000..24e9cb3
--- /dev/null
+++ b/tcl/interface/am-ft4232.cfg
@@ -0,0 +1,26 @@
+#
+# Ambiq Micro - FT4232 Target
+#
+
+# TCP server configuration
+gdb_port 3333
+telnet_port 4444
+gdb_memory_map enable
+gdb_flash_program enable
+
+interface ftdi
+#ftdi_device_desc "Quad RS232-HS"
+ftdi_vid_pid 0x2AEC 0x6011
+
+# Channel for using JTAG
+ftdi_channel 0
+
+ftdi_layout_init 0x8c58 0xffab
+
+# Signals
+ftdi_layout_signal SWD_EN -data 0
+ftdi_layout_signal SWDIO_OE -ndata 0x80
+# Use GPIOL0 as nTRST
+ftdi_layout_signal nTRST -data 0x10
+# Use GPIOL2 as nRST
+ftdi_layout_signal nRST -oe 0x40
diff --git a/tcl/target/am-apollo.cfg b/tcl/target/am-apollo.cfg
new file mode 100644
index 0000000..08cb7c1
--- /dev/null
+++ b/tcl/target/am-apollo.cfg
@@ -0,0 +1,58 @@
+#
+# Ambiq Micro - Apollo Target
+#
+
+if { [info exists CHIPNAME] } {
+   set  _CHIPNAME $CHIPNAME
+} else {
+   set  _CHIPNAME apollo
+}
+
+if { [info exists ENDIAN] } {
+   set  _ENDIAN $ENDIAN
+} else {
+   set  _ENDIAN little
+}
+
+# Work-area is a space in RAM used for flash programming
+# By default use 0kB
+if { [info exists WORKAREASIZE] } {
+   set  _WORKAREASIZE $WORKAREASIZE
+} else {
+   set  _WORKAREASIZE 0x200
+}
+
+if { [info exists CPUTAPID ] } {
+   set _CPUTAPID $CPUTAPID
+} else {
+   set _CPUTAPID 0x2BA01477
+}
+
+set _TRANSPORT swd
+transport select $_TRANSPORT
+
+swd newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id 
$_CPUTAPID
+
+set _TARGETNAME $_CHIPNAME.cpu
+target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position 
$_TARGETNAME
+
+$_TARGETNAME configure -work-area-phys 0x10000000 -work-area-size 
$_WORKAREASIZE -work-area-backup 0
+
+# flash size will be probed
+set _FLASHNAME $_CHIPNAME.flash0
+flash bank $_FLASHNAME ambiqmicro 0 0x00040000 0 0 $_TARGETNAME
+# This is a 512K chip - it has the 2nd bank
+set _FLASHNAME $_CHIPNAME.flash1
+flash bank $_FLASHNAME ambiqmicro 0x00040000 0x00040000 0 0 $_TARGETNAME
+
+# Reset target when gdb connects.
+$_TARGETNAME configure -event gdb-attach {
+    reset init
+    halt
+}
+# if srst is not fitted use SYSRESETREQ to
+# perform a soft reset
+cortex_m reset_config sysresetreq
+
+# SWD clock
+adapter_khz 100

-- 

------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to