1 |
f21e08aa
|
meri
|
#include <sys/types.h>
|
2 |
|
|
#include <lib_AT91SAM7.h>
|
3 |
|
|
#include <AT91SAM7.h>
|
4 |
|
|
#include <dfu/dbgu.h>
|
5 |
|
|
#include <board.h>
|
6 |
|
|
|
7 |
|
|
#define EFCS_CMD_WRITE_PAGE 0x1
|
8 |
|
|
#define EFCS_CMD_SET_LOCK_BIT 0x2
|
9 |
|
|
#define EFCS_CMD_WRITE_PAGE_LOCK 0x3
|
10 |
|
|
#define EFCS_CMD_CLEAR_LOCK 0x4
|
11 |
|
|
#define EFCS_CMD_ERASE_ALL 0x8
|
12 |
|
|
#define EFCS_CMD_SET_NVM_BIT 0xb
|
13 |
|
|
#define EFCS_CMD_CLEAR_NVM_BIT 0xd
|
14 |
|
|
#define EFCS_CMD_SET_SECURITY_BIT 0xf
|
15 |
|
|
|
16 |
373c172a
|
Harald Welte
|
static uint16_t page_from_ramaddr(const void *addr)
|
17 |
f21e08aa
|
meri
|
{
|
18 |
373c172a
|
Harald Welte
|
uint32_t ramaddr = (uint32_t) addr;
|
19 |
|
|
ramaddr -= (uint32_t) AT91C_IFLASH;
|
20 |
f21e08aa
|
meri
|
return ((ramaddr >> AT91C_IFLASH_PAGE_SHIFT));
|
21 |
|
|
}
|
22 |
|
|
#define PAGES_PER_LOCKREGION (AT91C_IFLASH_LOCK_REGION_SIZE>>AT91C_IFLASH_PAGE_SHIFT)
|
23 |
|
|
#define IS_FIRST_PAGE_OF_LOCKREGION(x) ((x % PAGES_PER_LOCKREGION) == 0)
|
24 |
|
|
#define LOCKREGION_FROM_PAGE(x) (x / PAGES_PER_LOCKREGION)
|
25 |
|
|
|
26 |
373c172a
|
Harald Welte
|
static int is_page_locked(uint16_t page)
|
27 |
f21e08aa
|
meri
|
{
|
28 |
373c172a
|
Harald Welte
|
uint16_t lockregion = LOCKREGION_FROM_PAGE(page);
|
29 |
f21e08aa
|
meri
|
|
30 |
|
|
return (AT91C_BASE_MC->MC_FSR & (lockregion << 16));
|
31 |
|
|
}
|
32 |
|
|
|
33 |
373c172a
|
Harald Welte
|
static void unlock_page(uint16_t page)
|
34 |
f21e08aa
|
meri
|
{
|
35 |
|
|
page &= 0x3ff;
|
36 |
|
|
AT91F_MC_EFC_PerformCmd(AT91C_BASE_MC, AT91C_MC_FCMD_UNLOCK |
|
37 |
|
|
AT91C_MC_CORRECT_KEY | (page << 8));
|
38 |
|
|
}
|
39 |
|
|
|
40 |
373c172a
|
Harald Welte
|
void flash_page(uint8_t *addr)
|
41 |
f21e08aa
|
meri
|
{
|
42 |
373c172a
|
Harald Welte
|
uint16_t page = page_from_ramaddr(addr) & 0x3ff;
|
43 |
|
|
uint32_t fsr = AT91F_MC_EFC_GetStatus(AT91C_BASE_MC);
|
44 |
f21e08aa
|
meri
|
DEBUGP("flash_page(0x%x=%u) ", addr, page);
|
45 |
|
|
|
46 |
|
|
if (is_page_locked(page)) {
|
47 |
|
|
DEBUGP("unlocking ");
|
48 |
|
|
unlock_page(page);
|
49 |
|
|
}
|
50 |
|
|
|
51 |
|
|
if (!(fsr & AT91C_MC_FRDY)) {
|
52 |
|
|
DEBUGP("NOT_FLASHING ");
|
53 |
|
|
return;
|
54 |
|
|
}
|
55 |
|
|
|
56 |
|
|
DEBUGP("performing start_prog ");
|
57 |
|
|
|
58 |
|
|
AT91F_MC_EFC_PerformCmd(AT91C_BASE_MC, AT91C_MC_FCMD_START_PROG |
|
59 |
|
|
AT91C_MC_CORRECT_KEY | (page << 8));
|
60 |
|
|
}
|
61 |
|
|
|
62 |
|
|
void flash_init(void)
|
63 |
|
|
{
|
64 |
|
|
unsigned int fmcn = AT91F_MC_EFC_ComputeFMCN(MCK);
|
65 |
|
|
|
66 |
|
|
AT91F_MC_EFC_CfgModeReg(AT91C_BASE_MC, (fmcn&0xff) << 16 |
|
67 |
|
|
AT91C_MC_FWS_3FWS);
|
68 |
|
|
}
|