summaryrefslogtreecommitdiff
path: root/board/freescale
diff options
context:
space:
mode:
authorWolfgang Denk <wd@denx.de>2008-04-08 00:10:17 +0200
committerWolfgang Denk <wd@denx.de>2008-04-08 00:10:17 +0200
commit2c78febd114b716714e7ac83c17bac5e30066512 (patch)
tree2fc53ae7781aca121aefa5e21796eee0c94f5611 /board/freescale
parent34e6cb8d1d9dc8194b2d8cad1cc39273ac58f8d8 (diff)
parent9b46432fc65ce0f0826b32e4f15c15b33ccb8d42 (diff)
Merge branch 'master' of git://www.denx.de/git/u-boot-coldfire
Diffstat (limited to 'board/freescale')
-rw-r--r--board/freescale/m5275evb/Makefile40
-rw-r--r--board/freescale/m5275evb/config.mk25
-rw-r--r--board/freescale/m5275evb/m5275evb.c112
-rw-r--r--board/freescale/m5275evb/mii.c319
-rw-r--r--board/freescale/m5275evb/u-boot.lds141
-rw-r--r--board/freescale/m54455evb/flash.c449
-rw-r--r--board/freescale/m547xevb/m547xevb.c3
7 files changed, 1021 insertions, 68 deletions
diff --git a/board/freescale/m5275evb/Makefile b/board/freescale/m5275evb/Makefile
new file mode 100644
index 0000000000..9a0fa80538
--- /dev/null
+++ b/board/freescale/m5275evb/Makefile
@@ -0,0 +1,40 @@
+#
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB = lib$(BOARD).a
+
+OBJS = $(BOARD).o mii.o
+
+$(LIB): .depend $(OBJS)
+ $(AR) crv $@ $(OBJS)
+
+#########################################################################
+
+.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/board/freescale/m5275evb/config.mk b/board/freescale/m5275evb/config.mk
new file mode 100644
index 0000000000..ccb2cf735d
--- /dev/null
+++ b/board/freescale/m5275evb/config.mk
@@ -0,0 +1,25 @@
+#
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+# Coldfire contribution by Bernhard Kuhn <bkuhn@metrowerks.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
+#
+
+TEXT_BASE = 0xffe00000
diff --git a/board/freescale/m5275evb/m5275evb.c b/board/freescale/m5275evb/m5275evb.c
new file mode 100644
index 0000000000..a1b2902935
--- /dev/null
+++ b/board/freescale/m5275evb/m5275evb.c
@@ -0,0 +1,112 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 2005-2008 Arthur Shipkowski (art@videon-central.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 <asm/immap.h>
+
+#define PERIOD 13 /* system bus period in ns */
+#define SDRAM_TREFI 7800 /* in ns */
+
+int checkboard(void)
+{
+ puts("Board: ");
+ puts("Freescale MCF5275 EVB\n");
+ return 0;
+};
+
+long int initdram(int board_type)
+{
+ volatile sdramctrl_t *sdp = (sdramctrl_t *)(MMAP_SDRAM);
+ volatile gpio_t *gpio_reg = (gpio_t *)(MMAP_GPIO);
+
+ gpio_reg->par_sdram = 0x3FF; /* Enable SDRAM */
+
+ /* Set up chip select */
+ sdp->sdbar0 = CFG_SDRAM_BASE;
+ sdp->sdbmr0 = MCF_SDRAMC_SDMRn_BAM_32M | MCF_SDRAMC_SDMRn_V;
+
+ /* Set up timing */
+ sdp->sdcfg1 = 0x83711630;
+ sdp->sdcfg2 = 0x46770000;
+
+ /* Enable clock */
+ sdp->sdcr = MCF_SDRAMC_SDCR_MODE_EN | MCF_SDRAMC_SDCR_CKE;
+
+ /* Set precharge */
+ sdp->sdcr |= MCF_SDRAMC_SDCR_IPALL;
+
+ /* Dummy write to start SDRAM */
+ *((volatile unsigned long *)CFG_SDRAM_BASE) = 0xa5a59696;
+
+ /* Send LEMR */
+ sdp->sdmr = MCF_SDRAMC_SDMR_BNKAD_LEMR
+ | MCF_SDRAMC_SDMR_AD(0x0)
+ | MCF_SDRAMC_SDMR_CMD;
+ *((volatile unsigned long *)CFG_SDRAM_BASE) = 0xa5a59696;
+
+ /* Send LMR */
+ sdp->sdmr = 0x058d0000;
+ *((volatile unsigned long *)CFG_SDRAM_BASE) = 0xa5a59696;
+
+ /* Stop sending commands */
+ sdp->sdmr &= ~(MCF_SDRAMC_SDMR_CMD);
+
+ /* Set precharge */
+ sdp->sdcr |= MCF_SDRAMC_SDCR_IPALL;
+ *((volatile unsigned long *)CFG_SDRAM_BASE) = 0xa5a59696;
+
+ /* Stop manual precharge, send 2 IREF */
+ sdp->sdcr &= ~(MCF_SDRAMC_SDCR_IPALL);
+ sdp->sdcr |= MCF_SDRAMC_SDCR_IREF;
+ *((volatile unsigned long *)CFG_SDRAM_BASE) = 0xa5a59696;
+ *((volatile unsigned long *)CFG_SDRAM_BASE) = 0xa5a59696;
+
+ /* Write mode register, clear reset DLL */
+ sdp->sdmr = 0x018d0000;
+ *((volatile unsigned long *)CFG_SDRAM_BASE) = 0xa5a59696;
+
+ /* Stop sending commands */
+ sdp->sdmr &= ~(MCF_SDRAMC_SDMR_CMD);
+ sdp->sdcr &= ~(MCF_SDRAMC_SDCR_MODE_EN);
+
+ /* Turn on auto refresh, lock SDMR */
+ sdp->sdcr =
+ MCF_SDRAMC_SDCR_CKE
+ | MCF_SDRAMC_SDCR_REF
+ | MCF_SDRAMC_SDCR_MUX(1)
+ /* 1 added to round up */
+ | MCF_SDRAMC_SDCR_RCNT((SDRAM_TREFI/(PERIOD*64)) - 1 + 1)
+ | MCF_SDRAMC_SDCR_DQS_OE(0x3);
+
+ return CFG_SDRAM_SIZE * 1024 * 1024;
+};
+
+int testdram(void)
+{
+ /* TODO: XXX XXX XXX */
+ printf("DRAM test not implemented!\n");
+
+ return (0);
+}
diff --git a/board/freescale/m5275evb/mii.c b/board/freescale/m5275evb/mii.c
new file mode 100644
index 0000000000..bbc93f6d48
--- /dev/null
+++ b/board/freescale/m5275evb/mii.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2004-2007 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 <asm/fec.h>
+#include <asm/immap.h>
+
+#include <config.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI)
+#undef MII_DEBUG
+#undef ET_DEBUG
+
+int fecpin_setclear(struct eth_device *dev, int setclear)
+{
+ struct fec_info_s *info = (struct fec_info_s *) dev->priv;
+ volatile gpio_t *gpio = (gpio_t *)MMAP_GPIO;
+
+ if (setclear) {
+ /* Enable Ethernet pins */
+ if (info->iobase == CFG_FEC0_IOBASE) {
+ gpio->par_feci2c |= 0x0F00;
+ gpio->par_fec0hl |= 0xC0;
+ } else {
+ gpio->par_feci2c |= 0x00A0;
+ gpio->par_fec1hl |= 0xC0;
+ }
+ } else {
+ if (info->iobase == CFG_FEC0_IOBASE) {
+ gpio->par_feci2c &= ~0x0F00;
+ gpio->par_fec0hl &= ~0xC0;
+ } else {
+ gpio->par_feci2c &= ~0x00A0;
+ gpio->par_fec1hl &= ~0xC0;
+ }
+ }
+
+ return 0;
+}
+
+#if defined(CFG_DISCOVER_PHY) || defined(CONFIG_CMD_MII)
+#include <miiphy.h>
+
+/* Make MII read/write commands for the FEC. */
+#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | (REG & 0x1f) << 18))
+
+#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | (REG & 0x1f) << 18) | (VAL & 0xffff))
+
+/* PHY identification */
+#define PHY_ID_LXT970 0x78100000 /* LXT970 */
+#define PHY_ID_LXT971 0x001378e0 /* LXT971 and 972 */
+#define PHY_ID_82555 0x02a80150 /* Intel 82555 */
+#define PHY_ID_QS6612 0x01814400 /* QS6612 */
+#define PHY_ID_AMD79C784 0x00225610 /* AMD 79C784 */
+#define PHY_ID_LSI80225 0x0016f870 /* LSI 80225 */
+#define PHY_ID_LSI80225B 0x0016f880 /* LSI 80225/B */
+#define PHY_ID_DP83848VV 0x20005C90 /* National 83848 */
+#define PHY_ID_DP83849 0x20005CA2 /* National 82849 */
+#define PHY_ID_KS8721BL 0x00221619 /* Micrel KS8721BL/SL */
+
+#define STR_ID_LXT970 "LXT970"
+#define STR_ID_LXT971 "LXT971"
+#define STR_ID_82555 "Intel82555"
+#define STR_ID_QS6612 "QS6612"
+#define STR_ID_AMD79C784 "AMD79C784"
+#define STR_ID_LSI80225 "LSI80225"
+#define STR_ID_LSI80225B "LSI80225/B"
+#define STR_ID_DP83848VV "N83848"
+#define STR_ID_DP83849 "N83849"
+#define STR_ID_KS8721BL "KS8721BL"
+
+/****************************************************************************
+ * mii_init -- Initialize the MII for MII command without ethernet
+ * This function is a subset of eth_init
+ ****************************************************************************
+ */
+void mii_reset(struct fec_info_s *info)
+{
+ volatile fec_t *fecp = (fec_t *) (info->miibase);
+ int i;
+
+ fecp->ecr = FEC_ECR_RESET;
+ for (i = 0; (fecp->ecr & FEC_ECR_RESET) && (i < FEC_RESET_DELAY); ++i) {
+ udelay(1);
+ }
+ if (i == FEC_RESET_DELAY) {
+ printf("FEC_RESET_DELAY timeout\n");
+ }
+}
+
+/* send command to phy using mii, wait for result */
+uint mii_send(uint mii_cmd)
+{
+ struct fec_info_s *info;
+ struct eth_device *dev;
+ volatile fec_t *ep;
+ uint mii_reply;
+ int j = 0;
+
+ /* retrieve from register structure */
+ dev = eth_get_dev();
+ info = dev->priv;
+
+ ep = (fec_t *) info->miibase;
+
+ ep->mmfr = mii_cmd; /* command to phy */
+
+ /* wait for mii complete */
+ while (!(ep->eir & FEC_EIR_MII) && (j < MCFFEC_TOUT_LOOP)) {
+ udelay(1);
+ j++;
+ }
+ if (j >= MCFFEC_TOUT_LOOP) {
+ printf("MII not complete\n");
+ return -1;
+ }
+
+ mii_reply = ep->mmfr; /* result from phy */
+ ep->eir = FEC_EIR_MII; /* clear MII complete */
+#ifdef ET_DEBUG
+ printf("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n",
+ __FILE__, __LINE__, __FUNCTION__, mii_cmd, mii_reply);
+#endif
+
+ return (mii_reply & 0xffff); /* data read from phy */
+}
+#endif /* CFG_DISCOVER_PHY || (CONFIG_COMMANDS & CONFIG_CMD_MII) */
+
+#if defined(CFG_DISCOVER_PHY)
+int mii_discover_phy(struct eth_device *dev)
+{
+#define MAX_PHY_PASSES 11
+ struct fec_info_s *info = dev->priv;
+ int phyaddr, pass;
+ uint phyno, phytype;
+
+ if (info->phyname_init)
+ return info->phy_addr;
+
+ phyaddr = -1; /* didn't find a PHY yet */
+ for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) {
+ if (pass > 1) {
+ /* PHY may need more time to recover from reset.
+ * The LXT970 needs 50ms typical, no maximum is
+ * specified, so wait 10ms before try again.
+ * With 11 passes this gives it 100ms to wake up.
+ */
+ udelay(10000); /* wait 10ms */
+ }
+
+ for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) {
+
+ phytype = mii_send(mk_mii_read(phyno, PHY_PHYIDR1));
+#ifdef ET_DEBUG
+ printf("PHY type 0x%x pass %d type\n", phytype, pass);
+#endif
+ if (phytype != 0xffff) {
+ phyaddr = phyno;
+ phytype <<= 16;
+ phytype |=
+ mii_send(mk_mii_read(phyno, PHY_PHYIDR2));
+
+ switch (phytype & 0xffffffff) {
+ case PHY_ID_KS8721BL:
+ strcpy(info->phy_name,
+ STR_ID_KS8721BL);
+ info->phyname_init = 1;
+ break;
+ default:
+ strcpy(info->phy_name, "unknown");
+ info->phyname_init = 1;
+ break;
+ }
+
+#ifdef ET_DEBUG
+ printf("PHY @ 0x%x pass %d type ", phyno, pass);
+ switch (phytype & 0xffffffff) {
+ case PHY_ID_KS8721BL:
+ printf(STR_ID_KS8721BL);
+ break;
+ default:
+ printf("0x%08x\n", phytype);
+ break;
+ }
+#endif
+ }
+ }
+ }
+ if (phyaddr < 0)
+ printf("No PHY device found.\n");
+
+ return phyaddr;
+}
+#endif /* CFG_DISCOVER_PHY */
+
+void mii_init(void) __attribute__((weak,alias("__mii_init")));
+
+void __mii_init(void)
+{
+ volatile fec_t *fecp;
+ struct fec_info_s *info;
+ struct eth_device *dev;
+ int miispd = 0, i = 0;
+ u16 autoneg = 0;
+
+ /* retrieve from register structure */
+ dev = eth_get_dev();
+ info = dev->priv;
+
+ fecp = (fec_t *) info->miibase;
+
+ fecpin_setclear(dev, 1);
+
+ mii_reset(info);
+
+ /* We use strictly polling mode only */
+ fecp->eimr = 0;
+
+ /* Clear any pending interrupt */
+ fecp->eir = 0xffffffff;
+
+ /* Set MII speed */
+ miispd = (gd->bus_clk / 1000000) / 5;
+ fecp->mscr = miispd << 1;
+
+ info->phy_addr = mii_discover_phy(dev);
+
+#define AUTONEGLINK (PHY_BMSR_AUTN_COMP | PHY_BMSR_LS)
+ while (i < MCFFEC_TOUT_LOOP) {
+ autoneg = 0;
+ miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &autoneg);
+ i++;
+
+ if ((autoneg & AUTONEGLINK) == AUTONEGLINK)
+ break;
+
+ udelay(500);
+ }
+ if (i >= MCFFEC_TOUT_LOOP) {
+ printf("Auto Negotiation not complete\n");
+ }
+
+ /* adapt to the half/full speed settings */
+ info->dup_spd = miiphy_duplex(dev->name, info->phy_addr) << 16;
+ info->dup_spd |= miiphy_speed(dev->name, info->phy_addr);
+}
+
+/*****************************************************************************
+ * Read and write a MII PHY register, routines used by MII Utilities
+ *
+ * FIXME: These routines are expected to return 0 on success, but mii_send
+ * does _not_ return an error code. Maybe 0xFFFF means error, i.e.
+ * no PHY connected...
+ * For now always return 0.
+ * FIXME: These routines only work after calling eth_init() at least once!
+ * Otherwise they hang in mii_send() !!! Sorry!
+ *****************************************************************************/
+
+int mcffec_miiphy_read(char *devname, unsigned char addr, unsigned char reg,
+ unsigned short *value)
+{
+ short rdreg; /* register working value */
+
+#ifdef MII_DEBUG
+ printf("miiphy_read(0x%x) @ 0x%x = ", reg, addr);
+#endif
+ rdreg = mii_send(mk_mii_read(addr, reg));
+
+ *value = rdreg;
+
+#ifdef MII_DEBUG
+ printf("0x%04x\n", *value);
+#endif
+
+ return 0;
+}
+
+int mcffec_miiphy_write(char *devname, unsigned char addr, unsigned char reg,
+ unsigned short value)
+{
+ short rdreg; /* register working value */
+
+#ifdef MII_DEBUG
+ printf("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
+#endif
+
+ rdreg = mii_send(mk_mii_write(addr, reg, value));
+
+#ifdef MII_DEBUG
+ printf("0x%04x\n", value);
+#endif
+
+ return 0;
+}
+
+#endif /* CONFIG_CMD_NET, FEC_ENET & NET_MULTI */
diff --git a/board/freescale/m5275evb/u-boot.lds b/board/freescale/m5275evb/u-boot.lds
new file mode 100644
index 0000000000..43d65001b3
--- /dev/null
+++ b/board/freescale/m5275evb/u-boot.lds
@@ -0,0 +1,141 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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
+ */
+
+OUTPUT_ARCH(m68k)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+ cpu/mcf52x2/start.o (.text)
+ common/dlmalloc.o (.text)
+ lib_generic/string.o (.text)
+ lib_generic/zlib.o (.text)
+
+ . = DEFINED(env_offset) ? env_offset : .;
+ common/environment.o(.text)
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ __got_start = .;
+ *(.got)
+ __got_end = .;
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ _sbss = .;
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/board/freescale/m54455evb/flash.c b/board/freescale/m54455evb/flash.c
index de2cca863a..6b50e8d829 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/board/freescale/m547xevb/m547xevb.c b/board/freescale/m547xevb/m547xevb.c
index 0286084a8e..539da78de9 100644
--- a/board/freescale/m547xevb/m547xevb.c
+++ b/board/freescale/m547xevb/m547xevb.c
@@ -43,6 +43,9 @@ long int initdram(int board_type)
volatile siu_t *siu = (siu_t *) (MMAP_SIU);
volatile sdram_t *sdram = (volatile sdram_t *)(MMAP_SDRAM);
u32 dramsize, i;
+#ifdef CFG_DRAMSZ1
+ u32 temp;
+#endif
siu->drv = CFG_SDRAM_DRVSTRENGTH;