#include <405_mal.h>
#include <miiphy.h>
#include <malloc.h>
-#include "vecnum.h"
/*
* Only compile for platform with AMCC EMAC ethernet controller and
* 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 )
+#define ETH_IRQ_NUM(dev) (VECNUM_ETH0 + ((dev) * VECNUM_ETH1_OFFS))
+
+#if defined(CONFIG_HAS_ETH3)
+#if !defined(CONFIG_440GX)
+#define UIC_ETHx (UIC_MASK(ETH_IRQ_NUM(0)) || UIC_MASK(ETH_IRQ_NUM(1)) || \
+ UIC_MASK(ETH_IRQ_NUM(2)) || UIC_MASK(ETH_IRQ_NUM(3)))
+#else
+/* Unfortunately 440GX spreads EMAC interrupts on multiple UIC's */
+#define UIC_ETHx (UIC_MASK(ETH_IRQ_NUM(0)) || UIC_MASK(ETH_IRQ_NUM(1)))
+#define UIC_ETHxB (UIC_MASK(ETH_IRQ_NUM(2)) || UIC_MASK(ETH_IRQ_NUM(3)))
+#endif /* !defined(CONFIG_440GX) */
+#elif defined(CONFIG_HAS_ETH2)
+#define UIC_ETHx (UIC_MASK(ETH_IRQ_NUM(0)) || UIC_MASK(ETH_IRQ_NUM(1)) || \
+ UIC_MASK(ETH_IRQ_NUM(2)))
+#elif defined(CONFIG_HAS_ETH1)
+#define UIC_ETHx (UIC_MASK(ETH_IRQ_NUM(0)) || UIC_MASK(ETH_IRQ_NUM(1)))
+#else
+#define UIC_ETHx UIC_MASK(ETH_IRQ_NUM(0))
+#endif
+
+/*
+ * Define a default version for UIC_ETHxB for non 440GX so that we can
+ * use common code for all 4xx variants
+ */
+#if !defined(UIC_ETHxB)
+#define UIC_ETHxB 0
+#endif
+
+#define UIC_MAL_SERR UIC_MASK(VECNUM_MAL_SERR)
+#define UIC_MAL_TXDE UIC_MASK(VECNUM_MAL_TXDE)
+#define UIC_MAL_RXDE UIC_MASK(VECNUM_MAL_RXDE)
+#define UIC_MAL_TXEOB UIC_MASK(VECNUM_MAL_TXEOB)
+#define UIC_MAL_RXEOB UIC_MASK(VECNUM_MAL_RXEOB)
+
+#define MAL_UIC_ERR (UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE)
+#define MAL_UIC_DEF (UIC_MAL_RXEOB | MAL_UIC_ERR)
+
+/*
+ * We have 3 different interrupt types:
+ * - MAL interrupts indicating successful transfer
+ * - MAL error interrupts indicating MAL related errors
+ * - EMAC interrupts indicating EMAC related errors
+ *
+ * All those interrupts can be on different UIC's, but since
+ * now at least all interrupts from one type are on the same
+ * UIC. Only exception is 440GX where the EMAC interrupts are
+ * spread over two UIC's!
+ */
+#if defined(CONFIG_440GX)
+#define UIC_BASE_MAL UIC1_DCR_BASE
+#define UIC_BASE_MAL_ERR UIC2_DCR_BASE
+#define UIC_BASE_EMAC UIC2_DCR_BASE
+#define UIC_BASE_EMAC_B UIC3_DCR_BASE
+#else
+#define UIC_BASE_MAL (UIC0_DCR_BASE + (UIC_NR(VECNUM_MAL_TXEOB) * 0x10))
+#define UIC_BASE_MAL_ERR (UIC0_DCR_BASE + (UIC_NR(VECNUM_MAL_SERR) * 0x10))
+#define UIC_BASE_EMAC (UIC0_DCR_BASE + (UIC_NR(ETH_IRQ_NUM(0)) * 0x10))
+#define UIC_BASE_EMAC_B (UIC0_DCR_BASE + (UIC_NR(ETH_IRQ_NUM(0)) * 0x10))
+#endif
#undef INFO_4XX_ENET
#define BI_PHYMODE_RTBI 4
#define BI_PHYMODE_TBI 5
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
#define BI_PHYMODE_SMII 6
#define BI_PHYMODE_MII 7
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define BI_PHYMODE_RMII 8
+#endif
#endif
+#define BI_PHYMODE_SGMII 9
#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
#define SDR0_MFR_ETH_CLK_SEL_V(n) ((0x01<<27) / (n+1))
#endif
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define SDR0_ETH_CFG_CLK_SEL_V(n) (0x01 << (8 + n))
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define MAL_RX_CHAN_MUL 8 /* 460EX/GT uses MAL channel 8 for EMAC1 */
+#else
+#define MAL_RX_CHAN_MUL 1
+#endif
+
+/*--------------------------------------------------------------------+
+ * Fixed PHY (PHY-less) support for Ethernet Ports.
+ *--------------------------------------------------------------------*/
+
+/*
+ * Some boards do not have a PHY for each ethernet port. These ports
+ * are known as Fixed PHY (or PHY-less) ports. For such ports, set
+ * the appropriate CONFIG_PHY_ADDR equal to CONFIG_FIXED_PHY and
+ * then define CONFIG_SYS_FIXED_PHY_PORTS to define what the speed and
+ * duplex should be for these ports in the board configuration
+ * file.
+ *
+ * For Example:
+ * #define CONFIG_FIXED_PHY 0xFFFFFFFF
+ *
+ * #define CONFIG_PHY_ADDR CONFIG_FIXED_PHY
+ * #define CONFIG_PHY1_ADDR 1
+ * #define CONFIG_PHY2_ADDR CONFIG_FIXED_PHY
+ * #define CONFIG_PHY3_ADDR 3
+ *
+ * #define CONFIG_SYS_FIXED_PHY_PORT(devnum,speed,duplex) \
+ * {devnum, speed, duplex},
+ *
+ * #define CONFIG_SYS_FIXED_PHY_PORTS \
+ * CONFIG_SYS_FIXED_PHY_PORT(0,1000,FULL) \
+ * CONFIG_SYS_FIXED_PHY_PORT(2,100,HALF)
+ */
+
+#ifndef CONFIG_FIXED_PHY
+#define CONFIG_FIXED_PHY 0xFFFFFFFF /* Fixed PHY (PHY-less) */
+#endif
+
+#ifndef CONFIG_SYS_FIXED_PHY_PORTS
+#define CONFIG_SYS_FIXED_PHY_PORTS /* default is an empty array */
+#endif
+
+struct fixed_phy_port {
+ unsigned int devnum; /* ethernet port */
+ unsigned int speed; /* specified speed 10,100 or 1000 */
+ unsigned int duplex; /* specified duplex FULL or HALF */
+};
+
+static const struct fixed_phy_port fixed_phy_port[] = {
+ CONFIG_SYS_FIXED_PHY_PORTS /* defined in board configuration file */
+};
+
/*-----------------------------------------------------------------------------+
* 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
#define CONFIG_EMAC_NR_START 0
#endif
-#if defined(CONFIG_405EX) || defined(CONFIG_440EPX)
-#define ETH_IRQ_NUM(dev) (VECNUM_ETH0 + ((dev)))
-#else
-#define ETH_IRQ_NUM(dev) (VECNUM_ETH0 + ((dev) * 2))
-#endif
-
#define MAL_RX_DESC_SIZE 2048
#define MAL_TX_DESC_SIZE 2048
#define MAL_ALLOC_SIZE (MAL_TX_DESC_SIZE + MAL_RX_DESC_SIZE)
int board_emac_count(void);
+static void emac_loopback_enable(EMAC_4XX_HW_PST hw_p)
+{
+#if defined(CONFIG_440SPE) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_405EX)
+ u32 val;
+
+ mfsdr(sdr_mfr, val);
+ val |= SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
+ mtsdr(sdr_mfr, val);
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ u32 val;
+
+ mfsdr(SDR0_ETH_CFG, val);
+ val |= SDR0_ETH_CFG_CLK_SEL_V(hw_p->devnum);
+ mtsdr(SDR0_ETH_CFG, val);
+#endif
+}
+
+static void emac_loopback_disable(EMAC_4XX_HW_PST hw_p)
+{
+#if defined(CONFIG_440SPE) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_405EX)
+ u32 val;
+
+ mfsdr(sdr_mfr, val);
+ val &= ~SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
+ mtsdr(sdr_mfr, val);
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ u32 val;
+
+ mfsdr(SDR0_ETH_CFG, val);
+ val &= ~SDR0_ETH_CFG_CLK_SEL_V(hw_p->devnum);
+ mtsdr(SDR0_ETH_CFG, val);
+#endif
+}
+
/*-----------------------------------------------------------------------------+
| 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) || \
- defined(CONFIG_405EX)
- unsigned long mfr;
-#endif
+ u32 val = 10000;
out_be32((void *)EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */
/* 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)
+ val--;
+ if (val == 0)
break;
}
- /* EMAC RESET */
-#if defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EX)
/* 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
+ emac_loopback_enable(hw_p);
+ /* EMAC RESET */
out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
-#if defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EX)
/* 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
-
+ emac_loopback_disable(hw_p);
#ifndef CONFIG_NETCONSOLE
hw_p->print_speed = 1; /* print speed message again next time */
#endif
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ /* don't bypass the TAHOE0/TAHOE1 cores for Linux */
+ mfsdr(SDR0_ETH_CFG, val);
+ val &= ~(SDR0_ETH_CFG_TAHOE0_BYPASS | SDR0_ETH_CFG_TAHOE1_BYPASS);
+ mtsdr(SDR0_ETH_CFG, val);
+#endif
+
return;
}
#if defined(CONFIG_405EX)
int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
{
- u32 gmiifer = 0;
+ u32 rgmiifer = 0;
/*
- * Right now only 2*RGMII is supported. Please extend when needed.
- * sr - 2007-09-19
+ * The 405EX(r)'s RGMII bridge can operate in one of several
+ * modes, only one of which (2 x RGMII) allows the
+ * simultaneous use of both EMACs on the 405EX.
*/
- switch (1) {
- case 1:
+
+ switch (CONFIG_EMAC_PHY_MODE) {
+
+ case EMAC_PHY_MODE_NONE:
+ /* No ports */
+ rgmiifer |= RGMII_FER_DIS << 0;
+ rgmiifer |= RGMII_FER_DIS << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_NONE;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ break;
+ case EMAC_PHY_MODE_NONE_RGMII:
+ /* 1 x RGMII port on channel 0 */
+ rgmiifer |= RGMII_FER_RGMII << 0;
+ rgmiifer |= RGMII_FER_DIS << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_RGMII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ break;
+ case EMAC_PHY_MODE_RGMII_NONE:
+ /* 1 x RGMII port on channel 1 */
+ rgmiifer |= RGMII_FER_DIS << 0;
+ rgmiifer |= RGMII_FER_RGMII << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_NONE;
+ bis->bi_phymode[1] = BI_PHYMODE_RGMII;
+ break;
+ case EMAC_PHY_MODE_RGMII_RGMII:
/* 2 x RGMII ports */
- out_be32((void *)RGMII_FER, 0x00000055);
+ rgmiifer |= RGMII_FER_RGMII << 0;
+ rgmiifer |= RGMII_FER_RGMII << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
bis->bi_phymode[0] = BI_PHYMODE_RGMII;
bis->bi_phymode[1] = BI_PHYMODE_RGMII;
break;
- case 2:
- /* 2 x SMII ports */
+ case EMAC_PHY_MODE_NONE_GMII:
+ /* 1 x GMII port on channel 0 */
+ rgmiifer |= RGMII_FER_GMII << 0;
+ rgmiifer |= RGMII_FER_DIS << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_GMII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ break;
+ case EMAC_PHY_MODE_NONE_MII:
+ /* 1 x MII port on channel 0 */
+ rgmiifer |= RGMII_FER_MII << 0;
+ rgmiifer |= RGMII_FER_DIS << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_MII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ break;
+ case EMAC_PHY_MODE_GMII_NONE:
+ /* 1 x GMII port on channel 1 */
+ rgmiifer |= RGMII_FER_DIS << 0;
+ rgmiifer |= RGMII_FER_GMII << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_NONE;
+ bis->bi_phymode[1] = BI_PHYMODE_GMII;
+ break;
+ case EMAC_PHY_MODE_MII_NONE:
+ /* 1 x MII port on channel 1 */
+ rgmiifer |= RGMII_FER_DIS << 0;
+ rgmiifer |= RGMII_FER_MII << 4;
+ out_be32((void *)RGMII_FER, rgmiifer);
+ bis->bi_phymode[0] = BI_PHYMODE_NONE;
+ bis->bi_phymode[1] = BI_PHYMODE_MII;
break;
default:
break;
}
/* Ensure we setup mdio for this devnum and ONLY this devnum */
- gmiifer = in_be32((void *)RGMII_FER);
- gmiifer |= (1 << (19-devnum));
- out_be32((void *)RGMII_FER, gmiifer);
+ rgmiifer = in_be32((void *)RGMII_FER);
+ rgmiifer |= (1 << (19-devnum));
+ out_be32((void *)RGMII_FER, rgmiifer);
return ((int)0x0);
}
#endif /* CONFIG_405EX */
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
+{
+ u32 eth_cfg;
+ u32 zmiifer; /* ZMII0_FER reg. */
+ u32 rmiifer; /* RGMII0_FER reg. Bridge 0 */
+ u32 rmiifer1; /* RGMII0_FER reg. Bridge 1 */
+ int mode;
+
+ zmiifer = 0;
+ rmiifer = 0;
+ rmiifer1 = 0;
+
+#if defined(CONFIG_460EX)
+ mode = 9;
+ mfsdr(SDR0_ETH_CFG, eth_cfg);
+ if (((eth_cfg & SDR0_ETH_CFG_SGMII0_ENABLE) > 0) &&
+ ((eth_cfg & SDR0_ETH_CFG_SGMII1_ENABLE) > 0))
+ mode = 11; /* config SGMII */
+#else
+ mode = 10;
+ mfsdr(SDR0_ETH_CFG, eth_cfg);
+ if (((eth_cfg & SDR0_ETH_CFG_SGMII0_ENABLE) > 0) &&
+ ((eth_cfg & SDR0_ETH_CFG_SGMII1_ENABLE) > 0) &&
+ ((eth_cfg & SDR0_ETH_CFG_SGMII2_ENABLE) > 0))
+ mode = 12; /* config SGMII */
+#endif
+
+ /* TODO:
+ * NOTE: 460GT has 2 RGMII bridge cores:
+ * emac0 ------ RGMII0_BASE
+ * |
+ * emac1 -----+
+ *
+ * emac2 ------ RGMII1_BASE
+ * |
+ * emac3 -----+
+ *
+ * 460EX has 1 RGMII bridge core:
+ * and RGMII1_BASE is disabled
+ * emac0 ------ RGMII0_BASE
+ * |
+ * emac1 -----+
+ */
+
+ /*
+ * Right now only 2*RGMII is supported. Please extend when needed.
+ * sr - 2008-02-19
+ * Add SGMII support.
+ * vg - 2008-07-28
+ */
+ switch (mode) {
+ case 1:
+ /* 1 MII - 460EX */
+ /* GMC0 EMAC4_0, ZMII Bridge */
+ zmiifer |= ZMII_FER_MII << ZMII_FER_V(0);
+ bis->bi_phymode[0] = BI_PHYMODE_MII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 2:
+ /* 2 MII - 460GT */
+ /* GMC0 EMAC4_0, GMC1 EMAC4_2, ZMII Bridge */
+ zmiifer |= ZMII_FER_MII << ZMII_FER_V(0);
+ zmiifer |= ZMII_FER_MII << ZMII_FER_V(2);
+ bis->bi_phymode[0] = BI_PHYMODE_MII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ bis->bi_phymode[2] = BI_PHYMODE_MII;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 3:
+ /* 2 RMII - 460EX */
+ /* GMC0 EMAC4_0, GMC0 EMAC4_1, ZMII Bridge */
+ zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0);
+ zmiifer |= ZMII_FER_RMII << ZMII_FER_V(1);
+ bis->bi_phymode[0] = BI_PHYMODE_RMII;
+ bis->bi_phymode[1] = BI_PHYMODE_RMII;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 4:
+ /* 4 RMII - 460GT */
+ /* GMC0 EMAC4_0, GMC0 EMAC4_1, GMC1 EMAC4_2, GMC1, EMAC4_3 */
+ /* ZMII Bridge */
+ 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_RMII;
+ bis->bi_phymode[1] = BI_PHYMODE_RMII;
+ bis->bi_phymode[2] = BI_PHYMODE_RMII;
+ bis->bi_phymode[3] = BI_PHYMODE_RMII;
+ break;
+ case 5:
+ /* 2 SMII - 460EX */
+ /* GMC0 EMAC4_0, GMC0 EMAC4_1, ZMII Bridge */
+ zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0);
+ zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1);
+ bis->bi_phymode[0] = BI_PHYMODE_SMII;
+ bis->bi_phymode[1] = BI_PHYMODE_SMII;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 6:
+ /* 4 SMII - 460GT */
+ /* GMC0 EMAC4_0, GMC0 EMAC4_1, GMC0 EMAC4_3, GMC0 EMAC4_3 */
+ /* ZMII Bridge */
+ 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_SMII;
+ bis->bi_phymode[1] = BI_PHYMODE_SMII;
+ bis->bi_phymode[2] = BI_PHYMODE_SMII;
+ bis->bi_phymode[3] = BI_PHYMODE_SMII;
+ break;
+ case 7:
+ /* This is the default mode that we want for board bringup - Maple */
+ /* 1 GMII - 460EX */
+ /* GMC0 EMAC4_0, RGMII Bridge 0 */
+ rmiifer |= RGMII_FER_MDIO(0);
+
+ if (devnum == 0) {
+ rmiifer |= RGMII_FER_GMII << RGMII_FER_V(2); /* CH0CFG - EMAC0 */
+ bis->bi_phymode[0] = BI_PHYMODE_GMII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ } else {
+ rmiifer |= RGMII_FER_GMII << RGMII_FER_V(3); /* CH1CFG - EMAC1 */
+ bis->bi_phymode[0] = BI_PHYMODE_NONE;
+ bis->bi_phymode[1] = BI_PHYMODE_GMII;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ }
+ break;
+ case 8:
+ /* 2 GMII - 460GT */
+ /* GMC0 EMAC4_0, RGMII Bridge 0 */
+ /* GMC1 EMAC4_2, RGMII Bridge 1 */
+ rmiifer |= RGMII_FER_GMII << RGMII_FER_V(2); /* CH0CFG - EMAC0 */
+ rmiifer1 |= RGMII_FER_GMII << RGMII_FER_V(2); /* CH0CFG - EMAC2 */
+ rmiifer |= RGMII_FER_MDIO(0); /* enable MDIO - EMAC0 */
+ rmiifer1 |= RGMII_FER_MDIO(0); /* enable MDIO - EMAC2 */
+
+ bis->bi_phymode[0] = BI_PHYMODE_GMII;
+ bis->bi_phymode[1] = BI_PHYMODE_NONE;
+ bis->bi_phymode[2] = BI_PHYMODE_GMII;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 9:
+ /* 2 RGMII - 460EX */
+ /* GMC0 EMAC4_0, GMC0 EMAC4_1, RGMII Bridge 0 */
+ rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
+ rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3);
+ rmiifer |= RGMII_FER_MDIO(0); /* enable MDIO - EMAC0 */
+
+ bis->bi_phymode[0] = BI_PHYMODE_RGMII;
+ bis->bi_phymode[1] = BI_PHYMODE_RGMII;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 10:
+ /* 4 RGMII - 460GT */
+ /* GMC0 EMAC4_0, GMC0 EMAC4_1, RGMII Bridge 0 */
+ /* GMC1 EMAC4_2, GMC1 EMAC4_3, RGMII Bridge 1 */
+ rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
+ rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3);
+ rmiifer1 |= RGMII_FER_RGMII << RGMII_FER_V(2);
+ rmiifer1 |= RGMII_FER_RGMII << RGMII_FER_V(3);
+ bis->bi_phymode[0] = BI_PHYMODE_RGMII;
+ bis->bi_phymode[1] = BI_PHYMODE_RGMII;
+ bis->bi_phymode[2] = BI_PHYMODE_RGMII;
+ bis->bi_phymode[3] = BI_PHYMODE_RGMII;
+ break;
+ case 11:
+ /* 2 SGMII - 460EX */
+ bis->bi_phymode[0] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[1] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 12:
+ /* 3 SGMII - 460GT */
+ bis->bi_phymode[0] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[1] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[2] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ default:
+ break;
+ }
+
+ /* Set EMAC for MDIO */
+ mfsdr(SDR0_ETH_CFG, eth_cfg);
+ eth_cfg |= SDR0_ETH_CFG_MDIO_SEL_EMAC0;
+ mtsdr(SDR0_ETH_CFG, eth_cfg);
+
+ out_be32((void *)RGMII_FER, rmiifer);
+#if defined(CONFIG_460GT)
+ out_be32((void *)RGMII_FER + RGMII1_BASE_OFFSET, rmiifer1);
+#endif
+
+ /* bypass the TAHOE0/TAHOE1 cores for U-Boot */
+ mfsdr(SDR0_ETH_CFG, eth_cfg);
+ eth_cfg |= (SDR0_ETH_CFG_TAHOE0_BYPASS | SDR0_ETH_CFG_TAHOE1_BYPASS);
+ mtsdr(SDR0_ETH_CFG, eth_cfg);
+
+ return 0;
+}
+#endif /* CONFIG_460EX || CONFIG_460GT */
+
static inline void *malloc_aligned(u32 size, u32 align)
{
return (void *)(((u32)malloc(size + align) + align - 1) &
#if defined(CONFIG_440GX) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
sys_info_t sysinfo;
#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
int ethgroup = -1;
#endif
+#endif
+ u32 bd_cached;
+ u32 bd_uncached = 0;
+#ifdef CONFIG_4xx_DCACHE
+ static u32 last_used_ea = 0;
#endif
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
- unsigned long mfr;
+ int rgmii_channel;
#endif
- u32 bd_cached;
- u32 bd_uncached = 0;
EMAC_4XX_HW_PST hw_p = dev->priv;
#if defined(CONFIG_440GX) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
/* Need to get the OPB frequency so we can access the PHY */
get_sys_info (&sysinfo);
out_be32((void *)ZMII_FER, 0);
udelay (100);
-#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#if defined(CONFIG_440GP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
out_be32((void *)ZMII_FER, (ZMII_FER_RMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
-#elif defined(CONFIG_440GX) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#elif defined(CONFIG_440GX) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis);
-#elif defined(CONFIG_440GP)
- /* set RMII mode */
- out_be32((void *)ZMII_FER, ZMII_RMII | ZMII_MDI0);
-#else
- if ((devnum == 0) || (devnum == 1)) {
- out_be32((void *)ZMII_FER, (ZMII_FER_SMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
- } else { /* ((devnum == 2) || (devnum == 3)) */
- out_be32((void *)ZMII_FER, ZMII_FER_MDI << ZMII_FER_V (devnum));
- out_be32((void *)RGMII_FER, ((RGMII_FER_RGMII << RGMII_FER_V (2)) |
- (RGMII_FER_RGMII << RGMII_FER_V (3))));
- }
#endif
out_be32((void *)ZMII_SSR, ZMII_SSR_SP << ZMII_SSR_V(devnum));
ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis);
#endif
- __asm__ volatile ("eieio");
+ sync();
- /* reset emac so we have access to the phy */
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EX)
/* provide clocks for EMAC internal loopback */
- mfsdr (sdr_mfr, mfr);
- mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum);
- mtsdr(sdr_mfr, mfr);
-#endif
+ emac_loopback_enable(hw_p);
+ /* EMAC RESET */
out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
+ /* remove clocks for EMAC internal loopback */
+ emac_loopback_disable(hw_p);
+
failsafe = 1000;
while ((in_be32((void *)EMAC_M0 + hw_p->hw_addr) & (EMAC_M0_SRST)) && failsafe) {
udelay (1000);
if (failsafe <= 0)
printf("\nProblem resetting EMAC!\n");
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_405EX)
- /* 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) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
/* Whack the M1 register */
mode_reg = 0x0;
out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg);
#endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */
+#if defined(CONFIG_GPCS_PHY_ADDR) || defined(CONFIG_GPCS_PHY1_ADDR) || \
+ defined(CONFIG_GPCS_PHY2_ADDR) || defined(CONFIG_GPCS_PHY3_ADDR)
+ if (bis->bi_phymode[devnum] == BI_PHYMODE_SGMII) {
+ /*
+ * In SGMII mode, GPCS access is needed for
+ * communication with the internal SGMII SerDes.
+ */
+ switch (devnum) {
+#if defined(CONFIG_GPCS_PHY_ADDR)
+ case 0:
+ reg = CONFIG_GPCS_PHY_ADDR;
+ break;
+#endif
+#if defined(CONFIG_GPCS_PHY1_ADDR)
+ case 1:
+ reg = CONFIG_GPCS_PHY1_ADDR;
+ break;
+#endif
+#if defined(CONFIG_GPCS_PHY2_ADDR)
+ case 2:
+ reg = CONFIG_GPCS_PHY2_ADDR;
+ break;
+#endif
+#if defined(CONFIG_GPCS_PHY3_ADDR)
+ case 3:
+ reg = CONFIG_GPCS_PHY3_ADDR;
+ break;
+#endif
+ }
+
+ mode_reg = in_be32((void *)EMAC_M1 + hw_p->hw_addr);
+ mode_reg |= EMAC_M1_MF_1000GPCS | EMAC_M1_IPPA_SET(reg);
+ out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg);
+
+ /* Configure GPCS interface to recommended setting for SGMII */
+ miiphy_reset(dev->name, reg);
+ miiphy_write(dev->name, reg, 0x04, 0x8120); /* AsymPause, FDX */
+ miiphy_write(dev->name, reg, 0x07, 0x2801); /* msg_pg, toggle */
+ miiphy_write(dev->name, reg, 0x00, 0x0140); /* 1Gbps, FDX */
+ }
+#endif /* defined(CONFIG_GPCS_PHY_ADDR) */
+
/* wait for PHY to complete auto negotiation */
reg_short = 0;
-#ifndef CONFIG_CS8952_PHY
switch (devnum) {
case 0:
reg = CONFIG_PHY_ADDR;
reg = CONFIG_PHY1_ADDR;
break;
#endif
-#if defined (CONFIG_440GX)
+#if defined (CONFIG_PHY2_ADDR)
case 2:
reg = CONFIG_PHY2_ADDR;
break;
+#endif
+#if defined (CONFIG_PHY3_ADDR)
case 3:
reg = CONFIG_PHY3_ADDR;
break;
bis->bi_phynum[devnum] = reg;
+ if (reg == CONFIG_FIXED_PHY)
+ goto get_speed;
+
#if defined(CONFIG_PHY_RESET)
/*
* Reset the phy, only if its the first time through
miiphy_write (dev->name, reg, 0x09, 0x0e00);
miiphy_write (dev->name, reg, 0x04, 0x01e1);
#endif
+#if defined(CONFIG_M88E1112_PHY)
+ if (bis->bi_phymode[devnum] == BI_PHYMODE_SGMII) {
+ /*
+ * Marvell 88E1112 PHY needs to have the SGMII MAC
+ * interace (page 2) properly configured to
+ * communicate with the 460EX/GT GPCS interface.
+ */
+
+ /* Set access to Page 2 */
+ miiphy_write(dev->name, reg, 0x16, 0x0002);
+
+ miiphy_write(dev->name, reg, 0x00, 0x0040); /* 1Gbps */
+ miiphy_read(dev->name, reg, 0x1a, ®_short);
+ reg_short |= 0x8000; /* bypass Auto-Negotiation */
+ miiphy_write(dev->name, reg, 0x1a, reg_short);
+ miiphy_reset(dev->name, reg); /* reset MAC interface */
+
+ /* Reset access to Page 0 */
+ miiphy_write(dev->name, reg, 0x16, 0x0000);
+ }
+#endif /* defined(CONFIG_M88E1112_PHY) */
miiphy_reset (dev->name, reg);
#if defined(CONFIG_440GX) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
#if defined(CONFIG_CIS8201_PHY)
miiphy_write (dev->name, reg, 0x1f, 0x0000);
/* end Vitesse/Cicada errata */
}
-#endif
+#endif /* defined(CONFIG_CIS8201_PHY) */
#if defined(CONFIG_ET1011C_PHY)
/*
miiphy_write(dev->name, reg, 0x1c, 0x74f0);
}
-#endif
+#endif /* defined(CONFIG_ET1011C_PHY) */
-#endif
+#endif /* defined(CONFIG_440GX) ... */
/* Start/Restart autonegotiation */
phy_setup_aneg (dev->name, reg);
udelay (1000);
}
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);
+get_speed:
+ if (reg == CONFIG_FIXED_PHY) {
+ for (i = 0; i < ARRAY_SIZE(fixed_phy_port); i++) {
+ if (devnum == fixed_phy_port[i].devnum) {
+ speed = fixed_phy_port[i].speed;
+ duplex = fixed_phy_port[i].duplex;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(fixed_phy_port)) {
+ printf("ERROR: PHY (%s) not configured correctly!\n",
+ dev->name);
+ return -1;
+ }
+ } else {
+ speed = miiphy_speed(dev->name, reg);
+ duplex = miiphy_duplex(dev->name, reg);
+ }
if (hw_p->print_speed) {
hw_p->print_speed = 0;
hw_p->devnum);
}
-#if defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
- !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX)
+#if defined(CONFIG_440) && \
+ !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
+ !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) && \
+ !defined(CONFIG_460EX) && !defined(CONFIG_460GT)
#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
mfsdr(sdr_mfr, reg);
if (speed == 100) {
#endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
+ if (devnum >= 2)
+ rgmii_channel = devnum - 2;
+ else
+ rgmii_channel = devnum;
+
if (speed == 1000)
- reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum));
+ reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V(rgmii_channel));
else if (speed == 100)
- reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V (devnum));
+ reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V(rgmii_channel));
else if (speed == 10)
- reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V (devnum));
+ reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V(rgmii_channel));
else {
printf("Error in RGMII Speed\n");
return -1;
}
out_be32((void *)RGMII_SSR, reg);
+#if defined(CONFIG_460GT)
+ if ((devnum == 2) || (devnum == 3))
+ out_be32((void *)RGMII_SSR + RGMII1_BASE_OFFSET, reg);
+#endif
#endif
/* set the Mal configuration reg */
#if defined(CONFIG_440GX) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000);
bd_cached = (u32)malloc_aligned(MAL_ALLOC_SIZE, 4096);
if (!bd_cached) {
- printf("%s: Error allocating MAL descriptor buffers!\n");
+ printf("%s: Error allocating MAL descriptor buffers!\n", __func__);
return -1;
}
#ifdef CONFIG_4xx_DCACHE
flush_dcache_range(bd_cached, bd_cached + MAL_ALLOC_SIZE);
- bd_uncached = bis->bi_memsize;
+ if (!last_used_ea)
+#if defined(CONFIG_SYS_MEM_TOP_HIDE)
+ bd_uncached = bis->bi_memsize + CONFIG_SYS_MEM_TOP_HIDE;
+#else
+ bd_uncached = bis->bi_memsize;
+#endif
+ else
+ bd_uncached = last_used_ea + MAL_ALLOC_SIZE;
+
+ last_used_ea = bd_uncached;
program_tlb(bd_cached, bd_uncached, MAL_ALLOC_SIZE,
TLB_WORD2_I_ENABLE);
#else
mtdcr (maltxbattr, 0x0);
mtdcr (malrxbattr, 0x0);
#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ mtdcr (malrxctp8r, hw_p->rx_phys);
+ /* set RX buffer size */
+ mtdcr (malrcbs8, ENET_MAX_MTU_ALIGNED / 16);
+#else
mtdcr (malrxctp1r, hw_p->rx_phys);
/* set RX buffer size */
mtdcr (malrcbs1, ENET_MAX_MTU_ALIGNED / 16);
+#endif
break;
#if defined (CONFIG_440GX)
case 2:
mtdcr (malrcbs3, ENET_MAX_MTU_ALIGNED / 16);
break;
#endif /* CONFIG_440GX */
+#if defined (CONFIG_460GT)
+ case 2:
+ /* setup MAL tx & rx channel pointers */
+ mtdcr (maltxbattr, 0x0);
+ mtdcr (malrxbattr, 0x0);
+ mtdcr (maltxctp2r, hw_p->tx_phys);
+ mtdcr (malrxctp16r, hw_p->rx_phys);
+ /* set RX buffer size */
+ mtdcr (malrcbs16, ENET_MAX_MTU_ALIGNED / 16);
+ break;
+ case 3:
+ /* setup MAL tx & rx channel pointers */
+ mtdcr (maltxbattr, 0x0);
+ mtdcr (malrxbattr, 0x0);
+ mtdcr (maltxctp3r, hw_p->tx_phys);
+ mtdcr (malrxctp24r, hw_p->rx_phys);
+ /* set RX buffer size */
+ mtdcr (malrcbs24, ENET_MAX_MTU_ALIGNED / 16);
+ break;
+#endif /* CONFIG_460GT */
case 0:
default:
/* setup MAL tx & rx channel pointers */
/* set transmit enable & receive enable */
out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_TXE | EMAC_M0_RXE);
- /* set receive fifo to 4k and tx fifo to 2k */
mode_reg = in_be32((void *)EMAC_M1 + hw_p->hw_addr);
- mode_reg |= EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K;
+
+ /* set rx-/tx-fifo size */
+ mode_reg = (mode_reg & ~EMAC_MR1_FIFO_MASK) | EMAC_MR1_FIFO_SIZE;
/* set speed */
if (speed == _1000BASET) {
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");
+ sync();
out_be32((void *)EMAC_TXM0 + hw_p->hw_addr,
in_be32((void *)EMAC_TXM0 + hw_p->hw_addr) | EMAC_TXM0_GNP0);
}
}
-
-#if defined (CONFIG_440) || defined(CONFIG_405EX)
-
-#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) || \
- defined(CONFIG_405EX)
-#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
+ u32 mal_isr;
+ u32 emac_isr = 0;
+ u32 mal_eob;
+ u32 uic_mal;
+ u32 uic_mal_err;
+ u32 uic_emac;
+ u32 uic_emac_b;
EMAC_4XX_HW_PST hw_p;
/*
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);
+ uic_mal = mfdcr(UIC_BASE_MAL + UIC_MSR);
+ uic_mal_err = mfdcr(UIC_BASE_MAL_ERR + UIC_MSR);
+ uic_emac = mfdcr(UIC_BASE_EMAC + UIC_MSR);
+ uic_emac_b = mfdcr(UIC_BASE_EMAC_B + UIC_MSR);
- if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
- && !(my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))
- && !(my_uicmsr_ethx & (UIC_ETH0 | UIC_ETH1))) {
+ if (!(uic_mal & (UIC_MAL_RXEOB | UIC_MAL_TXEOB))
+ && !(uic_mal_err & (UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE))
+ && !(uic_emac & UIC_ETHx) && !(uic_emac_b & UIC_ETHxB)) {
/* 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;
- }
- }
+ /* look at MAL and EMAC error interrupts */
+ if (uic_mal_err & (UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE)) {
+ /* we have a MAL error interrupt */
+ mal_isr = mfdcr(malesr);
+ mal_err(dev, mal_isr, uic_mal_err,
+ MAL_UIC_DEF, MAL_UIC_ERR);
- /* port by port dispatch of emac interrupts */
- if (hw_p->devnum == 0) {
- if (UIC_ETH0 & my_uicmsr_ethx) { /* look for EMAC errors */
- emac_isr = in_be32((void *)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 */
- }
- }
+ /* clear MAL error interrupt status bits */
+ mtdcr(UIC_BASE_MAL_ERR + UIC_SR,
+ UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE);
-#if !defined(CONFIG_440SP)
- if (hw_p->devnum == 1) {
- if (UIC_ETH1 & my_uicmsr_ethx) { /* look for EMAC errors */
- emac_isr = in_be32((void *)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 = in_be32((void *)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 */
- }
+ return -1;
}
- if (hw_p->devnum == 3) {
- if (UIC_ETH3 & my_uic2msr) { /* look for EMAC errors */
- emac_isr = in_be32((void *)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 */
+ /* look for EMAC errors */
+ if ((uic_emac & UIC_ETHx) || (uic_emac_b & UIC_ETHxB)) {
+ emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
+ emac_err(dev, emac_isr);
- /* 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;
- }
- }
+ /* clear EMAC error interrupt status bits */
+ mtdcr(UIC_BASE_EMAC + UIC_SR, UIC_ETHx);
+ mtdcr(UIC_BASE_EMAC_B + UIC_SR, UIC_ETHxB);
- 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;
+ return -1;
}
- } 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;
- }
+ /* handle MAX TX EOB interrupt from a tx */
+ if (uic_mal & UIC_MAL_TXEOB) {
+ /* clear MAL interrupt status bits */
+ mal_eob = mfdcr(maltxeobisr);
+ mtdcr(maltxeobisr, mal_eob);
+ mtdcr(UIC_BASE_MAL + UIC_SR, UIC_MAL_TXEOB);
+
+ /* indicate that we serviced an interrupt */
+ serviced = 1;
+ rc = 0;
}
- /* port by port dispatch of emac interrupts */
+ /* handle MAL RX EOB interupt from a receive */
+ /* check for EOB on valid channels */
+ if (uic_mal & UIC_MAL_RXEOB) {
+ mal_eob = mfdcr(malrxeobisr);
+ if (mal_eob &
+ (0x80000000 >> (hw_p->devnum * MAL_RX_CHAN_MUL))) {
+ /* push packet to upper layer */
+ enet_rcv(dev, emac_isr);
- if ((SEL_UIC_DEF(hw_p->devnum) & my_uicmsr) != 0) { /* look for EMAC errors */
- emac_isr = in_be32((void *)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 */
- }
+ /* clear MAL interrupt status bits */
+ mtdcr(UIC_BASE_MAL + UIC_SR, UIC_MAL_RXEOB);
- /* 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 */
-#if defined(CONFIG_405EZ)
- mtsdr (sdricintstat, SDR_ICRX_STAT | SDR_ICTX0_STAT | SDR_ICTX1_STAT);
-#endif /* defined(CONFIG_405EZ) */
- }
- while (serviced);
+ } while (serviced);
return (rc);
}
-#endif /* CONFIG_440 */
-
/*-----------------------------------------------------------------------------+
* MAL Error Routine
*-----------------------------------------------------------------------------*/
int loop_count = 0;
rx_eob_isr = mfdcr (malrxeobisr);
- if ((0x80000000 >> hw_p->devnum) & rx_eob_isr) {
+ if ((0x80000000 >> (hw_p->devnum * MAL_RX_CHAN_MUL)) & rx_eob_isr) {
/* clear EOB */
mtdcr (malrxeobisr, rx_eob_isr);
loop_count++;
handled++;
- data_len = (unsigned long) hw_p->rx[i].data_len; /* Get len */
+ data_len = (unsigned long) hw_p->rx[i].data_len & 0x0fff; /* Get len */
if (data_len) {
if (data_len > ENET_MAX_MTU) /* Check len */
data_len = 0;
msr = mfmsr ();
mtmsr (msr & ~(MSR_EE));
- length = hw_p->rx[user_index].data_len;
+ length = hw_p->rx[user_index].data_len & 0x0fff;
/* Pass the packet up to the protocol layers. */
/* NetReceive(NetRxPackets[rxIdx], length - 4); */
EMAC_4XX_HW_PST hw = NULL;
u8 ethaddr[4 + CONFIG_EMAC_NR_START][6];
u32 hw_addr[4];
+ u32 mal_ier;
#if defined(CONFIG_440GX)
unsigned long pfc1;
case 2:
memcpy(ethaddr[eth_num + CONFIG_EMAC_NR_START],
bis->bi_enet2addr, 6);
+#if defined(CONFIG_460GT)
+ hw_addr[eth_num] = 0x300;
+#else
hw_addr[eth_num] = 0x400;
+#endif
break;
#endif
#ifdef CONFIG_HAS_ETH3
case 3:
memcpy(ethaddr[eth_num + CONFIG_EMAC_NR_START],
bis->bi_enet3addr, 6);
+#if defined(CONFIG_460GT)
+ hw_addr[eth_num] = 0x400;
+#else
hw_addr[eth_num] = 0x600;
+#endif
break;
#endif
}
/* set the MAL IER ??? names may change with new spec ??? */
#if defined(CONFIG_440SPE) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
defined(CONFIG_405EX)
mal_ier =
MAL_IER_PT | MAL_IER_PRE | MAL_IER_PWE |
mtdcr (malier, mal_ier);
/* install MAL interrupt handler */
- irq_install_handler (VECNUM_MS,
+ irq_install_handler (VECNUM_MAL_SERR,
(interrupt_handler_t *) enetInt,
dev);
- irq_install_handler (VECNUM_MTE,
+ irq_install_handler (VECNUM_MAL_TXEOB,
(interrupt_handler_t *) enetInt,
dev);
- irq_install_handler (VECNUM_MRE,
+ irq_install_handler (VECNUM_MAL_RXEOB,
(interrupt_handler_t *) enetInt,
dev);
- irq_install_handler (VECNUM_TXDE,
+ irq_install_handler (VECNUM_MAL_TXDE,
(interrupt_handler_t *) enetInt,
dev);
- irq_install_handler (VECNUM_RXDE,
+ irq_install_handler (VECNUM_MAL_RXDE,
(interrupt_handler_t *) enetInt,
dev);
virgin = 1;