diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2007-07-05 18:01:18 +0200 |
---|---|---|
committer | Sascha Hauer <sha@octopus.labnet.pengutronix.de> | 2007-07-05 18:01:18 +0200 |
commit | 7837210e23455a5b7fbcc6b55c539a134e953d89 (patch) | |
tree | 47d3da033603c57e9346e96390ed1ff0f6f96c1e | |
parent | 6f5a40d81a0b925873b6de7637e4b43101bc5b89 (diff) | |
download | barebox-7837210e23455a5b7fbcc6b55c539a134e953d89.tar.gz barebox-7837210e23455a5b7fbcc6b55c539a134e953d89.tar.xz |
svn_rev_058
move all ethernet drivers to drivers/net
-rw-r--r-- | cpu/arm920t/Makefile | 5 | ||||
-rw-r--r-- | cpu/arm920t/at91rm9200/Makefile | 2 | ||||
-rw-r--r-- | cpu/arm920t/at91rm9200/ether.c | 299 | ||||
-rw-r--r-- | cpu/mcf52x2/fec.c | 600 | ||||
-rw-r--r-- | cpu/mpc8260/ether_fcc.c | 1171 | ||||
-rw-r--r-- | cpu/mpc8260/ether_scc.c | 348 | ||||
-rw-r--r-- | cpu/mpc85xx/ether_fcc.c | 470 | ||||
-rw-r--r-- | cpu/ppc4xx/4xx_enet.c | 1701 |
8 files changed, 4 insertions, 4592 deletions
diff --git a/cpu/arm920t/Makefile b/cpu/arm920t/Makefile index a05788504c..ca1471387f 100644 --- a/cpu/arm920t/Makefile +++ b/cpu/arm920t/Makefile @@ -1,3 +1,4 @@ obj-y += cpu.o interrupts.o -obj-y += start.o -obj-y += imx/
\ No newline at end of file +head-y += start.o +#obj-y += imx/ +obj-y += at91rm9200/ diff --git a/cpu/arm920t/at91rm9200/Makefile b/cpu/arm920t/at91rm9200/Makefile index 2135ea849a..769d5a3e54 100644 --- a/cpu/arm920t/at91rm9200/Makefile +++ b/cpu/arm920t/at91rm9200/Makefile @@ -1,6 +1,6 @@ obj-y += bcm5221.o obj-y += dm9161.o -obj-$(CONFIG_DRIVER_NET_AT91_ETHER += ether.o +obj-$(CONFIG_DRIVER_NET_AT91_ETHER) += ether.o obj-y += i2c.o obj-y += interrupts.o obj-y += lowlevel_init.o diff --git a/cpu/arm920t/at91rm9200/ether.c b/cpu/arm920t/at91rm9200/ether.c deleted file mode 100644 index 67008d0b91..0000000000 --- a/cpu/arm920t/at91rm9200/ether.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * (C) Copyright 2003 - * Author : Hamid Ikdoumi (Atmel) - * - * 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 <at91rm9200_net.h> -#include <net.h> -#include <miiphy.h> - -/* ----- Ethernet Buffer definitions ----- */ - -typedef struct { - unsigned long addr, size; -} rbf_t; - -#define RBF_ADDR 0xfffffffc -#define RBF_OWNER (1<<0) -#define RBF_WRAP (1<<1) -#define RBF_BROADCAST (1<<31) -#define RBF_MULTICAST (1<<30) -#define RBF_UNICAST (1<<29) -#define RBF_EXTERNAL (1<<28) -#define RBF_UNKOWN (1<<27) -#define RBF_SIZE 0x07ff -#define RBF_LOCAL4 (1<<26) -#define RBF_LOCAL3 (1<<25) -#define RBF_LOCAL2 (1<<24) -#define RBF_LOCAL1 (1<<23) - -#define RBF_FRAMEMAX 64 -#define RBF_FRAMELEN 0x600 - -#ifdef CONFIG_DRIVER_ETHER - -#if (CONFIG_COMMANDS & CFG_CMD_NET) - -/* alignment as per Errata #11 (64 bytes) is insufficient! */ -rbf_t rbfdt[RBF_FRAMEMAX] __attribute((aligned(512))); -rbf_t *rbfp; - -unsigned char rbf_framebuf[RBF_FRAMEMAX][RBF_FRAMELEN] __attribute((aligned(4))); - -/* structure to interface the PHY */ -AT91S_PhyOps PhyOps; - -AT91PS_EMAC p_mac; - -/*********** EMAC Phy layer Management functions *************************/ -/* - * Name: - * at91rm9200_EmacEnableMDIO - * Description: - * Enables the MDIO bit in MAC control register - * Arguments: - * p_mac - pointer to struct AT91S_EMAC - * Return value: - * none - */ -void at91rm9200_EmacEnableMDIO (AT91PS_EMAC p_mac) -{ - /* Mac CTRL reg set for MDIO enable */ - p_mac->EMAC_CTL |= AT91C_EMAC_MPE; /* Management port enable */ -} - -/* - * Name: - * at91rm9200_EmacDisableMDIO - * Description: - * Disables the MDIO bit in MAC control register - * Arguments: - * p_mac - pointer to struct AT91S_EMAC - * Return value: - * none - */ -void at91rm9200_EmacDisableMDIO (AT91PS_EMAC p_mac) -{ - /* Mac CTRL reg set for MDIO disable */ - p_mac->EMAC_CTL &= ~AT91C_EMAC_MPE; /* Management port disable */ -} - - -/* - * Name: - * at91rm9200_EmacReadPhy - * Description: - * Reads data from the PHY register - * Arguments: - * dev - pointer to struct net_device - * RegisterAddress - unsigned char - * pInput - pointer to value read from register - * Return value: - * TRUE - if data read successfully - */ -UCHAR at91rm9200_EmacReadPhy (AT91PS_EMAC p_mac, - unsigned char RegisterAddress, - unsigned short *pInput) -{ - p_mac->EMAC_MAN = (AT91C_EMAC_HIGH & ~AT91C_EMAC_LOW) | - (AT91C_EMAC_RW_R) | - (RegisterAddress << 18) | - (AT91C_EMAC_CODE_802_3); - - udelay (10000); - - *pInput = (unsigned short) p_mac->EMAC_MAN; - - return TRUE; -} - - -/* - * Name: - * at91rm9200_EmacWritePhy - * Description: - * Writes data to the PHY register - * Arguments: - * dev - pointer to struct net_device - * RegisterAddress - unsigned char - * pOutput - pointer to value to be written in the register - * Return value: - * TRUE - if data read successfully - */ -UCHAR at91rm9200_EmacWritePhy (AT91PS_EMAC p_mac, - unsigned char RegisterAddress, - unsigned short *pOutput) -{ - p_mac->EMAC_MAN = (AT91C_EMAC_HIGH & ~AT91C_EMAC_LOW) | - AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_W | - (RegisterAddress << 18) | *pOutput; - - udelay (10000); - - return TRUE; -} - -int eth_init (bd_t * bd) -{ - int ret; - int i; - - p_mac = AT91C_BASE_EMAC; - - /* PIO Disable Register */ - *AT91C_PIOA_PDR = AT91C_PA16_EMDIO | AT91C_PA15_EMDC | AT91C_PA14_ERXER | - AT91C_PA13_ERX1 | AT91C_PA12_ERX0 | AT91C_PA11_ECRS_ECRSDV | - AT91C_PA10_ETX1 | AT91C_PA9_ETX0 | AT91C_PA8_ETXEN | - AT91C_PA7_ETXCK_EREFCK; - -#ifdef CONFIG_AT91C_USE_RMII - *AT91C_PIOB_PDR = AT91C_PB19_ERXCK; - *AT91C_PIOB_BSR = AT91C_PB19_ERXCK; -#else - *AT91C_PIOB_PDR = AT91C_PB19_ERXCK | AT91C_PB18_ECOL | AT91C_PB17_ERXDV | - AT91C_PB16_ERX3 | AT91C_PB15_ERX2 | AT91C_PB14_ETXER | - AT91C_PB13_ETX3 | AT91C_PB12_ETX2; - - /* Select B Register */ - *AT91C_PIOB_BSR = AT91C_PB19_ERXCK | AT91C_PB18_ECOL | - AT91C_PB17_ERXDV | AT91C_PB16_ERX3 | AT91C_PB15_ERX2 | - AT91C_PB14_ETXER | AT91C_PB13_ETX3 | AT91C_PB12_ETX2; -#endif - - *AT91C_PMC_PCER = 1 << AT91C_ID_EMAC; /* Peripheral Clock Enable Register */ - - p_mac->EMAC_CFG |= AT91C_EMAC_CSR; /* Clear statistics */ - - /* Init Ehternet buffers */ - for (i = 0; i < RBF_FRAMEMAX; i++) { - rbfdt[i].addr = (unsigned long)rbf_framebuf[i]; - rbfdt[i].size = 0; - } - rbfdt[RBF_FRAMEMAX - 1].addr |= RBF_WRAP; - rbfp = &rbfdt[0]; - - p_mac->EMAC_SA2L = (bd->bi_enetaddr[3] << 24) | (bd->bi_enetaddr[2] << 16) - | (bd->bi_enetaddr[1] << 8) | (bd->bi_enetaddr[0]); - p_mac->EMAC_SA2H = (bd->bi_enetaddr[5] << 8) | (bd->bi_enetaddr[4]); - - p_mac->EMAC_RBQP = (long) (&rbfdt[0]); - p_mac->EMAC_RSR &= ~(AT91C_EMAC_RSR_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA); - - p_mac->EMAC_CFG = (p_mac->EMAC_CFG | AT91C_EMAC_CAF | AT91C_EMAC_NBC) - & ~AT91C_EMAC_CLK; - -#ifdef CONFIG_AT91C_USE_RMII - p_mac->EMAC_CFG |= AT91C_EMAC_RMII; -#endif - -#if (AT91C_MASTER_CLOCK > 40000000) - /* MDIO clock must not exceed 2.5 MHz, so enable MCK divider */ - p_mac->EMAC_CFG |= AT91C_EMAC_CLK_HCLK_64; -#endif - - p_mac->EMAC_CTL |= AT91C_EMAC_TE | AT91C_EMAC_RE; - - at91rm9200_GetPhyInterface (& PhyOps); - - if (!PhyOps.IsPhyConnected (p_mac)) - printf ("PHY not connected!!\n\r"); - - /* MII management start from here */ - if (!(p_mac->EMAC_SR & AT91C_EMAC_LINK)) { - if (!(ret = PhyOps.Init (p_mac))) { - printf ("MAC: error during MII initialization\n"); - return 0; - } - } else { - printf ("No link\n\r"); - return 0; - } - - return 0; -} - -int eth_send (volatile void *packet, int length) -{ - while (!(p_mac->EMAC_TSR & AT91C_EMAC_BNQ)); - p_mac->EMAC_TAR = (long) packet; - p_mac->EMAC_TCR = length; - while (p_mac->EMAC_TCR & 0x7ff); - p_mac->EMAC_TSR |= AT91C_EMAC_COMP; - return 0; -} - -int eth_rx (void) -{ - int size; - - if (!(rbfp->addr & RBF_OWNER)) - return 0; - - size = rbfp->size & RBF_SIZE; - NetReceive ((volatile uchar *) (rbfp->addr & RBF_ADDR), size); - - rbfp->addr &= ~RBF_OWNER; - if (rbfp->addr & RBF_WRAP) - rbfp = &rbfdt[0]; - else - rbfp++; - - p_mac->EMAC_RSR |= AT91C_EMAC_REC; - - return size; -} - -void eth_halt (void) -{ -}; - -#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) -int at91rm9200_miiphy_read(char *devname, unsigned char addr, - unsigned char reg, unsigned short * value) -{ - at91rm9200_EmacEnableMDIO (p_mac); - at91rm9200_EmacReadPhy (p_mac, reg, value); - at91rm9200_EmacDisableMDIO (p_mac); - return 0; -} - -int at91rm9200_miiphy_write(char *devname, unsigned char addr, - unsigned char reg, unsigned short value) -{ - at91rm9200_EmacEnableMDIO (p_mac); - at91rm9200_EmacWritePhy (p_mac, reg, &value); - at91rm9200_EmacDisableMDIO (p_mac); - return 0; -} - -#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */ - -int at91rm9200_miiphy_initialize(bd_t *bis) -{ -#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) - miiphy_register("at91rm9200phy", at91rm9200_miiphy_read, at91rm9200_miiphy_write); -#endif - return 0; -} - -#endif /* CONFIG_COMMANDS & CFG_CMD_NET */ - -#endif /* CONFIG_DRIVER_ETHER */ diff --git a/cpu/mcf52x2/fec.c b/cpu/mcf52x2/fec.c deleted file mode 100644 index fed57139f8..0000000000 --- a/cpu/mcf52x2/fec.c +++ /dev/null @@ -1,600 +0,0 @@ -/* - * (C) Copyright 2000-2004 - * 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> -#include <malloc.h> -#include <asm/fec.h> - -#ifdef CONFIG_M5271 -#include <asm/m5271.h> -#include <asm/immap_5271.h> -#endif - -#ifdef CONFIG_M5272 -#include <asm/m5272.h> -#include <asm/immap_5272.h> -#endif - -#ifdef CONFIG_M5282 -#include <asm/m5282.h> -#include <asm/immap_5282.h> -#endif - -#include <net.h> -#include <command.h> - -#ifdef CONFIG_M5272 -#define FEC_ADDR (CFG_MBAR + 0x840) -#endif -#if defined(CONFIG_M5282) || defined(CONFIG_M5271) -#define FEC_ADDR (CFG_MBAR + 0x1000) -#endif - -#undef ET_DEBUG -#undef MII_DEBUG - -#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET) - -#ifdef CFG_DISCOVER_PHY -#include <miiphy.h> -static void mii_discover_phy (void); -#endif - -/* Ethernet Transmit and Receive Buffers */ -#define DBUF_LENGTH 1520 - -#define TX_BUF_CNT 2 - -#define TOUT_LOOP 100 - -#define PKT_MAXBUF_SIZE 1518 -#define PKT_MINBUF_SIZE 64 -#define PKT_MAXBLR_SIZE 1520 - - -static char txbuf[DBUF_LENGTH]; - -static uint rxIdx; /* index of the current RX buffer */ -static uint txIdx; /* index of the current TX buffer */ - -/* - * FEC Ethernet Tx and Rx buffer descriptors allocated at the - * immr->udata_bd address on Dual-Port RAM - * Provide for Double Buffering - */ - -typedef volatile struct CommonBufferDescriptor { - cbd_t rxbd[PKTBUFSRX]; /* Rx BD */ - cbd_t txbd[TX_BUF_CNT]; /* Tx BD */ -} RTXBD; - -static RTXBD *rtx = NULL; - -int eth_send (volatile void *packet, int length) -{ - int j, rc; - volatile fec_t *fecp = (fec_t *) (FEC_ADDR); - - /* section 16.9.23.3 - * Wait for ready - */ - j = 0; - while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) - && (j < TOUT_LOOP)) { - udelay (1); - j++; - } - if (j >= TOUT_LOOP) { - printf ("TX not ready\n"); - } - - rtx->txbd[txIdx].cbd_bufaddr = (uint) packet; - rtx->txbd[txIdx].cbd_datlen = length; - rtx->txbd[txIdx].cbd_sc |= BD_ENET_TX_READY | BD_ENET_TX_LAST; - - /* Activate transmit Buffer Descriptor polling */ - fecp->fec_x_des_active = 0x01000000; /* Descriptor polling active */ - - j = 0; - while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) - && (j < TOUT_LOOP)) { - udelay (1); - j++; - } - if (j >= TOUT_LOOP) { - printf ("TX timeout\n"); - } -#ifdef ET_DEBUG - printf ("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n", - __FILE__, __LINE__, __FUNCTION__, j, rtx->txbd[txIdx].cbd_sc, - (rtx->txbd[txIdx].cbd_sc & 0x003C) >> 2); -#endif - - /* return only status bits */ ; - rc = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS); - - txIdx = (txIdx + 1) % TX_BUF_CNT; - - return rc; -} - -int eth_rx (void) -{ - int length; - volatile fec_t *fecp = (fec_t *) FEC_ADDR; - - for (;;) { - /* section 16.9.23.2 */ - if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { - length = -1; - break; /* nothing received - leave for() loop */ - } - - length = rtx->rxbd[rxIdx].cbd_datlen; - - if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) { -#ifdef ET_DEBUG - printf ("%s[%d] err: %x\n", - __FUNCTION__, __LINE__, - rtx->rxbd[rxIdx].cbd_sc); -#endif - } else { - /* Pass the packet up to the protocol layers. */ - NetReceive (NetRxPackets[rxIdx], length - 4); - } - - /* Give the buffer back to the FEC. */ - rtx->rxbd[rxIdx].cbd_datlen = 0; - - /* wrap around buffer index when necessary */ - if ((rxIdx + 1) >= PKTBUFSRX) { - rtx->rxbd[PKTBUFSRX - 1].cbd_sc = - (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); - rxIdx = 0; - } else { - rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY; - rxIdx++; - } - - /* Try to fill Buffer Descriptors */ - fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */ - } - - return length; -} - -/************************************************************** - * - * FEC Ethernet Initialization Routine - * - *************************************************************/ -#define FEC_ECNTRL_ETHER_EN 0x00000002 -#define FEC_ECNTRL_RESET 0x00000001 - -#define FEC_RCNTRL_BC_REJ 0x00000010 -#define FEC_RCNTRL_PROM 0x00000008 -#define FEC_RCNTRL_MII_MODE 0x00000004 -#define FEC_RCNTRL_DRT 0x00000002 -#define FEC_RCNTRL_LOOP 0x00000001 - -#define FEC_TCNTRL_FDEN 0x00000004 -#define FEC_TCNTRL_HBC 0x00000002 -#define FEC_TCNTRL_GTS 0x00000001 - -#define FEC_RESET_DELAY 50000 - -int eth_init (bd_t * bd) -{ -#ifndef CFG_ENET_BD_BASE - DECLARE_GLOBAL_DATA_PTR; -#endif - int i; - volatile fec_t *fecp = (fec_t *) (FEC_ADDR); - - /* Whack a reset. - * A delay is required between a reset of the FEC block and - * initialization of other FEC registers because the reset takes - * some time to complete. If you don't delay, subsequent writes - * to FEC registers might get killed by the reset routine which is - * still in progress. - */ - fecp->fec_ecntrl = FEC_ECNTRL_RESET; - for (i = 0; - (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY); - ++i) { - udelay (1); - } - if (i == FEC_RESET_DELAY) { - printf ("FEC_RESET_DELAY timeout\n"); - return 0; - } - - /* We use strictly polling mode only - */ - fecp->fec_imask = 0; - - /* Clear any pending interrupt */ - fecp->fec_ievent = 0xffffffff; - - /* Set station address */ -#define ea bd->bi_enetaddr - fecp->fec_addr_low = (ea[0] << 24) | (ea[1] << 16) | - (ea[2] << 8) | (ea[3]); - fecp->fec_addr_high = (ea[4] << 24) | (ea[5] << 16); -#ifdef ET_DEBUG - printf ("Eth Addrs: %02x:%02x:%02x:%02x:%02x:%02x\n", - ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]); -#endif -#undef ea - -#ifdef CONFIG_M5271 - /* Clear multicast address hash table - */ - fecp->fec_ghash_table_high = 0; - fecp->fec_ghash_table_low = 0; - - /* Clear individual address hash table - */ - fecp->fec_ihash_table_high = 0; - fecp->fec_ihash_table_low = 0; -#else - /* Clear multicast address hash table - */ -#ifdef CONFIG_M5282 - fecp->fec_ihash_table_high = 0; - fecp->fec_ihash_table_low = 0; -#else - fecp->fec_hash_table_high = 0; - fecp->fec_hash_table_low = 0; -#endif -#endif - - /* Set maximum receive buffer size. - */ - fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; - - /* - * Setup Buffers and Buffer Desriptors - */ - rxIdx = 0; - txIdx = 0; - - if (!rtx) { -#ifdef CFG_ENET_BD_BASE - rtx = (RTXBD *) CFG_ENET_BD_BASE; -#else - rtx = (RTXBD *) (CFG_MONITOR_BASE+gd->reloc_off - - (((PKTBUFSRX+TX_BUF_CNT)*+sizeof(cbd_t) - +0xFF) - & ~0xFF) - ); - debug("set ENET_DB_BASE to %lX\n",(long) rtx); -#endif - } - - /* - * Setup Receiver Buffer Descriptors (13.14.24.18) - * Settings: - * Empty, Wrap - */ - for (i = 0; i < PKTBUFSRX; i++) { - rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; - rtx->rxbd[i].cbd_datlen = 0; /* Reset */ - rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i]; - } - rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; - - /* - * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19) - * Settings: - * Last, Tx CRC - */ - for (i = 0; i < TX_BUF_CNT; i++) { - rtx->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC; - rtx->txbd[i].cbd_datlen = 0; /* Reset */ - rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]); - } - rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; - - /* Set receive and transmit descriptor base - */ - fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]); - fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]); - - /* Enable MII mode - */ - - fecp->fec_r_cntrl = (PKT_MAXBUF_SIZE << 16); /* set max frame length */ - fecp->fec_r_cntrl |= FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT; - fecp->fec_x_cntrl = 0; - /* Set MII speed */ - fecp->fec_mii_speed = (((CFG_CLK / 2) / (2500000 / 10)) + 5) / 10; - fecp->fec_mii_speed *= 2; - - /* Configure port B for MII. - */ - /* port initialization was already made in cpu_init_f() */ - - /* Now enable the transmit and receive processing - */ - fecp->fec_ecntrl = FEC_ECNTRL_ETHER_EN; - -#ifdef CFG_DISCOVER_PHY - /* wait for the PHY to wake up after reset */ - mii_discover_phy (); -#endif - - /* And last, try to fill Rx Buffer Descriptors */ - fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */ - - return 1; -} - -void eth_halt (void) -{ - volatile fec_t *fecp = (fec_t *) FEC_ADDR; - - fecp->fec_ecntrl = 0; -} - - -#if defined(CFG_DISCOVER_PHY) || (CONFIG_COMMANDS & CFG_CMD_MII) - -static int phyaddr = -1; /* didn't find a PHY yet */ -static uint phytype; - -/* 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)) - -/* Interrupt events/masks. -*/ -#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ -#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */ -#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */ -#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */ -#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */ -#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */ -#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */ -#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */ -#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */ -#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */ - -/* 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 */ - -/* send command to phy using mii, wait for result */ -static uint mii_send (uint mii_cmd) -{ - uint mii_reply; - volatile fec_t *ep = (fec_t *) (FEC_ADDR); - - ep->fec_mii_data = mii_cmd; /* command to phy */ - - /* wait for mii complete */ - while (!(ep->fec_ievent & FEC_ENET_MII)); /* spin until done */ - mii_reply = ep->fec_mii_data; /* result from phy */ - ep->fec_ievent = FEC_ENET_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 & CFG_CMD_MII) */ - -#if defined(CFG_DISCOVER_PHY) -static void mii_discover_phy (void) -{ -#define MAX_PHY_PASSES 11 - uint phyno; - int pass; - - 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 = 1; 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 ", phytype, pass); -#endif - if (phytype != 0xffff) { - phyaddr = phyno; - phytype <<= 16; - phytype |= mii_send (mk_mii_read (phyno, - PHY_PHYIDR2)); - -#ifdef ET_DEBUG - printf ("PHY @ 0x%x pass %d type ", phyno, - pass); - switch (phytype & 0xfffffff0) { - case PHY_ID_LXT970: - printf ("LXT970\n"); - break; - case PHY_ID_LXT971: - printf ("LXT971\n"); - break; - case PHY_ID_82555: - printf ("82555\n"); - break; - case PHY_ID_QS6612: - printf ("QS6612\n"); - break; - case PHY_ID_AMD79C784: - printf ("AMD79C784\n"); - break; - case PHY_ID_LSI80225B: - printf ("LSI L80225/B\n"); - break; - default: - printf ("0x%08x\n", phytype); - break; - } -#endif - } - } - } - if (phyaddr < 0) { - printf ("No PHY device found.\n"); - } -} -#endif /* CFG_DISCOVER_PHY */ - -#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII) - -static int mii_init_done = 0; - -/**************************************************************************** - * mii_init -- Initialize the MII for MII command without ethernet - * This function is a subset of eth_init - **************************************************************************** - */ -void mii_init (void) -{ - volatile fec_t *fecp = (fec_t *) (FEC_ADDR); - - int i; - - if (mii_init_done != 0) { - return; - } - - /* Whack a reset. - * A delay is required between a reset of the FEC block and - * initialization of other FEC registers because the reset takes - * some time to complete. If you don't delay, subsequent writes - * to FEC registers might get killed by the reset routine which is - * still in progress. - */ - - fecp->fec_ecntrl = FEC_ECNTRL_RESET; - for (i = 0; - (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY); - ++i) { - udelay (1); - } - if (i == FEC_RESET_DELAY) { - printf ("FEC_RESET_DELAY timeout\n"); - return; - } - - /* We use strictly polling mode only - */ - fecp->fec_imask = 0; - - /* Clear any pending interrupt - */ - fecp->fec_ievent = 0xffffffff; - - /* Set MII speed */ - fecp->fec_mii_speed = 0x0e; - - /* Configure port B for MII. - */ - /* port initialization was already made in cpu_init_f() */ - - /* Now enable the transmit and receive processing */ - fecp->fec_ecntrl = FEC_ECNTRL_ETHER_EN; - - mii_init_done = 1; -} - -/***************************************************************************** - * 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 mcf52x2_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 mcf52x2_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_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII) */ -#endif /* CFG_CMD_NET, FEC_ENET */ - -int mcf52x2_miiphy_initialize(bd_t *bis) -{ -#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET) -#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII) - miiphy_register("mcf52x2phy", mcf52x2_miiphy_read, mcf52x2_miiphy_write); -#endif -#endif - return 0; -} diff --git a/cpu/mpc8260/ether_fcc.c b/cpu/mpc8260/ether_fcc.c deleted file mode 100644 index 941dbfa655..0000000000 --- a/cpu/mpc8260/ether_fcc.c +++ /dev/null @@ -1,1171 +0,0 @@ -/* - * MPC8260 FCC Fast Ethernet - * - * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net) - * - * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Marius Groeger <mgroeger@sysgo.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 - */ - -/* - * MPC8260 FCC Fast Ethernet - * Basic ET HW initialization and packet RX/TX routines - * - * This code will not perform the IO port configuration. This should be - * done in the iop_conf_t structure specific for the board. - * - * TODO: - * add a PHY driver to do the negotiation - * reflect negotiation results in FPSMR - * look for ways to configure the board specific stuff elsewhere, eg. - * config_xxx.h or the board directory - */ - -#include <common.h> -#include <malloc.h> -#include <asm/cpm_8260.h> -#include <mpc8260.h> -#include <command.h> -#include <config.h> -#include <net.h> - -#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) -#include <miiphy.h> -#endif - -DECLARE_GLOBAL_DATA_PTR; - -#if defined(CONFIG_ETHER_ON_FCC) && (CONFIG_COMMANDS & CFG_CMD_NET) && \ - defined(CONFIG_NET_MULTI) - -static struct ether_fcc_info_s -{ - int ether_index; - int proff_enet; - ulong cpm_cr_enet_sblock; - ulong cpm_cr_enet_page; - ulong cmxfcr_mask; - ulong cmxfcr_value; -} - ether_fcc_info[] = -{ -#ifdef CONFIG_ETHER_ON_FCC1 -{ - 0, - PROFF_FCC1, - CPM_CR_FCC1_SBLOCK, - CPM_CR_FCC1_PAGE, - CFG_CMXFCR_MASK1, - CFG_CMXFCR_VALUE1 -}, -#endif - -#ifdef CONFIG_ETHER_ON_FCC2 -{ - 1, - PROFF_FCC2, - CPM_CR_FCC2_SBLOCK, - CPM_CR_FCC2_PAGE, - CFG_CMXFCR_MASK2, - CFG_CMXFCR_VALUE2 -}, -#endif - -#ifdef CONFIG_ETHER_ON_FCC3 -{ - 2, - PROFF_FCC3, - CPM_CR_FCC3_SBLOCK, - CPM_CR_FCC3_PAGE, - CFG_CMXFCR_MASK3, - CFG_CMXFCR_VALUE3 -}, -#endif -}; - -/*---------------------------------------------------------------------*/ - -/* Maximum input DMA size. Must be a should(?) be a multiple of 4. */ -#define PKT_MAXDMA_SIZE 1520 - -/* The FCC stores dest/src/type, data, and checksum for receive packets. */ -#define PKT_MAXBUF_SIZE 1518 -#define PKT_MINBUF_SIZE 64 - -/* Maximum input buffer size. Must be a multiple of 32. */ -#define PKT_MAXBLR_SIZE 1536 - -#define TOUT_LOOP 1000000 - -#define TX_BUF_CNT 2 -#ifdef __GNUC__ -static char txbuf[TX_BUF_CNT][PKT_MAXBLR_SIZE] __attribute__ ((aligned(8))); -#else -#error "txbuf must be 64-bit aligned" -#endif - -static uint rxIdx; /* index of the current RX buffer */ -static uint txIdx; /* index of the current TX buffer */ - -/* - * FCC Ethernet Tx and Rx buffer descriptors. - * Provide for Double Buffering - * Note: PKTBUFSRX is defined in net.h - */ - -typedef volatile struct rtxbd { - cbd_t rxbd[PKTBUFSRX]; - cbd_t txbd[TX_BUF_CNT]; -} RTXBD; - -/* Good news: the FCC supports external BDs! */ -#ifdef __GNUC__ -static RTXBD rtx __attribute__ ((aligned(8))); -#else -#error "rtx must be 64-bit aligned" -#endif - -static int fec_send(struct eth_device* dev, volatile void *packet, int length) -{ - int i; - int result = 0; - - if (length <= 0) { - printf("fec: bad packet size: %d\n", length); - goto out; - } - - for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) { - if (i >= TOUT_LOOP) { - puts ("fec: tx buffer not ready\n"); - goto out; - } - } - - rtx.txbd[txIdx].cbd_bufaddr = (uint)packet; - rtx.txbd[txIdx].cbd_datlen = length; - rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST | - BD_ENET_TX_WRAP); - - for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) { - if (i >= TOUT_LOOP) { - puts ("fec: tx error\n"); - goto out; - } - } - -#ifdef ET_DEBUG - printf("cycles: %d status: %04x\n", i, rtx.txbd[txIdx].cbd_sc); -#endif - - /* return only status bits */ - result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS; - -out: - return result; -} - -static int fec_recv(struct eth_device* dev) -{ - int length; - - for (;;) - { - if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { - length = -1; - break; /* nothing received - leave for() loop */ - } - length = rtx.rxbd[rxIdx].cbd_datlen; - - if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) { - printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc); - } - else { - /* Pass the packet up to the protocol layers. */ - NetReceive(NetRxPackets[rxIdx], length - 4); - } - - - /* Give the buffer back to the FCC. */ - rtx.rxbd[rxIdx].cbd_datlen = 0; - - /* wrap around buffer index when necessary */ - if ((rxIdx + 1) >= PKTBUFSRX) { - rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); - rxIdx = 0; - } - else { - rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY; - rxIdx++; - } - } - return length; -} - - -static int fec_init(struct eth_device* dev, bd_t *bis) -{ - struct ether_fcc_info_s * info = dev->priv; - int i; - volatile immap_t *immr = (immap_t *)CFG_IMMR; - volatile cpm8260_t *cp = &(immr->im_cpm); - fcc_enet_t *pram_ptr; - unsigned long mem_addr; - - - /* 28.9 - (1-2): ioports have been set up already */ - - /* 28.9 - (3): connect FCC's tx and rx clocks */ - immr->im_cpmux.cmx_uar = 0; - immr->im_cpmux.cmx_fcr = (immr->im_cpmux.cmx_fcr & ~info->cmxfcr_mask) | - info->cmxfcr_value; - - /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, Mode Ethernet */ - immr->im_fcc[info->ether_index].fcc_gfmr = - FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32; - - /* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet */ - immr->im_fcc[info->ether_index].fcc_fpsmr = CFG_FCC_PSMR | FCC_PSMR_ENCRC; - - /* 28.9 - (6): FDSR: Ethernet Syn */ - immr->im_fcc[info->ether_index].fcc_fdsr = 0xD555; - - /* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */ - rxIdx = 0; - txIdx = 0; - - /* Setup Receiver Buffer Descriptors */ - for (i = 0; i < PKTBUFSRX; i++) - { - rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; - rtx.rxbd[i].cbd_datlen = 0; - rtx.rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i]; - } - rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; - - /* Setup Ethernet Transmitter Buffer Descriptors */ - for (i = 0; i < TX_BUF_CNT; i++) - { - rtx.txbd[i].cbd_sc = (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC); - rtx.txbd[i].cbd_datlen = 0; - rtx.txbd[i].cbd_bufaddr = (uint)&txbuf[i][0]; - } - rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; - - /* 28.9 - (7): initialise parameter ram */ - pram_ptr = (fcc_enet_t *)&(immr->im_dprambase[info->proff_enet]); - - /* clear whole structure to make sure all reserved fields are zero */ - memset((void*)pram_ptr, 0, sizeof(fcc_enet_t)); - - /* - * common Parameter RAM area - * - * Allocate space in the reserved FCC area of DPRAM for the - * internal buffers. No one uses this space (yet), so we - * can do this. Later, we will add resource management for - * this area. - */ - mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64); - pram_ptr->fen_genfcc.fcc_riptr = mem_addr; - pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32; - /* - * Set maximum bytes per receive buffer. - * It must be a multiple of 32. - */ - pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE; - pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB | - CFG_CPMFCR_RAMTYPE) << 24; - pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]); - pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB | - CFG_CPMFCR_RAMTYPE) << 24; - pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]); - - /* protocol-specific area */ - pram_ptr->fen_cmask = 0xdebb20e3; /* CRC mask */ - pram_ptr->fen_cpres = 0xffffffff; /* CRC preset */ - pram_ptr->fen_retlim = 15; /* Retry limit threshold */ - pram_ptr->fen_mflr = PKT_MAXBUF_SIZE; /* maximum frame length register */ - /* - * Set Ethernet station address. - * - * This is supplied in the board information structure, so we - * copy that into the controller. - * So, far we have only been given one Ethernet address. We make - * it unique by setting a few bits in the upper byte of the - * non-static part of the address. - */ -#define ea eth_get_dev()->enetaddr - pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4]; - pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2]; - pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0]; -#undef ea - pram_ptr->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */ - /* pad pointer. use tiptr since we don't need a specific padding char */ - pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr; - pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE; /* maximum DMA1 length */ - pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE; /* maximum DMA2 length */ - pram_ptr->fen_rfthr = 1; - pram_ptr->fen_rfcnt = 1; - - /* 28.9 - (8): clear out events in FCCE */ - immr->im_fcc[info->ether_index].fcc_fcce = ~0x0; - - /* 28.9 - (9): FCCM: mask all events */ - immr->im_fcc[info->ether_index].fcc_fccm = 0; - - /* 28.9 - (10-12): we don't use ethernet interrupts */ - - /* 28.9 - (13) - * - * Let's re-initialize the channel now. We have to do it later - * than the manual describes because we have just now finished - * the BD initialization. - */ - cp->cp_cpcr = mk_cr_cmd(info->cpm_cr_enet_page, - info->cpm_cr_enet_sblock, - 0x0c, - CPM_CR_INIT_TRX) | CPM_CR_FLG; - do { - __asm__ __volatile__ ("eieio"); - } while (cp->cp_cpcr & CPM_CR_FLG); - - /* 28.9 - (14): enable tx/rx in gfmr */ - immr->im_fcc[info->ether_index].fcc_gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR; - - return 1; -} - -static void fec_halt(struct eth_device* dev) -{ - struct ether_fcc_info_s * info = dev->priv; - volatile immap_t *immr = (immap_t *)CFG_IMMR; - - /* write GFMR: disable tx/rx */ - immr->im_fcc[info->ether_index].fcc_gfmr &= - ~(FCC_GFMR_ENT | FCC_GFMR_ENR); -} - -int fec_initialize(bd_t *bis) -{ - struct eth_device* dev; - int i; - - for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++) - { - dev = (struct eth_device*) malloc(sizeof *dev); - memset(dev, 0, sizeof *dev); - - sprintf(dev->name, "FCC%d ETHERNET", - ether_fcc_info[i].ether_index + 1); - dev->priv = ðer_fcc_info[i]; - dev->init = fec_init; - dev->halt = fec_halt; - dev->send = fec_send; - dev->recv = fec_recv; - - eth_register(dev); - -#if (defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) \ - && defined(CONFIG_BITBANGMII) - miiphy_register(dev->name, - bb_miiphy_read, bb_miiphy_write); -#endif - } - - return 1; -} - -#ifdef CONFIG_ETHER_LOOPBACK_TEST - -#define ELBT_BUFSZ 1024 /* must be multiple of 32 */ - -#define ELBT_CRCSZ 4 - -#define ELBT_NRXBD 4 /* must be at least 2 */ -#define ELBT_NTXBD 4 - -#define ELBT_MAXRXERR 32 -#define ELBT_MAXTXERR 32 - -#define ELBT_CLSWAIT 1000 /* msec to wait for further input frames */ - -typedef - struct { - uint off; - char *lab; - } -elbt_prdesc; - -typedef - struct { - uint _l, _f, m, bc, mc, lg, no, sh, cr, ov, cl; - uint badsrc, badtyp, badlen, badbit; - } -elbt_rxeacc; - -static elbt_prdesc rxeacc_descs[] = { - { offsetof(elbt_rxeacc, _l), "Not Last in Frame" }, - { offsetof(elbt_rxeacc, _f), "Not First in Frame" }, - { offsetof(elbt_rxeacc, m), "Address Miss" }, - { offsetof(elbt_rxeacc, bc), "Broadcast Address" }, - { offsetof(elbt_rxeacc, mc), "Multicast Address" }, - { offsetof(elbt_rxeacc, lg), "Frame Length Violation"}, - { offsetof(elbt_rxeacc, no), "Non-Octet Alignment" }, - { offsetof(elbt_rxeacc, sh), "Short Frame" }, - { offsetof(elbt_rxeacc, cr), "CRC Error" }, - { offsetof(elbt_rxeacc, ov), "Overrun" }, - { offsetof(elbt_rxeacc, cl), "Collision" }, - { offsetof(elbt_rxeacc, badsrc), "Bad Src Address" }, - { offsetof(elbt_rxeacc, badtyp), "Bad Frame Type" }, - { offsetof(elbt_rxeacc, badlen), "Bad Frame Length" }, - { offsetof(elbt_rxeacc, badbit), "Data Compare Errors" }, -}; -static int rxeacc_ndesc = sizeof (rxeacc_descs) / sizeof (rxeacc_descs[0]); - -typedef - struct { - uint def, hb, lc, rl, rc, un, csl; - } -elbt_txeacc; - -static elbt_prdesc txeacc_descs[] = { - { offsetof(elbt_txeacc, def), "Defer Indication" }, - { offsetof(elbt_txeacc, hb), "Heartbeat" }, - { offsetof(elbt_txeacc, lc), "Late Collision" }, - { offsetof(elbt_txeacc, rl), "Retransmission Limit" }, - { offsetof(elbt_txeacc, rc), "Retry Count" }, - { offsetof(elbt_txeacc, un), "Underrun" }, - { offsetof(elbt_txeacc, csl), "Carrier Sense Lost" }, -}; -static int txeacc_ndesc = sizeof (txeacc_descs) / sizeof (txeacc_descs[0]); - -typedef - struct { - uchar rxbufs[ELBT_NRXBD][ELBT_BUFSZ]; - uchar txbufs[ELBT_NTXBD][ELBT_BUFSZ]; - cbd_t rxbd[ELBT_NRXBD]; - cbd_t txbd[ELBT_NTXBD]; - enum { Idle, Running, Closing, Closed } state; - int proff, page, sblock; - uint clstime, nsent, ntxerr, nrcvd, nrxerr; - ushort rxerrs[ELBT_MAXRXERR], txerrs[ELBT_MAXTXERR]; - elbt_rxeacc rxeacc; - elbt_txeacc txeacc; - } __attribute__ ((aligned(8))) -elbt_chan; - -static uchar patbytes[ELBT_NTXBD] = { - 0xff, 0xaa, 0x55, 0x00 -}; -static uint patwords[ELBT_NTXBD] = { - 0xffffffff, 0xaaaaaaaa, 0x55555555, 0x00000000 -}; - -#ifdef __GNUC__ -static elbt_chan elbt_chans[3] __attribute__ ((aligned(8))); -#else -#error "elbt_chans must be 64-bit aligned" -#endif - -#define CPM_CR_GRACEFUL_STOP_TX ((ushort)0x0005) - -static elbt_prdesc epram_descs[] = { - { offsetof(fcc_enet_t, fen_crcec), "CRC Errors" }, - { offsetof(fcc_enet_t, fen_alec), "Alignment Errors" }, - { offsetof(fcc_enet_t, fen_disfc), "Discarded Frames" }, - { offsetof(fcc_enet_t, fen_octc), "Octets" }, - { offsetof(fcc_enet_t, fen_colc), "Collisions" }, - { offsetof(fcc_enet_t, fen_broc), "Broadcast Frames" }, - { offsetof(fcc_enet_t, fen_mulc), "Multicast Frames" }, - { offsetof(fcc_enet_t, fen_uspc), "Undersize Frames" }, - { offsetof(fcc_enet_t, fen_frgc), "Fragments" }, - { offsetof(fcc_enet_t, fen_ospc), "Oversize Frames" }, - { offsetof(fcc_enet_t, fen_jbrc), "Jabbers" }, - { offsetof(fcc_enet_t, fen_p64c), "64 Octet Frames" }, - { offsetof(fcc_enet_t, fen_p65c), "65-127 Octet Frames" }, - { offsetof(fcc_enet_t, fen_p128c), "128-255 Octet Frames" }, - { offsetof(fcc_enet_t, fen_p256c), "256-511 Octet Frames" }, - { offsetof(fcc_enet_t, fen_p512c), "512-1023 Octet Frames" }, - { offsetof(fcc_enet_t, fen_p1024c), "1024-1518 Octet Frames"}, -}; -static int epram_ndesc = sizeof (epram_descs) / sizeof (epram_descs[0]); - -/* - * given an elbt_prdesc array and an array of base addresses, print - * each prdesc down the screen with the values fetched from each - * base address across the screen - */ -static void -print_desc (elbt_prdesc descs[], int ndesc, uchar *bases[], int nbase) -{ - elbt_prdesc *dp = descs, *edp = dp + ndesc; - int i; - - printf ("%32s", ""); - - for (i = 0; i < nbase; i++) - printf (" Channel %d", i); - - putc ('\n'); - - while (dp < edp) { - - printf ("%-32s", dp->lab); - - for (i = 0; i < nbase; i++) { - uint val = *(uint *)(bases[i] + dp->off); - - printf (" %10u", val); - } - - putc ('\n'); - - dp++; - } -} - -/* - * return number of bits that are set in a value; value contains - * nbits (right-justified) bits. - */ -static uint __inline__ -nbs (uint value, uint nbits) -{ - uint cnt = 0; - uint pos = sizeof (uint) * 8; - - __asm__ __volatile__ ("\ - mtctr %2\n\ -1: rlwnm. %2,%1,%4,31,31\n\ - beq 2f\n\ - addi %0,%0,1\n\ -2: subi %4,%4,1\n\ - bdnz 1b" - : "=r"(cnt) - : "r"(value), "r"(nbits), "r"(cnt), "r"(pos) - : "ctr", "cc" ); - - return (cnt); -} - -static ulong -badbits (uchar *bp, int n, ulong pat) -{ - ulong *lp, cnt = 0; - int nl; - - while (n > 0 && ((ulong)bp & (sizeof (ulong) - 1)) != 0) { - uchar diff; - - diff = *bp++ ^ (uchar)pat; - - if (diff) - cnt += nbs ((ulong)diff, 8); - - n--; - } - - lp = (ulong *)bp; - nl = n / sizeof (ulong); - n -= nl * sizeof (ulong); - - while (nl > 0) { - ulong diff; - - diff = *lp++ ^ pat; - - if (diff) - cnt += nbs (diff, 32); - - nl--; - } - - bp = (uchar *)lp; - - while (n > 0) { - uchar diff; - - diff = *bp++ ^ (uchar)pat; - - if (diff) - cnt += nbs ((ulong)diff, 8); - - n--; - } - - return (cnt); -} - -static inline unsigned short -swap16 (unsigned short x) -{ - return (((x & 0xff) << 8) | ((x & 0xff00) >> 8)); -} - -/* broadcast is not an error - we send them like that */ -#define BD_ENET_RX_ERRS (BD_ENET_RX_STATS & ~BD_ENET_RX_BC) - -void -eth_loopback_test (void) -{ - volatile immap_t *immr = (immap_t *)CFG_IMMR; - volatile cpm8260_t *cp = &(immr->im_cpm); - int c, nclosed; - ulong runtime, nmsec; - uchar *bases[3]; - - puts ("FCC Ethernet External loopback test\n"); - - memcpy (NetOurEther, gd->bd->bi_enetaddr, 6); - - /* - * global initialisations for all FCC channels - */ - - /* 28.9 - (1-2): ioports have been set up already */ - -#if defined(CONFIG_HYMOD) - /* - * Attention: this is board-specific - * 0, FCC1 - * 1, FCC2 - * 2, FCC3 - */ -# define FCC_START_LOOP 0 -# define FCC_END_LOOP 2 - - /* - * Attention: this is board-specific - * - FCC1 Rx-CLK is CLK10 - * - FCC1 Tx-CLK is CLK11 - * - FCC2 Rx-CLK is CLK13 - * - FCC2 Tx-CLK is CLK14 - * - FCC3 Rx-CLK is CLK15 - * - FCC3 Tx-CLK is CLK16 - */ - - /* 28.9 - (3): connect FCC's tx and rx clocks */ - immr->im_cpmux.cmx_uar = 0; - immr->im_cpmux.cmx_fcr = CMXFCR_RF1CS_CLK10|CMXFCR_TF1CS_CLK11|\ - CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14|\ - CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16; -#elif defined(CONFIG_SBC8260) || defined(CONFIG_SACSng) - /* - * Attention: this is board-specific - * 1, FCC2 - */ -# define FCC_START_LOOP 1 -# define FCC_END_LOOP 1 - - /* - * Attention: this is board-specific - * - FCC2 Rx-CLK is CLK13 - * - FCC2 Tx-CLK is CLK14 - */ - - /* 28.9 - (3): connect FCC's tx and rx clocks */ - immr->im_cpmux.cmx_uar = 0; - immr->im_cpmux.cmx_fcr = CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14; -#else -#error "eth_loopback_test not supported on your board" -#endif - - puts ("Initialise FCC channels:"); - - for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) { - elbt_chan *ecp = &elbt_chans[c]; - volatile fcc_t *fcp = &immr->im_fcc[c]; - volatile fcc_enet_t *fpp; - int i; - ulong addr; - - /* - * initialise channel data - */ - - printf (" %d", c); - - memset ((void *)ecp, 0, sizeof (*ecp)); - - ecp->state = Idle; - - switch (c) { - - case 0: /* FCC1 */ - ecp->proff = PROFF_FCC1; - ecp->page = CPM_CR_FCC1_PAGE; - ecp->sblock = CPM_CR_FCC1_SBLOCK; - break; - - case 1: /* FCC2 */ - ecp->proff = PROFF_FCC2; - ecp->page = CPM_CR_FCC2_PAGE; - ecp->sblock = CPM_CR_FCC2_SBLOCK; - break; - - case 2: /* FCC3 */ - ecp->proff = PROFF_FCC3; - ecp->page = CPM_CR_FCC3_PAGE; - ecp->sblock = CPM_CR_FCC3_SBLOCK; - break; - } - - /* - * set up tx buffers and bds - */ - - for (i = 0; i < ELBT_NTXBD; i++) { - cbd_t *bdp = &ecp->txbd[i]; - uchar *bp = &ecp->txbufs[i][0]; - - bdp->cbd_bufaddr = (uint)bp; - /* room for crc */ - bdp->cbd_datlen = ELBT_BUFSZ - ELBT_CRCSZ; - bdp->cbd_sc = BD_ENET_TX_READY | BD_ENET_TX_PAD | \ - BD_ENET_TX_LAST | BD_ENET_TX_TC; - - memset ((void *)bp, patbytes[i], ELBT_BUFSZ); - NetSetEther (bp, NetBcastAddr, 0x8000); - } - ecp->txbd[ELBT_NTXBD - 1].cbd_sc |= BD_ENET_TX_WRAP; - - /* - * set up rx buffers and bds - */ - - for (i = 0; i < ELBT_NRXBD; i++) { - cbd_t *bdp = &ecp->rxbd[i]; - uchar *bp = &ecp->rxbufs[i][0]; - - bdp->cbd_bufaddr = (uint)bp; - bdp->cbd_datlen = 0; - bdp->cbd_sc = BD_ENET_RX_EMPTY; - - memset ((void *)bp, 0, ELBT_BUFSZ); - } - ecp->rxbd[ELBT_NRXBD - 1].cbd_sc |= BD_ENET_RX_WRAP; - - /* - * set up the FCC channel hardware - */ - - /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, Mode Ethernet */ - fcp->fcc_gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32; - - /* 28.9 - (5): FPSMR: fd, enet CRC, Promis, RMON, Rx SHort */ - fcp->fcc_fpsmr = FCC_PSMR_FDE | FCC_PSMR_LPB | \ - FCC_PSMR_ENCRC | FCC_PSMR_PRO | \ - FCC_PSMR_MON | FCC_PSMR_RSH; - - /* 28.9 - (6): FDSR: Ethernet Syn */ - fcp->fcc_fdsr = 0xD555; - - /* 29.9 - (7): initialise parameter ram */ - fpp = (fcc_enet_t *)&(immr->im_dprambase[ecp->proff]); - - /* clear whole struct to make sure all resv fields are zero */ - memset ((void *)fpp, 0, sizeof (fcc_enet_t)); - - /* - * common Parameter RAM area - * - * Allocate space in the reserved FCC area of DPRAM for the - * internal buffers. No one uses this space (yet), so we - * can do this. Later, we will add resource management for - * this area. - */ - addr = CPM_FCC_SPECIAL_BASE + (c * 64); - fpp->fen_genfcc.fcc_riptr = addr; - fpp->fen_genfcc.fcc_tiptr = addr + 32; - - /* - * Set maximum bytes per receive buffer. - * It must be a multiple of 32. - * buffers are in 60x bus memory. - */ - fpp->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE; - fpp->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24; - fpp->fen_genfcc.fcc_rbase = (unsigned int)(&ecp->rxbd[0]); - fpp->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24; - fpp->fen_genfcc.fcc_tbase = (unsigned int)(&ecp->txbd[0]); - - /* protocol-specific area */ - fpp->fen_cmask = 0xdebb20e3; /* CRC mask */ - fpp->fen_cpres = 0xffffffff; /* CRC preset */ - fpp->fen_retlim = 15; /* Retry limit threshold */ - fpp->fen_mflr = PKT_MAXBUF_SIZE;/* max frame length register */ - - /* - * Set Ethernet station address. - * - * This is supplied in the board information structure, so we - * copy that into the controller. - * So, far we have only been given one Ethernet address. We use - * the same address for all channels - */ -#define ea gd->bd->bi_enetaddr - fpp->fen_paddrh = (ea[5] << 8) + ea[4]; - fpp->fen_paddrm = (ea[3] << 8) + ea[2]; - fpp->fen_paddrl = (ea[1] << 8) + ea[0]; -#undef ea - - fpp->fen_minflr = PKT_MINBUF_SIZE; /* min frame len register */ - /* - * pad pointer. use tiptr since we don't need - * a specific padding char - */ - fpp->fen_padptr = fpp->fen_genfcc.fcc_tiptr; - fpp->fen_maxd1 = PKT_MAXDMA_SIZE; /* max DMA1 length */ - fpp->fen_maxd2 = PKT_MAXDMA_SIZE; /* max DMA2 length */ - fpp->fen_rfthr = 1; - fpp->fen_rfcnt = 1; - - /* 28.9 - (8): clear out events in FCCE */ - fcp->fcc_fcce = ~0x0; - - /* 28.9 - (9): FCCM: mask all events */ - fcp->fcc_fccm = 0; - - /* 28.9 - (10-12): we don't use ethernet interrupts */ - - /* 28.9 - (13) - * - * Let's re-initialize the channel now. We have to do it later - * than the manual describes because we have just now finished - * the BD initialization. - */ - cp->cp_cpcr = mk_cr_cmd (ecp->page, ecp->sblock, \ - 0x0c, CPM_CR_INIT_TRX) | CPM_CR_FLG; - do { - __asm__ __volatile__ ("eieio"); - } while (cp->cp_cpcr & CPM_CR_FLG); - } - - puts (" done\nStarting test... (Ctrl-C to Finish)\n"); - - /* - * Note: don't want serial output from here until the end of the - * test - the delays would probably stuff things up. - */ - - clear_ctrlc (); - runtime = get_timer (0); - - do { - nclosed = 0; - - for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) { - volatile fcc_t *fcp = &immr->im_fcc[c]; - elbt_chan *ecp = &elbt_chans[c]; - int i; - - switch (ecp->state) { - - case Idle: - /* - * set the channel Running ... - */ - - /* 28.9 - (14): enable tx/rx in gfmr */ - fcp->fcc_gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR; - - ecp->state = Running; - break; - - case Running: - /* - * (while Running only) check for - * termination of the test - */ - - (void)ctrlc (); - - if (had_ctrlc ()) { - /* - * initiate a "graceful stop transmit" - * on the channel - */ - cp->cp_cpcr = mk_cr_cmd (ecp->page, \ - ecp->sblock, 0x0c, \ - CPM_CR_GRACEFUL_STOP_TX) | \ - CPM_CR_FLG; - do { - __asm__ __volatile__ ("eieio"); - } while (cp->cp_cpcr & CPM_CR_FLG); - - ecp->clstime = get_timer (0); - ecp->state = Closing; - } - /* fall through ... */ - - case Closing: - /* - * (while Running or Closing) poll the channel: - * - check for any non-READY tx buffers and - * make them ready - * - check for any non-EMPTY rx buffers and - * check that they were received correctly, - * adjust counters etc, then make empty - */ - - for (i = 0; i < ELBT_NTXBD; i++) { - cbd_t *bdp = &ecp->txbd[i]; - ushort sc = bdp->cbd_sc; - - if ((sc & BD_ENET_TX_READY) != 0) - continue; - - /* - * this frame has finished - * transmitting - */ - ecp->nsent++; - - if (sc & BD_ENET_TX_STATS) { - ulong n; - - /* - * we had an error on - * the transmission - */ - n = ecp->ntxerr++; - if (n < ELBT_MAXTXERR) - ecp->txerrs[n] = sc; - - if (sc & BD_ENET_TX_DEF) - ecp->txeacc.def++; - if (sc & BD_ENET_TX_HB) - ecp->txeacc.hb++; - if (sc & BD_ENET_TX_LC) - ecp->txeacc.lc++; - if (sc & BD_ENET_TX_RL) - ecp->txeacc.rl++; - if (sc & BD_ENET_TX_RCMASK) - ecp->txeacc.rc++; - if (sc & BD_ENET_TX_UN) - ecp->txeacc.un++; - if (sc & BD_ENET_TX_CSL) - ecp->txeacc.csl++; - - bdp->cbd_sc &= \ - ~BD_ENET_TX_STATS; - } - - if (ecp->state == Closing) - ecp->clstime = get_timer (0); - - /* make it ready again */ - bdp->cbd_sc |= BD_ENET_TX_READY; - } - - for (i = 0; i < ELBT_NRXBD; i++) { - cbd_t *bdp = &ecp->rxbd[i]; - ushort sc = bdp->cbd_sc, mask; - - if ((sc & BD_ENET_RX_EMPTY) != 0) - continue; - - /* we have a new frame in this buffer */ - ecp->nrcvd++; - - mask = BD_ENET_RX_LAST|BD_ENET_RX_FIRST; - if ((sc & mask) != mask) { - /* somethings wrong here ... */ - if (!(sc & BD_ENET_RX_LAST)) - ecp->rxeacc._l++; - if (!(sc & BD_ENET_RX_FIRST)) - ecp->rxeacc._f++; - } - - if (sc & BD_ENET_RX_ERRS) { - ulong n; - - /* - * we had some sort of error - * on the frame - */ - n = ecp->nrxerr++; - if (n < ELBT_MAXRXERR) - ecp->rxerrs[n] = sc; - - if (sc & BD_ENET_RX_MISS) - ecp->rxeacc.m++; - if (sc & BD_ENET_RX_BC) - ecp->rxeacc.bc++; - if (sc & BD_ENET_RX_MC) - ecp->rxeacc.mc++; - if (sc & BD_ENET_RX_LG) - ecp->rxeacc.lg++; - if (sc & BD_ENET_RX_NO) - ecp->rxeacc.no++; - if (sc & BD_ENET_RX_SH) - ecp->rxeacc.sh++; - if (sc & BD_ENET_RX_CR) - ecp->rxeacc.cr++; - if (sc & BD_ENET_RX_OV) - ecp->rxeacc.ov++; - if (sc & BD_ENET_RX_CL) - ecp->rxeacc.cl++; - - bdp->cbd_sc &= \ - ~BD_ENET_RX_ERRS; - } - else { - ushort datlen = bdp->cbd_datlen; - Ethernet_t *ehp; - ushort prot; - int ours, tb, n, nbytes; - - ehp = (Ethernet_t *) \ - &ecp->rxbufs[i][0]; - - ours = memcmp (ehp->et_src, \ - NetOurEther, 6); - - prot = swap16 (ehp->et_protlen); - tb = prot & 0x8000; - n = prot & 0x7fff; - - nbytes = ELBT_BUFSZ - \ - offsetof (Ethernet_t, \ - et_dsap) - \ - ELBT_CRCSZ; - - /* check the frame is correct */ - if (datlen != ELBT_BUFSZ) - ecp->rxeacc.badlen++; - else if (!ours) - ecp->rxeacc.badsrc++; - else if (!tb || n >= ELBT_NTXBD) - ecp->rxeacc.badtyp++; - else { - ulong patword = \ - patwords[n]; - uint nbb; - - nbb = badbits ( \ - &ehp->et_dsap, \ - nbytes, \ - patword); - - ecp->rxeacc.badbit += \ - nbb; - } - } - - if (ecp->state == Closing) - ecp->clstime = get_timer (0); - - /* make it empty again */ - bdp->cbd_sc |= BD_ENET_RX_EMPTY; - } - - if (ecp->state != Closing) - break; - - /* - * (while Closing) check to see if - * waited long enough - */ - - if (get_timer (ecp->clstime) >= ELBT_CLSWAIT) { - /* write GFMR: disable tx/rx */ - fcp->fcc_gfmr &= \ - ~(FCC_GFMR_ENT | FCC_GFMR_ENR); - ecp->state = Closed; - } - - break; - - case Closed: - nclosed++; - break; - } - } - - } while (nclosed < (FCC_END_LOOP - FCC_START_LOOP + 1)); - - runtime = get_timer (runtime); - if (runtime <= ELBT_CLSWAIT) { - printf ("Whoops! somehow elapsed time (%ld) is wrong (<= %d)\n", - runtime, ELBT_CLSWAIT); - return; - } - nmsec = runtime - ELBT_CLSWAIT; - - printf ("Test Finished in %ldms (plus %dms close wait period)!\n\n", - nmsec, ELBT_CLSWAIT); - - /* - * now print stats - */ - - for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) { - elbt_chan *ecp = &elbt_chans[c]; - uint rxpps, txpps, nerr; - - rxpps = (ecp->nrcvd * 1000) / nmsec; - txpps = (ecp->nsent * 1000) / nmsec; - - printf ("Channel %d: %d rcvd (%d pps, %d rxerrs), " - "%d sent (%d pps, %d txerrs)\n\n", c, - ecp->nrcvd, rxpps, ecp->nrxerr, - ecp->nsent, txpps, ecp->ntxerr); - - if ((nerr = ecp->nrxerr) > 0) { - ulong i; - - printf ("\tFirst %d rx errs:", nerr); - for (i = 0; i < nerr; i++) - printf (" %04x", ecp->rxerrs[i]); - putc ('\n'); - } - - if ((nerr = ecp->ntxerr) > 0) { - ulong i; - - printf ("\tFirst %d tx errs:", nerr); - for (i = 0; i < nerr; i++) - printf (" %04x", ecp->txerrs[i]); - putc ('\n'); - } - } - - puts ("Receive Error Counts:\n"); - for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) - bases[c] = (uchar *)&elbt_chans[c].rxeacc; - print_desc (rxeacc_descs, rxeacc_ndesc, bases, 3); - - puts ("\nTransmit Error Counts:\n"); - for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) - bases[c] = (uchar *)&elbt_chans[c].txeacc; - print_desc (txeacc_descs, txeacc_ndesc, bases, 3); - - puts ("\nRMON(-like) Counters:\n"); - for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) - bases[c] = (uchar *)&immr->im_dprambase[elbt_chans[c].proff]; - print_desc (epram_descs, epram_ndesc, bases, 3); -} - -#endif /* CONFIG_ETHER_LOOPBACK_TEST */ - -#endif /* CONFIG_ETHER_ON_FCC && CFG_CMD_NET && CONFIG_NET_MULTI */ diff --git a/cpu/mpc8260/ether_scc.c b/cpu/mpc8260/ether_scc.c deleted file mode 100644 index d22e8b216c..0000000000 --- a/cpu/mpc8260/ether_scc.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * MPC8260 SCC Ethernet - * - * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net) - * - * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Marius Groeger <mgroeger@sysgo.de> - * - * (C) Copyright (c) 2001 - * Advent Networks, Inc. <http://www.adventnetworks.com> - * Jay Monkman <jtm@smoothsmoothie.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/cpm_8260.h> -#include <mpc8260.h> -#include <net.h> -#include <command.h> -#include <config.h> - -#if defined(CONFIG_ETHER_ON_SCC) && (CONFIG_COMMANDS & CFG_CMD_NET) - -#if (CONFIG_ETHER_INDEX == 1) -# define PROFF_ENET PROFF_SCC1 -# define CPM_CR_ENET_PAGE CPM_CR_SCC1_PAGE -# define CPM_CR_ENET_SBLOCK CPM_CR_SCC1_SBLOCK -# define CMXSCR_MASK (CMXSCR_SC1 |\ - CMXSCR_RS1CS_MSK |\ - CMXSCR_TS1CS_MSK) - -#elif (CONFIG_ETHER_INDEX == 2) -# define PROFF_ENET PROFF_SCC2 -# define CPM_CR_ENET_PAGE CPM_CR_SCC2_PAGE -# define CPM_CR_ENET_SBLOCK CPM_CR_SCC2_SBLOCK -# define CMXSCR_MASK (CMXSCR_SC2 |\ - CMXSCR_RS2CS_MSK |\ - CMXSCR_TS2CS_MSK) - -#elif (CONFIG_ETHER_INDEX == 3) -# define PROFF_ENET PROFF_SCC3 -# define CPM_CR_ENET_PAGE CPM_CR_SCC3_PAGE -# define CPM_CR_ENET_SBLOCK CPM_CR_SCC3_SBLOCK -# define CMXSCR_MASK (CMXSCR_SC3 |\ - CMXSCR_RS3CS_MSK |\ - CMXSCR_TS3CS_MSK) -#elif (CONFIG_ETHER_INDEX == 4) -# define PROFF_ENET PROFF_SCC4 -# define CPM_CR_ENET_PAGE CPM_CR_SCC4_PAGE -# define CPM_CR_ENET_SBLOCK CPM_CR_SCC4_SBLOCK -# define CMXSCR_MASK (CMXSCR_SC4 |\ - CMXSCR_RS4CS_MSK |\ - CMXSCR_TS4CS_MSK) - -#endif - - -/* Ethernet Transmit and Receive Buffers */ -#define DBUF_LENGTH 1520 - -#define TX_BUF_CNT 2 - -#define TOUT_LOOP 1000000 - -static char txbuf[TX_BUF_CNT][ DBUF_LENGTH ]; - -static uint rxIdx; /* index of the current RX buffer */ -static uint txIdx; /* index of the current TX buffer */ - -/* - * SCC Ethernet Tx and Rx buffer descriptors allocated at the - * immr->udata_bd address on Dual-Port RAM - * Provide for Double Buffering - */ - -typedef volatile struct CommonBufferDescriptor { - cbd_t rxbd[PKTBUFSRX]; /* Rx BD */ - cbd_t txbd[TX_BUF_CNT]; /* Tx BD */ -} RTXBD; - -static RTXBD *rtx; - - -int eth_send(volatile void *packet, int length) -{ - int i; - int result = 0; - - if (length <= 0) { - printf("scc: bad packet size: %d\n", length); - goto out; - } - - for(i=0; rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) { - if (i >= TOUT_LOOP) { - puts ("scc: tx buffer not ready\n"); - goto out; - } - } - - rtx->txbd[txIdx].cbd_bufaddr = (uint)packet; - rtx->txbd[txIdx].cbd_datlen = length; - rtx->txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST | - BD_ENET_TX_WRAP); - - for(i=0; rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) { - if (i >= TOUT_LOOP) { - puts ("scc: tx error\n"); - goto out; - } - } - - /* return only status bits */ - result = rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS; - - out: - return result; -} - - -int eth_rx(void) -{ - int length; - - for (;;) - { - if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { - length = -1; - break; /* nothing received - leave for() loop */ - } - - length = rtx->rxbd[rxIdx].cbd_datlen; - - if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) - { - printf("err: %x\n", rtx->rxbd[rxIdx].cbd_sc); - } - else - { - /* Pass the packet up to the protocol layers. */ - NetReceive(NetRxPackets[rxIdx], length - 4); - } - - - /* Give the buffer back to the SCC. */ - rtx->rxbd[rxIdx].cbd_datlen = 0; - - /* wrap around buffer index when necessary */ - if ((rxIdx + 1) >= PKTBUFSRX) { - rtx->rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | - BD_ENET_RX_EMPTY); - rxIdx = 0; - } - else { - rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY; - rxIdx++; - } - } - return length; -} - -/************************************************************** - * - * SCC Ethernet Initialization Routine - * - *************************************************************/ - -int eth_init(bd_t *bis) -{ - int i; - volatile immap_t *immr = (immap_t *)CFG_IMMR; - scc_enet_t *pram_ptr; - uint dpaddr; - - rxIdx = 0; - txIdx = 0; - - /* assign static pointer to BD area */ - dpaddr = m8260_cpm_dpalloc(sizeof(RTXBD) + 2, 16); - rtx = (RTXBD *)&immr->im_dprambase[dpaddr]; - - /* 24.21 - (1-3): ioports have been set up already */ - - /* 24.21 - (4,5): connect SCC's tx and rx clocks, use NMSI for SCC */ - immr->im_cpmux.cmx_uar = 0; - immr->im_cpmux.cmx_scr = ( (immr->im_cpmux.cmx_scr & ~CMXSCR_MASK) | - CFG_CMXSCR_VALUE); - - - /* 24.21 (6) write RBASE and TBASE to parameter RAM */ - pram_ptr = (scc_enet_t *)&(immr->im_dprambase[PROFF_ENET]); - pram_ptr->sen_genscc.scc_rbase = (unsigned int)(&rtx->rxbd[0]); - pram_ptr->sen_genscc.scc_tbase = (unsigned int)(&rtx->txbd[0]); - - pram_ptr->sen_genscc.scc_rfcr = 0x18; /* Nrml Ops and Mot byte ordering */ - pram_ptr->sen_genscc.scc_tfcr = 0x18; /* Mot byte ordering, Nrml access */ - - pram_ptr->sen_genscc.scc_mrblr = DBUF_LENGTH; /* max. package len 1520 */ - - pram_ptr->sen_cpres = ~(0x0); /* Preset CRC */ - pram_ptr->sen_cmask = 0xdebb20e3; /* Constant Mask for CRC */ - - - /* 24.21 - (7): Write INIT RX AND TX PARAMETERS to CPCR */ - while(immr->im_cpm.cp_cpcr & CPM_CR_FLG); - immr->im_cpm.cp_cpcr = mk_cr_cmd(CPM_CR_ENET_PAGE, - CPM_CR_ENET_SBLOCK, - 0x0c, - CPM_CR_INIT_TRX) | CPM_CR_FLG; - - /* 24.21 - (8-18): Set up parameter RAM */ - pram_ptr->sen_crcec = 0x0; /* Error Counter CRC (unused) */ - pram_ptr->sen_alec = 0x0; /* Align Error Counter (unused) */ - pram_ptr->sen_disfc = 0x0; /* Discard Frame Counter (unused) */ - - pram_ptr->sen_pads = 0x8888; /* Short Frame PAD Characters */ - - pram_ptr->sen_retlim = 15; /* Retry Limit Threshold */ - - pram_ptr->sen_maxflr = 1518; /* MAX Frame Length Register */ - pram_ptr->sen_minflr = 64; /* MIN Frame Length Register */ - - pram_ptr->sen_maxd1 = DBUF_LENGTH; /* MAX DMA1 Length Register */ - pram_ptr->sen_maxd2 = DBUF_LENGTH; /* MAX DMA2 Length Register */ - - pram_ptr->sen_gaddr1 = 0x0; /* Group Address Filter 1 (unused) */ - pram_ptr->sen_gaddr2 = 0x0; /* Group Address Filter 2 (unused) */ - pram_ptr->sen_gaddr3 = 0x0; /* Group Address Filter 3 (unused) */ - pram_ptr->sen_gaddr4 = 0x0; /* Group Address Filter 4 (unused) */ - -# define ea bis->bi_enetaddr - pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4]; - pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2]; - pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0]; -# undef ea - - pram_ptr->sen_pper = 0x0; /* Persistence (unused) */ - - pram_ptr->sen_iaddr1 = 0x0; /* Individual Address Filter 1 (unused) */ - pram_ptr->sen_iaddr2 = 0x0; /* Individual Address Filter 2 (unused) */ - pram_ptr->sen_iaddr3 = 0x0; /* Individual Address Filter 3 (unused) */ - pram_ptr->sen_iaddr4 = 0x0; /* Individual Address Filter 4 (unused) */ - - pram_ptr->sen_taddrh = 0x0; /* Tmp Address (MSB) (unused) */ - pram_ptr->sen_taddrm = 0x0; /* Tmp Address (unused) */ - pram_ptr->sen_taddrl = 0x0; /* Tmp Address (LSB) (unused) */ - - - /* 24.21 - (19): Initialize RxBD */ - for (i = 0; i < PKTBUFSRX; i++) - { - rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; - rtx->rxbd[i].cbd_datlen = 0; /* Reset */ - rtx->rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i]; - } - - rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; - - /* 24.21 - (20): Initialize TxBD */ - for (i = 0; i < TX_BUF_CNT; i++) - { - rtx->txbd[i].cbd_sc = (BD_ENET_TX_PAD | - BD_ENET_TX_LAST | - BD_ENET_TX_TC); - rtx->txbd[i].cbd_datlen = 0; /* Reset */ - rtx->txbd[i].cbd_bufaddr = (uint)&txbuf[i][0]; - } - - rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; - - /* 24.21 - (21): Write 0xffff to SCCE */ - immr->im_scc[CONFIG_ETHER_INDEX-1].scc_scce = ~(0x0); - - /* 24.21 - (22): Write to SCCM to enable TXE, RXF, TXB events */ - immr->im_scc[CONFIG_ETHER_INDEX-1].scc_sccm = (SCCE_ENET_TXE | - SCCE_ENET_RXF | - SCCE_ENET_TXB); - - /* 24.21 - (23): we don't use ethernet interrupts */ - - /* 24.21 - (24): Clear GSMR_H to enable normal operations */ - immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrh = 0; - - /* 24.21 - (25): Clear GSMR_L to enable normal operations */ - immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl = (SCC_GSMRL_TCI | - SCC_GSMRL_TPL_48 | - SCC_GSMRL_TPP_10 | - SCC_GSMRL_MODE_ENET); - - /* 24.21 - (26): Initialize DSR */ - immr->im_scc[CONFIG_ETHER_INDEX-1].scc_dsr = 0xd555; - - /* 24.21 - (27): Initialize PSMR2 - * - * Settings: - * CRC = 32-Bit CCITT - * NIB = Begin searching for SFD 22 bits after RENA - * FDE = Full Duplex Enable - * BRO = Reject broadcast packets - * PROMISCOUS = Catch all packets regardless of dest. MAC adress - */ - immr->im_scc[CONFIG_ETHER_INDEX-1].scc_psmr = SCC_PSMR_ENCRC | - SCC_PSMR_NIB22 | -#if defined(CONFIG_SCC_ENET_FULL_DUPLEX) - SCC_PSMR_FDE | -#endif -#if defined(CONFIG_SCC_ENET_NO_BROADCAST) - SCC_PSMR_BRO | -#endif -#if defined(CONFIG_SCC_ENET_PROMISCOUS) - SCC_PSMR_PRO | -#endif - 0; - - /* 24.21 - (28): Write to GSMR_L to enable SCC */ - immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl |= (SCC_GSMRL_ENR | - SCC_GSMRL_ENT); - - return 0; -} - - -void eth_halt(void) -{ - volatile immap_t *immr = (immap_t *)CFG_IMMR; - immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl &= ~(SCC_GSMRL_ENR | - SCC_GSMRL_ENT); -} - - -#endif /* CONFIG_ETHER_ON_SCC && CFG_CMD_NET */ diff --git a/cpu/mpc85xx/ether_fcc.c b/cpu/mpc85xx/ether_fcc.c deleted file mode 100644 index 128fc3173b..0000000000 --- a/cpu/mpc85xx/ether_fcc.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * MPC8560 FCC Fast Ethernet - * Copyright (c) 2003 Motorola,Inc. - * Xianghua Xiao, (X.Xiao@motorola.com) - * - * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net) - * - * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Marius Groeger <mgroeger@sysgo.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 - */ - -/* - * MPC8560 FCC Fast Ethernet - * Basic ET HW initialization and packet RX/TX routines - * - * This code will not perform the IO port configuration. This should be - * done in the iop_conf_t structure specific for the board. - * - * TODO: - * add a PHY driver to do the negotiation - * reflect negotiation results in FPSMR - * look for ways to configure the board specific stuff elsewhere, eg. - * config_xxx.h or the board directory - */ - -#include <common.h> -#include <malloc.h> -#include <asm/cpm_85xx.h> -#include <command.h> -#include <config.h> -#include <net.h> - -#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) -#include <miiphy.h> -#endif - -#if defined(CONFIG_CPM2) - -#if defined(CONFIG_ETHER_ON_FCC) && (CONFIG_COMMANDS & CFG_CMD_NET) && \ - defined(CONFIG_NET_MULTI) - -static struct ether_fcc_info_s -{ - int ether_index; - int proff_enet; - ulong cpm_cr_enet_sblock; - ulong cpm_cr_enet_page; - ulong cmxfcr_mask; - ulong cmxfcr_value; -} - ether_fcc_info[] = -{ -#ifdef CONFIG_ETHER_ON_FCC1 -{ - 0, - PROFF_FCC1, - CPM_CR_FCC1_SBLOCK, - CPM_CR_FCC1_PAGE, - CFG_CMXFCR_MASK1, - CFG_CMXFCR_VALUE1 -}, -#endif - -#ifdef CONFIG_ETHER_ON_FCC2 -{ - 1, - PROFF_FCC2, - CPM_CR_FCC2_SBLOCK, - CPM_CR_FCC2_PAGE, - CFG_CMXFCR_MASK2, - CFG_CMXFCR_VALUE2 -}, -#endif - -#ifdef CONFIG_ETHER_ON_FCC3 -{ - 2, - PROFF_FCC3, - CPM_CR_FCC3_SBLOCK, - CPM_CR_FCC3_PAGE, - CFG_CMXFCR_MASK3, - CFG_CMXFCR_VALUE3 -}, -#endif -}; - -/*---------------------------------------------------------------------*/ - -/* Maximum input DMA size. Must be a should(?) be a multiple of 4. */ -#define PKT_MAXDMA_SIZE 1520 - -/* The FCC stores dest/src/type, data, and checksum for receive packets. */ -#define PKT_MAXBUF_SIZE 1518 -#define PKT_MINBUF_SIZE 64 - -/* Maximum input buffer size. Must be a multiple of 32. */ -#define PKT_MAXBLR_SIZE 1536 - -#define TOUT_LOOP 1000000 - -#define TX_BUF_CNT 2 - -static uint rxIdx; /* index of the current RX buffer */ -static uint txIdx; /* index of the current TX buffer */ - -/* - * FCC Ethernet Tx and Rx buffer descriptors. - * Provide for Double Buffering - * Note: PKTBUFSRX is defined in net.h - */ - -typedef volatile struct rtxbd { - cbd_t rxbd[PKTBUFSRX]; - cbd_t txbd[TX_BUF_CNT]; -} RTXBD; - -/* Good news: the FCC supports external BDs! */ -#ifdef __GNUC__ -static RTXBD rtx __attribute__ ((aligned(8))); -#else -#error "rtx must be 64-bit aligned" -#endif - -#undef ET_DEBUG - -static int fec_send(struct eth_device* dev, volatile void *packet, int length) -{ - int i = 0; - int result = 0; - - if (length <= 0) { - printf("fec: bad packet size: %d\n", length); - goto out; - } - - for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) { - if (i >= TOUT_LOOP) { - printf("fec: tx buffer not ready\n"); - goto out; - } - } - - rtx.txbd[txIdx].cbd_bufaddr = (uint)packet; - rtx.txbd[txIdx].cbd_datlen = length; - rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST | \ - BD_ENET_TX_TC | BD_ENET_TX_PAD); - - for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) { - if (i >= TOUT_LOOP) { - printf("fec: tx error\n"); - goto out; - } - } - -#ifdef ET_DEBUG - printf("cycles: 0x%x txIdx=0x%04x status: 0x%04x\n", i, txIdx,rtx.txbd[txIdx].cbd_sc); - printf("packets at 0x%08x, length_in_bytes=0x%x\n",(uint)packet,length); - for(i=0;i<(length/16 + 1);i++) { - printf("%08x %08x %08x %08x\n",*((uint *)rtx.txbd[txIdx].cbd_bufaddr+i*4),\ - *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 1),*((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 2), \ - *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 3)); - } -#endif - - /* return only status bits */ - result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS; - txIdx = (txIdx + 1) % TX_BUF_CNT; - -out: - return result; -} - -static int fec_recv(struct eth_device* dev) -{ - int length; - - for (;;) - { - if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { - length = -1; - break; /* nothing received - leave for() loop */ - } - length = rtx.rxbd[rxIdx].cbd_datlen; - - if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) { - printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc); - } - else { - /* Pass the packet up to the protocol layers. */ - NetReceive(NetRxPackets[rxIdx], length - 4); - } - - - /* Give the buffer back to the FCC. */ - rtx.rxbd[rxIdx].cbd_datlen = 0; - - /* wrap around buffer index when necessary */ - if ((rxIdx + 1) >= PKTBUFSRX) { - rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); - rxIdx = 0; - } - else { - rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY; - rxIdx++; - } - } - return length; -} - - -static int fec_init(struct eth_device* dev, bd_t *bis) -{ - struct ether_fcc_info_s * info = dev->priv; - int i; - volatile immap_t *immr = (immap_t *)CFG_IMMR; - volatile ccsr_cpm_cp_t *cp = &(immr->im_cpm.im_cpm_cp); - fcc_enet_t *pram_ptr; - unsigned long mem_addr; - - - /* 28.9 - (1-2): ioports have been set up already */ - - /* 28.9 - (3): connect FCC's tx and rx clocks */ - immr->im_cpm.im_cpm_mux.cmxuar = 0; /* ATM */ - immr->im_cpm.im_cpm_mux.cmxfcr = (immr->im_cpm.im_cpm_mux.cmxfcr & ~info->cmxfcr_mask) | - info->cmxfcr_value; - - /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, set Mode Ethernet */ - if(info->ether_index == 0) { - immr->im_cpm.im_cpm_fcc1.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32; - } else if (info->ether_index == 1) { - immr->im_cpm.im_cpm_fcc2.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32; - } else if (info->ether_index == 2) { - immr->im_cpm.im_cpm_fcc3.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32; - } - - /* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet,MII */ - if(info->ether_index == 0) { - immr->im_cpm.im_cpm_fcc1.fpsmr = CFG_FCC_PSMR | FCC_PSMR_ENCRC; - } else if (info->ether_index == 1){ - immr->im_cpm.im_cpm_fcc2.fpsmr = CFG_FCC_PSMR | FCC_PSMR_ENCRC; - } else if (info->ether_index == 2){ - immr->im_cpm.im_cpm_fcc3.fpsmr = CFG_FCC_PSMR | FCC_PSMR_ENCRC; - } - - /* 28.9 - (6): FDSR: Ethernet Syn */ - if(info->ether_index == 0) { - immr->im_cpm.im_cpm_fcc1.fdsr = 0xD555; - } else if (info->ether_index == 1) { - immr->im_cpm.im_cpm_fcc2.fdsr = 0xD555; - } else if (info->ether_index == 2) { - immr->im_cpm.im_cpm_fcc3.fdsr = 0xD555; - } - - /* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */ - rxIdx = 0; - txIdx = 0; - - /* Setup Receiver Buffer Descriptors */ - for (i = 0; i < PKTBUFSRX; i++) - { - rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; - rtx.rxbd[i].cbd_datlen = 0; - rtx.rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i]; - } - rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; - - /* Setup Ethernet Transmitter Buffer Descriptors */ - for (i = 0; i < TX_BUF_CNT; i++) - { - rtx.txbd[i].cbd_sc = 0; - rtx.txbd[i].cbd_datlen = 0; - rtx.txbd[i].cbd_bufaddr = 0; - } - rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; - - /* 28.9 - (7): initialize parameter ram */ - pram_ptr = (fcc_enet_t *)&(immr->im_cpm.im_dprambase[info->proff_enet]); - - /* clear whole structure to make sure all reserved fields are zero */ - memset((void*)pram_ptr, 0, sizeof(fcc_enet_t)); - - /* - * common Parameter RAM area - * - * Allocate space in the reserved FCC area of DPRAM for the - * internal buffers. No one uses this space (yet), so we - * can do this. Later, we will add resource management for - * this area. - * CPM_FCC_SPECIAL_BASE: 0xB000 for MPC8540, MPC8560 - * 0x9000 for MPC8541, MPC8555 - */ - mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64); - pram_ptr->fen_genfcc.fcc_riptr = mem_addr; - pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32; - /* - * Set maximum bytes per receive buffer. - * It must be a multiple of 32. - */ - pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE; /* 1536 */ - /* localbus SDRAM should be preferred */ - pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB | - CFG_CPMFCR_RAMTYPE) << 24; - pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]); - pram_ptr->fen_genfcc.fcc_rbdstat = 0; - pram_ptr->fen_genfcc.fcc_rbdlen = 0; - pram_ptr->fen_genfcc.fcc_rdptr = 0; - /* localbus SDRAM should be preferred */ - pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB | - CFG_CPMFCR_RAMTYPE) << 24; - pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]); - pram_ptr->fen_genfcc.fcc_tbdstat = 0; - pram_ptr->fen_genfcc.fcc_tbdlen = 0; - pram_ptr->fen_genfcc.fcc_tdptr = 0; - - /* protocol-specific area */ - pram_ptr->fen_statbuf = 0x0; - pram_ptr->fen_cmask = 0xdebb20e3; /* CRC mask */ - pram_ptr->fen_cpres = 0xffffffff; /* CRC preset */ - pram_ptr->fen_crcec = 0; - pram_ptr->fen_alec = 0; - pram_ptr->fen_disfc = 0; - pram_ptr->fen_retlim = 15; /* Retry limit threshold */ - pram_ptr->fen_retcnt = 0; - pram_ptr->fen_pper = 0; - pram_ptr->fen_boffcnt = 0; - pram_ptr->fen_gaddrh = 0; - pram_ptr->fen_gaddrl = 0; - pram_ptr->fen_mflr = PKT_MAXBUF_SIZE; /* maximum frame length register */ - /* - * Set Ethernet station address. - * - * This is supplied in the board information structure, so we - * copy that into the controller. - * So far we have only been given one Ethernet address. We make - * it unique by setting a few bits in the upper byte of the - * non-static part of the address. - */ -#define ea eth_get_dev()->enetaddr - pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4]; - pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2]; - pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0]; -#undef ea - pram_ptr->fen_ibdcount = 0; - pram_ptr->fen_ibdstart = 0; - pram_ptr->fen_ibdend = 0; - pram_ptr->fen_txlen = 0; - pram_ptr->fen_iaddrh = 0; /* disable hash */ - pram_ptr->fen_iaddrl = 0; - pram_ptr->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register: 64 */ - /* pad pointer. use tiptr since we don't need a specific padding char */ - pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr; - pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE; /* maximum DMA1 length:1520 */ - pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE; /* maximum DMA2 length:1520 */ - -#if defined(ET_DEBUG) - printf("parm_ptr(0xff788500) = %p\n",pram_ptr); - printf("pram_ptr->fen_genfcc.fcc_rbase %08x\n", - pram_ptr->fen_genfcc.fcc_rbase); - printf("pram_ptr->fen_genfcc.fcc_tbase %08x\n", - pram_ptr->fen_genfcc.fcc_tbase); -#endif - - /* 28.9 - (8)(9): clear out events in FCCE */ - /* 28.9 - (9): FCCM: mask all events */ - if(info->ether_index == 0) { - immr->im_cpm.im_cpm_fcc1.fcce = ~0x0; - immr->im_cpm.im_cpm_fcc1.fccm = 0; - } else if (info->ether_index == 1) { - immr->im_cpm.im_cpm_fcc2.fcce = ~0x0; - immr->im_cpm.im_cpm_fcc2.fccm = 0; - } else if (info->ether_index == 2) { - immr->im_cpm.im_cpm_fcc3.fcce = ~0x0; - immr->im_cpm.im_cpm_fcc3.fccm = 0; - } - - /* 28.9 - (10-12): we don't use ethernet interrupts */ - - /* 28.9 - (13) - * - * Let's re-initialize the channel now. We have to do it later - * than the manual describes because we have just now finished - * the BD initialization. - */ - cp->cpcr = mk_cr_cmd(info->cpm_cr_enet_page, - info->cpm_cr_enet_sblock, - 0x0c, - CPM_CR_INIT_TRX) | CPM_CR_FLG; - do { - __asm__ __volatile__ ("eieio"); - } while (cp->cpcr & CPM_CR_FLG); - - /* 28.9 - (14): enable tx/rx in gfmr */ - if(info->ether_index == 0) { - immr->im_cpm.im_cpm_fcc1.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR; - } else if (info->ether_index == 1) { - immr->im_cpm.im_cpm_fcc2.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR; - } else if (info->ether_index == 2) { - immr->im_cpm.im_cpm_fcc3.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR; - } - - return 1; -} - -static void fec_halt(struct eth_device* dev) -{ - struct ether_fcc_info_s * info = dev->priv; - volatile immap_t *immr = (immap_t *)CFG_IMMR; - - /* write GFMR: disable tx/rx */ - if(info->ether_index == 0) { - immr->im_cpm.im_cpm_fcc1.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR); - } else if(info->ether_index == 1) { - immr->im_cpm.im_cpm_fcc2.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR); - } else if(info->ether_index == 2) { - immr->im_cpm.im_cpm_fcc3.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR); - } -} - -int fec_initialize(bd_t *bis) -{ - struct eth_device* dev; - int i; - - for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++) - { - dev = (struct eth_device*) malloc(sizeof *dev); - memset(dev, 0, sizeof *dev); - - sprintf(dev->name, "FCC%d ETHERNET", - ether_fcc_info[i].ether_index + 1); - dev->priv = ðer_fcc_info[i]; - dev->init = fec_init; - dev->halt = fec_halt; - dev->send = fec_send; - dev->recv = fec_recv; - - eth_register(dev); - -#if (defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) \ - && defined(CONFIG_BITBANGMII) - miiphy_register(dev->name, - bb_miiphy_read, bb_miiphy_write); -#endif - } - - return 1; -} - -#endif /* CONFIG_ETHER_ON_FCC && CFG_CMD_NET && CONFIG_NET_MULTI */ - -#endif /* CONFIG_CPM2 */ diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c deleted file mode 100644 index 5183eeaf5e..0000000000 --- a/cpu/ppc4xx/4xx_enet.c +++ /dev/null @@ -1,1701 +0,0 @@ -/*-----------------------------------------------------------------------------+ - * - * This source code has been made available to you by IBM on an AS-IS - * basis. Anyone receiving this source is licensed under IBM - * copyrights to use it in any way he or she deems fit, including - * copying it, modifying it, compiling it, and redistributing it either - * with or without modifications. No license under IBM patents or - * patent applications is to be implied by the copyright license. - * - * Any user of this software should understand that IBM cannot provide - * technical support for this software and will not be responsible for - * any consequences resulting from the use of this software. - * - * Any person who transfers this source code or any derivative work - * must include the IBM copyright notice, this paragraph, and the - * preceding two paragraphs in the transferred software. - * - * COPYRIGHT I B M CORPORATION 1995 - * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M - *-----------------------------------------------------------------------------*/ -/*-----------------------------------------------------------------------------+ - * - * File Name: enetemac.c - * - * Function: Device driver for the ethernet EMAC3 macro on the 405GP. - * - * Author: Mark Wisner - * - * Change Activity- - * - * Date Description of Change BY - * --------- --------------------- --- - * 05-May-99 Created MKW - * 27-Jun-99 Clean up JWB - * 16-Jul-99 Added MAL error recovery and better IP packet handling MKW - * 29-Jul-99 Added Full duplex support MKW - * 06-Aug-99 Changed names for Mal CR reg MKW - * 23-Aug-99 Turned off SYE when running at 10Mbs MKW - * 24-Aug-99 Marked descriptor empty after call_xlc MKW - * 07-Sep-99 Set MAL RX buffer size reg to ENET_MAX_MTU_ALIGNED / 16 MCG - * to avoid chaining maximum sized packets. Push starting - * RX descriptor address up to the next cache line boundary. - * 16-Jan-00 Added support for booting with IP of 0x0 MKW - * 15-Mar-00 Updated enetInit() to enable broadcast addresses in the - * EMAC_RXM register. JWB - * 12-Mar-01 anne-sophie.harnois@nextream.fr - * - Variables are compatible with those already defined in - * include/net.h - * - Receive buffer descriptor ring is used to send buffers - * to the user - * - Info print about send/received/handled packet number if - * INFO_405_ENET is set - * 17-Apr-01 stefan.roese@esd-electronics.com - * - MAL reset in "eth_halt" included - * - Enet speed and duplex output now in one line - * 08-May-01 stefan.roese@esd-electronics.com - * - MAL error handling added (eth_init called again) - * 13-Nov-01 stefan.roese@esd-electronics.com - * - Set IST bit in EMAC_M1 reg upon 100MBit or full duplex - * 04-Jan-02 stefan.roese@esd-electronics.com - * - Wait for PHY auto negotiation to complete added - * 06-Feb-02 stefan.roese@esd-electronics.com - * - Bug fixed in waiting for auto negotiation to complete - * 26-Feb-02 stefan.roese@esd-electronics.com - * - rx and tx buffer descriptors now allocated (no fixed address - * used anymore) - * 17-Jun-02 stefan.roese@esd-electronics.com - * - MAL error debug printf 'M' removed (rx de interrupt may - * occur upon many incoming packets with only 4 rx buffers). - *-----------------------------------------------------------------------------* - * 17-Nov-03 travis.sawyer@sandburst.com - * - ported from 405gp_enet.c to utilized upto 4 EMAC ports - * in the 440GX. This port should work with the 440GP - * (2 EMACs) also - * 15-Aug-05 sr@denx.de - * - merged 405gp_enet.c and 440gx_enet.c to generic 4xx_enet.c - now handling all 4xx cpu's. - *-----------------------------------------------------------------------------*/ - -#include <config.h> -#include <common.h> -#include <net.h> -#include <asm/processor.h> -#include <commproc.h> -#include <ppc4xx.h> -#include <ppc4xx_enet.h> -#include <405_mal.h> -#include <miiphy.h> -#include <malloc.h> -#include "vecnum.h" - -/* - * Only compile for platform with AMCC EMAC ethernet controller and - * network support enabled. - * Remark: CONFIG_405 describes Xilinx PPC405 FPGA without EMAC controller! - */ -#if (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_405) && !defined(CONFIG_IOP480) - -#if !(defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) -#error "CONFIG_MII has to be defined!" -#endif - -#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_NET_MULTI) -#error "CONFIG_NET_MULTI has to be defined for NetConsole" -#endif - -#define EMAC_RESET_TIMEOUT 1000 /* 1000 ms reset timeout */ -#define PHY_AUTONEGOTIATE_TIMEOUT 4000 /* 4000 ms autonegotiate timeout */ - -/* Ethernet Transmit and Receive Buffers */ -/* AS.HARNOIS - * In the same way ENET_MAX_MTU and ENET_MAX_MTU_ALIGNED are set from - * PKTSIZE and PKTSIZE_ALIGN (include/net.h) - */ -#define ENET_MAX_MTU PKTSIZE -#define ENET_MAX_MTU_ALIGNED PKTSIZE_ALIGN - -/*-----------------------------------------------------------------------------+ - * Defines for MAL/EMAC interrupt conditions as reported in the UIC (Universal - * Interrupt Controller). - *-----------------------------------------------------------------------------*/ -#define MAL_UIC_ERR ( UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE) -#define MAL_UIC_DEF (UIC_MAL_RXEOB | MAL_UIC_ERR) -#define EMAC_UIC_DEF UIC_ENET -#define EMAC_UIC_DEF1 UIC_ENET1 -#define SEL_UIC_DEF(p) (p ? UIC_ENET1 : UIC_ENET ) - -#undef INFO_4XX_ENET - -#define BI_PHYMODE_NONE 0 -#define BI_PHYMODE_ZMII 1 -#define BI_PHYMODE_RGMII 2 -#define BI_PHYMODE_GMII 3 -#define BI_PHYMODE_RTBI 4 -#define BI_PHYMODE_TBI 5 -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -#define BI_PHYMODE_SMII 6 -#define BI_PHYMODE_MII 7 -#endif - -#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -#define SDR0_MFR_ETH_CLK_SEL_V(n) ((0x01<<27) / (n+1)) -#endif - -/*-----------------------------------------------------------------------------+ - * Global variables. TX and RX descriptors and buffers. - *-----------------------------------------------------------------------------*/ -/* IER globals */ -static uint32_t mal_ier; - -#if !defined(CONFIG_NET_MULTI) -struct eth_device *emac0_dev = NULL; -#endif - -/* - * Get count of EMAC devices (doesn't have to be the max. possible number - * supported by the cpu) - */ -#if defined(CONFIG_HAS_ETH3) -#define LAST_EMAC_NUM 4 -#elif defined(CONFIG_HAS_ETH2) -#define LAST_EMAC_NUM 3 -#elif defined(CONFIG_HAS_ETH1) -#define LAST_EMAC_NUM 2 -#else -#define LAST_EMAC_NUM 1 -#endif - -/*-----------------------------------------------------------------------------+ - * Prototypes and externals. - *-----------------------------------------------------------------------------*/ -static void enet_rcv (struct eth_device *dev, unsigned long malisr); - -int enetInt (struct eth_device *dev); -static void mal_err (struct eth_device *dev, unsigned long isr, - unsigned long uic, unsigned long maldef, - unsigned long mal_errr); -static void emac_err (struct eth_device *dev, unsigned long isr); - -extern int phy_setup_aneg (char *devname, unsigned char addr); -extern int emac4xx_miiphy_read (char *devname, unsigned char addr, - unsigned char reg, unsigned short *value); -extern int emac4xx_miiphy_write (char *devname, unsigned char addr, - unsigned char reg, unsigned short value); - -/*-----------------------------------------------------------------------------+ -| ppc_4xx_eth_halt -| Disable MAL channel, and EMACn -+-----------------------------------------------------------------------------*/ -static void ppc_4xx_eth_halt (struct eth_device *dev) -{ - EMAC_4XX_HW_PST hw_p = dev->priv; - uint32_t failsafe = 10000; -#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - unsigned long mfr; -#endif - - out32 (EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */ - - /* 1st reset MAL channel */ - /* Note: writing a 0 to a channel has no effect */ -#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) - mtdcr (maltxcarr, (MAL_CR_MMSR >> (hw_p->devnum * 2))); -#else - mtdcr (maltxcarr, (MAL_CR_MMSR >> hw_p->devnum)); -#endif - mtdcr (malrxcarr, (MAL_CR_MMSR >> hw_p->devnum)); - - /* wait for reset */ - while (mfdcr (malrxcasr) & (MAL_CR_MMSR >> hw_p->devnum)) { - udelay (1000); /* Delay 1 MS so as not to hammer the register */ - failsafe--; - if (failsafe == 0) - break; - } - - /* EMAC RESET */ -#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - /* provide clocks for EMAC internal loopback */ - mfsdr (sdr_mfr, mfr); - mfr |= SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum); - mtsdr(sdr_mfr, mfr); -#endif - - out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST); - -#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - /* remove clocks for EMAC internal loopback */ - mfsdr (sdr_mfr, mfr); - mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum); - mtsdr(sdr_mfr, mfr); -#endif - - -#ifndef CONFIG_NETCONSOLE - hw_p->print_speed = 1; /* print speed message again next time */ -#endif - - return; -} - -#if defined (CONFIG_440GX) -int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) -{ - unsigned long pfc1; - unsigned long zmiifer; - unsigned long rmiifer; - - mfsdr(sdr_pfc1, pfc1); - pfc1 = SDR0_PFC1_EPS_DECODE(pfc1); - - zmiifer = 0; - rmiifer = 0; - - switch (pfc1) { - case 1: - zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0); - zmiifer |= ZMII_FER_RMII << ZMII_FER_V(1); - zmiifer |= ZMII_FER_RMII << ZMII_FER_V(2); - zmiifer |= ZMII_FER_RMII << ZMII_FER_V(3); - bis->bi_phymode[0] = BI_PHYMODE_ZMII; - bis->bi_phymode[1] = BI_PHYMODE_ZMII; - bis->bi_phymode[2] = BI_PHYMODE_ZMII; - bis->bi_phymode[3] = BI_PHYMODE_ZMII; - break; - case 2: - zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0); - zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1); - zmiifer |= ZMII_FER_SMII << ZMII_FER_V(2); - zmiifer |= ZMII_FER_SMII << ZMII_FER_V(3); - bis->bi_phymode[0] = BI_PHYMODE_ZMII; - bis->bi_phymode[1] = BI_PHYMODE_ZMII; - bis->bi_phymode[2] = BI_PHYMODE_ZMII; - bis->bi_phymode[3] = BI_PHYMODE_ZMII; - break; - case 3: - zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0); - rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2); - bis->bi_phymode[0] = BI_PHYMODE_ZMII; - bis->bi_phymode[1] = BI_PHYMODE_NONE; - bis->bi_phymode[2] = BI_PHYMODE_RGMII; - bis->bi_phymode[3] = BI_PHYMODE_NONE; - break; - case 4: - zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0); - zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1); - rmiifer |= RGMII_FER_RGMII << RGMII_FER_V (2); - rmiifer |= RGMII_FER_RGMII << RGMII_FER_V (3); - bis->bi_phymode[0] = BI_PHYMODE_ZMII; - bis->bi_phymode[1] = BI_PHYMODE_ZMII; - bis->bi_phymode[2] = BI_PHYMODE_RGMII; - bis->bi_phymode[3] = BI_PHYMODE_RGMII; - break; - case 5: - zmiifer |= ZMII_FER_SMII << ZMII_FER_V (0); - zmiifer |= ZMII_FER_SMII << ZMII_FER_V (1); - zmiifer |= ZMII_FER_SMII << ZMII_FER_V (2); - rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3); - bis->bi_phymode[0] = BI_PHYMODE_ZMII; - bis->bi_phymode[1] = BI_PHYMODE_ZMII; - bis->bi_phymode[2] = BI_PHYMODE_ZMII; - bis->bi_phymode[3] = BI_PHYMODE_RGMII; - break; - case 6: - zmiifer |= ZMII_FER_SMII << ZMII_FER_V (0); - zmiifer |= ZMII_FER_SMII << ZMII_FER_V (1); - rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2); - bis->bi_phymode[0] = BI_PHYMODE_ZMII; - bis->bi_phymode[1] = BI_PHYMODE_ZMII; - bis->bi_phymode[2] = BI_PHYMODE_RGMII; - break; - case 0: - default: - zmiifer = ZMII_FER_MII << ZMII_FER_V(devnum); - rmiifer = 0x0; - bis->bi_phymode[0] = BI_PHYMODE_ZMII; - bis->bi_phymode[1] = BI_PHYMODE_ZMII; - bis->bi_phymode[2] = BI_PHYMODE_ZMII; - bis->bi_phymode[3] = BI_PHYMODE_ZMII; - break; - } - - /* Ensure we setup mdio for this devnum and ONLY this devnum */ - zmiifer |= (ZMII_FER_MDI) << ZMII_FER_V(devnum); - - out32 (ZMII_FER, zmiifer); - out32 (RGMII_FER, rmiifer); - - return ((int)pfc1); -} -#endif /* CONFIG_440_GX */ - -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) -{ - unsigned long zmiifer=0x0; - - /* - * Right now only 2*RGMII is supported. Please extend when needed. - * sr - 2006-08-29 - */ - switch (1) { - case 0: - /* 1 x GMII port */ - out32 (ZMII_FER, 0x00); - out32 (RGMII_FER, 0x00000037); - bis->bi_phymode[0] = BI_PHYMODE_GMII; - bis->bi_phymode[1] = BI_PHYMODE_NONE; - break; - case 1: - /* 2 x RGMII ports */ - out32 (ZMII_FER, 0x00); - out32 (RGMII_FER, 0x00000055); - bis->bi_phymode[0] = BI_PHYMODE_RGMII; - bis->bi_phymode[1] = BI_PHYMODE_RGMII; - break; - case 2: - /* 2 x SMII ports */ - - break; - default: - break; - } - - /* Ensure we setup mdio for this devnum and ONLY this devnum */ - zmiifer = in32 (ZMII_FER); - zmiifer |= (ZMII_FER_MDI) << ZMII_FER_V(devnum); - out32 (ZMII_FER, zmiifer); - - return ((int)0x0); -} -#endif /* CONFIG_440EPX */ - -static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) -{ - int i, j; - unsigned long reg = 0; - unsigned long msr; - unsigned long speed; - unsigned long duplex; - unsigned long failsafe; - unsigned mode_reg; - unsigned short devnum; - unsigned short reg_short; -#if defined(CONFIG_440GX) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) - sys_info_t sysinfo; -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - int ethgroup = -1; -#endif -#endif -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || defined(CONFIG_440SPE) - unsigned long mfr; -#endif - - - EMAC_4XX_HW_PST hw_p = dev->priv; - - /* before doing anything, figure out if we have a MAC address */ - /* if not, bail */ - if (memcmp (dev->enetaddr, "\0\0\0\0\0\0", 6) == 0) { - printf("ERROR: ethaddr not set!\n"); - return -1; - } - -#if defined(CONFIG_440GX) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) - /* Need to get the OPB frequency so we can access the PHY */ - get_sys_info (&sysinfo); -#endif - - msr = mfmsr (); - mtmsr (msr & ~(MSR_EE)); /* disable interrupts */ - - devnum = hw_p->devnum; - -#ifdef INFO_4XX_ENET - /* AS.HARNOIS - * We should have : - * hw_p->stats.pkts_handled <= hw_p->stats.pkts_rx <= hw_p->stats.pkts_handled+PKTBUFSRX - * In the most cases hw_p->stats.pkts_handled = hw_p->stats.pkts_rx, but it - * is possible that new packets (without relationship with - * current transfer) have got the time to arrived before - * netloop calls eth_halt - */ - printf ("About preceeding transfer (eth%d):\n" - "- Sent packet number %d\n" - "- Received packet number %d\n" - "- Handled packet number %d\n", - hw_p->devnum, - hw_p->stats.pkts_tx, - hw_p->stats.pkts_rx, hw_p->stats.pkts_handled); - - hw_p->stats.pkts_tx = 0; - hw_p->stats.pkts_rx = 0; - hw_p->stats.pkts_handled = 0; - hw_p->print_speed = 1; /* print speed message again next time */ -#endif - - hw_p->tx_err_index = 0; /* Transmit Error Index for tx_err_log */ - hw_p->rx_err_index = 0; /* Receive Error Index for rx_err_log */ - - hw_p->rx_slot = 0; /* MAL Receive Slot */ - hw_p->rx_i_index = 0; /* Receive Interrupt Queue Index */ - hw_p->rx_u_index = 0; /* Receive User Queue Index */ - - hw_p->tx_slot = 0; /* MAL Transmit Slot */ - hw_p->tx_i_index = 0; /* Transmit Interrupt Queue Index */ - hw_p->tx_u_index = 0; /* Transmit User Queue Index */ - -#if defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) - /* set RMII mode */ - /* NOTE: 440GX spec states that mode is mutually exclusive */ - /* NOTE: Therefore, disable all other EMACS, since we handle */ - /* NOTE: only one emac at a time */ - reg = 0; - out32 (ZMII_FER, 0); - udelay (100); - -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) - out32 (ZMII_FER, (ZMII_FER_RMII | ZMII_FER_MDI) << ZMII_FER_V (devnum)); -#elif defined(CONFIG_440GX) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis); -#elif defined(CONFIG_440GP) - /* set RMII mode */ - out32 (ZMII_FER, ZMII_RMII | ZMII_MDI0); -#else - if ((devnum == 0) || (devnum == 1)) { - out32 (ZMII_FER, (ZMII_FER_SMII | ZMII_FER_MDI) << ZMII_FER_V (devnum)); - } else { /* ((devnum == 2) || (devnum == 3)) */ - out32 (ZMII_FER, ZMII_FER_MDI << ZMII_FER_V (devnum)); - out32 (RGMII_FER, ((RGMII_FER_RGMII << RGMII_FER_V (2)) | - (RGMII_FER_RGMII << RGMII_FER_V (3)))); - } -#endif - - out32 (ZMII_SSR, ZMII_SSR_SP << ZMII_SSR_V(devnum)); -#endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */ - - __asm__ volatile ("eieio"); - - /* reset emac so we have access to the phy */ -#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - /* provide clocks for EMAC internal loopback */ - mfsdr (sdr_mfr, mfr); - mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum); - mtsdr(sdr_mfr, mfr); -#endif - - out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST); - __asm__ volatile ("eieio"); - - failsafe = 1000; - while ((in32 (EMAC_M0 + hw_p->hw_addr) & (EMAC_M0_SRST)) && failsafe) { - udelay (1000); - failsafe--; - } - if (failsafe <= 0) - printf("\nProblem resetting EMAC!\n"); - -#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - /* remove clocks for EMAC internal loopback */ - mfsdr (sdr_mfr, mfr); - mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum); - mtsdr(sdr_mfr, mfr); -#endif - -#if defined(CONFIG_440GX) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) - /* Whack the M1 register */ - mode_reg = 0x0; - mode_reg &= ~0x00000038; - if (sysinfo.freqOPB <= 50000000); - else if (sysinfo.freqOPB <= 66666667) - mode_reg |= EMAC_M1_OBCI_66; - else if (sysinfo.freqOPB <= 83333333) - mode_reg |= EMAC_M1_OBCI_83; - else if (sysinfo.freqOPB <= 100000000) - mode_reg |= EMAC_M1_OBCI_100; - else - mode_reg |= EMAC_M1_OBCI_GT100; - - out32 (EMAC_M1 + hw_p->hw_addr, mode_reg); -#endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */ - - /* wait for PHY to complete auto negotiation */ - reg_short = 0; -#ifndef CONFIG_CS8952_PHY - switch (devnum) { - case 0: - reg = CONFIG_PHY_ADDR; - break; -#if defined (CONFIG_PHY1_ADDR) - case 1: - reg = CONFIG_PHY1_ADDR; - break; -#endif -#if defined (CONFIG_440GX) - case 2: - reg = CONFIG_PHY2_ADDR; - break; - case 3: - reg = CONFIG_PHY3_ADDR; - break; -#endif - default: - reg = CONFIG_PHY_ADDR; - break; - } - - bis->bi_phynum[devnum] = reg; - -#if defined(CONFIG_PHY_RESET) - /* - * Reset the phy, only if its the first time through - * otherwise, just check the speeds & feeds - */ - if (hw_p->first_init == 0) { -#if defined(CONFIG_M88E1111_PHY) - miiphy_write (dev->name, reg, 0x14, 0x0ce3); - miiphy_write (dev->name, reg, 0x18, 0x4101); - miiphy_write (dev->name, reg, 0x09, 0x0e00); - miiphy_write (dev->name, reg, 0x04, 0x01e1); -#endif - miiphy_reset (dev->name, reg); - -#if defined(CONFIG_440GX) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) - -#if defined(CONFIG_CIS8201_PHY) - /* - * Cicada 8201 PHY needs to have an extended register whacked - * for RGMII mode. - */ - if (((devnum == 2) || (devnum == 3)) && (4 == ethgroup)) { -#if defined(CONFIG_CIS8201_SHORT_ETCH) - miiphy_write (dev->name, reg, 23, 0x1300); -#else - miiphy_write (dev->name, reg, 23, 0x1000); -#endif - /* - * Vitesse VSC8201/Cicada CIS8201 errata: - * Interoperability problem with Intel 82547EI phys - * This work around (provided by Vitesse) changes - * the default timer convergence from 8ms to 12ms - */ - miiphy_write (dev->name, reg, 0x1f, 0x2a30); - miiphy_write (dev->name, reg, 0x08, 0x0200); - miiphy_write (dev->name, reg, 0x1f, 0x52b5); - miiphy_write (dev->name, reg, 0x02, 0x0004); - miiphy_write (dev->name, reg, 0x01, 0x0671); - miiphy_write (dev->name, reg, 0x00, 0x8fae); - miiphy_write (dev->name, reg, 0x1f, 0x2a30); - miiphy_write (dev->name, reg, 0x08, 0x0000); - miiphy_write (dev->name, reg, 0x1f, 0x0000); - /* end Vitesse/Cicada errata */ - } -#endif -#endif - /* Start/Restart autonegotiation */ - phy_setup_aneg (dev->name, reg); - udelay (1000); - } -#endif /* defined(CONFIG_PHY_RESET) */ - - miiphy_read (dev->name, reg, PHY_BMSR, ®_short); - - /* - * Wait if PHY is capable of autonegotiation and autonegotiation is not complete - */ - if ((reg_short & PHY_BMSR_AUTN_ABLE) - && !(reg_short & PHY_BMSR_AUTN_COMP)) { - puts ("Waiting for PHY auto negotiation to complete"); - i = 0; - while (!(reg_short & PHY_BMSR_AUTN_COMP)) { - /* - * Timeout reached ? - */ - if (i > PHY_AUTONEGOTIATE_TIMEOUT) { - puts (" TIMEOUT !\n"); - break; - } - - if ((i++ % 1000) == 0) { - putc ('.'); - } - udelay (1000); /* 1 ms */ - miiphy_read (dev->name, reg, PHY_BMSR, ®_short); - - } - puts (" done\n"); - udelay (500000); /* another 500 ms (results in faster booting) */ - } -#endif /* #ifndef CONFIG_CS8952_PHY */ - - speed = miiphy_speed (dev->name, reg); - duplex = miiphy_duplex (dev->name, reg); - - if (hw_p->print_speed) { - hw_p->print_speed = 0; - printf ("ENET Speed is %d Mbps - %s duplex connection\n", - (int) speed, (duplex == HALF) ? "HALF" : "FULL"); - } - -#if defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \ - !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) - mfsdr(sdr_mfr, reg); - if (speed == 100) { - reg = (reg & ~SDR0_MFR_ZMII_MODE_MASK) | SDR0_MFR_ZMII_MODE_RMII_100M; - } else { - reg = (reg & ~SDR0_MFR_ZMII_MODE_MASK) | SDR0_MFR_ZMII_MODE_RMII_10M; - } - mtsdr(sdr_mfr, reg); -#endif - - /* Set ZMII/RGMII speed according to the phy link speed */ - reg = in32 (ZMII_SSR); - if ( (speed == 100) || (speed == 1000) ) - out32 (ZMII_SSR, reg | (ZMII_SSR_SP << ZMII_SSR_V (devnum))); - else - out32 (ZMII_SSR, reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum)))); - - if ((devnum == 2) || (devnum == 3)) { - if (speed == 1000) - reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum)); - else if (speed == 100) - reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V (devnum)); - else if (speed == 10) - reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V (devnum)); - else { - printf("Error in RGMII Speed\n"); - return -1; - } - out32 (RGMII_SSR, reg); - } -#endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */ - -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - if (speed == 1000) - reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum)); - else if (speed == 100) - reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V (devnum)); - else if (speed == 10) - reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V (devnum)); - else { - printf("Error in RGMII Speed\n"); - return -1; - } - out32 (RGMII_SSR, reg); -#endif - - /* set the Mal configuration reg */ -#if defined(CONFIG_440GX) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) - mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | - MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000); -#else - mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT); - /* Errata 1.12: MAL_1 -- Disable MAL bursting */ - if (get_pvr() == PVR_440GP_RB) { - mtdcr (malmcr, mfdcr(malmcr) & ~MAL_CR_PLBB); - } -#endif - - /* Free "old" buffers */ - if (hw_p->alloc_tx_buf) - free (hw_p->alloc_tx_buf); - if (hw_p->alloc_rx_buf) - free (hw_p->alloc_rx_buf); - - /* - * Malloc MAL buffer desciptors, make sure they are - * aligned on cache line boundary size - * (401/403/IOP480 = 16, 405 = 32) - * and doesn't cross cache block boundaries. - */ - hw_p->alloc_tx_buf = - (mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_TX_BUFF) + - ((2 * CFG_CACHELINE_SIZE) - 2)); - if (NULL == hw_p->alloc_tx_buf) - return -1; - if (((int) hw_p->alloc_tx_buf & CACHELINE_MASK) != 0) { - hw_p->tx = - (mal_desc_t *) ((int) hw_p->alloc_tx_buf + - CFG_CACHELINE_SIZE - - ((int) hw_p-> - alloc_tx_buf & CACHELINE_MASK)); - } else { - hw_p->tx = hw_p->alloc_tx_buf; - } - - hw_p->alloc_rx_buf = - (mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_RX_BUFF) + - ((2 * CFG_CACHELINE_SIZE) - 2)); - if (NULL == hw_p->alloc_rx_buf) { - free(hw_p->alloc_tx_buf); - hw_p->alloc_tx_buf = NULL; - return -1; - } - - if (((int) hw_p->alloc_rx_buf & CACHELINE_MASK) != 0) { - hw_p->rx = - (mal_desc_t *) ((int) hw_p->alloc_rx_buf + - CFG_CACHELINE_SIZE - - ((int) hw_p-> - alloc_rx_buf & CACHELINE_MASK)); - } else { - hw_p->rx = hw_p->alloc_rx_buf; - } - - for (i = 0; i < NUM_TX_BUFF; i++) { - hw_p->tx[i].ctrl = 0; - hw_p->tx[i].data_len = 0; - if (hw_p->first_init == 0) { - hw_p->txbuf_ptr = - (char *) malloc (ENET_MAX_MTU_ALIGNED); - if (NULL == hw_p->txbuf_ptr) { - free(hw_p->alloc_rx_buf); - free(hw_p->alloc_tx_buf); - hw_p->alloc_rx_buf = NULL; - hw_p->alloc_tx_buf = NULL; - for(j = 0; j < i; j++) { - free(hw_p->tx[i].data_ptr); - hw_p->tx[i].data_ptr = NULL; - } - } - } - hw_p->tx[i].data_ptr = hw_p->txbuf_ptr; - if ((NUM_TX_BUFF - 1) == i) - hw_p->tx[i].ctrl |= MAL_TX_CTRL_WRAP; - hw_p->tx_run[i] = -1; - } - - for (i = 0; i < NUM_RX_BUFF; i++) { - hw_p->rx[i].ctrl = 0; - hw_p->rx[i].data_len = 0; - /* rx[i].data_ptr = (char *) &rx_buff[i]; */ - hw_p->rx[i].data_ptr = (char *) NetRxPackets[i]; - if ((NUM_RX_BUFF - 1) == i) - hw_p->rx[i].ctrl |= MAL_RX_CTRL_WRAP; - hw_p->rx[i].ctrl |= MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR; - hw_p->rx_ready[i] = -1; - } - - reg = 0x00000000; - - reg |= dev->enetaddr[0]; /* set high address */ - reg = reg << 8; - reg |= dev->enetaddr[1]; - - out32 (EMAC_IAH + hw_p->hw_addr, reg); - - reg = 0x00000000; - reg |= dev->enetaddr[2]; /* set low address */ - reg = reg << 8; - reg |= dev->enetaddr[3]; - reg = reg << 8; - reg |= dev->enetaddr[4]; - reg = reg << 8; - reg |= dev->enetaddr[5]; - - out32 (EMAC_IAL + hw_p->hw_addr, reg); - - switch (devnum) { - case 1: - /* setup MAL tx & rx channel pointers */ -#if defined (CONFIG_405EP) || defined (CONFIG_440EP) || defined (CONFIG_440GR) - mtdcr (maltxctp2r, hw_p->tx); -#else - mtdcr (maltxctp1r, hw_p->tx); -#endif -#if defined(CONFIG_440) - mtdcr (maltxbattr, 0x0); - mtdcr (malrxbattr, 0x0); -#endif - mtdcr (malrxctp1r, hw_p->rx); - /* set RX buffer size */ - mtdcr (malrcbs1, ENET_MAX_MTU_ALIGNED / 16); - break; -#if defined (CONFIG_440GX) - case 2: - /* setup MAL tx & rx channel pointers */ - mtdcr (maltxbattr, 0x0); - mtdcr (malrxbattr, 0x0); - mtdcr (maltxctp2r, hw_p->tx); - mtdcr (malrxctp2r, hw_p->rx); - /* set RX buffer size */ - mtdcr (malrcbs2, ENET_MAX_MTU_ALIGNED / 16); - break; - case 3: - /* setup MAL tx & rx channel pointers */ - mtdcr (maltxbattr, 0x0); - mtdcr (maltxctp3r, hw_p->tx); - mtdcr (malrxbattr, 0x0); - mtdcr (malrxctp3r, hw_p->rx); - /* set RX buffer size */ - mtdcr (malrcbs3, ENET_MAX_MTU_ALIGNED / 16); - break; -#endif /* CONFIG_440GX */ - case 0: - default: - /* setup MAL tx & rx channel pointers */ -#if defined(CONFIG_440) - mtdcr (maltxbattr, 0x0); - mtdcr (malrxbattr, 0x0); -#endif - mtdcr (maltxctp0r, hw_p->tx); - mtdcr (malrxctp0r, hw_p->rx); - /* set RX buffer size */ - mtdcr (malrcbs0, ENET_MAX_MTU_ALIGNED / 16); - break; - } - - /* Enable MAL transmit and receive channels */ -#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) - mtdcr (maltxcasr, (MAL_TXRX_CASR >> (hw_p->devnum*2))); -#else - mtdcr (maltxcasr, (MAL_TXRX_CASR >> hw_p->devnum)); -#endif - mtdcr (malrxcasr, (MAL_TXRX_CASR >> hw_p->devnum)); - - /* set transmit enable & receive enable */ - out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_TXE | EMAC_M0_RXE); - - /* set receive fifo to 4k and tx fifo to 2k */ - mode_reg = in32 (EMAC_M1 + hw_p->hw_addr); - mode_reg |= EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K; - - /* set speed */ - if (speed == _1000BASET) { -#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - unsigned long pfc1; - - mfsdr (sdr_pfc1, pfc1); - pfc1 |= SDR0_PFC1_EM_1000; - mtsdr (sdr_pfc1, pfc1); -#endif - mode_reg = mode_reg | EMAC_M1_MF_1000MBPS | EMAC_M1_IST; - } else if (speed == _100BASET) - mode_reg = mode_reg | EMAC_M1_MF_100MBPS | EMAC_M1_IST; - else - mode_reg = mode_reg & ~0x00C00000; /* 10 MBPS */ - if (duplex == FULL) - mode_reg = mode_reg | 0x80000000 | EMAC_M1_IST; - - out32 (EMAC_M1 + hw_p->hw_addr, mode_reg); - - /* Enable broadcast and indvidual address */ - /* TBS: enabling runts as some misbehaved nics will send runts */ - out32 (EMAC_RXM + hw_p->hw_addr, EMAC_RMR_BAE | EMAC_RMR_IAE); - - /* we probably need to set the tx mode1 reg? maybe at tx time */ - - /* set transmit request threshold register */ - out32 (EMAC_TRTR + hw_p->hw_addr, 0x18000000); /* 256 byte threshold */ - - /* set receive low/high water mark register */ -#if defined(CONFIG_440) - /* 440s has a 64 byte burst length */ - out32 (EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x80009000); -#else - /* 405s have a 16 byte burst length */ - out32 (EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x0f002000); -#endif /* defined(CONFIG_440) */ - out32 (EMAC_TXM1 + hw_p->hw_addr, 0xf8640000); - - /* Set fifo limit entry in tx mode 0 */ - out32 (EMAC_TXM0 + hw_p->hw_addr, 0x00000003); - /* Frame gap set */ - out32 (EMAC_I_FRAME_GAP_REG + hw_p->hw_addr, 0x00000008); - - /* Set EMAC IER */ - hw_p->emac_ier = EMAC_ISR_PTLE | EMAC_ISR_BFCS | EMAC_ISR_ORE | EMAC_ISR_IRE; - if (speed == _100BASET) - hw_p->emac_ier = hw_p->emac_ier | EMAC_ISR_SYE; - - out32 (EMAC_ISR + hw_p->hw_addr, 0xffffffff); /* clear pending interrupts */ - out32 (EMAC_IER + hw_p->hw_addr, hw_p->emac_ier); - - if (hw_p->first_init == 0) { - /* - * Connect interrupt service routines - */ - irq_install_handler (VECNUM_ETH0 + (hw_p->devnum * 2), - (interrupt_handler_t *) enetInt, dev); - } - - mtmsr (msr); /* enable interrupts again */ - - hw_p->bis = bis; - hw_p->first_init = 1; - - return (1); -} - - -static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr, - int len) -{ - struct enet_frame *ef_ptr; - ulong time_start, time_now; - unsigned long temp_txm0; - EMAC_4XX_HW_PST hw_p = dev->priv; - - ef_ptr = (struct enet_frame *) ptr; - - /*-----------------------------------------------------------------------+ - * Copy in our address into the frame. - *-----------------------------------------------------------------------*/ - (void) memcpy (ef_ptr->source_addr, dev->enetaddr, ENET_ADDR_LENGTH); - - /*-----------------------------------------------------------------------+ - * If frame is too long or too short, modify length. - *-----------------------------------------------------------------------*/ - /* TBS: where does the fragment go???? */ - if (len > ENET_MAX_MTU) - len = ENET_MAX_MTU; - - /* memcpy ((void *) &tx_buff[tx_slot], (const void *) ptr, len); */ - memcpy ((void *) hw_p->txbuf_ptr, (const void *) ptr, len); - - /*-----------------------------------------------------------------------+ - * set TX Buffer busy, and send it - *-----------------------------------------------------------------------*/ - hw_p->tx[hw_p->tx_slot].ctrl = (MAL_TX_CTRL_LAST | - EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP) & - ~(EMAC_TX_CTRL_ISA | EMAC_TX_CTRL_RSA); - if ((NUM_TX_BUFF - 1) == hw_p->tx_slot) - hw_p->tx[hw_p->tx_slot].ctrl |= MAL_TX_CTRL_WRAP; - - hw_p->tx[hw_p->tx_slot].data_len = (short) len; - hw_p->tx[hw_p->tx_slot].ctrl |= MAL_TX_CTRL_READY; - - __asm__ volatile ("eieio"); - - out32 (EMAC_TXM0 + hw_p->hw_addr, - in32 (EMAC_TXM0 + hw_p->hw_addr) | EMAC_TXM0_GNP0); -#ifdef INFO_4XX_ENET - hw_p->stats.pkts_tx++; -#endif - - /*-----------------------------------------------------------------------+ - * poll unitl the packet is sent and then make sure it is OK - *-----------------------------------------------------------------------*/ - time_start = get_timer (0); - while (1) { - temp_txm0 = in32 (EMAC_TXM0 + hw_p->hw_addr); - /* loop until either TINT turns on or 3 seconds elapse */ - if ((temp_txm0 & EMAC_TXM0_GNP0) != 0) { - /* transmit is done, so now check for errors - * If there is an error, an interrupt should - * happen when we return - */ - time_now = get_timer (0); - if ((time_now - time_start) > 3000) { - return (-1); - } - } else { - return (len); - } - } -} - - -#if defined (CONFIG_440) - -#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) -/* - * Hack: On 440SP all enet irq sources are located on UIC1 - * Needs some cleanup. --sr - */ -#define UIC0MSR uic1msr -#define UIC0SR uic1sr -#else -#define UIC0MSR uic0msr -#define UIC0SR uic0sr -#endif - -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -#define UICMSR_ETHX uic0msr -#define UICSR_ETHX uic0sr -#else -#define UICMSR_ETHX uic1msr -#define UICSR_ETHX uic1sr -#endif - -int enetInt (struct eth_device *dev) -{ - int serviced; - int rc = -1; /* default to not us */ - unsigned long mal_isr; - unsigned long emac_isr = 0; - unsigned long mal_rx_eob; - unsigned long my_uic0msr, my_uic1msr; - unsigned long my_uicmsr_ethx; - -#if defined(CONFIG_440GX) - unsigned long my_uic2msr; -#endif - EMAC_4XX_HW_PST hw_p; - - /* - * Because the mal is generic, we need to get the current - * eth device - */ -#if defined(CONFIG_NET_MULTI) - dev = eth_get_dev(); -#else - dev = emac0_dev; -#endif - - hw_p = dev->priv; - - /* enter loop that stays in interrupt code until nothing to service */ - do { - serviced = 0; - - my_uic0msr = mfdcr (UIC0MSR); - my_uic1msr = mfdcr (uic1msr); -#if defined(CONFIG_440GX) - my_uic2msr = mfdcr (uic2msr); -#endif - my_uicmsr_ethx = mfdcr (UICMSR_ETHX); - - if (!(my_uic0msr & (UIC_MRE | UIC_MTE)) - && !(my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE)) - && !(my_uicmsr_ethx & (UIC_ETH0 | UIC_ETH1))) { - /* not for us */ - return (rc); - } -#if defined (CONFIG_440GX) - if (!(my_uic0msr & (UIC_MRE | UIC_MTE)) - && !(my_uic2msr & (UIC_ETH2 | UIC_ETH3))) { - /* not for us */ - return (rc); - } -#endif - /* get and clear controller status interrupts */ - /* look at Mal and EMAC interrupts */ - if ((my_uic0msr & (UIC_MRE | UIC_MTE)) - || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { - /* we have a MAL interrupt */ - mal_isr = mfdcr (malesr); - /* look for mal error */ - if (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE)) { - mal_err (dev, mal_isr, my_uic1msr, MAL_UIC_DEF, MAL_UIC_ERR); - serviced = 1; - rc = 0; - } - } - - /* port by port dispatch of emac interrupts */ - if (hw_p->devnum == 0) { - if (UIC_ETH0 & my_uicmsr_ethx) { /* look for EMAC errors */ - emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); - if ((hw_p->emac_ier & emac_isr) != 0) { - emac_err (dev, emac_isr); - serviced = 1; - rc = 0; - } - } - if ((hw_p->emac_ier & emac_isr) - || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { - mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */ - mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ - mtdcr (UICSR_ETHX, UIC_ETH0); /* Clear */ - return (rc); /* we had errors so get out */ - } - } - -#if !defined(CONFIG_440SP) - if (hw_p->devnum == 1) { - if (UIC_ETH1 & my_uicmsr_ethx) { /* look for EMAC errors */ - emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); - if ((hw_p->emac_ier & emac_isr) != 0) { - emac_err (dev, emac_isr); - serviced = 1; - rc = 0; - } - } - if ((hw_p->emac_ier & emac_isr) - || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { - mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */ - mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ - mtdcr (UICSR_ETHX, UIC_ETH1); /* Clear */ - return (rc); /* we had errors so get out */ - } - } -#if defined (CONFIG_440GX) - if (hw_p->devnum == 2) { - if (UIC_ETH2 & my_uic2msr) { /* look for EMAC errors */ - emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); - if ((hw_p->emac_ier & emac_isr) != 0) { - emac_err (dev, emac_isr); - serviced = 1; - rc = 0; - } - } - if ((hw_p->emac_ier & emac_isr) - || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { - mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */ - mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ - mtdcr (uic2sr, UIC_ETH2); - return (rc); /* we had errors so get out */ - } - } - - if (hw_p->devnum == 3) { - if (UIC_ETH3 & my_uic2msr) { /* look for EMAC errors */ - emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); - if ((hw_p->emac_ier & emac_isr) != 0) { - emac_err (dev, emac_isr); - serviced = 1; - rc = 0; - } - } - if ((hw_p->emac_ier & emac_isr) - || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { - mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */ - mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ - mtdcr (uic2sr, UIC_ETH3); - return (rc); /* we had errors so get out */ - } - } -#endif /* CONFIG_440GX */ -#endif /* !CONFIG_440SP */ - - /* handle MAX TX EOB interrupt from a tx */ - if (my_uic0msr & UIC_MTE) { - mal_rx_eob = mfdcr (maltxeobisr); - mtdcr (maltxeobisr, mal_rx_eob); - mtdcr (UIC0SR, UIC_MTE); - } - /* handle MAL RX EOB interupt from a receive */ - /* check for EOB on valid channels */ - if (my_uic0msr & UIC_MRE) { - mal_rx_eob = mfdcr (malrxeobisr); - if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */ - /* clear EOB - mtdcr(malrxeobisr, mal_rx_eob); */ - enet_rcv (dev, emac_isr); - /* indicate that we serviced an interrupt */ - serviced = 1; - rc = 0; - } - } - - mtdcr (UIC0SR, UIC_MRE); /* Clear */ - mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ - switch (hw_p->devnum) { - case 0: - mtdcr (UICSR_ETHX, UIC_ETH0); - break; - case 1: - mtdcr (UICSR_ETHX, UIC_ETH1); - break; -#if defined (CONFIG_440GX) - case 2: - mtdcr (uic2sr, UIC_ETH2); - break; - case 3: - mtdcr (uic2sr, UIC_ETH3); - break; -#endif /* CONFIG_440GX */ - default: - break; - } - } while (serviced); - - return (rc); -} - -#else /* CONFIG_440 */ - -int enetInt (struct eth_device *dev) -{ - int serviced; - int rc = -1; /* default to not us */ - unsigned long mal_isr; - unsigned long emac_isr = 0; - unsigned long mal_rx_eob; - unsigned long my_uicmsr; - - EMAC_4XX_HW_PST hw_p; - - /* - * Because the mal is generic, we need to get the current - * eth device - */ -#if defined(CONFIG_NET_MULTI) - dev = eth_get_dev(); -#else - dev = emac0_dev; -#endif - - hw_p = dev->priv; - - /* enter loop that stays in interrupt code until nothing to service */ - do { - serviced = 0; - - my_uicmsr = mfdcr (uicmsr); - - if ((my_uicmsr & (MAL_UIC_DEF | EMAC_UIC_DEF)) == 0) { /* not for us */ - return (rc); - } - /* get and clear controller status interrupts */ - /* look at Mal and EMAC interrupts */ - if ((MAL_UIC_DEF & my_uicmsr) != 0) { /* we have a MAL interrupt */ - mal_isr = mfdcr (malesr); - /* look for mal error */ - if ((my_uicmsr & MAL_UIC_ERR) != 0) { - mal_err (dev, mal_isr, my_uicmsr, MAL_UIC_DEF, MAL_UIC_ERR); - serviced = 1; - rc = 0; - } - } - - /* port by port dispatch of emac interrupts */ - - if ((SEL_UIC_DEF(hw_p->devnum) & my_uicmsr) != 0) { /* look for EMAC errors */ - emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); - if ((hw_p->emac_ier & emac_isr) != 0) { - emac_err (dev, emac_isr); - serviced = 1; - rc = 0; - } - } - if (((hw_p->emac_ier & emac_isr) != 0) || ((MAL_UIC_ERR & my_uicmsr) != 0)) { - mtdcr (uicsr, MAL_UIC_DEF | SEL_UIC_DEF(hw_p->devnum)); /* Clear */ - return (rc); /* we had errors so get out */ - } - - /* handle MAX TX EOB interrupt from a tx */ - if (my_uicmsr & UIC_MAL_TXEOB) { - mal_rx_eob = mfdcr (maltxeobisr); - mtdcr (maltxeobisr, mal_rx_eob); - mtdcr (uicsr, UIC_MAL_TXEOB); - } - /* handle MAL RX EOB interupt from a receive */ - /* check for EOB on valid channels */ - if (my_uicmsr & UIC_MAL_RXEOB) - { - mal_rx_eob = mfdcr (malrxeobisr); - if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */ - /* clear EOB - mtdcr(malrxeobisr, mal_rx_eob); */ - enet_rcv (dev, emac_isr); - /* indicate that we serviced an interrupt */ - serviced = 1; - rc = 0; - } - } - mtdcr (uicsr, MAL_UIC_DEF|EMAC_UIC_DEF|EMAC_UIC_DEF1); /* Clear */ - } - while (serviced); - - return (rc); -} - -#endif /* CONFIG_440 */ - -/*-----------------------------------------------------------------------------+ - * MAL Error Routine - *-----------------------------------------------------------------------------*/ -static void mal_err (struct eth_device *dev, unsigned long isr, - unsigned long uic, unsigned long maldef, - unsigned long mal_errr) -{ - EMAC_4XX_HW_PST hw_p = dev->priv; - - mtdcr (malesr, isr); /* clear interrupt */ - - /* clear DE interrupt */ - mtdcr (maltxdeir, 0xC0000000); - mtdcr (malrxdeir, 0x80000000); - -#ifdef INFO_4XX_ENET - printf ("\nMAL error occured.... ISR = %lx UIC = = %lx MAL_DEF = %lx MAL_ERR= %lx \n", isr, uic, maldef, mal_errr); -#endif - - eth_init (hw_p->bis); /* start again... */ -} - -/*-----------------------------------------------------------------------------+ - * EMAC Error Routine - *-----------------------------------------------------------------------------*/ -static void emac_err (struct eth_device *dev, unsigned long isr) -{ - EMAC_4XX_HW_PST hw_p = dev->priv; - - printf ("EMAC%d error occured.... ISR = %lx\n", hw_p->devnum, isr); - out32 (EMAC_ISR + hw_p->hw_addr, isr); -} - -/*-----------------------------------------------------------------------------+ - * enet_rcv() handles the ethernet receive data - *-----------------------------------------------------------------------------*/ -static void enet_rcv (struct eth_device *dev, unsigned long malisr) -{ - struct enet_frame *ef_ptr; - unsigned long data_len; - unsigned long rx_eob_isr; - EMAC_4XX_HW_PST hw_p = dev->priv; - - int handled = 0; - int i; - int loop_count = 0; - - rx_eob_isr = mfdcr (malrxeobisr); - if ((0x80000000 >> hw_p->devnum) & rx_eob_isr) { - /* clear EOB */ - mtdcr (malrxeobisr, rx_eob_isr); - - /* EMAC RX done */ - while (1) { /* do all */ - i = hw_p->rx_slot; - - if ((MAL_RX_CTRL_EMPTY & hw_p->rx[i].ctrl) - || (loop_count >= NUM_RX_BUFF)) - break; - loop_count++; - hw_p->rx_slot++; - if (NUM_RX_BUFF == hw_p->rx_slot) - hw_p->rx_slot = 0; - handled++; - data_len = (unsigned long) hw_p->rx[i].data_len; /* Get len */ - if (data_len) { - if (data_len > ENET_MAX_MTU) /* Check len */ - data_len = 0; - else { - if (EMAC_RX_ERRORS & hw_p->rx[i].ctrl) { /* Check Errors */ - data_len = 0; - hw_p->stats.rx_err_log[hw_p-> - rx_err_index] - = hw_p->rx[i].ctrl; - hw_p->rx_err_index++; - if (hw_p->rx_err_index == - MAX_ERR_LOG) - hw_p->rx_err_index = - 0; - } /* emac_erros */ - } /* data_len < max mtu */ - } /* if data_len */ - if (!data_len) { /* no data */ - hw_p->rx[i].ctrl |= MAL_RX_CTRL_EMPTY; /* Free Recv Buffer */ - - hw_p->stats.data_len_err++; /* Error at Rx */ - } - - /* !data_len */ - /* AS.HARNOIS */ - /* Check if user has already eaten buffer */ - /* if not => ERROR */ - else if (hw_p->rx_ready[hw_p->rx_i_index] != -1) { - if (hw_p->is_receiving) - printf ("ERROR : Receive buffers are full!\n"); - break; - } else { - hw_p->stats.rx_frames++; - hw_p->stats.rx += data_len; - ef_ptr = (struct enet_frame *) hw_p->rx[i]. - data_ptr; -#ifdef INFO_4XX_ENET - hw_p->stats.pkts_rx++; -#endif - /* AS.HARNOIS - * use ring buffer - */ - hw_p->rx_ready[hw_p->rx_i_index] = i; - hw_p->rx_i_index++; - if (NUM_RX_BUFF == hw_p->rx_i_index) - hw_p->rx_i_index = 0; - - /* AS.HARNOIS - * free receive buffer only when - * buffer has been handled (eth_rx) - rx[i].ctrl |= MAL_RX_CTRL_EMPTY; - */ - } /* if data_len */ - } /* while */ - } /* if EMACK_RXCHL */ -} - - -static int ppc_4xx_eth_rx (struct eth_device *dev) -{ - int length; - int user_index; - unsigned long msr; - EMAC_4XX_HW_PST hw_p = dev->priv; - - hw_p->is_receiving = 1; /* tell driver */ - - for (;;) { - /* AS.HARNOIS - * use ring buffer and - * get index from rx buffer desciptor queue - */ - user_index = hw_p->rx_ready[hw_p->rx_u_index]; - if (user_index == -1) { - length = -1; - break; /* nothing received - leave for() loop */ - } - - msr = mfmsr (); - mtmsr (msr & ~(MSR_EE)); - - length = hw_p->rx[user_index].data_len; - - /* Pass the packet up to the protocol layers. */ - /* NetReceive(NetRxPackets[rxIdx], length - 4); */ - /* NetReceive(NetRxPackets[i], length); */ - NetReceive (NetRxPackets[user_index], length - 4); - /* Free Recv Buffer */ - hw_p->rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY; - /* Free rx buffer descriptor queue */ - hw_p->rx_ready[hw_p->rx_u_index] = -1; - hw_p->rx_u_index++; - if (NUM_RX_BUFF == hw_p->rx_u_index) - hw_p->rx_u_index = 0; - -#ifdef INFO_4XX_ENET - hw_p->stats.pkts_handled++; -#endif - - mtmsr (msr); /* Enable IRQ's */ - } - - hw_p->is_receiving = 0; /* tell driver */ - - return length; -} - -int ppc_4xx_eth_initialize (bd_t * bis) -{ - static int virgin = 0; - struct eth_device *dev; - int eth_num = 0; - EMAC_4XX_HW_PST hw = NULL; - -#if defined(CONFIG_440GX) - unsigned long pfc1; - - mfsdr (sdr_pfc1, pfc1); - pfc1 &= ~(0x01e00000); - pfc1 |= 0x01200000; - mtsdr (sdr_pfc1, pfc1); -#endif - /* set phy num and mode */ - bis->bi_phynum[0] = CONFIG_PHY_ADDR; - bis->bi_phymode[0] = 0; - -#if defined(CONFIG_PHY1_ADDR) - bis->bi_phynum[1] = CONFIG_PHY1_ADDR; - bis->bi_phymode[1] = 0; -#endif -#if defined(CONFIG_440GX) - bis->bi_phynum[2] = CONFIG_PHY2_ADDR; - bis->bi_phynum[3] = CONFIG_PHY3_ADDR; - bis->bi_phymode[2] = 2; - bis->bi_phymode[3] = 2; - - ppc_4xx_eth_setup_bridge(0, bis); -#endif - - for (eth_num = 0; eth_num < LAST_EMAC_NUM; eth_num++) { - - /* See if we can actually bring up the interface, otherwise, skip it */ - switch (eth_num) { - default: /* fall through */ - case 0: - if (memcmp (bis->bi_enetaddr, "\0\0\0\0\0\0", 6) == 0) { - bis->bi_phymode[eth_num] = BI_PHYMODE_NONE; - continue; - } - break; -#ifdef CONFIG_HAS_ETH1 - case 1: - if (memcmp (bis->bi_enet1addr, "\0\0\0\0\0\0", 6) == 0) { - bis->bi_phymode[eth_num] = BI_PHYMODE_NONE; - continue; - } - break; -#endif -#ifdef CONFIG_HAS_ETH2 - case 2: - if (memcmp (bis->bi_enet2addr, "\0\0\0\0\0\0", 6) == 0) { - bis->bi_phymode[eth_num] = BI_PHYMODE_NONE; - continue; - } - break; -#endif -#ifdef CONFIG_HAS_ETH3 - case 3: - if (memcmp (bis->bi_enet3addr, "\0\0\0\0\0\0", 6) == 0) { - bis->bi_phymode[eth_num] = BI_PHYMODE_NONE; - continue; - } - break; -#endif - } - - /* Allocate device structure */ - dev = (struct eth_device *) malloc (sizeof (*dev)); - if (dev == NULL) { - printf ("ppc_4xx_eth_initialize: " - "Cannot allocate eth_device %d\n", eth_num); - return (-1); - } - memset(dev, 0, sizeof(*dev)); - - /* Allocate our private use data */ - hw = (EMAC_4XX_HW_PST) malloc (sizeof (*hw)); - if (hw == NULL) { - printf ("ppc_4xx_eth_initialize: " - "Cannot allocate private hw data for eth_device %d", - eth_num); - free (dev); - return (-1); - } - memset(hw, 0, sizeof(*hw)); - - switch (eth_num) { - default: /* fall through */ - case 0: - hw->hw_addr = 0; - memcpy (dev->enetaddr, bis->bi_enetaddr, 6); - break; -#ifdef CONFIG_HAS_ETH1 - case 1: - hw->hw_addr = 0x100; - memcpy (dev->enetaddr, bis->bi_enet1addr, 6); - break; -#endif -#ifdef CONFIG_HAS_ETH2 - case 2: - hw->hw_addr = 0x400; - memcpy (dev->enetaddr, bis->bi_enet2addr, 6); - break; -#endif -#ifdef CONFIG_HAS_ETH3 - case 3: - hw->hw_addr = 0x600; - memcpy (dev->enetaddr, bis->bi_enet3addr, 6); - break; -#endif - } - - hw->devnum = eth_num; - hw->print_speed = 1; - - sprintf (dev->name, "ppc_4xx_eth%d", eth_num); - dev->priv = (void *) hw; - dev->init = ppc_4xx_eth_init; - dev->halt = ppc_4xx_eth_halt; - dev->send = ppc_4xx_eth_send; - dev->recv = ppc_4xx_eth_rx; - - if (0 == virgin) { - /* set the MAL IER ??? names may change with new spec ??? */ -#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - mal_ier = - MAL_IER_PT | MAL_IER_PRE | MAL_IER_PWE | - MAL_IER_DE | MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE ; -#else - mal_ier = - MAL_IER_DE | MAL_IER_NE | MAL_IER_TE | - MAL_IER_OPBE | MAL_IER_PLBE; -#endif - mtdcr (malesr, 0xffffffff); /* clear pending interrupts */ - mtdcr (maltxdeir, 0xffffffff); /* clear pending interrupts */ - mtdcr (malrxdeir, 0xffffffff); /* clear pending interrupts */ - mtdcr (malier, mal_ier); - - /* install MAL interrupt handler */ - irq_install_handler (VECNUM_MS, - (interrupt_handler_t *) enetInt, - dev); - irq_install_handler (VECNUM_MTE, - (interrupt_handler_t *) enetInt, - dev); - irq_install_handler (VECNUM_MRE, - (interrupt_handler_t *) enetInt, - dev); - irq_install_handler (VECNUM_TXDE, - (interrupt_handler_t *) enetInt, - dev); - irq_install_handler (VECNUM_RXDE, - (interrupt_handler_t *) enetInt, - dev); - virgin = 1; - } - -#if defined(CONFIG_NET_MULTI) - eth_register (dev); -#else - emac0_dev = dev; -#endif - -#if defined(CONFIG_NET_MULTI) -#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) - miiphy_register (dev->name, - emac4xx_miiphy_read, emac4xx_miiphy_write); -#endif -#endif - } /* end for each supported device */ - return (1); -} - - -#if !defined(CONFIG_NET_MULTI) -void eth_halt (void) { - if (emac0_dev) { - ppc_4xx_eth_halt(emac0_dev); - free(emac0_dev); - emac0_dev = NULL; - } -} - -int eth_init (bd_t *bis) -{ - ppc_4xx_eth_initialize(bis); - if (emac0_dev) { - return ppc_4xx_eth_init(emac0_dev, bis); - } else { - printf("ERROR: ethaddr not set!\n"); - return -1; - } -} - -int eth_send(volatile void *packet, int length) -{ - return (ppc_4xx_eth_send(emac0_dev, packet, length)); -} - -int eth_rx(void) -{ - return (ppc_4xx_eth_rx(emac0_dev)); -} - -int emac4xx_miiphy_initialize (bd_t * bis) -{ -#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) - miiphy_register ("ppc_4xx_eth0", - emac4xx_miiphy_read, emac4xx_miiphy_write); -#endif - - return 0; -} -#endif /* !defined(CONFIG_NET_MULTI) */ - -#endif /* #if (CONFIG_COMMANDS & CFG_CMD_NET) */ |