[U-Boot-Users] [PATCH] ColdFire: Add dspi and serial flash support for MCF5445x

Tsi-Chung Liew Tsi-Chung.Liew at freescale.com
Tue Mar 25 21:48:32 CET 2008


Signed-off-by: TsiChung Liew <Tsi-Chung.Liew at freescale.com>
---
 board/freescale/m54455evb/flash.c |  449 +++++++++++++++++++++++++++++++------
 cpu/mcf5445x/Makefile             |    2 +-
 cpu/mcf5445x/dspi.c               |   73 ++++++
 include/asm-m68k/coldfire/dspi.h  |   10 +
 include/configs/M54455EVB.h       |   28 +++-
 5 files changed, 492 insertions(+), 70 deletions(-)
 create mode 100644 cpu/mcf5445x/dspi.c

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 at denx.de.
+ *
+ * Copyright (C) 2004-2008 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew at 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 f5edddf..a3c71e3 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
 
 /*
-- 
1.5.4.1





More information about the U-Boot mailing list