ColdFire: Add dspi and serial flash support for MCF5445x
authorTsiChung Liew <Tsi-Chung.Liew@freescale.com>
Tue, 25 Mar 2008 20:41:15 +0000 (15:41 -0500)
committerJohn Rigby <jrigby@freescale.com>
Mon, 31 Mar 2008 21:10:29 +0000 (15:10 -0600)
Signed-off-by: TsiChung Liew <Tsi-Chung.Liew@freescale.com>
Acked-by: John Rigby <jrigby@freescale.com>
board/freescale/m54455evb/flash.c
cpu/mcf5445x/Makefile
cpu/mcf5445x/dspi.c [new file with mode: 0644]
include/asm-m68k/coldfire/dspi.h
include/configs/M54455EVB.h

index de2cca8..6b50e8d 100644 (file)
@@ -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
index 26ec298..a549fdd 100644 (file)
@@ -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 (file)
index 0000000..44d8505
--- /dev/null
@@ -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 */
index 3c579d3..8327e1b 100644 (file)
@@ -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__ */
index 5f55761..f33ccb0 100644 (file)
 #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
 
 #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
 #      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
 
 /*