/***************************************************************************
* Copyright (C) 2006 by Magnus Lundin *
* lundin@mlu.mine.nu *
* *
* Copyright (C) 2008 by Gheorghe Guran (atlas) *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************/
/***************************************************************************
*
* New flash setup command:
*
* flash bank <driver> <base_addr> <size> <chip_width> <bus_width> <target_id>
* [<chip_type> <banks>
* <sectors_per_bank> <pages_per_sector>
* <page_size> <num_nvmbits>
* <ext_freq_khz>]
*
* <ext_freq_khz> - MUST be used if clock is from external source,
* CAN be used if main oscillator frequency is known (recommended)
* Examples:
* ==== RECOMMENDED (covers clock speed) ============
* flash bank at91sam7 0x00100000 0 0 4 $_TARGETNAME AT91SAM7XC256 1 16 64 256 3 25000
* (if auto-detect fails; provides clock spec)
* flash bank at91sam7 0 0 0 0 $_TARGETNAME 0 0 0 0 0 0 25000
* (auto-detect everything except the clock)
* ==== NOT RECOMMENDED !!! (clock speed is not configured) ====
* flash bank at91sam7 0x00100000 0 0 4 $_TARGETNAME AT91SAM7XC256 1 16 64 256 3 0
* (if auto-detect fails)
* flash bank at91sam7 0 0 0 0 $_TARGETNAME
* (old style, auto-detect everything)
****************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.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, const uint8_t *buffer, uint32_t offset,
uint32_t count);
static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number);
static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode);
static uint32_t at91sam7_wait_status_busy(struct flash_bank *bank, uint32_t waitbits, int timeout);
static int at91sam7_flash_command(struct flash_bank *bank, uint8_t cmd, uint16_t pagen);
static const uint32_t MC_FMR[4] = { 0xFFFFFF60, 0xFFFFFF70, 0xFFFFFF80, 0xFFFFFF90 };
static const uint32_t MC_FCR[4] = { 0xFFFFFF64, 0xFFFFFF74, 0xFFFFFF84, 0xFFFFFF94 };
static const uint32_t MC_FSR[4] = { 0xFFFFFF68, 0xFFFFFF78, 0xFFFFFF88, 0xFFFFFF98 };
static const 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;
const 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,
0x0400, /* 1K */
0x0800, /* 2K */
-1,
0x1c000, /* 112K */
0x1000, /* 4K */
0x14000, /* 80K */
0x28000, /* 160K */
0x2000, /* 8K */
0x4000, /* 16K */
0x8000, /* 32K */
0x10000, /* 64K */
0x20000, /* 128K */
0x40000, /* 256K */
0x18000, /* 96K */
0x80000, /* 512K */
};
#endif
static uint32_t at