summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTsiChung Liew <Tsi-Chung.Liew@freescale.com>2008-03-25 15:41:15 -0500
committerJohn Rigby <jrigby@freescale.com>2008-03-31 15:10:29 -0600
commitbae61eefe15b4d454060a7140e49ae58322be803 (patch)
treeb475fc5b8a9b754da1ac7eabae3ca66630b65c3e
parent48ead7a7a922fceaf494e352abfab8216a41b417 (diff)
downloadu-boot-imx-bae61eefe15b4d454060a7140e49ae58322be803.zip
u-boot-imx-bae61eefe15b4d454060a7140e49ae58322be803.tar.gz
u-boot-imx-bae61eefe15b4d454060a7140e49ae58322be803.tar.bz2
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>
-rw-r--r--board/freescale/m54455evb/flash.c449
-rw-r--r--cpu/mcf5445x/Makefile2
-rw-r--r--cpu/mcf5445x/dspi.c73
-rw-r--r--include/asm-m68k/coldfire/dspi.h10
-rw-r--r--include/configs/M54455EVB.h28
5 files changed, 492 insertions, 70 deletions
diff --git a/board/freescale/m54455evb/flash.c b/board/freescale/m54455evb/flash.c
index de2cca8..6b50e8d 100644
--- a/board/freescale/m54455evb/flash.c
+++ b/board/freescale/m54455evb/flash.c
@@ -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;
-
- /* start erase block */
- *addr = (FPW) INTEL_CLEAR; /* clear status register */
- *addr = (FPW) INTEL_ERASE; /* erase setup */
- *addr = (FPW) INTEL_CONFIRM; /* erase confirm */
-
- while ((*addr & (FPW) INTEL_FINISHED) !=
- (FPW) INTEL_FINISHED) {
-
- 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 */
-
- rcode = 1;
- break;
+ switch (flashtype) {
+ case 1:
+ {
+ FPWV *base; /* first address in bank */
+ FPWV *atmeladdr;
+
+ flag = disable_interrupts();
+
+ atmeladdr = (FPWV *) addr; /* concatenate to 8 bit */
+ base = (FPWV *) (CFG_ATMEL_BASE); /* First sector */
+
+ 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 (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;
+ }
}
- }
-
- *addr = (FPW) INTEL_RESET; /* resest to read mode */
- } else {
- FPWV *base; /* first address in bank */
- FPWV *atmeladdr;
-
- flag = disable_interrupts();
- atmeladdr = (FPWV *) addr; /* concatenate to 8 bit */
- base = (FPWV *) (CFG_ATMEL_BASE); /* First sector */
-
- 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 */
+ *atmeladdr = (u8) 0x00F000F0; /* reset to read mode */
+ break;
+ }
- if (flag)
- enable_interrupts();
+ case 2:
+ {
+ *addr = (FPW) INTEL_READID;
+ min = addr[INTEL_CFI_TERB] & 0xff;
+ min = 1 << min; /* ms */
+ min = (min / info->sector_count) * 1000;
+
+ /* start erase block */
+ *addr = (FPW) INTEL_CLEAR; /* clear status register */
+ *addr = (FPW) INTEL_ERASE; /* erase setup */
+ *addr = (FPW) INTEL_CONFIRM; /* erase confirm */
+
+ while ((*addr & (FPW) INTEL_FINISHED) !=
+ (FPW) INTEL_FINISHED) {
+
+ 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 */
+
+ rcode = 1;
+ break;
+ }
+ }
- while ((*atmeladdr & (u8) 0x00800080) !=
- (u8) 0x00800080) {
- if (get_timer(start) >
- CFG_FLASH_ERASE_TOUT) {
- printf("Timeout\n");
- *atmeladdr = (u8) 0x00F000F0; /* reset to read mode */
+ *addr = (FPW) INTEL_RESET; /* resest to read mode */
+ break;
+ }
- rcode = 1;
- break;
+#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;
}
- }
- *atmeladdr = (u8) 0x00F000F0; /* reset to read mode */
- } /* Atmel or Intel */
+ 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
diff --git a/cpu/mcf5445x/Makefile b/cpu/mcf5445x/Makefile
index 26ec298..a549fdd 100644
--- a/cpu/mcf5445x/Makefile
+++ b/cpu/mcf5445x/Makefile
@@ -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))
diff --git a/cpu/mcf5445x/dspi.c b/cpu/mcf5445x/dspi.c
new file mode 100644
index 0000000..44d8505
--- /dev/null
+++ b/cpu/mcf5445x/dspi.c
@@ -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 */
diff --git a/include/asm-m68k/coldfire/dspi.h b/include/asm-m68k/coldfire/dspi.h
index 3c579d3..8327e1b 100644
--- a/include/asm-m68k/coldfire/dspi.h
+++ b/include/asm-m68k/coldfire/dspi.h
@@ -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__ */
diff --git a/include/configs/M54455EVB.h b/include/configs/M54455EVB.h
index 5f55761..f33ccb0 100644
--- a/include/configs/M54455EVB.h
+++ b/include/configs/M54455EVB.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
/*