This is an automated email from Gerrit.

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

-- gerrit

commit 0ffdd2a88a9fe3020fb6eea26e509f7cd460d4ea
Author: Peter Andersson <[email protected]>
Date:   Mon Aug 22 11:54:53 2016 +0200

    flash CC13xx/26xx: cc13xx/cc26xx flash support
    
    Flash NOR driver for CC13xx and CC26xx. Uses TI's rom library
    functions for erasing and flashing. Protection of last sector as
    this contain magics that may disable JTAG, preventing users from
    inadvertedly semi-bricking the target. It is possible to erase and
    program last sector by "unlocking" it with a target specific
    command.
    
    Change-Id: I523853a60ca165044454726730e83a245938b501
    Signed-off-by: Peter Andersson <[email protected]>

diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index c167e8f..e6dceec 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -18,6 +18,7 @@ NOR_DRIVERS = \
        at91sam7.c \
        atsamv.c \
        avrf.c \
+       cc13xx_26xx_rom.c \
        cfi.c \
        dsp5680xx_flash.c \
        efm32.c \
diff --git a/src/flash/nor/cc13xx_26xx_rom.c b/src/flash/nor/cc13xx_26xx_rom.c
new file mode 100644
index 0000000..32b9355
--- /dev/null
+++ b/src/flash/nor/cc13xx_26xx_rom.c
@@ -0,0 +1,671 @@
+/***************************************************************************
+ *   Copyright (C) 2016 by Peter Andersson <[email protected]>      *
+ *                                                                         *
+ *   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     *
+ *   (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.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "imp.h"
+#include <helper/binarybuffer.h>
+#include <helper/time_support.h>
+#include <target/algorithm.h>
+#include <target/armv7m.h>
+
+/* Presume 20KB of RAM. Would there be more, we're fine anyway. */
+#define DEFAULT_SP                                             (0x20000000 + 
1024*20)
+
+#define ROM_VERSION_TESTED                             0xa232
+#define ROM_API_TABLE                                  0x10000180
+
+#define ROM_API_OFFSET_VERSION                 (0)
+#define ROM_API_OFFSET_FLASH_TABLE             (10*4)
+#define ROM_API_FLASH_OFFSET_ERASE             (5*4)
+#define ROM_API_FLASH_OFFSET_WRITE             (6*4)
+
+#define FLASH_BASE                                                             
                                        0x40030000
+#define FLASH_O_STAT                                                0x0000001C
+#define FLASH_O_FLASH_SIZE                                          0x0000002C
+#define FLASH_O_FSM_WR_ENA                                          0x00002288
+#define FLASH_O_FSM_BSLE0                                           0x000022E0
+#define FLASH_O_FSM_BSLE1                                           0x000022E4
+#define FLASH_O_FSM_BSLP0                                           0x000022F0
+#define FLASH_O_FSM_BSLP1                                           0x000022F4
+#define FLASH_O_FCFG_B0_SSIZE0                                      0x00002430
+
+#define FLASH_FCFG_B0_SSIZE0_B0_SECT_SIZE_W                                  4
+#define FLASH_FCFG_B0_SSIZE0_B0_SECT_SIZE_M                         0x0000000F
+#define FLASH_FCFG_B0_SSIZE0_B0_SECT_SIZE_S                                  0
+
+#define FLASH_FLASH_SIZE_SECTORS_W                                           8
+#define FLASH_FLASH_SIZE_SECTORS_M                                  0x000000FF
+#define FLASH_FLASH_SIZE_SECTORS_S                                           0
+
+#define FLASH_STAT_BUSY                                             0x00000002
+
+#define FSM_REG_WRT_ENABLE                             5
+#define FSM_REG_WRT_DISABLE                            2
+
+#define VIMS_BASE                                              0x40034000
+
+#define VIMS_O_STAT                                            0x00000000
+#define VIMS_STAT_MODE_CHANGING                        0x00000008
+#define VIMS_STAT_MODE_M                               0x00000003
+
+#define VIMS_O_CTL                                             0x00000004
+#define VIMS_CTL_MODE_M                                        0x00000003
+
+#define VIMS_MODE_CHANGING                             0x4
+#define VIMS_MODE_DISABLED                             0x00000000 
/*(VIMS_CTL_MODE_GPRAM)*/
+#define VIMS_MODE_ENABLED                              0x00000001 
/*(VIMS_CTL_MODE_CACHE)*/
+#define VIMS_MODE_OFF                                  0x00000003 
/*(VIMS_CTL_MODE_OFF)*/
+
+#define VIMS_MODE_SET_TIMEOUT_MS               3000
+#define FLASH_TIMEOUT_MS                               3000
+
+struct cc_info {
+       int probed;
+       uint32_t flash_table_addr;
+       uint8_t last_sector_access;
+};
+
+/* Call a function in the rom library.
+ * r3 - the address of the rom library function
+ * r0-r2 optional parameters to the rom function
+ */
+static const uint8_t trampoline_code[] = {
+       0x98, 0x47,             /* blx     r3 */
+       0x00, 0xbe,             /* bkpt    #0 */
+};
+
+
+/* flash bank cc13xx26xx <base> <size> 0 0 <target#> */
+FLASH_BANK_COMMAND_HANDLER(cc13xx_26xx_flash_bank_command)
+{
+       struct cc_info *info;
+
+       if (CMD_ARGC < 6)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       bank->base = 0x00000000;
+       info = malloc(sizeof(struct cc_info));
+       memset(info, 0, sizeof(struct cc_info));
+
+       bank->driver_priv = info;
+
+       return ERROR_OK;
+}
+
+static int cc13xx_26xx_check_protection(struct flash_bank *bank, uint32_t 
sector_nbr)
+{
+       int prot_res = -1; /* protection status unknown by default */
+       do {
+               int res;
+               uint32_t prot_status_le;
+               uint32_t prot_status_lp;
+               if (sector_nbr <= 31) {
+                       res = target_read_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_BSLE0,
+                                       &prot_status_le);
+                       if (res == ERROR_FAIL)
+                               break;
+
+                       res = target_read_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_BSLP0,
+                                       &prot_status_lp);
+                       if (res == ERROR_FAIL)
+                               break;
+
+                       prot_res = (prot_status_le & (1 << sector_nbr)) &&
+                                       (prot_status_lp & (1 << sector_nbr));
+               } else if (sector_nbr <= 63) {
+                       res = target_read_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_BSLE1,
+                                       &prot_status_le);
+                       if (res == ERROR_FAIL)
+                               break;
+
+                       res = target_read_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_BSLP1,
+                                       &prot_status_lp);
+                       if (res == ERROR_FAIL)
+                               break;
+
+                       prot_res = (prot_status_le & (1 << (sector_nbr & 
0x1f))) &&
+                                       (prot_status_lp & (1 << (sector_nbr & 
0x1f)));
+               }
+       } while (0);
+
+       return prot_res;
+}
+
+static int cc13xx_26xx_protect_check(struct flash_bank *bank)
+{
+       /* probe sector protection status */
+       int sect;
+
+       for (sect = 0; sect < bank->num_sectors; sect++)
+               bank->sectors[sect].is_protected = 
cc13xx_26xx_check_protection(bank, sect);
+
+       return ERROR_OK;
+}
+
+static int cc13xx_26xx_get_vims_mode(struct flash_bank *bank, uint32_t 
*vims_mode)
+{
+       uint32_t cur_vims_mode;
+       int res;
+
+       res = target_read_u32(bank->target, VIMS_BASE + VIMS_O_STAT, 
&cur_vims_mode);
+       if (ERROR_OK != res)
+               return res;
+       if (cur_vims_mode & VIMS_STAT_MODE_CHANGING)
+               *vims_mode = VIMS_MODE_CHANGING;
+       else
+               *vims_mode = cur_vims_mode & VIMS_STAT_MODE_M;
+
+       return ERROR_OK;
+}
+
+static int cc13xx_26xx_set_vims_mode(struct flash_bank *bank, uint32_t 
vims_mode)
+{
+       int64_t timeout;
+       uint32_t cur_vims_mode;
+       uint32_t new_vims_mode;
+       int res;
+
+       res = target_read_u32(bank->target, VIMS_BASE + VIMS_O_CTL, 
&cur_vims_mode);
+       if (ERROR_OK != res)
+               return res;
+       cur_vims_mode &= ~VIMS_CTL_MODE_M;
+       cur_vims_mode |= (vims_mode & VIMS_CTL_MODE_M);
+       res = target_write_u32(bank->target, VIMS_BASE + VIMS_O_CTL, 
cur_vims_mode);
+       if (ERROR_OK != res)
+               return res;
+
+       timeout = timeval_ms() + VIMS_MODE_SET_TIMEOUT_MS;
+       do {
+               if (timeval_ms() >= timeout) {
+                       LOG_ERROR("VIMS setting timeout");
+                       res = ERROR_TARGET_TIMEOUT;
+                       break;
+               }
+               res = cc13xx_26xx_get_vims_mode(bank, &new_vims_mode);
+       } while (ERROR_OK == res && new_vims_mode != vims_mode);
+       LOG_DEBUG("vims set %i", vims_mode);
+
+       return res;
+}
+
+static int cc13xx_26xx_await_flash_ready(struct flash_bank *bank)
+{
+       int64_t timeout;
+       uint32_t stat;
+       int res;
+
+       timeout = timeval_ms() + FLASH_TIMEOUT_MS;
+       do {
+               res = target_read_u32(bank->target, FLASH_BASE + FLASH_O_STAT, 
&stat);
+               if (ERROR_OK != res)
+                       return res;
+               if ((stat & FLASH_STAT_BUSY) == 0) {
+                       LOG_DEBUG("flash ready");
+                       break;
+               }
+               if (timeval_ms() >= timeout) {
+                       LOG_ERROR("flash busy timeout");
+                       res = ERROR_TARGET_TIMEOUT;
+                       break;
+               }
+       } while (res == ERROR_OK);
+
+       return res;
+}
+
+static int cc13xx_26xx_erase(struct flash_bank *bank, int first, int last)
+{
+       struct cc_info *info = (struct cc_info *)bank->driver_priv;
+
+       int sect;
+       struct reg_param reg_params[3];
+       uint32_t flash_erase_rom_func;
+       struct working_area *erase_algorithm;
+       struct armv7m_algorithm arch_info;
+
+       int res = ERROR_OK, res_vims;
+
+       assert(info);
+
+       /* check last sector access */
+       if (last == bank->num_sectors-1 && !info->last_sector_access) {
+               LOG_ERROR("No access to last sector. Get access by calling "
+                               "'cc13xx26xx access_last_sector <bank_id> on'");
+               return ERROR_FAIL;
+       }
+
+       /* get rom flash erase function address */
+       res = target_read_u32(bank->target,
+                       info->flash_table_addr + ROM_API_FLASH_OFFSET_ERASE,
+                       &flash_erase_rom_func);
+       if (ERROR_OK != res)
+               return res;
+       LOG_DEBUG("flash erase func addr %08x", flash_erase_rom_func);
+
+       /* disable flash cache */
+       res = cc13xx_26xx_set_vims_mode(bank, VIMS_MODE_DISABLED);
+       if (ERROR_OK != res)
+               return res;
+
+       /* place our trampoline in ram */
+       res = target_alloc_working_area(bank->target, sizeof(trampoline_code),
+                       &erase_algorithm);
+       if (ERROR_OK != res)
+               return res;
+
+       res = target_write_buffer(bank->target, erase_algorithm->address,
+                       sizeof(trampoline_code), trampoline_code);
+       if (ERROR_OK != res)
+               goto cleanup;
+
+       /* setup call procedure */
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* sector erase 
address*/
+       init_reg_param(&reg_params[1], "r3", 32, PARAM_OUT);    /* func */
+       init_reg_param(&reg_params[2], "sp", 32, PARAM_OUT);    /* stack 
pointer */
+
+       /* erase requested sectors */
+       for (sect = first; sect <= last; sect++) {
+               uint32_t sector_address = bank->base + 
bank->sectors[sect].offset;
+
+               res = cc13xx_26xx_await_flash_ready(bank);
+               if (ERROR_OK != res)
+                       break;
+
+               LOG_DEBUG("erase sector %d", sect);
+
+               /* Explicitly set SP to something valid, or else the board may
+                * be semi-bricked. Seems it can be unlocked again by using
+                * TI's SmartRF programmer 2 and running a CC2650 forced mass 
erase
+                */
+               buf_set_u32(reg_params[0].value, 0, 32, sector_address);
+               buf_set_u32(reg_params[1].value, 0, 32, flash_erase_rom_func);
+               buf_set_u32(reg_params[2].value, 0, 32, DEFAULT_SP);
+               LOG_DEBUG("call trampoline");
+
+               arch_info.common_magic = ARMV7M_COMMON_MAGIC;
+               arch_info.core_mode = ARM_MODE_THREAD;
+
+               res = target_run_algorithm(bank->target,
+                               0, NULL,
+                               3, reg_params,
+                               erase_algorithm->address,
+                               0,
+                               10000,
+                               &arch_info);
+               if (ERROR_OK != res)
+                       break;
+       }
+
+       LOG_DEBUG("cleanup reg_param");
+
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+       destroy_reg_param(&reg_params[2]);
+
+cleanup:
+
+       LOG_DEBUG("cleanup algo area");
+       target_free_working_area(bank->target, erase_algorithm);
+
+       res_vims = cc13xx_26xx_set_vims_mode(bank, VIMS_MODE_ENABLED);
+
+       return res == ERROR_OK ? res_vims : res;
+}
+
+static int cc13xx_26xx_protect(struct flash_bank *bank, int set, int first, 
int last)
+{
+       int res, res_clean, sect;
+
+       if (!set) {
+               /* not supported, must do a device reset */
+               LOG_USER("CC13xx/CC26xx can only be unprotected by a device 
reset");
+               return ERROR_JTAG_NOT_IMPLEMENTED;
+       }
+
+       res = target_write_u32(bank->target, FLASH_BASE + FLASH_O_FSM_WR_ENA,
+                       FSM_REG_WRT_ENABLE);
+       if (ERROR_OK != res)
+               return res;
+
+       for (sect = first; sect <= last; sect++) {
+               uint32_t x;
+               if (sect <= 31) {
+                       res = target_read_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_BSLE0,
+                                                       &x);
+                       if (ERROR_OK != res)
+                               break;
+                       res = target_write_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_BSLE0,
+                                                       x | (1 << sect));
+                       if (ERROR_OK != res)
+                               break;
+                       res = target_read_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_BSLP0,
+                                                       &x);
+                       if (ERROR_OK != res)
+                               break;
+                       res = target_write_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_BSLP0,
+                                                       x | (1 << sect));
+                       if (ERROR_OK != res)
+                               break;
+               } else if (sect <= 63) {
+                       res = target_read_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_BSLE1,
+                                                       &x);
+                       if (ERROR_OK != res)
+                               break;
+                       res = target_write_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_BSLE1,
+                                                       x | (1 << (sect & 
0x1f)));
+                       if (ERROR_OK != res)
+                               break;
+                       res = target_read_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_BSLP1,
+                                                       &x);
+                       if (ERROR_OK != res)
+                               break;
+                       res = target_write_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_BSLP1,
+                                                       x | (1 << (sect & 
0x1f)));
+                       if (ERROR_OK != res)
+                               break;
+               }
+       }
+
+       res_clean = target_write_u32(bank->target, FLASH_BASE + 
FLASH_O_FSM_WR_ENA,
+                       FSM_REG_WRT_DISABLE);
+
+       return res == ERROR_OK ? res_clean : res;
+}
+
+static int cc13xx_26xx_write(struct flash_bank *bank, const uint8_t *buffer,
+               uint32_t offset, uint32_t count)
+{
+       struct cc_info *info = (struct cc_info *)bank->driver_priv;
+
+       uint32_t buffer_size = 16384;
+       struct reg_param reg_params[5];
+       uint32_t flash_write_rom_func;
+       struct working_area *write_algorithm;
+       struct working_area *source;
+       struct armv7m_algorithm arch_info;
+
+       int res = ERROR_OK, res_vims;
+
+       assert(info);
+
+       /* check last sector access */
+       if (offset + count - 1 >= bank->sectors[bank->num_sectors-1].offset
+                       && !info->last_sector_access) {
+               LOG_ERROR("No access to last sector. Get access by calling "
+                               "'cc13xx26xx access_last_sector <bank_id> on'");
+               return ERROR_FAIL;
+       }
+
+       /* get rom flash erase function address  */
+       res = target_read_u32(bank->target,
+                       info->flash_table_addr + ROM_API_FLASH_OFFSET_WRITE,
+                       &flash_write_rom_func);
+       if (ERROR_OK != res)
+               return res;
+       LOG_DEBUG("flash write func addr %08x", flash_write_rom_func);
+
+       /* disable flash cache */
+       res = cc13xx_26xx_set_vims_mode(bank, VIMS_MODE_DISABLED);
+       if (ERROR_OK != res)
+               return res;
+
+       /* place our trampoline in ram */
+       res = target_alloc_working_area(bank->target, sizeof(trampoline_code),
+                       &write_algorithm);
+       if (ERROR_OK != res)
+               return res;
+
+       res = target_write_buffer(bank->target, write_algorithm->address,
+                       sizeof(trampoline_code), trampoline_code);
+       if (ERROR_OK != res)
+               goto cleanup;
+
+       /* memory buffer */
+       while (target_alloc_working_area_try(bank->target, buffer_size, &source)
+                       != ERROR_OK) {
+               buffer_size /= 2;
+               if (buffer_size <= 256) {
+                       LOG_WARNING("no large enough working area available, "
+                                       "can't do block memory writes");
+                       res = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+                       goto cleanup;
+               }
+       }
+
+       /* setup call procedure */
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* data address 
*/
+       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);    /* write flash 
address */
+       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);    /* length */
+       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);    /* func */
+       init_reg_param(&reg_params[4], "sp", 32, PARAM_OUT);    /* stack 
pointer */
+
+       /* erase requested sectors */
+       while (res == ERROR_OK && count > 0) {
+               uint32_t length = source->size > count ? count : source->size;
+
+               res = cc13xx_26xx_await_flash_ready(bank);
+               if (ERROR_OK != res)
+                       break;
+
+               LOG_DEBUG("copy data into source buffer");
+               res = target_write_buffer(bank->target, source->address,
+                               length, buffer);
+               if (ERROR_OK != res)
+                       break;
+
+               LOG_DEBUG("program offset %08x, %i bytes", offset, length);
+
+               /* Explicitly set SP to something valid, or else the board may
+                * be semi-bricked. Seems it can be unlocked again by using
+                * TI's SmartRF programmer 2 and running a CC2650 forced mass 
erase
+                */
+               buf_set_u32(reg_params[0].value, 0, 32, source->address);
+               buf_set_u32(reg_params[1].value, 0, 32, offset);
+               buf_set_u32(reg_params[2].value, 0, 32, length);
+               buf_set_u32(reg_params[3].value, 0, 32, flash_write_rom_func);
+               buf_set_u32(reg_params[4].value, 0, 32, DEFAULT_SP);
+
+               LOG_DEBUG("call trampoline");
+               arch_info.common_magic = ARMV7M_COMMON_MAGIC;
+               arch_info.core_mode = ARM_MODE_THREAD;
+
+               res = target_run_algorithm(bank->target,
+                               0, NULL,
+                               5, reg_params,
+                               write_algorithm->address,
+                               0,
+                               10000,
+                               &arch_info);
+
+               buffer += length;
+               offset += length;
+               count -= length;
+       }
+
+       LOG_DEBUG("cleanup reg_param");
+
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+       destroy_reg_param(&reg_params[2]);
+       destroy_reg_param(&reg_params[3]);
+       destroy_reg_param(&reg_params[4]);
+
+       LOG_DEBUG("cleanup working area");
+       target_free_working_area(bank->target, source);
+
+cleanup:
+
+       LOG_DEBUG("cleanup algo area");
+       target_free_working_area(bank->target, write_algorithm);
+       res_vims = cc13xx_26xx_set_vims_mode(bank, VIMS_MODE_ENABLED);
+
+       return res == ERROR_OK ? res_vims : res;
+}
+
+static int cc13xx_26xx_probe(struct flash_bank *bank)
+{
+       struct cc_info *info = (struct cc_info *)bank->driver_priv;
+       uint32_t rom_version;
+       uint32_t rom_flash_table_address;
+       uint32_t sector_size;
+       uint32_t num_sectors;
+       uint32_t i;
+       int res;
+
+       assert(info);
+
+       /* get rom library version and flash library func table address */
+       res = target_read_u32(bank->target,
+                       ROM_API_TABLE + ROM_API_OFFSET_VERSION,
+                       &rom_version);
+       if (ERROR_OK != res)
+               return res;
+
+       if (rom_version != ROM_VERSION_TESTED) {
+               LOG_WARNING("cc13xx_26xx flash driver only tested on "
+                               "rom version %08x, but found %08x",
+                               ROM_VERSION_TESTED, rom_version);
+       }
+
+       res = target_read_u32(bank->target,
+                       ROM_API_TABLE + ROM_API_OFFSET_FLASH_TABLE,
+                       &rom_flash_table_address);
+       if (ERROR_OK != res)
+               return res;
+       info->flash_table_addr = rom_flash_table_address;
+
+       /* get sector size */
+       res = target_read_u32(bank->target,
+                       FLASH_BASE + FLASH_O_FCFG_B0_SSIZE0,
+                       &sector_size);
+       if (ERROR_OK != res)
+               return res;
+
+       sector_size &= FLASH_FCFG_B0_SSIZE0_B0_SECT_SIZE_M;
+       sector_size >>= FLASH_FCFG_B0_SSIZE0_B0_SECT_SIZE_S;
+       sector_size *= 1024;
+
+       /* get number of sectors */
+       res = target_read_u32(bank->target, FLASH_BASE + FLASH_O_FLASH_SIZE,
+                       &num_sectors);
+       if (ERROR_OK != res)
+               return res;
+       num_sectors &= FLASH_FLASH_SIZE_SECTORS_M;
+       num_sectors >>= FLASH_FLASH_SIZE_SECTORS_S;
+       bank->num_sectors = num_sectors;
+
+       bank->size = num_sectors * sector_size;
+
+       /* create flash sector model */
+       if (bank->sectors) {
+               free(bank->sectors);
+               bank->sectors = NULL;
+       }
+       bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
+
+       for (i = 0; i < num_sectors; i++) {
+               bank->sectors[i].offset = i * sector_size;
+               bank->sectors[i].size = sector_size;
+               bank->sectors[i].is_erased = -1;
+               bank->sectors[i].is_protected = -1;
+       }
+
+       info->probed = true;
+
+       return ERROR_OK;
+}
+
+static int cc13xx_26xx_auto_probe(struct flash_bank *bank)
+{
+       struct cc_info *info = (struct cc_info *)bank->driver_priv;
+       assert(info);
+       return cc13xx_26xx_probe(bank);
+}
+
+COMMAND_HANDLER(cc13xx_26xx_handle_access_last_sector)
+{
+       if (CMD_ARGC < 2)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       struct flash_bank *bank;
+       int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       struct cc_info *info = (struct cc_info *)bank->driver_priv;
+       assert(info);
+
+       /* skip flash bank arg */
+       CMD_ARGC--;
+       CMD_ARGV++;
+
+       while (CMD_ARGC) {
+               if (0 == strcmp("on", CMD_ARGV[0]))
+                       info->last_sector_access = true;
+               else if (0 == strcmp("off", CMD_ARGV[0]))
+                       info->last_sector_access = false;
+                else
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               CMD_ARGC--;
+               CMD_ARGV++;
+       }
+
+       command_print(CMD_CTX, "last sector access: %s",
+                       info->last_sector_access ? "enabled" : "disabled");
+
+       return ERROR_OK;
+}
+
+static const struct command_registration cc13xx_26xx_exec_command_handlers[] = 
{
+       {
+               .name = "access_last_sector",
+               .handler = cc13xx_26xx_handle_access_last_sector,
+               .mode = COMMAND_EXEC,
+               .usage = "bank_id 'off'|'on'",
+               .help = "Grants or denies modification access to last sector.",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+
+static const struct command_registration cc13xx26xx_command_handlers[] = {
+       {
+               .name = "cc13xx26xx",
+               .mode = COMMAND_ANY,
+               .help = "cc13xx/cc26xx flash command group",
+               .usage = "",
+               .chain = cc13xx_26xx_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+struct flash_driver cc13xx_26xx_flash = {
+       .name = "cc13xx26xx",
+       .commands = cc13xx26xx_command_handlers,
+       .flash_bank_command = cc13xx_26xx_flash_bank_command,
+       .erase = cc13xx_26xx_erase,
+       .protect = cc13xx_26xx_protect,
+       .write = cc13xx_26xx_write,
+       .read = default_flash_read,
+       .probe = cc13xx_26xx_probe,
+       .auto_probe = cc13xx_26xx_auto_probe,
+       .erase_check = default_flash_blank_check,
+       .protect_check = cc13xx_26xx_protect_check,
+};
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index 56a5cb2..bf4140e 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -30,6 +30,7 @@ extern struct flash_driver at91sam7_flash;
 extern struct flash_driver at91samd_flash;
 extern struct flash_driver atsamv_flash;
 extern struct flash_driver avr_flash;
+extern struct flash_driver cc13xx_26xx_flash;
 extern struct flash_driver cfi_flash;
 extern struct flash_driver dsp5680xx_flash;
 extern struct flash_driver efm32_flash;
@@ -82,6 +83,7 @@ static struct flash_driver *flash_drivers[] = {
        &at91samd_flash,
        &atsamv_flash,
        &avr_flash,
+       &cc13xx_26xx_flash,
        &cfi_flash,
        &dsp5680xx_flash,
        &efm32_flash,
diff --git a/tcl/target/cc26xx.cfg b/tcl/target/cc26xx.cfg
index 1492e6a..149a9d4 100755
--- a/tcl/target/cc26xx.cfg
+++ b/tcl/target/cc26xx.cfg
@@ -41,3 +41,7 @@ jtag configure $_CHIPNAME.jrc -event post-reset 
"ti_cjtag_to_4pin_jtag $_CHIPNAM
 #
 set _TARGETNAME $_CHIPNAME.cpu
 target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.dap
+
+$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 
$_WORKAREASIZE -work-area-backup 0
+
+flash bank $CHIPNAME.flash cc13xx26xx 0 0 0 0 $_TARGETNAME

-- 

------------------------------------------------------------------------------
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to