
This patch enables writing (the environment) to the internal flash in the microcontroller.
Signed-off-by: Gunnar Rangoy gunnar@rangoy.com Signed-off-by: Paul Driveklepp pauldriveklepp@gmail.com Signed-off-by: Olav Morken olavmrk@gmail.com --- cpu/at32uc/flashc.c | 69 +++++++++++++++++++++++++++++++++++++++++-- cpu/at32uc/flashc.h | 17 ++++++++++ include/configs/atevk1100.h | 2 +- 3 files changed, 84 insertions(+), 4 deletions(-)
diff --git a/cpu/at32uc/flashc.c b/cpu/at32uc/flashc.c index f33a4bb..e626e1f 100644 --- a/cpu/at32uc/flashc.c +++ b/cpu/at32uc/flashc.c @@ -45,6 +45,7 @@ unsigned long flash_init(void) { unsigned long fsz; unsigned long size; + unsigned int i;
fsz = FLASHC_BFEXT(FSZ, flashc_readl(FSR));
@@ -55,6 +56,10 @@ unsigned long flash_init(void) /* Currently, all interflash have pages which are 128 words. */ flash_info[0].sector_count = size / (128*4);
+ for(i=0; i<flash_info[0].sector_count; i++){ + flash_info[0].start[i] = i*128*4 + CFG_FLASH_BASE; + } + return size; }
@@ -62,19 +67,77 @@ void flash_print_info(flash_info_t *info) { printf("Flash: Vendor ID: 0x%02lx, Product ID: 0x%02lx\n", info->flash_id >> 16, info->flash_id & 0xffff); - printf("Size: %ld MB in %d sectors\n", + printf("Size: %ld kB in %d sectors\n", info->size >> 10, info->sector_count); }
+static void flash_wait_ready(void) +{ + while(! flashc_readl(FSR) & FLASHC_BIT(FRDY) ); +} + int flash_erase(flash_info_t *info, int s_first, int s_last) { - /* TODO */ + int page; + + for(page=s_first;page<s_last; page++){ + flash_wait_ready(); + flashc_writel( + FCMD,FLASHC_BF(CMD, FLASHC_EP) + |FLASHC_BF(PAGEN, page) + |FLASHC_BF(KEY, 0xa5)); + } return ERR_OK; }
+static void write_flash_page(unsigned int pagen, const u32 *data) +{ + unsigned int i; + u32 *dst; + + dst = (u32 *) CFG_FLASH_BASE; + + /* clear page buffer */ + flash_wait_ready(); + flashc_writel(FCMD, + FLASHC_BF(CMD, FLASHC_CPB) | + FLASHC_BF(KEY, 0xa5)); + + /* fill page buffer*/ + flash_wait_ready(); + for(i=0; i<128; i++){ + dst[i]=data[i]; + } + + /* issue write command */ + flashc_writel(FCMD, + FLASHC_BF(CMD, FLASHC_WP)| + FLASHC_BF(PAGEN, pagen)| + FLASHC_BF(KEY, 0xa5)); +} + int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong count) { - /* TODO */ + unsigned int i; + + if (addr % (4*128)) { + printf("flash: write_buff(): ERROR, addr(0x%08lx) not " + "on page boundary", addr); + return ERR_ALIGN; + } + if (count % (4*128)) { + printf("flash: write_buff(): ERROR, count(0x%lu) not " + "a multiple of pagesize", count); + return ERR_ALIGN; + } + + for (i = 0; i < count; i += 128*4) { + unsigned int pagen; + pagen = (addr-CFG_FLASH_BASE+i) / (128*4); + write_flash_page(pagen, (u32*) (src+i)); + } + + return ERR_OK; }
diff --git a/cpu/at32uc/flashc.h b/cpu/at32uc/flashc.h index 23618bc..3e97781 100644 --- a/cpu/at32uc/flashc.h +++ b/cpu/at32uc/flashc.h @@ -43,6 +43,23 @@ #define FLASHC_LOCK_OFFSET 16 #define FLASHC_LOCK_SIZE 16
+#define FLASHC_NOP 0 /*No operation*/ +#define FLASHC_WP 1 /*Write Page*/ +#define FLASHC_EP 2 /*Erase Page*/ +#define FLASHC_CPB 3 /*Clear Page Buffer*/ +#define FLASHC_LP 4 /*Lock region containing given Page*/ +#define FLASHC_UP 5 /*Unlock region containing given Page*/ +#define FLASHC_EA 6 /*Erase All*/ +#define FLASHC_WGPB 7 /*Write General-Purpose Fuse Bit*/ +#define FLASHC_EGPB 8 /*Erase General-Purpose Fuse Bit*/ +#define FLASHC_SSB 9 /*Set Security Bit*/ +#define FLASHC_PGPFB 10 /*Program GP Fuse Byte*/ +#define FLASHC_EAGPF 11 /*Erase All GPFuses*/ +#define FLASHC_QPR 12 /*Quick Page Read*/ +#define FLASHC_WUP 13 /*Write User Page*/ +#define FLASHC_EUP 14 /*Erase User Page*/ +#define FLASHC_QPRUP 15 /*Quick Page Read User Page*/ +
/* Bit manipulation macros */ #define FLASHC_BIT(name) \ diff --git a/include/configs/atevk1100.h b/include/configs/atevk1100.h index 166027a..776a3a1 100644 --- a/include/configs/atevk1100.h +++ b/include/configs/atevk1100.h @@ -160,7 +160,7 @@ #define CFG_FLASH_BASE 0x80000000 #define CFG_FLASH_SIZE 0x80000 #define CFG_MAX_FLASH_BANKS 1 -#define CFG_MAX_FLASH_SECT 135 +#define CFG_MAX_FLASH_SECT 1024
#define CFG_MONITOR_BASE CFG_FLASH_BASE