mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
ColdFire: Add dspi and serial flash support for MCF5445x
Signed-off-by: TsiChung Liew <Tsi-Chung.Liew@freescale.com> Acked-by: John Rigby <jrigby@freescale.com>
This commit is contained in:
parent
48ead7a7a9
commit
bae61eefe1
5 changed files with 485 additions and 63 deletions
|
@ -95,6 +95,11 @@ typedef volatile unsigned char FLASH_PORT_WIDTHV;
|
|||
#define FLASH_28F256P30T 0x00BD /* Intel 28F256P30T ( 256M = 16M x 16 ) */
|
||||
#define FLASH_28F256P30B 0x00BE /* Intel 28F256P30B ( 256M = 16M x 16 ) */
|
||||
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
#define STM_ID_M25P16 0x20152015
|
||||
#define FLASH_M25P16 0x0055
|
||||
#endif
|
||||
|
||||
#define SYNC __asm__("nop")
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
|
@ -111,6 +116,12 @@ void inline spin_wheel(void);
|
|||
void flash_sync_real_protect(flash_info_t * info);
|
||||
uchar intel_sector_protected(flash_info_t * info, ushort sector);
|
||||
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
int write_ser_data(flash_info_t * info, ulong dest, uchar * data, ulong cnt);
|
||||
int serial_flash_read_status(int chipsel);
|
||||
static int ser_flash_cs = 0;
|
||||
#endif
|
||||
|
||||
flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
|
||||
|
||||
ulong flash_init(void)
|
||||
|
@ -119,6 +130,10 @@ ulong flash_init(void)
|
|||
ulong size = 0;
|
||||
ulong fbase = 0;
|
||||
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
dspi_init();
|
||||
#endif
|
||||
|
||||
for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
|
||||
memset(&flash_info[i], 0, sizeof(flash_info_t));
|
||||
|
||||
|
@ -129,6 +144,11 @@ ulong flash_init(void)
|
|||
case 1:
|
||||
fbase = (ulong) CFG_FLASH1_BASE;
|
||||
break;
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
case 2:
|
||||
fbase = (ulong) CFG_FLASH2_BASE;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
flash_get_size((FPWV *) fbase, &flash_info[i]);
|
||||
|
@ -152,7 +172,6 @@ int flash_get_offsets(ulong base, flash_info_t * info)
|
|||
{
|
||||
int i, j, k;
|
||||
int sectors, bs, banks;
|
||||
ulong start;
|
||||
|
||||
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_ATM) {
|
||||
int sect[] = CFG_ATMEL_SECT;
|
||||
|
@ -196,6 +215,15 @@ int flash_get_offsets(ulong base, flash_info_t * info)
|
|||
|
||||
*addr16 = (FPW) INTEL_RESET; /* restore read mode */
|
||||
}
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM) {
|
||||
info->start[0] = CFG_FLASH2_BASE;
|
||||
for (k = 0, i = 0; i < CFG_STM_SECT; i++, k++) {
|
||||
info->start[k + 1] = info->start[k] + CFG_STM_SECTSZ;
|
||||
info->protect[k] = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
@ -211,6 +239,11 @@ void flash_print_info(flash_info_t * info)
|
|||
case FLASH_MAN_ATM:
|
||||
printf("ATMEL ");
|
||||
break;
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
case FLASH_MAN_STM:
|
||||
printf("ST ");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("Unknown Vendor ");
|
||||
break;
|
||||
|
@ -221,8 +254,13 @@ void flash_print_info(flash_info_t * info)
|
|||
printf("AT49BV040A\n");
|
||||
break;
|
||||
case FLASH_28F128J3A:
|
||||
printf("Intel 28F128J3A\n");
|
||||
printf("28F128J3A\n");
|
||||
break;
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
case FLASH_M25P16:
|
||||
printf("M25P16\n");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("Unknown Chip Type\n");
|
||||
return;
|
||||
|
@ -267,6 +305,45 @@ ulong flash_get_size(FPWV * addr, flash_info_t * info)
|
|||
u16 value;
|
||||
int i;
|
||||
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
if ((ulong) addr == CFG_FLASH2_BASE) {
|
||||
int manufactId = 0;
|
||||
int deviceId = 0;
|
||||
|
||||
ser_flash_cs = 1;
|
||||
|
||||
dspi_tx(ser_flash_cs, 0x80, SER_RDID);
|
||||
dspi_tx(ser_flash_cs, 0x80, 0);
|
||||
dspi_tx(ser_flash_cs, 0x80, 0);
|
||||
dspi_tx(ser_flash_cs, 0x80, 0);
|
||||
|
||||
dspi_rx();
|
||||
manufactId = dspi_rx();
|
||||
deviceId = dspi_rx() << 8;
|
||||
deviceId |= dspi_rx();
|
||||
|
||||
dspi_tx(ser_flash_cs, 0x00, 0);
|
||||
dspi_rx();
|
||||
|
||||
switch (manufactId) {
|
||||
case (u8) STM_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_STM;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (deviceId) {
|
||||
case (u16) STM_ID_M25P16:
|
||||
info->flash_id += FLASH_M25P16;
|
||||
break;
|
||||
}
|
||||
|
||||
info->sector_count = CFG_STM_SECT;
|
||||
info->size = CFG_STM_SECT * CFG_STM_SECTSZ;
|
||||
|
||||
return (info->size);
|
||||
}
|
||||
#endif
|
||||
|
||||
addr[FLASH_CYCLE1] = (FPWV) 0x00AA00AA; /* for Atmel, Intel ignores this */
|
||||
addr[FLASH_CYCLE2] = (FPWV) 0x00550055; /* for Atmel, Intel ignores this */
|
||||
addr[FLASH_CYCLE1] = (FPWV) 0x00900090; /* selects Intel or Atmel */
|
||||
|
@ -383,6 +460,21 @@ int flash_cmd_rd(volatile u16 * addr, int index)
|
|||
return (int)addr[index];
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
int serial_flash_read_status(int chipsel)
|
||||
{
|
||||
u16 status;
|
||||
|
||||
dspi_tx(chipsel, 0x80, SER_RDSR);
|
||||
dspi_rx();
|
||||
|
||||
dspi_tx(chipsel, 0x00, 0);
|
||||
status = dspi_rx();
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function gets the u-boot flash sector protection status
|
||||
* (flash_info_t.protect[]) in sync with the sector protection
|
||||
|
@ -462,8 +554,11 @@ int flash_erase(flash_info_t * info, int s_first, int s_last)
|
|||
{
|
||||
int flag, prot, sect;
|
||||
ulong type, start, last;
|
||||
int rcode = 0, intel = 0;
|
||||
|
||||
int rcode = 0, flashtype = 0;
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
int count;
|
||||
u16 status;
|
||||
#endif
|
||||
if ((s_first < 0) || (s_first > s_last)) {
|
||||
if (info->flash_id == FLASH_UNKNOWN)
|
||||
printf("- missing\n");
|
||||
|
@ -474,19 +569,25 @@ int flash_erase(flash_info_t * info, int s_first, int s_last)
|
|||
|
||||
type = (info->flash_id & FLASH_VENDMASK);
|
||||
|
||||
if (type != (FLASH_MAN_INTEL & FLASH_VENDMASK)) {
|
||||
if (type != (FLASH_MAN_ATM & FLASH_VENDMASK)) {
|
||||
type = (info->flash_id & FLASH_VENDMASK);
|
||||
printf
|
||||
("Can't erase unknown flash type %08lx - aborted\n",
|
||||
info->flash_id);
|
||||
return 1;
|
||||
}
|
||||
switch (type) {
|
||||
case FLASH_MAN_ATM:
|
||||
flashtype = 1;
|
||||
break;
|
||||
case FLASH_MAN_INTEL:
|
||||
flashtype = 2;
|
||||
break;
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
case FLASH_MAN_STM:
|
||||
flashtype = 3;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
type = (info->flash_id & FLASH_VENDMASK);
|
||||
printf("Can't erase unknown flash type %08lx - aborted\n",
|
||||
info->flash_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (type == FLASH_MAN_INTEL)
|
||||
intel = 1;
|
||||
|
||||
prot = 0;
|
||||
for (sect = s_first; sect <= s_last; ++sect) {
|
||||
if (info->protect[sect]) {
|
||||
|
@ -503,6 +604,51 @@ int flash_erase(flash_info_t * info, int s_first, int s_last)
|
|||
start = get_timer(0);
|
||||
last = start;
|
||||
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
/* Perform bulk erase */
|
||||
if (flashtype == 3) {
|
||||
if ((s_last - s_first) == (CFG_STM_SECT - 1)) {
|
||||
if (prot == 0) {
|
||||
dspi_tx(ser_flash_cs, 0x00, SER_WREN);
|
||||
dspi_rx();
|
||||
|
||||
status = serial_flash_read_status(ser_flash_cs);
|
||||
if (((status & 0x9C) != 0)
|
||||
&& ((status & 0x02) != 0x02)) {
|
||||
printf("Can't erase flash\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
dspi_tx(ser_flash_cs, 0x00, SER_BULK_ERASE);
|
||||
dspi_rx();
|
||||
|
||||
count = 0;
|
||||
start = get_timer(0);
|
||||
do {
|
||||
status =
|
||||
serial_flash_read_status
|
||||
(ser_flash_cs);
|
||||
|
||||
if (count++ > 0x10000) {
|
||||
spin_wheel();
|
||||
count = 0;
|
||||
}
|
||||
|
||||
if (get_timer(start) >
|
||||
CFG_FLASH_ERASE_TOUT) {
|
||||
printf("Timeout\n");
|
||||
return 1;
|
||||
}
|
||||
} while (status & 0x01);
|
||||
|
||||
printf("\b. done\n");
|
||||
return 0;
|
||||
} else if (prot == CFG_STM_SECT) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Start erase on unprotected sectors */
|
||||
for (sect = s_first; sect <= s_last; sect++) {
|
||||
if (info->protect[sect] == 0) { /* not protected */
|
||||
|
@ -515,65 +661,116 @@ int flash_erase(flash_info_t * info, int s_first, int s_last)
|
|||
/* arm simple, non interrupt dependent timer */
|
||||
start = get_timer(0);
|
||||
|
||||
if (intel) {
|
||||
*addr = (FPW) INTEL_READID;
|
||||
min = addr[INTEL_CFI_TERB] & 0xff;
|
||||
min = 1 << min; /* ms */
|
||||
min = (min / info->sector_count) * 1000;
|
||||
switch (flashtype) {
|
||||
case 1:
|
||||
{
|
||||
FPWV *base; /* first address in bank */
|
||||
FPWV *atmeladdr;
|
||||
|
||||
/* start erase block */
|
||||
*addr = (FPW) INTEL_CLEAR; /* clear status register */
|
||||
*addr = (FPW) INTEL_ERASE; /* erase setup */
|
||||
*addr = (FPW) INTEL_CONFIRM; /* erase confirm */
|
||||
flag = disable_interrupts();
|
||||
|
||||
while ((*addr & (FPW) INTEL_FINISHED) !=
|
||||
(FPW) INTEL_FINISHED) {
|
||||
atmeladdr = (FPWV *) addr; /* concatenate to 8 bit */
|
||||
base = (FPWV *) (CFG_ATMEL_BASE); /* First sector */
|
||||
|
||||
if (get_timer(start) >
|
||||
CFG_FLASH_ERASE_TOUT) {
|
||||
printf("Timeout\n");
|
||||
*addr = (FPW) INTEL_SUSERASE; /* suspend erase */
|
||||
*addr = (FPW) INTEL_RESET; /* reset to read mode */
|
||||
base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */
|
||||
base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */
|
||||
base[FLASH_CYCLE1] = (u8) 0x00800080; /* erase mode */
|
||||
base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */
|
||||
base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */
|
||||
*atmeladdr = (u8) 0x00300030; /* erase sector */
|
||||
|
||||
rcode = 1;
|
||||
break;
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
while ((*atmeladdr & (u8) 0x00800080) !=
|
||||
(u8) 0x00800080) {
|
||||
if (get_timer(start) >
|
||||
CFG_FLASH_ERASE_TOUT) {
|
||||
printf("Timeout\n");
|
||||
*atmeladdr = (u8) 0x00F000F0; /* reset to read mode */
|
||||
|
||||
rcode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*atmeladdr = (u8) 0x00F000F0; /* reset to read mode */
|
||||
break;
|
||||
}
|
||||
|
||||
*addr = (FPW) INTEL_RESET; /* resest to read mode */
|
||||
} else {
|
||||
FPWV *base; /* first address in bank */
|
||||
FPWV *atmeladdr;
|
||||
case 2:
|
||||
{
|
||||
*addr = (FPW) INTEL_READID;
|
||||
min = addr[INTEL_CFI_TERB] & 0xff;
|
||||
min = 1 << min; /* ms */
|
||||
min = (min / info->sector_count) * 1000;
|
||||
|
||||
flag = disable_interrupts();
|
||||
/* start erase block */
|
||||
*addr = (FPW) INTEL_CLEAR; /* clear status register */
|
||||
*addr = (FPW) INTEL_ERASE; /* erase setup */
|
||||
*addr = (FPW) INTEL_CONFIRM; /* erase confirm */
|
||||
|
||||
atmeladdr = (FPWV *) addr; /* concatenate to 8 bit */
|
||||
base = (FPWV *) (CFG_ATMEL_BASE); /* First sector */
|
||||
while ((*addr & (FPW) INTEL_FINISHED) !=
|
||||
(FPW) INTEL_FINISHED) {
|
||||
|
||||
base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */
|
||||
base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */
|
||||
base[FLASH_CYCLE1] = (u8) 0x00800080; /* erase mode */
|
||||
base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */
|
||||
base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */
|
||||
*atmeladdr = (u8) 0x00300030; /* erase sector */
|
||||
if (get_timer(start) >
|
||||
CFG_FLASH_ERASE_TOUT) {
|
||||
printf("Timeout\n");
|
||||
*addr = (FPW) INTEL_SUSERASE; /* suspend erase */
|
||||
*addr = (FPW) INTEL_RESET; /* reset to read mode */
|
||||
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
while ((*atmeladdr & (u8) 0x00800080) !=
|
||||
(u8) 0x00800080) {
|
||||
if (get_timer(start) >
|
||||
CFG_FLASH_ERASE_TOUT) {
|
||||
printf("Timeout\n");
|
||||
*atmeladdr = (u8) 0x00F000F0; /* reset to read mode */
|
||||
|
||||
rcode = 1;
|
||||
break;
|
||||
rcode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*addr = (FPW) INTEL_RESET; /* resest to read mode */
|
||||
break;
|
||||
}
|
||||
|
||||
*atmeladdr = (u8) 0x00F000F0; /* reset to read mode */
|
||||
} /* Atmel or Intel */
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
case 3:
|
||||
{
|
||||
u8 sec = ((ulong) addr >> 16) & 0xFF;
|
||||
|
||||
dspi_tx(ser_flash_cs, 0x00, SER_WREN);
|
||||
dspi_rx();
|
||||
status =
|
||||
serial_flash_read_status
|
||||
(ser_flash_cs);
|
||||
if (((status & 0x9C) != 0)
|
||||
&& ((status & 0x02) != 0x02)) {
|
||||
printf("Error Programming\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
dspi_tx(ser_flash_cs, 0x80,
|
||||
SER_SECT_ERASE);
|
||||
dspi_tx(ser_flash_cs, 0x80, sec);
|
||||
dspi_tx(ser_flash_cs, 0x80, 0);
|
||||
dspi_tx(ser_flash_cs, 0x00, 0);
|
||||
|
||||
dspi_rx();
|
||||
dspi_rx();
|
||||
dspi_rx();
|
||||
dspi_rx();
|
||||
|
||||
do {
|
||||
status =
|
||||
serial_flash_read_status
|
||||
(ser_flash_cs);
|
||||
|
||||
if (get_timer(start) >
|
||||
CFG_FLASH_ERASE_TOUT) {
|
||||
printf("Timeout\n");
|
||||
return 1;
|
||||
}
|
||||
} while (status & 0x01);
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
} /* switch (flashtype) */
|
||||
}
|
||||
}
|
||||
printf(" done\n");
|
||||
|
@ -583,6 +780,8 @@ int flash_erase(flash_info_t * info, int s_first, int s_last)
|
|||
|
||||
int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (info->flash_id == FLASH_UNKNOWN)
|
||||
return 4;
|
||||
|
||||
|
@ -623,7 +822,7 @@ int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
|
|||
{
|
||||
ulong cp, wp;
|
||||
u16 data;
|
||||
int count, i, l, rc, port_width;
|
||||
int i, l, rc, port_width;
|
||||
|
||||
/* get lower word aligned address */
|
||||
wp = addr;
|
||||
|
@ -724,6 +923,51 @@ int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
|
|||
|
||||
} /* case FLASH_MAN_INTEL */
|
||||
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
case FLASH_MAN_STM:
|
||||
{
|
||||
ulong wp;
|
||||
u8 *data = (u8 *) src;
|
||||
int left; /* number of bytes left to program */
|
||||
|
||||
wp = addr;
|
||||
|
||||
/* page align, each page is 256 bytes */
|
||||
if ((wp % 0x100) != 0) {
|
||||
left = (0x100 - (wp & 0xFF));
|
||||
write_ser_data(info, wp, data, left);
|
||||
cnt -= left;
|
||||
wp += left;
|
||||
data += left;
|
||||
}
|
||||
|
||||
/* page program - 256 bytes at a time */
|
||||
if (cnt > 255) {
|
||||
count = 0;
|
||||
while (cnt >= 0x100) {
|
||||
write_ser_data(info, wp, data, 0x100);
|
||||
cnt -= 0x100;
|
||||
wp += 0x100;
|
||||
data += 0x100;
|
||||
|
||||
if (count++ > 0x400) {
|
||||
spin_wheel();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* remainint bytes */
|
||||
if (cnt && (cnt < 256)) {
|
||||
write_ser_data(info, wp, data, cnt);
|
||||
wp += cnt;
|
||||
data += cnt;
|
||||
cnt -= cnt;
|
||||
}
|
||||
|
||||
printf("\b.");
|
||||
}
|
||||
#endif
|
||||
} /* switch */
|
||||
|
||||
return ERR_OK;
|
||||
|
@ -844,6 +1088,75 @@ int write_data(flash_info_t * info, ulong dest, FPW data)
|
|||
return (0);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)
|
||||
int write_ser_data(flash_info_t * info, ulong dest, uchar * data, ulong cnt)
|
||||
{
|
||||
ulong start;
|
||||
int status, i;
|
||||
u8 flashdata;
|
||||
|
||||
/* Check if Flash is (sufficiently) erased */
|
||||
dspi_tx(ser_flash_cs, 0x80, SER_READ);
|
||||
dspi_tx(ser_flash_cs, 0x80, (dest >> 16) & 0xFF);
|
||||
dspi_tx(ser_flash_cs, 0x80, (dest >> 8) & 0xFF);
|
||||
dspi_tx(ser_flash_cs, 0x80, dest & 0xFF);
|
||||
dspi_rx();
|
||||
dspi_rx();
|
||||
dspi_rx();
|
||||
dspi_rx();
|
||||
dspi_tx(ser_flash_cs, 0x80, 0);
|
||||
flashdata = dspi_rx();
|
||||
dspi_tx(ser_flash_cs, 0x00, 0);
|
||||
dspi_rx();
|
||||
|
||||
if ((flashdata & *data) != *data) {
|
||||
printf("not erased at %08lx (%lx)\n", (ulong) dest,
|
||||
(ulong) flashdata);
|
||||
return (2);
|
||||
}
|
||||
|
||||
dspi_tx(ser_flash_cs, 0x00, SER_WREN);
|
||||
dspi_rx();
|
||||
|
||||
status = serial_flash_read_status(ser_flash_cs);
|
||||
if (((status & 0x9C) != 0) && ((status & 0x02) != 0x02)) {
|
||||
printf("Error Programming\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
start = get_timer(0);
|
||||
|
||||
dspi_tx(ser_flash_cs, 0x80, SER_PAGE_PROG);
|
||||
dspi_tx(ser_flash_cs, 0x80, ((dest & 0xFF0000) >> 16));
|
||||
dspi_tx(ser_flash_cs, 0x80, ((dest & 0xFF00) >> 8));
|
||||
dspi_tx(ser_flash_cs, 0x80, (dest & 0xFF));
|
||||
dspi_rx();
|
||||
dspi_rx();
|
||||
dspi_rx();
|
||||
dspi_rx();
|
||||
|
||||
for (i = 0; i < (cnt - 1); i++) {
|
||||
dspi_tx(ser_flash_cs, 0x80, *data);
|
||||
dspi_rx();
|
||||
data++;
|
||||
}
|
||||
|
||||
dspi_tx(ser_flash_cs, 0x00, *data);
|
||||
dspi_rx();
|
||||
|
||||
do {
|
||||
status = serial_flash_read_status(ser_flash_cs);
|
||||
|
||||
if (get_timer(start) > CFG_FLASH_ERASE_TOUT) {
|
||||
printf("Timeout\n");
|
||||
return 1;
|
||||
}
|
||||
} while (status & 0x01);
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Write a word to Flash for ATMEL FLASH
|
||||
* A word is 16 bits, whichever the bus width of the flash bank
|
||||
|
|
|
@ -28,7 +28,7 @@ include $(TOPDIR)/config.mk
|
|||
LIB = lib$(CPU).a
|
||||
|
||||
START = start.o
|
||||
COBJS = cpu.o speed.o cpu_init.o interrupts.o pci.o
|
||||
COBJS = cpu.o speed.o cpu_init.o interrupts.o pci.o dspi.o
|
||||
|
||||
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
|
||||
|
|
73
cpu/mcf5445x/dspi.c
Normal file
73
cpu/mcf5445x/dspi.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
*
|
||||
* (C) Copyright 2000-2003
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* Copyright (C) 2004-2008 Freescale Semiconductor, Inc.
|
||||
* TsiChung Liew (Tsi-Chung.Liew@freescale.com)
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <spi.h>
|
||||
|
||||
#if defined(CONFIG_CF_DSPI)
|
||||
#include <asm/immap.h>
|
||||
void dspi_init(void)
|
||||
{
|
||||
volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
|
||||
volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
|
||||
|
||||
gpio->par_dspi = GPIO_PAR_DSPI_PCS5_PCS5 | GPIO_PAR_DSPI_PCS2_PCS2 |
|
||||
GPIO_PAR_DSPI_PCS1_PCS1 | GPIO_PAR_DSPI_PCS0_PCS0 |
|
||||
GPIO_PAR_DSPI_SIN_SIN | GPIO_PAR_DSPI_SOUT_SOUT |
|
||||
GPIO_PAR_DSPI_SCK_SCK;
|
||||
|
||||
dspi->dmcr = DSPI_DMCR_MSTR | DSPI_DMCR_CSIS7 | DSPI_DMCR_CSIS6 |
|
||||
DSPI_DMCR_CSIS5 | DSPI_DMCR_CSIS4 | DSPI_DMCR_CSIS3 |
|
||||
DSPI_DMCR_CSIS2 | DSPI_DMCR_CSIS1 | DSPI_DMCR_CSIS0 |
|
||||
DSPI_DMCR_CRXF | DSPI_DMCR_CTXF;
|
||||
|
||||
dspi->dctar0 = DSPI_DCTAR_TRSZ(7) | DSPI_DCTAR_CPOL | DSPI_DCTAR_CPHA |
|
||||
DSPI_DCTAR_PCSSCK_1CLK | DSPI_DCTAR_PASC(0) |
|
||||
DSPI_DCTAR_PDT(0) | DSPI_DCTAR_CSSCK(0) |
|
||||
DSPI_DCTAR_ASC(0) | DSPI_DCTAR_PBR(0) |
|
||||
DSPI_DCTAR_DT(1) | DSPI_DCTAR_BR(1);
|
||||
}
|
||||
|
||||
void dspi_tx(int chipsel, u8 attrib, u16 data)
|
||||
{
|
||||
volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
|
||||
|
||||
while ((dspi->dsr & 0x0000F000) >= 4) ;
|
||||
|
||||
dspi->dtfr = (attrib << 24) | ((1 << chipsel) << 16) | data;
|
||||
}
|
||||
|
||||
u16 dspi_rx(void)
|
||||
{
|
||||
volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
|
||||
|
||||
while ((dspi->dsr & 0x000000F0) == 0) ;
|
||||
|
||||
return (dspi->drfr & 0xFFFF);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HARD_SPI */
|
|
@ -64,10 +64,15 @@ typedef struct dspi {
|
|||
#define DSPI_DMCR_CTXF (0x00000800)
|
||||
#define DSPI_DMCR_DRXF (0x00001000)
|
||||
#define DSPI_DMCR_DTXF (0x00002000)
|
||||
#define DSPI_DMCR_MDIS (0x00004000)
|
||||
#define DSPI_DMCR_CSIS0 (0x00010000)
|
||||
#define DSPI_DMCR_CSIS1 (0x00020000)
|
||||
#define DSPI_DMCR_CSIS2 (0x00040000)
|
||||
#define DSPI_DMCR_CSIS3 (0x00080000)
|
||||
#define DSPI_DMCR_CSIS4 (0x00100000)
|
||||
#define DSPI_DMCR_CSIS5 (0x00200000)
|
||||
#define DSPI_DMCR_CSIS6 (0x00400000)
|
||||
#define DSPI_DMCR_CSIS7 (0x00800000)
|
||||
#define DSPI_DMCR_ROOE (0x01000000)
|
||||
#define DSPI_DMCR_PCSSE (0x02000000)
|
||||
#define DSPI_DMCR_MTFE (0x04000000)
|
||||
|
@ -92,6 +97,7 @@ typedef struct dspi {
|
|||
#define DSPI_DCTAR_CPHA (0x02000000)
|
||||
#define DSPI_DCTAR_CPOL (0x04000000)
|
||||
#define DSPI_DCTAR_TRSZ(x) (((x)&0x0000000F)<<27)
|
||||
#define DSPI_DCTAR_DBR (0x80000000)
|
||||
#define DSPI_DCTAR_PCSSCK_1CLK (0x00000000)
|
||||
#define DSPI_DCTAR_PCSSCK_3CLK (0x00400000)
|
||||
#define DSPI_DCTAR_PCSSCK_5CLK (0x00800000)
|
||||
|
@ -153,4 +159,8 @@ typedef struct dspi {
|
|||
/* Bit definitions and macros for DRFDR group */
|
||||
#define DSPI_DRFDR_RXDATA(x) (((x)&0x0000FFFF))
|
||||
|
||||
void dspi_init(void);
|
||||
void dspi_tx(int chipsel, u8 attrib, u16 data);
|
||||
u16 dspi_rx(void);
|
||||
|
||||
#endif /* __DSPI_H__ */
|
||||
|
|
|
@ -171,6 +171,10 @@
|
|||
#define CFG_I2C_OFFSET 0x58000
|
||||
#define CFG_IMMR CFG_MBAR
|
||||
|
||||
/* DSPI and Serial Flash */
|
||||
#define CONFIG_CF_DSPI
|
||||
#define CONFIG_SERIAL_FLASH
|
||||
|
||||
/* PCI */
|
||||
#ifdef CONFIG_CMD_PCI
|
||||
#define CONFIG_PCI 1
|
||||
|
@ -309,7 +313,7 @@
|
|||
|
||||
#else
|
||||
|
||||
# define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
|
||||
# define CFG_MAX_FLASH_BANKS 3 /* max number of memory banks */
|
||||
|
||||
# define CFG_ATMEL_REGION 4
|
||||
# define CFG_ATMEL_TOTALSECT 11
|
||||
|
@ -326,6 +330,28 @@
|
|||
# define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */
|
||||
# define CFG_FLASH_CHECKSUM
|
||||
|
||||
#ifdef CONFIG_SERIAL_FLASH
|
||||
# define CFG_FLASH2_BASE 0x01000000
|
||||
# define CFG_STM_SECT 32
|
||||
# define CFG_STM_SECTSZ 0x10000
|
||||
|
||||
# undef CFG_FLASH_ERASE_TOUT
|
||||
# define CFG_FLASH_ERASE_TOUT 20000
|
||||
|
||||
# define SER_WREN 0x06
|
||||
# define SER_WRDI 0x04
|
||||
# define SER_RDID 0x9F
|
||||
# define SER_RDSR 0x05
|
||||
# define SER_WRSR 0x01
|
||||
# define SER_READ 0x03
|
||||
# define SER_F_READ 0x0B
|
||||
# define SER_PAGE_PROG 0x02
|
||||
# define SER_SECT_ERASE 0xD8
|
||||
# define SER_BULK_ERASE 0xC7
|
||||
# define SER_DEEP_PWRDN 0xB9
|
||||
# define SER_RES 0xAB
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue