diff options
author | TsiChungLiew <Tsi-Chung.Liew@freescale.com> | 2007-08-15 20:32:06 -0500 |
---|---|---|
committer | John Rigby <jrigby@freescale.com> | 2007-08-16 17:43:20 -0600 |
commit | f28e1bd9daa6de5eb33ae4822bda6b008ccb4e9e (patch) | |
tree | 1cddf80f261eb34e934d4a647264b7d0a27d2bbf /board | |
parent | 870470dbf6f4bb9864e0d97aeedbc17c167c6d1c (diff) | |
download | u-boot-f28e1bd9daa6de5eb33ae4822bda6b008ccb4e9e.tar.gz u-boot-f28e1bd9daa6de5eb33ae4822bda6b008ccb4e9e.tar.xz u-boot-f28e1bd9daa6de5eb33ae4822bda6b008ccb4e9e.zip |
ColdFire: Update Freescale MCF52x2 platforms
Signed-off-by: TsiChungLiew <Tsi-Chung.Liew@freescale.com>
Diffstat (limited to 'board')
-rw-r--r-- | board/m5271evb/Makefile | 2 | ||||
-rw-r--r-- | board/m5271evb/m5271evb.c | 3 | ||||
-rw-r--r-- | board/m5271evb/mii.c | 303 | ||||
-rw-r--r-- | board/m5272c3/Makefile | 2 | ||||
-rw-r--r-- | board/m5272c3/m5272c3.c | 7 | ||||
-rw-r--r-- | board/m5272c3/mii.c | 303 | ||||
-rw-r--r-- | board/m5282evb/Makefile | 2 | ||||
-rw-r--r-- | board/m5282evb/config.mk | 2 | ||||
-rw-r--r-- | board/m5282evb/flash.c | 378 | ||||
-rw-r--r-- | board/m5282evb/m5282evb.c | 61 | ||||
-rw-r--r-- | board/m5282evb/mii.c | 304 |
11 files changed, 977 insertions, 390 deletions
diff --git a/board/m5271evb/Makefile b/board/m5271evb/Makefile index 424ab1cf9e..2ec71ee1d2 100644 --- a/board/m5271evb/Makefile +++ b/board/m5271evb/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a -COBJS = $(BOARD).o +COBJS = $(BOARD).o mii.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/m5271evb/m5271evb.c b/board/m5271evb/m5271evb.c index c26c91d1b7..9caad6325a 100644 --- a/board/m5271evb/m5271evb.c +++ b/board/m5271evb/m5271evb.c @@ -22,8 +22,7 @@ */ #include <common.h> -#include <asm/m5271.h> -#include <asm/immap_5271.h> +#include <asm/immap.h> int checkboard (void) { puts ("Board: Freescale M5271EVB\n"); diff --git a/board/m5271evb/mii.c b/board/m5271evb/mii.c new file mode 100644 index 0000000000..f6c63c302b --- /dev/null +++ b/board/m5271evb/mii.c @@ -0,0 +1,303 @@ +/* + * 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) +{ + if (setclear) { + /* Enable Ethernet pins */ + mbar_writeByte(MCF_GPIO_PAR_FECI2C, CFG_FECI2C); + } else { + } + + 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 */ + +int 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/m5272c3/Makefile b/board/m5272c3/Makefile index cf07cf40fd..be704b76f0 100644 --- a/board/m5272c3/Makefile +++ b/board/m5272c3/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a -COBJS = $(BOARD).o flash.o +COBJS = $(BOARD).o flash.o mii.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/m5272c3/m5272c3.c b/board/m5272c3/m5272c3.c index 0dfeaf24f5..6dcda4f254 100644 --- a/board/m5272c3/m5272c3.c +++ b/board/m5272c3/m5272c3.c @@ -22,18 +22,17 @@ */ #include <common.h> -#include <asm/m5272.h> -#include <asm/immap_5272.h> +#include <asm/immap.h> int checkboard (void) { puts ("Board: "); - puts("MOTOROLA MCF5272C3 EVB\n"); + puts ("Freescale MCF5272C3 EVB\n"); return 0; }; long int initdram (int board_type) { - volatile sdramctrl_t * sdp = (sdramctrl_t *)(CFG_MBAR + MCFSIM_SDCR); + volatile sdramctrl_t * sdp = (sdramctrl_t *)(MMAP_SDRAM); sdp->sdram_sdtr = 0xf539; sdp->sdram_sdcr = 0x4211; diff --git a/board/m5272c3/mii.c b/board/m5272c3/mii.c new file mode 100644 index 0000000000..fadcbb3ef8 --- /dev/null +++ b/board/m5272c3/mii.c @@ -0,0 +1,303 @@ +/* + * 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) +{ + volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO; + + if (setclear) { + gpio->gpio_pbcnt |= GPIO_PBCNT_E_MDC | GPIO_PBCNT_E_RXER | GPIO_PBCNT_E_RXD1 | GPIO_PBCNT_E_RXD2 | GPIO_PBCNT_E_RXD3 | GPIO_PBCNT_E_TXD1 | GPIO_PBCNT_E_TXD2 | GPIO_PBCNT_E_TXD3; + } else { + } + 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_AMD79C874VC 0x0022561B /* AMD 79C874 */ +#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 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_AMD79C874VC "AMD79C874VC" +#define STR_ID_LSI80225 "LSI80225" +#define STR_ID_LSI80225B "LSI80225/B" +#define STR_ID_DP83848VV "N83848" +#define STR_ID_DP83849 "N83849" + +/**************************************************************************** + * 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_AMD79C874VC: + strcpy(info->phy_name, + STR_ID_AMD79C874VC); + 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_AMD79C874VC: + printf(STR_ID_AMD79C874VC); + break; + default: + printf("0x%08x\n", phytype); + break; + } +#endif + } + } + } + if (phyaddr < 0) + printf("No PHY device found.\n"); + + return phyaddr; +} +#endif /* CFG_DISCOVER_PHY */ + +int 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/m5282evb/Makefile b/board/m5282evb/Makefile index cf07cf40fd..2ec71ee1d2 100644 --- a/board/m5282evb/Makefile +++ b/board/m5282evb/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a -COBJS = $(BOARD).o flash.o +COBJS = $(BOARD).o mii.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/m5282evb/config.mk b/board/m5282evb/config.mk index 848430736b..0aa236122f 100644 --- a/board/m5282evb/config.mk +++ b/board/m5282evb/config.mk @@ -22,4 +22,4 @@ # MA 02111-1307 USA # -TEXT_BASE = 0x20000 +TEXT_BASE = 0xFFE00000 diff --git a/board/m5282evb/flash.c b/board/m5282evb/flash.c deleted file mode 100644 index 36a7c310f9..0000000000 --- a/board/m5282evb/flash.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * (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 <common.h> - -#define PHYS_FLASH_1 CFG_FLASH_BASE -#define FLASH_BANK_SIZE 0x200000 - -flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; - -void flash_print_info (flash_info_t * info) -{ - int i; - - switch (info->flash_id & FLASH_VENDMASK) { - case (AMD_MANUFACT & FLASH_VENDMASK): - printf ("AMD: "); - break; - default: - printf ("Unknown Vendor "); - break; - } - - switch (info->flash_id & FLASH_TYPEMASK) { - case (AMD_ID_PL160CB & FLASH_TYPEMASK): - printf ("AM29PL160CB (16Mbit)\n"); - break; - default: - printf ("Unknown Chip Type\n"); - goto Done; - break; - } - - printf (" Size: %ld MB in %d Sectors\n", - info->size >> 20, info->sector_count); - - printf (" Sector Start Addresses:"); - for (i = 0; i < info->sector_count; i++) { - if ((i % 5) == 0) { - printf ("\n "); - } - printf (" %08lX%s", info->start[i], - info->protect[i] ? " (RO)" : " "); - } - printf ("\n"); - - Done: - return; -} - - -unsigned long flash_init (void) -{ - int i, j; - ulong size = 0; - - for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { - ulong flashbase = 0; - - flash_info[i].flash_id = - (AMD_MANUFACT & FLASH_VENDMASK) | - (AMD_ID_PL160CB & FLASH_TYPEMASK); - flash_info[i].size = FLASH_BANK_SIZE; - flash_info[i].sector_count = CFG_MAX_FLASH_SECT; - memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); - if (i == 0) - flashbase = PHYS_FLASH_1; - else - panic ("configured to many flash banks!\n"); - - for (j = 0; j < flash_info[i].sector_count; j++) { - if (j == 0) { - /* 1st is 16 KiB */ - flash_info[i].start[j] = flashbase; - } - if ((j >= 1) && (j <= 2)) { - /* 2nd and 3rd are 8 KiB */ - flash_info[i].start[j] = - flashbase + 0x4000 + 0x2000 * (j - 1); - } - if (j == 3) { - /* 4th is 32 KiB */ - flash_info[i].start[j] = flashbase + 0x8000; - } - if ((j >= 4) && (j <= 34)) { - /* rest is 256 KiB */ - flash_info[i].start[j] = - flashbase + 0x10000 + 0x10000 * (j - - 4); - } - } - size += flash_info[i].size; - } - - flash_protect (FLAG_PROTECT_SET, - CFG_FLASH_BASE, - CFG_FLASH_BASE + 0xffff, &flash_info[0]); - - return size; -} - - -#define CMD_READ_ARRAY 0x00F0 -#define CMD_UNLOCK1 0x00AA -#define CMD_UNLOCK2 0x0055 -#define CMD_ERASE_SETUP 0x0080 -#define CMD_ERASE_CONFIRM 0x0030 -#define CMD_PROGRAM 0x00A0 -#define CMD_UNLOCK_BYPASS 0x0020 - -#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555<<1))) -#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002AA<<1))) - -#define BIT_ERASE_DONE 0x0080 -#define BIT_RDY_MASK 0x0080 -#define BIT_PROGRAM_ERROR 0x0020 -#define BIT_TIMEOUT 0x80000000 /* our flag */ - -#define READY 1 -#define ERR 2 -#define TMO 4 - - -int flash_erase (flash_info_t * info, int s_first, int s_last) -{ - ulong result; - int iflag, cflag, prot, sect; - int rc = ERR_OK; - int chip1; - - /* first look for protection bits */ - - if (info->flash_id == FLASH_UNKNOWN) - return ERR_UNKNOWN_FLASH_TYPE; - - if ((s_first < 0) || (s_first > s_last)) { - return ERR_INVAL; - } - - if ((info->flash_id & FLASH_VENDMASK) != - (AMD_MANUFACT & FLASH_VENDMASK)) { - return ERR_UNKNOWN_FLASH_VENDOR; - } - - prot = 0; - for (sect = s_first; sect <= s_last; ++sect) { - if (info->protect[sect]) { - prot++; - } - } - if (prot) - return ERR_PROTECTED; - - /* - * Disable interrupts which might cause a timeout - * here. Remember that our exception vectors are - * at address 0 in the flash, and we don't want a - * (ticker) exception to happen while the flash - * chip is in programming mode. - */ - - cflag = icache_status (); - icache_disable (); - iflag = disable_interrupts (); - - printf ("\n"); - - /* Start erase on unprotected sectors */ - for (sect = s_first; sect <= s_last && !ctrlc (); sect++) { - printf ("Erasing sector %2d ... ", sect); - - /* arm simple, non interrupt dependent timer */ - set_timer (0); - - if (info->protect[sect] == 0) { /* not protected */ - volatile u16 *addr = - (volatile u16 *) (info->start[sect]); - - MEM_FLASH_ADDR1 = CMD_UNLOCK1; - MEM_FLASH_ADDR2 = CMD_UNLOCK2; - MEM_FLASH_ADDR1 = CMD_ERASE_SETUP; - - MEM_FLASH_ADDR1 = CMD_UNLOCK1; - MEM_FLASH_ADDR2 = CMD_UNLOCK2; - *addr = CMD_ERASE_CONFIRM; - - /* wait until flash is ready */ - chip1 = 0; - - do { - result = *addr; - - /* check timeout */ - if (get_timer (0) > CFG_FLASH_ERASE_TOUT) { - MEM_FLASH_ADDR1 = CMD_READ_ARRAY; - chip1 = TMO; - break; - } - - if (!chip1 - && (result & 0xFFFF) & BIT_ERASE_DONE) - chip1 = READY; - - } while (!chip1); - - MEM_FLASH_ADDR1 = CMD_READ_ARRAY; - - if (chip1 == ERR) { - rc = ERR_PROG_ERROR; - goto outahere; - } - if (chip1 == TMO) { - rc = ERR_TIMOUT; - goto outahere; - } - - printf ("ok.\n"); - } else { /* it was protected */ - - printf ("protected!\n"); - } - } - - if (ctrlc ()) - printf ("User Interrupt!\n"); - - outahere: - /* allow flash to settle - wait 10 ms */ - udelay (10000); - - if (iflag) - enable_interrupts (); - - if (cflag) - icache_enable (); - - return rc; -} - -static int write_word (flash_info_t * info, ulong dest, ulong data) -{ - volatile u16 *addr = (volatile u16 *) dest; - ulong result; - int rc = ERR_OK; - int cflag, iflag; - int chip1; - - /* - * Check if Flash is (sufficiently) erased - */ - result = *addr; - if ((result & data) != data) - return ERR_NOT_ERASED; - - - /* - * Disable interrupts which might cause a timeout - * here. Remember that our exception vectors are - * at address 0 in the flash, and we don't want a - * (ticker) exception to happen while the flash - * chip is in programming mode. - */ - - cflag = icache_status (); - icache_disable (); - iflag = disable_interrupts (); - - MEM_FLASH_ADDR1 = CMD_UNLOCK1; - MEM_FLASH_ADDR2 = CMD_UNLOCK2; - MEM_FLASH_ADDR1 = CMD_PROGRAM; - *addr = data; - - /* arm simple, non interrupt dependent timer */ - set_timer (0); - - /* wait until flash is ready */ - chip1 = 0; - do { - result = *addr; - - /* check timeout */ - if (get_timer (0) > CFG_FLASH_ERASE_TOUT) { - chip1 = ERR | TMO; - break; - } - if (!chip1 && ((result & 0x80) == (data & 0x80))) - chip1 = READY; - - } while (!chip1); - - *addr = CMD_READ_ARRAY; - - if (chip1 == ERR || *addr != data) - rc = ERR_PROG_ERROR; - - if (iflag) - enable_interrupts (); - - if (cflag) - icache_enable (); - - return rc; -} - - -int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) -{ - ulong wp, data; - int rc; - - if (addr & 1) { - printf ("unaligned destination not supported\n"); - return ERR_ALIGN; - } - -#if 0 - if (cnt & 1) { - printf ("odd transfer sizes not supported\n"); - return ERR_ALIGN; - } -#endif - - wp = addr; - - if (addr & 1) { - data = (*((volatile u8 *) addr) << 8) | *((volatile u8 *) - src); - if ((rc = write_word (info, wp - 1, data)) != 0) { - return (rc); - } - src += 1; - wp += 1; - cnt -= 1; - } - - while (cnt >= 2) { - data = *((volatile u16 *) src); - if ((rc = write_word (info, wp, data)) != 0) { - return (rc); - } - src += 2; - wp += 2; - cnt -= 2; - } - - if (cnt == 1) { - data = (*((volatile u8 *) src) << 8) | - *((volatile u8 *) (wp + 1)); - if ((rc = write_word (info, wp, data)) != 0) { - return (rc); - } - src += 1; - wp += 1; - cnt -= 1; - } - - return ERR_OK; -} diff --git a/board/m5282evb/m5282evb.c b/board/m5282evb/m5282evb.c index a08af68ae3..243d6a4d83 100644 --- a/board/m5282evb/m5282evb.c +++ b/board/m5282evb/m5282evb.c @@ -22,14 +22,71 @@ */ #include <common.h> +#include <asm/immap.h> + +DECLARE_GLOBAL_DATA_PTR; int checkboard (void) { - puts ("MOTOROLA M5272EVB Evaluation Board\n"); + puts ("Board: Freescale M5282EVB Evaluation Board\n"); return 0; } long int initdram (int board_type) { - return 0x1000000; + u32 dramsize, i, dramclk; + + dramsize = CFG_SDRAM_SIZE * 0x100000; + for (i = 0x13; i < 0x20; i++) { + if (dramsize == (1 << i)) + break; + } + i--; + + if (!(MCFSDRAMC_DACR0 & MCFSDRAMC_DACR_RE)) + { + dramclk = gd->bus_clk / (CFG_HZ * CFG_HZ); + + /* Initialize DRAM Control Register: DCR */ + MCFSDRAMC_DCR = (0 + | MCFSDRAMC_DCR_RTIM_6 + | MCFSDRAMC_DCR_RC((15 * dramclk)>>4)); + + /* Initialize DACR0 */ + MCFSDRAMC_DACR0 = (0 + | MCFSDRAMC_DACR_BASE(CFG_SDRAM_BASE) + | MCFSDRAMC_DACR_CASL(1) + | MCFSDRAMC_DACR_CBM(3) + | MCFSDRAMC_DACR_PS_32); + + /* Initialize DMR0 */ + MCFSDRAMC_DMR0 = (0 + | ((dramsize - 1) & 0xFFFC0000) + | MCFSDRAMC_DMR_V); + + /* Set IP (bit 3) in DACR */ + MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_IP; + + /* Wait 30ns to allow banks to precharge */ + for (i = 0; i < 5; i++) { + asm ("nop"); + } + + /* Write to this block to initiate precharge */ + *(u32 *)(CFG_SDRAM_BASE) = 0xA5A59696; + + /* Set RE (bit 15) in DACR */ + MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_RE; + + /* Wait for at least 8 auto refresh cycles to occur */ + for (i = 0; i < 2000; i++) { + asm(" nop"); + } + + /* Finish the configuration by issuing the IMRS. */ + MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_IMRS; + + /* Write to the SDRAM Mode Register */ + *(u32 *)(CFG_SDRAM_BASE + 0x400) = 0xA5A59696; + } } diff --git a/board/m5282evb/mii.c b/board/m5282evb/mii.c new file mode 100644 index 0000000000..ebd3ed9387 --- /dev/null +++ b/board/m5282evb/mii.c @@ -0,0 +1,304 @@ +/* + * 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) +{ + if (setclear) { + MCFGPIO_PASPAR |= 0x0F00; + MCFGPIO_PEHLPAR = CFG_PEHLPAR; + } else { + MCFGPIO_PASPAR &= 0xF0FF; + MCFGPIO_PEHLPAR &= ~CFG_PEHLPAR; + } + 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_AMD79C874VC 0x0022561B /* AMD 79C874 */ +#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 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_AMD79C874VC "AMD79C874VC" +#define STR_ID_LSI80225 "LSI80225" +#define STR_ID_LSI80225B "LSI80225/B" +#define STR_ID_DP83848VV "N83848" +#define STR_ID_DP83849 "N83849" + +/**************************************************************************** + * 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_AMD79C874VC: + strcpy(info->phy_name, + STR_ID_AMD79C874VC); + 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_AMD79C874VC: + printf(STR_ID_AMD79C874VC); + break; + default: + printf("0x%08x\n", phytype); + break; + } +#endif + } + } + } + if (phyaddr < 0) + printf("No PHY device found.\n"); + + return phyaddr; +} +#endif /* CFG_DISCOVER_PHY */ + +int 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 */ |