This is an automated email from Gerrit.

"Name of user not set <toms.sturma...@gmail.com>" just uploaded a new patch set 
to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7115

-- gerrit

commit d71c7de353d82ad80aeeef13f1fd58890f5036de
Author: Toms Stūrmanis <toms.sturma...@gmail.com>
Date:   Thu Aug 11 20:22:09 2022 +0300

    src/flash/nor: flash driver for RSL10
    
    Add new flash driver for internal flash of onsemi RSL10 device.
    
    Signed-off-by: Toms Stūrmanis <toms.sturma...@gmail.com>
    Change-Id: I8030542cb9805e94f56d7a69404cef5d88d6dd5a

diff --git a/contrib/loaders/flash/rsl10/Makefile 
b/contrib/loaders/flash/rsl10/Makefile
new file mode 100644
index 0000000000..2580b7e1df
--- /dev/null
+++ b/contrib/loaders/flash/rsl10/Makefile
@@ -0,0 +1,28 @@
+BIN2C = ../../../../src/helper/bin2char.sh
+
+CROSS_COMPILE ?= arm-none-eabi-
+
+CC=$(CROSS_COMPILE)gcc
+OBJCOPY=$(CROSS_COMPILE)objcopy
+OBJDUMP=$(CROSS_COMPILE)objdump
+
+CFLAGS = -static -nostartfiles -mlittle-endian -Wa,-EL
+
+all: rom_launcher.inc erase_sector.inc
+
+.PHONY: clean
+
+%.elf: %.S
+       $(CC) $(CFLAGS) $< -o $@
+
+%.lst: %.elf
+       $(OBJDUMP) -S $< > $@
+
+%.bin: %.elf
+       $(OBJCOPY) -Obinary $< $@
+
+%.inc: %.bin
+       $(BIN2C) < $< > $@
+
+clean:
+       -rm -f *.elf *.lst *.bin *.inc
diff --git a/contrib/loaders/flash/rsl10/rom_launcher.S 
b/contrib/loaders/flash/rsl10/rom_launcher.S
new file mode 100644
index 0000000000..2e8dfe230f
--- /dev/null
+++ b/contrib/loaders/flash/rsl10/rom_launcher.S
@@ -0,0 +1,22 @@
+
+       .text
+       .syntax unified
+       .cpu cortex-m4
+       .thumb
+    .align 8
+
+/*
+ * Params :
+ * r0-r2 = arguments
+ * r3 = target address in rom
+ */
+
+       .thumb_func
+       .global _start
+_start:
+launch_program_in_rom:
+    // variables are already set, addres to jump is in r3
+    blx r3
+exit:
+       // Wait for OpenOCD
+       bkpt    #0x00
diff --git a/contrib/loaders/flash/rsl10/rom_launcher.inc 
b/contrib/loaders/flash/rsl10/rom_launcher.inc
new file mode 100644
index 0000000000..795c8e0d92
--- /dev/null
+++ b/contrib/loaders/flash/rsl10/rom_launcher.inc
@@ -0,0 +1,2 @@
+/* Autogenerated with ../../../../src/helper/bin2char.sh */
+0x98,0x47,0x00,0xbe,
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index e3afc0ddf1..b80ce18166 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -77,7 +77,8 @@ NOR_DRIVERS = \
        %D%/w600.c \
        %D%/xcf.c \
        %D%/xmc1xxx.c \
-       %D%/xmc4xxx.c
+       %D%/xmc4xxx.c \
+       %D%/rsl10.c
 
 NORHEADERS = \
        %D%/core.h \
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index e3fd36ad71..ee54ef2d67 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -78,6 +78,7 @@ extern const struct flash_driver w600_flash;
 extern const struct flash_driver xcf_flash;
 extern const struct flash_driver xmc1xxx_flash;
 extern const struct flash_driver xmc4xxx_flash;
+extern const struct flash_driver rsl10_flash;
 
 /**
  * The list of built-in flash drivers.
@@ -153,6 +154,7 @@ static const struct flash_driver * const flash_drivers[] = {
        &xmc1xxx_flash,
        &xmc4xxx_flash,
        &w600_flash,
+       &rsl10_flash,
        NULL,
 };
 
diff --git a/src/flash/nor/rsl10.c b/src/flash/nor/rsl10.c
new file mode 100644
index 0000000000..644e2334d9
--- /dev/null
+++ b/src/flash/nor/rsl10.c
@@ -0,0 +1,577 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ *   Copyright (C) 2022 by Toms Stūrmanis                                  *
+ *   toms.sturma...@gmail.com                                              *
+ ***************************************************************************/
+
+#include <stdint.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/binarybuffer.h>
+#include <target/algorithm.h>
+#include <target/armv7m.h>
+
+#include "imp.h"
+#include "rsl10.h"
+
+const struct flash_driver rsl10_flash;
+
+struct rsl10_info {
+       uint32_t refcount;
+
+       struct rsl10_bank {
+               struct rsl10_info *chip;
+               bool probed;
+       } bank[5];
+       struct target *target;
+
+       unsigned int flash_size_kb;
+       unsigned int ram_size_kb;
+};
+
+static bool rsl10_bank_is_probed(const struct flash_bank *bank)
+{
+       struct rsl10_bank *nbank = bank->driver_priv;
+       assert(nbank);
+       return nbank->probed;
+}
+
+static int rsl10_probe(struct flash_bank *bank);
+
+static int rsl10_get_probed_chip_if_halted(
+               struct flash_bank *bank, struct rsl10_info **chip
+)
+{
+       if (bank->target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       struct rsl10_bank *nbank = bank->driver_priv;
+       *chip = nbank->chip;
+
+       if (rsl10_bank_is_probed(bank))
+               return ERROR_OK;
+
+       return rsl10_probe(bank);
+}
+
+static int rsl10_protect_check(struct flash_bank *bank)
+{
+       struct rsl10_bank *nbank = bank->driver_priv;
+       struct rsl10_info *chip = nbank->chip;
+
+       assert(chip);
+
+       uint32_t status = -1;
+       uint32_t test_bit = -1;
+       int res = -1;
+       uint32_t parts = bank->num_sectors / 3;
+
+       READ_U32(RSL10_FLASH_IF_STATUS, status);
+       LOG_DEBUG("parts: %d, status: %" PRIx32, parts, status);
+
+       if (bank->base == RSL10_FLASH_MAIN_ADDRESS) {
+               for (unsigned int i = 0; i < bank->num_sectors; i++) {
+                       if (i < parts)
+                               bank->sectors[i].is_protected =
+                                               (status & 
RSL10_MAIN_LOW_W_UNLOCKED) ? false : true;
+                       else if (parts <= i && i < 2 * parts)
+                               bank->sectors[i].is_protected =
+                                               (status & 
RSL10_MAIN_MIDDLE_W_UNLOCKED) ? false : true;
+                       else
+                               bank->sectors[i].is_protected =
+                                               (status & 
RSL10_MAIN_HIGH_W_UNLOCKED) ? false : true;
+               }
+       } else {
+               switch (bank->base) {
+               case RSL10_FLASH_NVR1_ADDRESS:
+                       test_bit = RSL10_NVR1_W_UNLOCKED;
+                       break;
+               case RSL10_FLASH_NVR2_ADDRESS:
+                       test_bit = RSL10_NVR2_W_UNLOCKED;
+                       break;
+               case RSL10_FLASH_NVR3_ADDRESS:
+                       test_bit = RSL10_NVR3_W_UNLOCKED;
+                       break;
+               default:
+                       break;
+               }
+
+               bank->sectors[0].is_protected = (status & test_bit) ? false : 
true;
+       }
+       return ERROR_OK;
+}
+
+static int rsl10_protect(
+               struct flash_bank *bank, int set, unsigned int first, unsigned 
int last
+)
+{
+       int res;
+       struct rsl10_info *chip;
+       OK(rsl10_get_probed_chip_if_halted(bank, &chip));
+
+       if (bank->base == RSL10_FLASH_MAIN_ADDRESS) {
+               uint32_t bits = 0;
+               uint32_t parts = bank->num_sectors / 3;
+               if (first <= parts)
+                       bits |= RSL10_MAIN_LOW_W_ENABLE;
+               if (last >= 2 * parts)
+                       bits |= RSL10_MAIN_HIGH_W_ENABLE;
+               if (parts <= last && first <= 2 * parts)
+                       bits |= RSL10_MAIN_MIDDLE_W_ENABLE;
+
+               uint32_t status = 0;
+               READ_U32(RSL10_FLASH_MAIN_CTRL, status);
+               uint32_t value = 0;
+               if (set)
+                       value = status & ~bits;
+               else
+                       value = status | bits;
+
+               WRITE_U32(RSL10_FLASH_MAIN_CTRL, value);
+               WRITE_U32(RSL10_FLASH_MAIN_WRITE_UNLOCK, RSL10_FLASH_MAIN_KEY);
+       } else {
+               uint32_t bit = 0;
+               switch (bank->base) {
+               case RSL10_FLASH_NVR1_ADDRESS:
+                       bit = RSL10_NVR1_W_ENABLE;
+                       break;
+               case RSL10_FLASH_NVR2_ADDRESS:
+                       bit = RSL10_NVR2_W_ENABLE;
+                       break;
+               case RSL10_FLASH_NVR3_ADDRESS:
+                       bit = RSL10_NVR3_W_ENABLE;
+                       break;
+               default:
+                       break;
+               }
+
+               uint32_t status = 0;
+               READ_U32(RSL10_FLASH_NVR_CTRL, status);
+               uint32_t value = 0;
+               if (set)
+                       value = status & ~bit;
+               else
+                       value = status | bit;
+               WRITE_U32(RSL10_FLASH_NVR_CTRL, value);
+               WRITE_U32(RSL10_FLASH_NVR_WRITE_UNLOCK, RSL10_FLASH_NVR_KEY);
+       }
+
+       return ERROR_OK;
+}
+
+static int rsl10_check_device(struct flash_bank *bank)
+{
+       uint32_t configid;
+       int res;
+       READ_U32(RSL10_ID, configid);
+       if (configid != 0x9010106) {
+               LOG_ERROR("This is not supported(RSL10) device, use other flash 
driver!!!");
+               return ERROR_TARGET_INVALID;
+       }
+       return ERROR_OK;
+}
+
+static int rsl10_probe(struct flash_bank *bank)
+{
+       struct rsl10_bank *nbank = bank->driver_priv;
+       struct rsl10_info *chip = nbank->chip;
+
+       rsl10_check_device(bank);
+       free(bank->sectors);
+
+       uint32_t bank_id = 0;
+       switch (bank->base) {
+       case RSL10_FLASH_MAIN_ADDRESS:
+               bank_id = 0;
+               break;
+       case RSL10_FLASH_NVR1_ADDRESS:
+               bank_id = 1;
+               break;
+       case RSL10_FLASH_NVR2_ADDRESS:
+               bank_id = 2;
+               break;
+       case RSL10_FLASH_NVR3_ADDRESS:
+               bank_id = 3;
+               break;
+       default:
+               return ERROR_FAIL;
+       }
+
+       uint32_t flash_page_size = 2048;
+
+       bank->num_sectors = bank->size / flash_page_size;
+       chip->ram_size_kb = bank->size / 1024;
+       chip->flash_size_kb = bank->size / 1024;
+       bank->sectors = alloc_block_array(0, flash_page_size, 
bank->num_sectors);
+       if (!bank->sectors)
+               return ERROR_FAIL;
+
+       chip->bank[bank_id].probed = true;
+       return ERROR_OK;
+}
+
+static int rsl10_auto_probe(struct flash_bank *bank)
+{
+       if (rsl10_bank_is_probed(bank))
+               return ERROR_OK;
+
+       return rsl10_probe(bank);
+}
+
+static int rsl10_ll_flash_erase(struct rsl10_info *chip, uint32_t address)
+{
+       struct target *target = chip->target;
+       struct working_area *write_algorithm;
+       int res = ERROR_OK;
+
+       static const uint8_t rsl10_flash_erase_code[] = {
+#include "../../../contrib/loaders/flash/rsl10/rom_launcher.inc"
+       };
+
+       LOG_DEBUG("erasing buffer flash address=0x%" PRIx32, address);
+
+       if (target_alloc_working_area(
+                                       target, sizeof(rsl10_flash_erase_code), 
&write_algorithm
+                       ) != ERROR_OK) {
+               LOG_WARNING("no working area available, no fallback, just 
exit!!!");
+               return ERROR_FAIL;
+       }
+
+       res = target_write_buffer(
+                       target, write_algorithm->address, 
sizeof(rsl10_flash_erase_code),
+                       rsl10_flash_erase_code
+       );
+       if (res != ERROR_OK)
+               goto clear_algorithm;
+
+       struct reg_param reg_params[2];
+       struct armv7m_algorithm armv7m_info;
+       armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
+       armv7m_info.core_mode = ARM_MODE_THREAD;
+
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
+       init_reg_param(&reg_params[1], "r3", 32, PARAM_OUT);
+
+       buf_set_u32(reg_params[0].value, 0, 32, address);
+       uint32_t cmd = 0;
+       res = target_read_u32(target, RSL10_ROM_ERASE_SECTOR, &cmd);
+       if (res != ERROR_OK)
+               goto clear_algorithm;
+       buf_set_u32(reg_params[1].value, 0, 32, cmd);
+
+       res = target_run_algorithm(
+                       target, 0, NULL, 2, reg_params, 
write_algorithm->address,
+                       write_algorithm->address + 
sizeof(rsl10_flash_erase_code) - 2, 1000,
+                       &armv7m_info
+       );
+
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+
+clear_algorithm:
+       target_free_working_area(target, write_algorithm);
+       return res;
+}
+
+static int rsl10_ll_flash_write(
+               struct rsl10_info *chip, uint32_t address, const uint8_t 
*buffer,
+               uint32_t bytes
+)
+{
+       struct target *target = chip->target;
+       struct working_area *write_algorithm;
+       int res = ERROR_OK;
+
+       if (bytes == 4)
+               LOG_INFO(
+                               "Writing 0x%" PRIx32 " to flash address=0x%" 
PRIx32 " bytes=0x%" PRIx32,
+                               *(uint32_t *)buffer, address, bytes
+               );
+       else
+               LOG_INFO(
+                               "Writing buffer to flash address=0x%" PRIx32 " 
bytes=0x%" PRIx32,
+                               address, bytes
+               );
+
+       static const uint8_t rsl10_flash_write_code[] = {
+#include "../../../contrib/loaders/flash/rsl10/rom_launcher.inc"
+       };
+
+       assert(bytes % 4 == 0);
+
+       /* allocate working area with flash programming code */
+       if (target_alloc_working_area(
+                                       target, sizeof(rsl10_flash_write_code), 
&write_algorithm
+                       ) != ERROR_OK) {
+               LOG_WARNING("no working area available, no fallback, just 
exit!!!");
+
+               return ERROR_FAIL;
+       }
+
+       res = target_write_buffer(
+                       target, write_algorithm->address, 
sizeof(rsl10_flash_write_code),
+                       rsl10_flash_write_code
+       );
+       if (res != ERROR_OK)
+               return res;
+
+       struct working_area *source;
+
+#define MAX_SIZE 0x1800
+       /* memory buffer */
+       uint32_t buffer_size = MAX_SIZE;
+       while (target_alloc_working_area(target, buffer_size, &source) != 
ERROR_OK) {
+               buffer_size /= 2;
+               buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
+               if (buffer_size <= 256) {
+                       LOG_WARNING("No large enough working area available, 
can't do "
+                                                                       "block 
memory writes");
+                       target_free_working_area(target, write_algorithm);
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
+       }
+
+       struct reg_param reg_params[4];
+       struct armv7m_algorithm armv7m_info;
+       armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
+       armv7m_info.core_mode = ARM_MODE_THREAD;
+
+       uint32_t sent_bytes = 0;
+       uint32_t write_address = 0;
+       uint32_t bytes_to_send = 0;
+       uint32_t remaining_bytes = 0;
+       bool fix_last = false;
+       bool fix_address = false;
+
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* start addr */
+       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* length */
+       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* data */
+       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* data */
+
+       if (address % 8 != 0) {
+               address -= 4;
+               bytes += 4;
+               fix_address = true;
+       }
+
+       uint32_t cmd = 0;
+       res = target_read_u32(target, RSL10_ROM_WRITE_BUFFER, &cmd);
+       if (res != ERROR_OK)
+               goto free_everything;
+
+       while (sent_bytes < bytes) {
+               remaining_bytes = bytes - sent_bytes;
+               bytes_to_send = remaining_bytes >= MAX_SIZE ? MAX_SIZE : 
remaining_bytes;
+
+               if (bytes_to_send % 8 != 0) {
+                       bytes_to_send += 4;
+                       fix_last = true;
+               }
+
+               if (fix_address) {
+                       res = target_write_buffer(
+                                       target, source->address + 4, 
bytes_to_send - 4, buffer
+                       );
+                       uint32_t fix_data = 0;
+                       res = target_read_u32(target, address, &fix_data);
+                       if (res != ERROR_OK)
+                               goto free_everything;
+                       res =
+                                       target_write_buffer(target, 
source->address, 4, (uint8_t *)&fix_data);
+                       if (res != ERROR_OK)
+                               goto free_everything;
+                       fix_address = false;
+               } else {
+                       res = target_write_buffer(
+                                       target, source->address, bytes_to_send, 
buffer + sent_bytes
+                       );
+                       if (res != ERROR_OK)
+                               goto free_everything;
+               }
+
+               write_address = address + sent_bytes;
+
+               if (fix_last) {
+                       uint32_t fix_data = 0;
+                       res =
+                                       target_read_u32(target, write_address + 
bytes_to_send - 4, &fix_data);
+                       if (res != ERROR_OK)
+                               goto free_everything;
+                       res = target_write_buffer(
+                                       target, source->address + bytes_to_send 
- 4, 4, (uint8_t *)&fix_data
+                       );
+                       if (res != ERROR_OK)
+                               goto free_everything;
+               }
+
+               buf_set_u32(reg_params[0].value, 0, 32, write_address);
+               buf_set_u32(reg_params[1].value, 0, 32, bytes_to_send / 4);
+               buf_set_u32(reg_params[2].value, 0, 32, source->address);
+               buf_set_u32(reg_params[3].value, 0, 32, cmd);
+
+               res = target_run_algorithm(
+                               target, 0, NULL, 4, reg_params, 
write_algorithm->address,
+                               write_algorithm->address + 
sizeof(rsl10_flash_write_code) - 2, 1000,
+                               &armv7m_info
+               );
+
+               if (res != ERROR_OK) {
+                       LOG_WARNING("failed to write algo");
+                       goto free_everything;
+               }
+
+               sent_bytes += bytes_to_send;
+               LOG_DEBUG("ret: %d, sending: %x, sent: %x", res, sent_bytes, 
bytes_to_send);
+       }
+
+free_everything:
+       target_free_working_area(target, source);
+
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+       destroy_reg_param(&reg_params[2]);
+       destroy_reg_param(&reg_params[3]);
+
+       target_free_working_area(target, write_algorithm);
+
+       return res;
+}
+
+static int rsl10_write(
+               struct flash_bank *bank, const uint8_t *buffer, uint32_t offset,
+               uint32_t count
+)
+{
+       struct rsl10_info *chip;
+
+       int res = 0;
+       OK(rsl10_get_probed_chip_if_halted(bank, &chip));
+       rsl10_ll_flash_write(chip, bank->base + offset, buffer, count);
+       return ERROR_OK;
+}
+
+static int
+rsl10_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
+{
+       LOG_INFO("erase bank: %x, %x", first, last);
+       int res;
+       struct rsl10_info *chip;
+
+       OK(rsl10_get_probed_chip_if_halted(bank, &chip));
+       for (uint32_t i = first; i <= last; i++)
+               rsl10_ll_flash_erase(chip, bank->base + i * 0x800);
+
+       return ERROR_OK;
+}
+
+static void rsl10_free_driver_priv(struct flash_bank *bank)
+{
+       struct rsl10_bank *nbank = bank->driver_priv;
+       struct rsl10_info *chip = nbank->chip;
+       if (!chip)
+               return;
+
+       chip->refcount--;
+       if (chip->refcount == 0) {
+               free(chip);
+               bank->driver_priv = NULL;
+       }
+}
+
+static struct rsl10_info *rsl10_get_chip(struct target *target)
+{
+       struct flash_bank *bank_iter;
+
+       /* iterate over rsl10 banks of same target */
+       for (bank_iter = flash_bank_list(); bank_iter; bank_iter = 
bank_iter->next) {
+               if (bank_iter->driver != &rsl10_flash)
+                       continue;
+
+               if (bank_iter->target != target)
+                       continue;
+
+               struct rsl10_bank *nbank = bank_iter->driver_priv;
+               if (!nbank)
+                       continue;
+
+               if (nbank->chip)
+                       return nbank->chip;
+       }
+       return NULL;
+}
+
+FLASH_BANK_COMMAND_HANDLER(rsl10_flash_bank_command)
+{
+       struct rsl10_info *chip = NULL;
+       struct rsl10_bank *nbank = NULL;
+       LOG_INFO("Creating flash @ " TARGET_ADDR_FMT, bank->base);
+
+       switch (bank->base) {
+       case RSL10_FLASH_MAIN_ADDRESS:
+       case RSL10_FLASH_NVR1_ADDRESS:
+       case RSL10_FLASH_NVR2_ADDRESS:
+       case RSL10_FLASH_NVR3_ADDRESS:
+       case RSL10_FLASH_NVR4_ADDRESS:
+               break;
+       default:
+               LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, bank->base);
+               return ERROR_FAIL;
+       }
+
+       chip = rsl10_get_chip(bank->target);
+       if (!chip) {
+               chip = calloc(1, sizeof(*chip));
+               if (!chip)
+                       return ERROR_FAIL;
+
+               chip->target = bank->target;
+       }
+
+       switch (bank->base) {
+       case RSL10_FLASH_MAIN_ADDRESS:
+               nbank = &chip->bank[0];
+               break;
+       case RSL10_FLASH_NVR1_ADDRESS:
+               nbank = &chip->bank[1];
+               break;
+       case RSL10_FLASH_NVR2_ADDRESS:
+               nbank = &chip->bank[2];
+               break;
+       case RSL10_FLASH_NVR3_ADDRESS:
+               nbank = &chip->bank[3];
+               break;
+       case RSL10_FLASH_NVR4_ADDRESS:
+               nbank = &chip->bank[4];
+               break;
+       }
+       assert(nbank);
+
+       chip->refcount++;
+       nbank->chip = chip;
+       nbank->probed = false;
+       bank->driver_priv = nbank;
+       bank->write_start_alignment = bank->write_end_alignment = 4;
+
+       return ERROR_OK;
+}
+
+const struct flash_driver rsl10_flash = {
+               .name = "rsl10",
+               /* .commands            = nrf5_command_handlers, */
+               .flash_bank_command = rsl10_flash_bank_command,
+               /* .info                        = nrf5_info, */
+               .erase = rsl10_erase,
+               .protect = rsl10_protect,
+               .write = rsl10_write,
+               .read = default_flash_read,
+               .probe = rsl10_probe,
+               .auto_probe = rsl10_auto_probe,
+               .erase_check = default_flash_blank_check,
+               .protect_check = rsl10_protect_check,
+               .free_driver_priv = rsl10_free_driver_priv,
+};
diff --git a/src/flash/nor/rsl10.h b/src/flash/nor/rsl10.h
new file mode 100644
index 0000000000..10432623f6
--- /dev/null
+++ b/src/flash/nor/rsl10.h
@@ -0,0 +1,76 @@
+#ifndef RSL10_H_
+#define RSL10_H_
+
+#define BIT(n) (1UL << (n))
+#define WRITE_U32(reg, value)                                                  
\
+       do {                                                                    
     \
+               res = target_write_u32(bank->target, reg, value);               
           \
+               if (res != ERROR_OK)                                            
           \
+                       return res;                                             
                 \
+       } while (0)
+
+#define READ_U32(reg, value)                                                   
\
+       do {                                                                    
     \
+               res = target_read_u32(bank->target, reg, &value);               
           \
+               if (res != ERROR_OK)                                            
           \
+                       return res;                                             
                 \
+       } while (0)
+
+#define OK(func)                                                               
\
+       do {                                                                    
     \
+               res = func;                                                     
           \
+               if (res != ERROR_OK)                                            
           \
+                       return res;                                             
                 \
+       } while (0)
+
+enum rsl10_flash_addresses {
+       RSL10_FLASH_MAIN_ADDRESS = 0x00100000,
+       RSL10_FLASH_NVR1_ADDRESS = 0x00080000,
+       RSL10_FLASH_NVR2_ADDRESS = 0x00080800,
+       RSL10_FLASH_NVR3_ADDRESS = 0x00081000,
+       RSL10_FLASH_NVR4_ADDRESS = 0x00081800,
+};
+
+enum rsl10_registers {
+       RSL10_ID = 0x1FFFFFFC,
+
+       RSL10_FLASH_BASE = 0x40000000,
+#define RSL10_FLASH_REG(offset) (RSL10_FLASH_BASE + offset)
+       RSL10_FLASH_MAIN_WRITE_UNLOCK = RSL10_FLASH_REG(0x504),
+       RSL10_FLASH_MAIN_CTRL = RSL10_FLASH_REG(0x508),
+       RSL10_FLASH_IF_STATUS = RSL10_FLASH_REG(0x538),
+       RSL10_FLASH_NVR_WRITE_UNLOCK = RSL10_FLASH_REG(0x548),
+       RSL10_FLASH_NVR_CTRL = RSL10_FLASH_REG(0x54C),
+};
+
+enum rsl10_keys {
+       RSL10_FLASH_MAIN_KEY = 0xDBC8264E,
+       RSL10_FLASH_NVR_KEY = 0x71B371F5,
+};
+
+enum rsl10_write_bits {
+       RSL10_MAIN_LOW_W_ENABLE = BIT(0),
+       RSL10_MAIN_MIDDLE_W_ENABLE = BIT(1),
+       RSL10_MAIN_HIGH_W_ENABLE = BIT(2),
+
+       RSL10_MAIN_HIGH_W_UNLOCKED = BIT(2),
+       RSL10_MAIN_MIDDLE_W_UNLOCKED = BIT(1),
+       RSL10_MAIN_LOW_W_UNLOCKED = BIT(0),
+
+       RSL10_NVR1_W_ENABLE = BIT(1),
+       RSL10_NVR2_W_ENABLE = BIT(2),
+       RSL10_NVR3_W_ENABLE = BIT(3),
+
+       RSL10_NVR1_W_UNLOCKED = BIT(4),
+       RSL10_NVR2_W_UNLOCKED = BIT(5),
+       RSL10_NVR3_W_UNLOCKED = BIT(6),
+};
+
+enum rsl10_rom_commands {
+       RSL10_ROM_WRITE_WORD_PAIR = 0x3C,
+       RSL10_ROM_WRITE_BUFFER = 0x40,
+       RSL10_ROM_ERASE_SECTOR = 0x44,
+       RSL10_ROM_ERASE_ALL = 0x48,
+};
+
+#endif /* RSL10_H_ */
diff --git a/tcl/target/rsl10.cfg b/tcl/target/rsl10.cfg
new file mode 100644
index 0000000000..8426ee6f6a
--- /dev/null
+++ b/tcl/target/rsl10.cfg
@@ -0,0 +1,111 @@
+#
+# RSL10
+#
+
+source [find target/swj-dp.tcl]
+
+if { [info exists CHIPNAME] } {
+       set _CHIPNAME $CHIPNAME
+} else {
+       set _CHIPNAME rsl10
+}
+
+if { [info exists WORKAREASIZE] } {
+   set _WORKAREASIZE $WORKAREASIZE
+} else {
+   set _WORKAREASIZE 0x8000
+}
+
+if { [info exists CPUTAPID] } {
+       set _CPUTAPID $CPUTAPID
+} else {
+       set _CPUTAPID 0x2ba01477
+}
+
+swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID
+dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
+
+set _TARGETNAME $_CHIPNAME.cpu
+target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap
+
+adapter speed 1000
+
+$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 
$_WORKAREASIZE -work-area-backup 0
+
+# TODO: configure reset
+# reset_config srst_only srst_nogate connect_assert_srst
+
+$_TARGETNAME configure -event examine-fail rsl10_lock_warning
+
+proc rsl10_lock_warning {} {
+    echo "****** WARNING ******"
+    echo "RSL10 device probably has lock engaged."
+    echo "Debug access is denied."
+    echo "Use 'rsl10_unlock key0 key1 key2 key3' to erase and unlock the 
device."
+    echo "****** ....... ******"
+    echo ""
+    poll off
+}
+
+proc rsl10_unlock {p0 p1 p2 p3} {
+    set target [target current]
+    set dap [$target cget -dap]
+    poll off
+
+    $dap apsel 0
+    $dap apcsw 0x23000000
+    $dap apreg 0 0 0x23000052
+
+    # unlock debug
+    $dap apreg 0 4 0x400000F0
+    $dap apreg 0 12 $p0
+    $dap apreg 0 12 $p1
+    $dap apreg 0 12 $p2
+    $dap apreg 0 12 $p3
+
+    $dap apreg 0 12
+
+    # restore debug
+    reset init
+    flash protect 3 0 0 off
+    flash fillw 0x00081040 0x00000000 1
+    flash protect 3 0 0 on
+
+    echo "****** WARNING ******"
+    echo "$target device has been successfully erased and unlocked."
+    echo "****** ....... ******"
+    echo ""
+}
+
+proc rsl10_lock {p0 p1 p2 p3} {
+    reset init
+    flash protect 3 0 0 off
+    flash erase_sector 3 0 0
+
+    # save keys in flash
+    flash fillw 0x00081044 $p0 1
+    flash fillw 0x00081048 $p1 1
+    flash fillw 0x0008104c $p2 1
+    flash fillw 0x00081050 $p3 1
+
+    # lock debug port
+    flash fillw 0x00081040 0x4C6F634B 1
+
+    flash protect 3 0 0 on
+
+    set target [target current]
+    echo "****** WARNING ******"
+    echo "$target device has been successfully prepared to lock."
+    echo "Debug port is locked after restart."
+    echo "Unlock with 'rsl10_unlock $p0 $p1 $p2 $p3'"
+    echo "****** ....... ******"
+    echo ""
+}
+
+flash bank $_CHIPNAME.main rsl10 0x00100000 0x60000 0 0 $_TARGETNAME
+flash bank $_CHIPNAME.nvr1 rsl10 0x00080000 0x800 0 0 $_TARGETNAME
+flash bank $_CHIPNAME.nvr2 rsl10 0x00080800 0x800 0 0 $_TARGETNAME
+flash bank $_CHIPNAME.nvr3 rsl10 0x00081000 0x800 0 0 $_TARGETNAME
+
+# TODO: implement flashing for nvr4
+# flash bank $_CHIPNAME.nvr4 rsl10 0x00081800 0x400 0 0 $_TARGETNAME

-- 

Reply via email to