This is an automated email from Gerrit.

"Jeremy Grosser <jer...@synack.me>" just uploaded a new patch set to Gerrit, 
which you can find at https://review.openocd.org/c/openocd/+/8220

-- gerrit

commit e9237c816ffcc8b28378fe76735f5d3555900d67
Author: Jeremy Grosser <jer...@synack.me>
Date:   Mon Apr 22 15:32:32 2024 -0700

    flash/nor/mspm0: Add TI MSPM0xxxx support
    
    Tested with LP-MSPM0G3507 development board
    
    Change-Id: Ibe71a25a2aa2d213b153fd1c13a5231753e4614c
    Signed-off-by: Jeremy Grosser <jer...@synack.me>

diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index afa11e7d40..a1c6da332b 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -44,6 +44,7 @@ NOR_DRIVERS = \
        %D%/max32xxx.c \
        %D%/mdr.c \
        %D%/msp432.c \
+       %D%/mspm0.c \
        %D%/mrvlqspi.c \
        %D%/niietcm4.c \
        %D%/non_cfi.c \
diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h
index 7d6f8c5cc4..27a2fde2bf 100644
--- a/src/flash/nor/driver.h
+++ b/src/flash/nor/driver.h
@@ -272,6 +272,7 @@ extern const struct flash_driver lpcspifi_flash;
 extern const struct flash_driver max32xxx_flash;
 extern const struct flash_driver mdr_flash;
 extern const struct flash_driver mrvlqspi_flash;
+extern const struct flash_driver mspm0_flash;
 extern const struct flash_driver msp432_flash;
 extern const struct flash_driver niietcm4_flash;
 extern const struct flash_driver npcx_flash;
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index 34359889a6..1abfc2257b 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -50,6 +50,7 @@ static const struct flash_driver * const flash_drivers[] = {
        &mdr_flash,
        &mrvlqspi_flash,
        &msp432_flash,
+    &mspm0_flash,
        &niietcm4_flash,
        &npcx_flash,
        &nrf5_flash,
diff --git a/src/flash/nor/mspm0.c b/src/flash/nor/mspm0.c
new file mode 100644
index 0000000000..df8cc6a0d9
--- /dev/null
+++ b/src/flash/nor/mspm0.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "imp.h"
+
+#define FLASHCTL_BASE       (0x400CD000UL)
+#define FLASHCTL_CMDEXEC    (FLASHCTL_BASE + 0x1100)
+#define FLASHCTL_CMDTYPE    (FLASHCTL_BASE + 0x1104)
+#define FLASHCTL_CMDADDR    (FLASHCTL_BASE + 0x1120)
+#define FLASHCTL_CMDBYTEN   (FLASHCTL_BASE + 0x1124)
+#define FLASHCTL_CMDDATA0   (FLASHCTL_BASE + 0x1130)
+#define FLASHCTL_CMDDATA1   (FLASHCTL_BASE + 0x1134)
+#define FLASHCTL_CMDWEPROTA (FLASHCTL_BASE + 0x11D0)
+#define FLASHCTL_CMDWEPROTB (FLASHCTL_BASE + 0x11D4)
+#define FLASHCTL_CMDWEPROTC (FLASHCTL_BASE + 0x11D8)
+#define FLASHCTL_STATCMD    (FLASHCTL_BASE + 0x13D0)
+
+#define CMDTYPE_SIZE_SECTOR (0x04 << 3)
+#define CMDTYPE_SIZE_WORD   (0x00 << 3) // one word of flash is 64 bits
+
+#define CMDTYPE_COMMAND_NOOP            0x00
+#define CMDTYPE_COMMAND_PROGRAM         0x01
+#define CMDTYPE_COMMAND_ERASE           0x02
+#define CMDTYPE_COMMAND_READ_VERIFY     0x03
+#define CMDTYPE_COMMAND_BLANK_VERIFY    0x04
+
+#define STATCMD_FAILMISC        (1 << 12)
+#define STATCMD_FAILMODE        (1 << 7)
+#define STATCMD_FAILILLADDR     (1 << 6)
+#define STATCMD_FAILVERIFY      (1 << 5)
+#define STATCMD_FAILWEPROT      (1 << 4)
+#define STATCMD_CMDINPROGRESS   (1 << 2)
+#define STATCMD_CMDPASS         (1 << 1)
+#define STATCMD_CMDDONE         (1 << 0)
+
+#define CPUSS_BASE          (0x40400000)
+#define CPUSS_CTL           (CPUSS_BASE + 0x1300)
+#define SECTOR_SIZE 1024
+
+struct mspm0_flash_bank {
+};
+
+static const struct command_registration mspm0_any_command_handlers[] = {
+    COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration mspm0_command_handlers[] = {
+    {
+        .name = "mspm0",
+        .mode = COMMAND_ANY,
+        .help = "TI mspm0 flash command group",
+        .usage = "",
+        .chain = mspm0_any_command_handlers,
+    },
+    COMMAND_REGISTRATION_DONE
+};
+
+FLASH_BANK_COMMAND_HANDLER(mspm0_flash_bank_command)
+{
+    bank->driver_priv = malloc(sizeof(struct mspm0_flash_bank));
+    if(!bank->driver_priv) {
+        return ERROR_FLASH_OPERATION_FAILED;
+    }
+    (void)memset(bank->driver_priv, 0, sizeof(struct mspm0_flash_bank));
+    bank->sectors = NULL;
+    return ERROR_OK;
+}
+
+static void mspm0_unprotect_sector(struct flash_bank *bank, uint32_t sector) {
+    struct target *target = bank->target;
+    if(sector < 32) {
+        target_write_u32(target, FLASHCTL_CMDWEPROTA, ~(1 << sector));
+    }else if(sector < (32 + 256)) {
+        target_write_u32(target, FLASHCTL_CMDWEPROTB, ~(1 << ((sector - 32) / 
8)));
+    }else{
+        target_write_u32(target, FLASHCTL_CMDWEPROTC, ~(1 << ((sector - 288) / 
8)));
+    }
+}
+
+static void mspm0_protect_main(struct flash_bank *bank) {
+    struct target *target = bank->target;
+    target_write_u32(target, FLASHCTL_CMDWEPROTA, 0xffffffff);
+    target_write_u32(target, FLASHCTL_CMDWEPROTB, 0xffffffff);
+    target_write_u32(target, FLASHCTL_CMDWEPROTC, 0xffffffff);
+}
+
+static void mspm0_disable_cache(struct flash_bank *bank) {
+    target_write_u32(bank->target, CPUSS_CTL, 0);
+}
+
+static void mspm0_enable_cache(struct flash_bank *bank) {
+    target_write_u32(bank->target, CPUSS_CTL, 0x7);
+}
+
+static int mspm0_flash_wait(struct flash_bank *bank) {
+    struct target *target = bank->target;
+    uint32_t statcmd;
+
+    do{
+        target_read_u32(target, FLASHCTL_STATCMD, &statcmd);
+    }while((statcmd & STATCMD_CMDDONE) == 0);
+
+    if(statcmd & STATCMD_FAILWEPROT) {
+        return ERROR_FLASH_PROTECTED;
+    }
+
+    if(statcmd & (STATCMD_FAILVERIFY | STATCMD_FAILMISC)) {
+        return ERROR_FLASH_OPERATION_FAILED;
+    }
+
+    if(statcmd & STATCMD_FAILILLADDR) {
+        return ERROR_FLASH_SECTOR_INVALID;
+    }
+
+    if(statcmd & STATCMD_FAILMODE) {
+        return ERROR_FLASH_BUSY;
+    }
+
+    if(statcmd != (STATCMD_CMDDONE | STATCMD_CMDPASS)) {
+        return ERROR_FLASH_OPERATION_FAILED;
+    }
+
+    return ERROR_OK;
+}
+
+int mspm0_erase(struct flash_bank *bank, unsigned int first, unsigned int 
last) {
+    struct target *target = bank->target;
+    uint32_t sector;
+    int err = ERROR_FLASH_SECTOR_INVALID;
+
+    mspm0_disable_cache(bank);
+
+    for(sector = first; sector <= last; sector++) {
+        mspm0_unprotect_sector(bank, sector);
+        target_write_u32(target, FLASHCTL_CMDTYPE, CMDTYPE_SIZE_SECTOR | 
CMDTYPE_COMMAND_ERASE);
+        target_write_u32(target, FLASHCTL_CMDADDR, bank->base + 
bank->sectors[sector].offset);
+        target_write_u32(target, FLASHCTL_CMDEXEC, 1);
+        err = mspm0_flash_wait(bank);
+    }
+
+    mspm0_protect_main(bank);
+
+    return err;
+}
+
+static int mspm0_write_word(struct flash_bank *bank, uint32_t addr, uint32_t 
*data) {
+    struct target *target = bank->target;
+    uint32_t sector = addr / SECTOR_SIZE;
+    int err;
+
+    mspm0_unprotect_sector(bank, sector);
+    target_write_u32(target, FLASHCTL_CMDTYPE, CMDTYPE_SIZE_WORD | 
CMDTYPE_COMMAND_PROGRAM);
+    target_write_u32(target, FLASHCTL_CMDADDR, addr);
+    target_write_u32(target, FLASHCTL_CMDBYTEN, 0xFFFFFFFF);
+    target_write_u32(target, FLASHCTL_CMDDATA0, data[0]);
+    target_write_u32(target, FLASHCTL_CMDDATA1, data[1]);
+    target_write_u32(target, FLASHCTL_CMDEXEC, 1);
+    err = mspm0_flash_wait(bank);
+
+    return err;
+}
+
+int mspm0_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t 
offset, uint32_t count) {
+    uint32_t *ptr = (uint32_t *)buffer;
+    uint32_t i;
+    int err;
+
+    err = mspm0_erase(bank, offset / SECTOR_SIZE, (offset + count) / 
SECTOR_SIZE);
+    if(err != ERROR_OK) {
+        return err;
+    }
+
+    mspm0_disable_cache(bank);
+    for(i = 0; i < count; i += 8) {
+        err = mspm0_write_word(bank, offset + i, ptr);
+        ptr += 2;
+        if(err != ERROR_OK) {
+            return err;
+        }
+    }
+
+    mspm0_protect_main(bank);
+    mspm0_enable_cache(bank);
+
+    return ERROR_OK;
+}
+
+int mspm0_probe(struct flash_bank *bank) {
+    uint32_t sramflash;
+
+    bank->bank_number = 0;
+    bank->base = 0x00000000;
+    bank->chip_width = 8;
+    bank->bus_width = 4;
+    target_read_u32(bank->target, 0x41C40018, &sramflash);
+    bank->size = (sramflash & 0xFFF) * 1024;
+    bank->num_sectors = bank->size / SECTOR_SIZE;
+    bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
+    for(unsigned int sector = 0; sector < bank->num_sectors; sector++) {
+        bank->sectors[sector] = (struct flash_sector){
+            .offset = bank->base + (SECTOR_SIZE * sector),
+            .size = SECTOR_SIZE,
+            .is_erased = false,
+            .is_protected = false,
+        };
+    }
+
+    bank->num_prot_blocks = 0;
+    bank->next = NULL;
+
+    return ERROR_OK;
+}
+
+int mspm0_protect_check(struct flash_bank *bank) {
+    return ERROR_OK;
+}
+
+int mspm0_info(struct flash_bank *bank, struct command_invocation *cmd) {
+    return ERROR_OK;
+}
+
+int mspm0_auto_probe(struct flash_bank *bank) {
+    if(bank->sectors != NULL) {
+        return ERROR_OK;
+    }else{
+        return mspm0_probe(bank);
+    }
+}
+
+const struct flash_driver mspm0_flash = {
+    .name               = "mspm0",
+    .commands           = mspm0_command_handlers,   //  done
+    .flash_bank_command = mspm0_flash_bank_command, //  done
+    .erase              = mspm0_erase,              //  done
+    .protect            = NULL,
+    .write              = mspm0_write,              //  done
+    .read               = default_flash_read,
+    .verify             = default_flash_verify,
+    .probe              = mspm0_probe,              //  done
+    .erase_check        = default_flash_blank_check,
+    .protect_check      = mspm0_protect_check,      //  TODO
+    .info               = mspm0_info,               //  TODO
+    .auto_probe         = mspm0_auto_probe,         //  done
+    .free_driver_priv   = default_flash_free_driver_priv,
+};
diff --git a/tcl/target/ti_mspm0.cfg b/tcl/target/ti_mspm0.cfg
new file mode 100644
index 0000000000..fb1c6c1d3d
--- /dev/null
+++ b/tcl/target/ti_mspm0.cfg
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+source [find target/swj-dp.tcl]
+
+if { [info exists CHIPNAME] } {
+       set _CHIPNAME $CHIPNAME
+} else {
+       set _CHIPNAME mspm0
+}
+
+if { [info exists WORKAREASIZE] } {
+       set _WORKAREASIZE $WORKAREASIZE
+} else {
+       set _WORKAREASIZE 0x4000
+}
+
+if { [info exists CPUTAPID] } {
+    set _CPUTAPID $CPUTAPID
+} else {
+    set _CPUTAPID 0x6ba02477
+}
+
+swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID
+dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
+
+set _TARGETNAME $_CHIPNAME.cpu
+target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap
+
+$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 
$_WORKAREASIZE -work-area-backup 0
+
+flash bank $_CHIPNAME.flash mspm0 0 0 0 0 $_TARGETNAME
+
+adapter speed 2000
+
+reset_config srst_open_drain
+cortex_m reset_config sysresetreq
+
+# At power on, if flash 0x00000000 .. 0x00000008 are erased and no secondary
+# bootloader is configured, the ROM BSL will wait up to 10 seconds for a
+# handshake on UART or I2C. If the timeout expires with no handshake, the
+# device goes into STANDBY and the AHB is not accessible from the debug port.
+# The only way out of this state is a power on reset.
+#
+# If you see "Could not find MEM-AP to control the core" and
+# "Examination failed" errors, this is likely what has happened.
+#
+# Telnet to openocd and issue "reset" until "Examination succeed", then you 
have
+# 10 seconds to halt the CPU before it goes into STANDBY again. Once halted,
+# you can write to the flash and reset normally.

-- 

Reply via email to