flash: add Stellaris Blizzard class
[fw/openocd] / src / flash / nor / stellaris.c
index ff1c2e48fc94f1da478680f5b1456c6aa6c1e493..39c189c43b5903b5aa4d84c9f2586f33379245af 100644 (file)
  ***************************************************************************/
 
 /***************************************************************************
-* STELLARIS is tested on LM3S811, LM3S6965
+* STELLARIS flash is tested on LM3S811, LM3S6965, LM3s3748, more.
 ***************************************************************************/
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include "imp.h"
-#include "stellaris.h"
 #include <target/algorithm.h>
 #include <target/armv7m.h>
 
 
 #define DID0_VER(did0) ((did0 >> 28)&0x07)
 
+/* STELLARIS control registers */
+#define SCB_BASE       0x400FE000
+#define DID0           0x000
+#define DID1           0x004
+#define DC0                    0x008
+#define DC1                    0x010
+#define DC2                    0x014
+#define DC3                    0x018
+#define DC4                    0x01C
+
+#define RIS                    0x050
+#define RCC                    0x060
+#define PLLCFG         0x064
+#define RCC2           0x070
+#define NVMSTAT                0x1a0
+
+/* "legacy" flash memory protection registers (64KB max) */
+#define FMPRE          0x130
+#define FMPPE          0x134
+
+/* new flash memory protection registers (for more than 64KB) */
+#define FMPRE0         0x200           /* PRE1 = PRE0 + 4, etc */
+#define FMPPE0         0x400           /* PPE1 = PPE0 + 4, etc */
+
+#define USECRL         0x140
+
+#define FLASH_CONTROL_BASE     0x400FD000
+#define FLASH_FMA      (FLASH_CONTROL_BASE | 0x000)
+#define FLASH_FMD      (FLASH_CONTROL_BASE | 0x004)
+#define FLASH_FMC      (FLASH_CONTROL_BASE | 0x008)
+#define FLASH_CRIS     (FLASH_CONTROL_BASE | 0x00C)
+#define FLASH_CIM      (FLASH_CONTROL_BASE | 0x010)
+#define FLASH_MISC     (FLASH_CONTROL_BASE | 0x014)
+
+#define AMISC  1
+#define PMISC  2
+
+#define AMASK  1
+#define PMASK  2
+
+/* Flash Controller Command bits */
+#define FMC_WRKEY      (0xA442 << 16)
+#define FMC_COMT       (1 << 3)
+#define FMC_MERASE     (1 << 2)
+#define FMC_ERASE      (1 << 1)
+#define FMC_WRITE      (1 << 0)
+
+/* STELLARIS constants */
+
+/* values to write in FMA to commit write-"once" values */
+#define FLASH_FMA_PRE(x)       (2 * (x))       /* for FMPPREx */
+#define FLASH_FMA_PPE(x)       (2 * (x) + 1)   /* for FMPPPEx */
+
+
 static void stellaris_read_clock_info(struct flash_bank *bank);
 static int stellaris_mass_erase(struct flash_bank *bank);
 
+struct stellaris_flash_bank
+{
+       /* chip id register */
+       uint32_t did0;
+       uint32_t did1;
+       uint32_t dc0;
+       uint32_t dc1;
+
+       const char * target_name;
+
+       uint32_t sramsiz;
+       uint32_t flshsz;
+       /* 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;
+};
+
+// Autogenerated by contrib/gen-stellaris-part-header.pl
+// From Stellaris Firmware Development Package revision 8049
 static struct {
        uint32_t partno;
-       char *partname;
+       const char *partname;
 }      StellarisParts[] =
 {
        {0x0001,"LM3S101"},
@@ -80,6 +166,7 @@ static struct {
        {0x10C1,"LM3S1150"},
        {0x10C4,"LM3S1162"},
        {0x10C2,"LM3S1165"},
+       {0x10EC,"LM3S1166"},
        {0x10C6,"LM3S1332"},
        {0x10BC,"LM3S1435"},
        {0x10BA,"LM3S1439"},
@@ -89,11 +176,14 @@ static struct {
        {0x1006,"LM3S1607"},
        {0x10DA,"LM3S1608"},
        {0x10C0,"LM3S1620"},
+       {0x10CD,"LM3S1621"},
        {0x1003,"LM3S1625"},
        {0x1004,"LM3S1626"},
        {0x1005,"LM3S1627"},
        {0x10B3,"LM3S1635"},
+       {0x10EB,"LM3S1636"},
        {0x10BD,"LM3S1637"},
+       {0x10B1,"LM3S1651"},
        {0x10B9,"LM3S1751"},
        {0x1010,"LM3S1776"},
        {0x1016,"LM3S1811"},
@@ -105,12 +195,29 @@ static struct {
        {0x10BE,"LM3S1958"},
        {0x10B5,"LM3S1960"},
        {0x10B8,"LM3S1968"},
+       {0x10EA,"LM3S1969"},
+       {0x10CE,"LM3S1B21"},
+       {0x10CA,"LM3S1C21"},
+       {0x10CB,"LM3S1C26"},
+       {0x1098,"LM3S1C58"},
+       {0x10B0,"LM3S1D21"},
+       {0x10CC,"LM3S1D26"},
+       {0x101D,"LM3S1F11"},
+       {0x101B,"LM3S1F16"},
+       {0x10AF,"LM3S1G21"},
+       {0x1095,"LM3S1G58"},
+       {0x101E,"LM3S1H11"},
+       {0x101C,"LM3S1H16"},
        {0x100F,"LM3S1J11"},
        {0x103C,"LM3S1J16"},
        {0x100E,"LM3S1N11"},
        {0x103B,"LM3S1N16"},
+       {0x10B2,"LM3S1P51"},
+       {0x109E,"LM3S1R21"},
+       {0x10C9,"LM3S1R26"},
        {0x1030,"LM3S1W16"},
        {0x102F,"LM3S1Z16"},
+       {0x10D4,"LM3S2016"},
        {0x1051,"LM3S2110"},
        {0x1084,"LM3S2139"},
        {0x1039,"LM3S2276"},
@@ -132,12 +239,17 @@ static struct {
        {0x106D,"LM3S2793"},
        {0x10E3,"LM3S2911"},
        {0x10E2,"LM3S2918"},
+       {0x10ED,"LM3S2919"},
        {0x1054,"LM3S2939"},
        {0x108F,"LM3S2948"},
        {0x1058,"LM3S2950"},
        {0x1055,"LM3S2965"},
        {0x106C,"LM3S2B93"},
+       {0x1094,"LM3S2D93"},
+       {0x1093,"LM3S2U93"},
+       {0x1008,"LM3S3634"},
        {0x1043,"LM3S3651"},
+       {0x10C8,"LM3S3654"},
        {0x1044,"LM3S3739"},
        {0x1049,"LM3S3748"},
        {0x1045,"LM3S3749"},
@@ -162,15 +274,28 @@ static struct {
        {0x100B,"LM3S5951"},
        {0x104E,"LM3S5956"},
        {0x1068,"LM3S5B91"},
+       {0x102E,"LM3S5C31"},
+       {0x102C,"LM3S5C36"},
+       {0x105E,"LM3S5C51"},
+       {0x105B,"LM3S5C56"},
+       {0x105F,"LM3S5D51"},
+       {0x105C,"LM3S5D56"},
+       {0x1087,"LM3S5D91"},
+       {0x102D,"LM3S5G31"},
+       {0x101F,"LM3S5G36"},
+       {0x105D,"LM3S5G51"},
+       {0x104F,"LM3S5G56"},
        {0x1009,"LM3S5K31"},
        {0x104A,"LM3S5K36"},
        {0x100A,"LM3S5P31"},
        {0x1048,"LM3S5P36"},
+       {0x10B6,"LM3S5P3B"},
        {0x100D,"LM3S5P51"},
        {0x104C,"LM3S5P56"},
        {0x1007,"LM3S5R31"},
        {0x104B,"LM3S5R36"},
        {0x1047,"LM3S5T36"},
+       {0x107F,"LM3S5U91"},
        {0x1046,"LM3S5Y36"},
        {0x10A1,"LM3S6100"},
        {0x1074,"LM3S6110"},
@@ -185,12 +310,18 @@ static struct {
        {0x108B,"LM3S6637"},
        {0x10A3,"LM3S6730"},
        {0x1077,"LM3S6753"},
+       {0x10D1,"LM3S6816"},
        {0x10E9,"LM3S6911"},
+       {0x10D3,"LM3S6916"},
        {0x10E8,"LM3S6918"},
        {0x1089,"LM3S6938"},
        {0x1072,"LM3S6950"},
        {0x1078,"LM3S6952"},
        {0x1073,"LM3S6965"},
+       {0x10AA,"LM3S6C11"},
+       {0x10AC,"LM3S6C65"},
+       {0x109F,"LM3S6G11"},
+       {0x10AB,"LM3S6G65"},
        {0x1064,"LM3S8530"},
        {0x108E,"LM3S8538"},
        {0x1061,"LM3S8630"},
@@ -203,24 +334,51 @@ static struct {
        {0x10A6,"LM3S8962"},
        {0x1062,"LM3S8970"},
        {0x10D7,"LM3S8971"},
+       {0x10AE,"LM3S8C62"},
+       {0x10AD,"LM3S8G62"},
+       {0x10CF,"LM3S9781"},
        {0x1067,"LM3S9790"},
        {0x106B,"LM3S9792"},
+       {0x102D,"LM3S9971"},
        {0x1020,"LM3S9997"},
+       {0x10D0,"LM3S9B81"},
        {0x1066,"LM3S9B90"},
        {0x106A,"LM3S9B92"},
        {0x106E,"LM3S9B95"},
        {0x106F,"LM3S9B96"},
+       {0x101D,"LM3S9BN2"},
+       {0x101E,"LM3S9BN5"},
+       {0x101F,"LM3S9BN6"},
+       {0x1070,"LM3S9C97"},
+       {0x107A,"LM3S9CN5"},
+       {0x10A9,"LM3S9D81"},
+       {0x107E,"LM3S9D90"},
+       {0x1092,"LM3S9D92"},
+       {0x10C8,"LM3S9D95"},
+       {0x109D,"LM3S9D96"},
+       {0x107B,"LM3S9DN5"},
+       {0x107C,"LM3S9DN6"},
+       {0x1060,"LM3S9G97"},
+       {0x1079,"LM3S9GN5"},
+       {0x101B,"LM3S9L71"},
        {0x1018,"LM3S9L97"},
+       {0x10A8,"LM3S9U81"},
+       {0x107D,"LM3S9U90"},
+       {0x1090,"LM3S9U92"},
+       {0x10B7,"LM3S9U95"},
+       {0x109B,"LM3S9U96"},
        {0,"Unknown part"}
 };
 
-static char * StellarisClassname[5] =
+static char * StellarisClassname[7] =
 {
        "Sandstorm",
        "Fury",
        "Unknown",
        "DustDevil",
-       "Tempest"
+       "Tempest",
+       "Blizzard",
+       "Firestorm"
 };
 
 /***************************************************************************
@@ -693,7 +851,7 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
 
        if (!set)
        {
-               LOG_ERROR("Hardware doesn't suppport page-level unprotect. "
+               LOG_ERROR("Hardware doesn't support page-level unprotect. "
                        "Try the 'recover' command.");
                return ERROR_INVALID_ARGUMENTS;
        }
@@ -751,7 +909,7 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
         * REVISIT DustDevil-A0 parts have an erratum making FMPPE commits
         * inadvisable ... it makes future mass erase operations fail.
         */
-       LOG_WARNING("Flash protection cannot be removed once commited, commit is NOT executed !");
+       LOG_WARNING("Flash protection cannot be removed once committed, commit is NOT executed !");
        /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
 
        /* Wait until erase complete */
@@ -773,6 +931,8 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
        return ERROR_OK;
 }
 
+/* see contib/loaders/flash/stellaris.s for src */
+
 static const uint8_t stellaris_write_code[] =
 {
 /*
@@ -816,7 +976,7 @@ static int stellaris_write_block(struct flash_bank *bank,
                uint8_t *buffer, uint32_t offset, uint32_t wcount)
 {
        struct target *target = bank->target;
-       uint32_t buffer_size = 8192;
+       uint32_t buffer_size = 16384;
        struct working_area *source;
        struct working_area *write_algorithm;
        uint32_t address = bank->base + offset;
@@ -884,8 +1044,7 @@ static int stellaris_write_block(struct flash_bank *bank,
                                (unsigned) (wcount - thisrun_count));
                retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
                                write_algorithm->address,
-                               write_algorithm->address +
-                                       sizeof(stellaris_write_code) - 10,
+                               0,
                                10000, &armv7m_info);
                if (retval != ERROR_OK)
                {