cfi: allow optional buffer write support
[fw/openocd] / src / flash / nor / at91sam7.c
index 606cc32b02908b469ed6ff816c43df2976d0eda4..3fabe478d683612faf2936cb53196b8e4cce9906 100644 (file)
 #endif
 
 #include "imp.h"
-#include "at91sam7.h"
 #include <helper/binarybuffer.h>
 
+
+/* AT91SAM7 control registers */
+#define DBGU_CIDR                      0xFFFFF240
+#define CKGR_MCFR                      0xFFFFFC24
+#define CKGR_MOR                       0xFFFFFC20
+#define CKGR_MCFR_MAINRDY      0x10000
+#define CKGR_PLLR                      0xFFFFFC2c
+#define CKGR_PLLR_DIV          0xff
+#define CKGR_PLLR_MUL          0x07ff0000
+#define PMC_MCKR                       0xFFFFFC30
+#define PMC_MCKR_CSS           0x03
+#define PMC_MCKR_PRES          0x1c
+
+/* Flash Controller Commands */
+#define WP             0x01
+#define SLB            0x02
+#define WPL            0x03
+#define CLB            0x04
+#define EA             0x08
+#define SGPB   0x0B
+#define CGPB   0x0D
+#define SSB            0x0F
+
+/* MC_FSR bit definitions */
+#define MC_FSR_FRDY                    1
+#define MC_FSR_EOL                     2
+
+/* AT91SAM7 constants */
+#define RC_FREQ                                32000
+
+/* Flash timing modes */
+#define FMR_TIMING_NONE                0
+#define FMR_TIMING_NVBITS      1
+#define FMR_TIMING_FLASH       2
+
+/* Flash size constants */
+#define FLASH_SIZE_8KB         1
+#define FLASH_SIZE_16KB                2
+#define FLASH_SIZE_32KB                3
+#define FLASH_SIZE_64KB                5
+#define FLASH_SIZE_128KB       7
+#define FLASH_SIZE_256KB       9
+#define FLASH_SIZE_512KB       10
+#define FLASH_SIZE_1024KB      12
+#define FLASH_SIZE_2048KB      14
+
+
 static int at91sam7_protect_check(struct flash_bank *bank);
 static int at91sam7_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count);
 
@@ -67,6 +113,50 @@ static uint32_t MC_FSR[4] = { 0xFFFFFF68, 0xFFFFFF78, 0xFFFFFF88, 0xFFFFFF98 };
 
 static char * EPROC[8]= {"Unknown","ARM946-E","ARM7TDMI","Unknown","ARM920T","ARM926EJ-S","Unknown","Unknown"};
 
+struct at91sam7_flash_bank
+{
+       /* chip id register */
+       uint32_t cidr;
+       uint16_t cidr_ext;
+       uint16_t cidr_nvptyp;
+       uint16_t cidr_arch;
+       uint16_t cidr_sramsiz;
+       uint16_t cidr_nvpsiz;
+       uint16_t cidr_nvpsiz2;
+       uint16_t cidr_eproc;
+       uint16_t cidr_version;
+       char *target_name;
+
+       /* flash auto-detection */
+       uint8_t  flash_autodetection;
+
+       /* flash geometry */
+       uint16_t pages_per_sector;
+       uint16_t pagesize;
+       uint16_t pages_in_lockregion;
+
+       /* nv memory bits */
+       uint16_t num_lockbits_on;
+       uint16_t lockbits;
+       uint16_t num_nvmbits;
+       uint16_t num_nvmbits_on;
+       uint16_t nvmbits;
+       uint8_t  securitybit;
+
+       /* 0: not init
+        * 1: fmcn for nvbits (1uS)
+        * 2: fmcn for flash (1.5uS) */
+       uint8_t  flashmode;
+
+       /* main clock status */
+       uint8_t  mck_valid;
+       uint32_t mck_freq;
+
+       /* external clock frequency */
+       uint32_t ext_freq;
+
+};
+
 #if 0
 static long SRAMSIZ[16] = {
        -1,
@@ -298,7 +388,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
        uint32_t ext_freq;
        uint32_t bank_size;
        uint32_t base_address = 0;
-       char *target_name = "Unknown";
+       char *target_name_t = "Unknown";
 
        at91sam7_info = t_bank->driver_priv;
 
@@ -386,7 +476,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
                        if (arch == 0x70)
                        {
                                num_nvmbits = 2;
-                               target_name = "AT91SAM7S161/16";
+                               target_name_t = "AT91SAM7S161/16";
                        }
                        break;
 
@@ -399,12 +489,12 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
                        if (arch == 0x70)
                        {
                                num_nvmbits = 2;
-                               target_name = "AT91SAM7S321/32";
+                               target_name_t = "AT91SAM7S321/32";
                        }
                        if (arch == 0x72)
                        {
                                num_nvmbits = 3;
-                               target_name = "AT91SAM7SE32";
+                               target_name_t = "AT91SAM7SE32";
                        }
                        break;
 
@@ -417,7 +507,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
                        if (arch == 0x70)
                        {
                                num_nvmbits = 2;
-                               target_name = "AT91SAM7S64";
+                               target_name_t = "AT91SAM7S64";
                        }
                        break;
 
@@ -430,22 +520,22 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
                        if (arch == 0x70)
                        {
                                num_nvmbits = 2;
-                               target_name = "AT91SAM7S128";
+                               target_name_t = "AT91SAM7S128";
                        }
                        if (arch == 0x71)
                        {
                                num_nvmbits = 3;
-                               target_name = "AT91SAM7XC128";
+                               target_name_t = "AT91SAM7XC128";
                        }
                        if (arch == 0x72)
                        {
                                num_nvmbits = 3;
-                               target_name = "AT91SAM7SE128";
+                               target_name_t = "AT91SAM7SE128";
                        }
                        if (arch == 0x75)
                        {
                                num_nvmbits = 3;
-                               target_name = "AT91SAM7X128";
+                               target_name_t = "AT91SAM7X128";
                        }
                        break;
 
@@ -458,27 +548,27 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
                        if (arch == 0x60)
                        {
                                num_nvmbits = 3;
-                               target_name = "AT91SAM7A3";
+                               target_name_t = "AT91SAM7A3";
                        }
                        if (arch == 0x70)
                        {
                                num_nvmbits = 2;
-                               target_name = "AT91SAM7S256";
+                               target_name_t = "AT91SAM7S256";
                        }
                        if (arch == 0x71)
                        {
                                num_nvmbits = 3;
-                               target_name = "AT91SAM7XC256";
+                               target_name_t = "AT91SAM7XC256";
                        }
                        if (arch == 0x72)
                        {
                                num_nvmbits = 3;
-                               target_name = "AT91SAM7SE256";
+                               target_name_t = "AT91SAM7SE256";
                        }
                        if (arch == 0x75)
                        {
                                num_nvmbits = 3;
-                               target_name = "AT91SAM7X256";
+                               target_name_t = "AT91SAM7X256";
                        }
                        break;
 
@@ -491,22 +581,22 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
                        if (arch == 0x70)
                        {
                                num_nvmbits = 2;
-                               target_name = "AT91SAM7S512";
+                               target_name_t = "AT91SAM7S512";
                        }
                        if (arch == 0x71)
                        {
                                num_nvmbits = 3;
-                               target_name = "AT91SAM7XC512";
+                               target_name_t = "AT91SAM7XC512";
                        }
                        if (arch == 0x72)
                        {
                                num_nvmbits = 3;
-                               target_name = "AT91SAM7SE512";
+                               target_name_t = "AT91SAM7SE512";
                        }
                        if (arch == 0x75)
                        {
                                num_nvmbits = 3;
-                               target_name = "AT91SAM7X512";
+                               target_name_t = "AT91SAM7X512";
                        }
                        break;
 
@@ -517,7 +607,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
                        break;
        }
 
-       if (strcmp(target_name, "Unknown") == 0)
+       if (strcmp(target_name_t, "Unknown") == 0)
        {
                LOG_ERROR("Target autodetection failed! Please specify target parameters in configuration file");
                return ERROR_FLASH_OPERATION_FAILED;
@@ -573,7 +663,7 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
                at91sam7_info->cidr_eproc = (cidr >> 5)&0x0007;
                at91sam7_info->cidr_version = cidr&0x001F;
 
-               at91sam7_info->target_name  = target_name;
+               at91sam7_info->target_name  = target_name_t;
                at91sam7_info->flashmode = 0;
                at91sam7_info->ext_freq = ext_freq;
                at91sam7_info->num_nvmbits = num_nvmbits;
@@ -731,7 +821,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
        uint16_t page_size;
        uint16_t num_nvmbits;
 
-       char *target_name;
+       char *target_name_t;
 
        int bnk, sec;
 
@@ -775,8 +865,8 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
                return ERROR_OK;
        }
 
-       target_name = calloc(strlen(CMD_ARGV[7]) + 1, sizeof(char));
-       strcpy(target_name, CMD_ARGV[7]);
+       target_name_t = calloc(strlen(CMD_ARGV[7]) + 1, sizeof(char));
+       strcpy(target_name_t, CMD_ARGV[7]);
 
        /* calculate bank size  */
        bank_size = num_sectors * pages_per_sector * page_size;
@@ -816,7 +906,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
 
                at91sam7_info = t_bank->driver_priv;
 
-               at91sam7_info->target_name  = target_name;
+               at91sam7_info->target_name  = target_name_t;
                at91sam7_info->flashmode = 0;
                at91sam7_info->ext_freq  = ext_freq;
                at91sam7_info->num_nvmbits = num_nvmbits;
@@ -1034,7 +1124,7 @@ static int at91sam7_probe(struct flash_bank *bank)
        return ERROR_OK;
 }
 
-static int at91sam7_info(struct flash_bank *bank, char *buf, int buf_size)
+static int get_at91sam7_info(struct flash_bank *bank, char *buf, int buf_size)
 {
        int printed;
        struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
@@ -1212,5 +1302,5 @@ struct flash_driver at91sam7_flash = {
        .auto_probe = at91sam7_probe,
        .erase_check = at91sam7_erase_check,
        .protect_check = at91sam7_protect_check,
-       .info = at91sam7_info,
+       .info = get_at91sam7_info,
 };