#include <common.h>
#include <net.h>
#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
#include <commproc.h>
#include <ppc4xx.h>
#include <ppc4xx_enet.h>
#include <405_mal.h>
#include <miiphy.h>
#include <malloc.h>
-#include "vecnum.h"
+#include <asm/ppc4xx-intvec.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_CMD_NET) && !defined(CONFIG_405) && !defined(CONFIG_IOP480)
-#if !(defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII))
+#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
#error "CONFIG_MII has to be defined!"
#endif
#endif
#define EMAC_RESET_TIMEOUT 1000 /* 1000 ms reset timeout */
-#define PHY_AUTONEGOTIATE_TIMEOUT 4000 /* 4000 ms autonegotiate timeout */
+#define PHY_AUTONEGOTIATE_TIMEOUT 5000 /* 5000 ms autonegotiate timeout */
/* Ethernet Transmit and Receive Buffers */
/* AS.HARNOIS
#define BI_PHYMODE_GMII 3
#define BI_PHYMODE_RTBI 4
#define BI_PHYMODE_TBI 5
-#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#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
-#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#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
+
/*-----------------------------------------------------------------------------+
* Global variables. TX and RX descriptors and buffers.
*-----------------------------------------------------------------------------*/
/*
* Get count of EMAC devices (doesn't have to be the max. possible number
* supported by the cpu)
+ *
+ * CONFIG_BOARD_EMAC_COUNT added so now a "dynamic" way to configure the
+ * EMAC count is possible. As it is needed for the Kilauea/Haleakala
+ * 405EX/405EXr eval board, using the same binary.
*/
+#if defined(CONFIG_BOARD_EMAC_COUNT)
+#define LAST_EMAC_NUM board_emac_count()
+#else /* CONFIG_BOARD_EMAC_COUNT */
#if defined(CONFIG_HAS_ETH3)
#define LAST_EMAC_NUM 4
#elif defined(CONFIG_HAS_ETH2)
#else
#define LAST_EMAC_NUM 1
#endif
+#endif /* CONFIG_BOARD_EMAC_COUNT */
/* normal boards start with EMAC0 */
#if !defined(CONFIG_EMAC_NR_START)
#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)
+
/*-----------------------------------------------------------------------------+
* Prototypes and externals.
*-----------------------------------------------------------------------------*/
extern int emac4xx_miiphy_write (char *devname, unsigned char addr,
unsigned char reg, unsigned short value);
+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)
- unsigned long mfr;
-#endif
+ u32 val = 10000;
- out32 (EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */
+ out_be32((void *)EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */
/* 1st reset MAL channel */
/* Note: writing a 0 to a channel has no effect */
/* 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)
/* 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);
- out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
+ /* EMAC RESET */
+ out_be32((void *)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
-
+ 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;
}
/* 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);
+ out_be32((void *)ZMII_FER, zmiifer);
+ out_be32((void *)RGMII_FER, rmiifer);
return ((int)pfc1);
}
switch (pfc1) {
case SDR0_PFC1_SELECT_CONFIG_2:
/* 1 x GMII port */
- out32 (ZMII_FER, 0x00);
- out32 (RGMII_FER, 0x00000037);
+ out_be32((void *)ZMII_FER, 0x00);
+ out_be32((void *)RGMII_FER, 0x00000037);
bis->bi_phymode[0] = BI_PHYMODE_GMII;
bis->bi_phymode[1] = BI_PHYMODE_NONE;
break;
case SDR0_PFC1_SELECT_CONFIG_4:
/* 2 x RGMII ports */
- out32 (ZMII_FER, 0x00);
- out32 (RGMII_FER, 0x00000055);
+ out_be32((void *)ZMII_FER, 0x00);
+ out_be32((void *)RGMII_FER, 0x00000055);
bis->bi_phymode[0] = BI_PHYMODE_RGMII;
bis->bi_phymode[1] = BI_PHYMODE_RGMII;
break;
case SDR0_PFC1_SELECT_CONFIG_6:
/* 2 x SMII ports */
- out32 (ZMII_FER,
- ((ZMII_FER_SMII) << ZMII_FER_V(0)) |
- ((ZMII_FER_SMII) << ZMII_FER_V(1)));
- out32 (RGMII_FER, 0x00000000);
+ out_be32((void *)ZMII_FER,
+ ((ZMII_FER_SMII) << ZMII_FER_V(0)) |
+ ((ZMII_FER_SMII) << ZMII_FER_V(1)));
+ out_be32((void *)RGMII_FER, 0x00000000);
bis->bi_phymode[0] = BI_PHYMODE_SMII;
bis->bi_phymode[1] = BI_PHYMODE_SMII;
break;
case SDR0_PFC1_SELECT_CONFIG_1_2:
/* only 1 x MII supported */
- out32 (ZMII_FER, (ZMII_FER_MII) << ZMII_FER_V(0));
- out32 (RGMII_FER, 0x00000000);
+ out_be32((void *)ZMII_FER, (ZMII_FER_MII) << ZMII_FER_V(0));
+ out_be32((void *)RGMII_FER, 0x00000000);
bis->bi_phymode[0] = BI_PHYMODE_MII;
bis->bi_phymode[1] = BI_PHYMODE_NONE;
break;
}
/* Ensure we setup mdio for this devnum and ONLY this devnum */
- zmiifer = in32 (ZMII_FER);
+ zmiifer = in_be32((void *)ZMII_FER);
zmiifer |= (ZMII_FER_MDI) << ZMII_FER_V(devnum);
- out32 (ZMII_FER, zmiifer);
+ out_be32((void *)ZMII_FER, zmiifer);
return ((int)0x0);
}
#endif /* CONFIG_440EPX */
+#if defined(CONFIG_405EX)
+int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
+{
+ u32 gmiifer = 0;
+
+ /*
+ * Right now only 2*RGMII is supported. Please extend when needed.
+ * sr - 2007-09-19
+ */
+ switch (1) {
+ case 1:
+ /* 2 x RGMII ports */
+ out_be32((void *)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 */
+ gmiifer = in_be32((void *)RGMII_FER);
+ gmiifer |= (1 << (19-devnum));
+ out_be32((void *)RGMII_FER, gmiifer);
+
+ 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;
+#else
+ mode = 10;
+#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
+ */
+ 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;
+ 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) &
+ ~(align - 1));
+}
+
static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
{
- int i, j;
+ int i;
unsigned long reg = 0;
unsigned long msr;
unsigned long speed;
unsigned short reg_short;
#if defined(CONFIG_440GX) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+ 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_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_405EX)
int ethgroup = -1;
#endif
#endif
-#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || defined(CONFIG_440SPE)
- unsigned long mfr;
+ 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_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_405EX)
+ int rgmii_channel;
#endif
-
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_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);
#endif
/* NOTE: Therefore, disable all other EMACS, since we handle */
/* NOTE: only one emac at a time */
reg = 0;
- out32 (ZMII_FER, 0);
+ out_be32((void *)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)
+#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) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
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));
+ out_be32((void *)ZMII_SSR, ZMII_SSR_SP << ZMII_SSR_V(devnum));
#endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */
+#if defined(CONFIG_405EX)
+ 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_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
+ emac_loopback_enable(hw_p);
- out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
- __asm__ volatile ("eieio");
+ /* 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 ((in32 (EMAC_M0 + hw_p->hw_addr) & (EMAC_M0_SRST)) && failsafe) {
+ while ((in_be32((void *)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)
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_405EX)
/* Whack the M1 register */
mode_reg = 0x0;
mode_reg &= ~0x00000038;
else
mode_reg |= EMAC_M1_OBCI_GT100;
- out32 (EMAC_M1 + hw_p->hw_addr, mode_reg);
+ out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg);
#endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */
/* wait for PHY to complete auto negotiation */
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;
#if defined(CONFIG_440GX) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
- defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_405EX)
#if defined(CONFIG_CIS8201_PHY)
/*
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
/* Set ZMII/RGMII speed according to the phy link speed */
- reg = in32 (ZMII_SSR);
+ reg = in_be32((void *)ZMII_SSR);
if ( (speed == 100) || (speed == 1000) )
- out32 (ZMII_SSR, reg | (ZMII_SSR_SP << ZMII_SSR_V (devnum)));
+ out_be32((void *)ZMII_SSR, reg | (ZMII_SSR_SP << ZMII_SSR_V (devnum)));
else
- out32 (ZMII_SSR, reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum))));
+ out_be32((void *)ZMII_SSR, reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum))));
if ((devnum == 2) || (devnum == 3)) {
if (speed == 1000)
printf("Error in RGMII Speed\n");
return -1;
}
- out32 (RGMII_SSR, reg);
+ out_be32((void *)RGMII_SSR, reg);
}
#endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */
-#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#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;
}
- out32 (RGMII_SSR, reg);
+ 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_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);
#else
}
#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;
- }
+ if (hw_p->first_init == 0) {
+ debug("*** Allocating descriptor memory ***\n");
- 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;
- }
+ bd_cached = (u32)malloc_aligned(MAL_ALLOC_SIZE, 4096);
+ if (!bd_cached) {
+ printf("%s: Error allocating MAL descriptor buffers!\n");
+ 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;
+#ifdef CONFIG_4xx_DCACHE
+ flush_dcache_range(bd_cached, bd_cached + MAL_ALLOC_SIZE);
+ if (!last_used_ea)
+#if defined(CFG_MEM_TOP_HIDE)
+ bd_uncached = bis->bi_memsize + CFG_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
+ bd_uncached = bd_cached;
+#endif
+ hw_p->tx_phys = bd_cached;
+ hw_p->rx_phys = bd_cached + MAL_TX_DESC_SIZE;
+ hw_p->tx = (mal_desc_t *)(bd_uncached);
+ hw_p->rx = (mal_desc_t *)(bd_uncached + MAL_TX_DESC_SIZE);
+ debug("hw_p->tx=%08x, hw_p->rx=%08x\n", hw_p->tx, hw_p->rx);
}
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;
- }
- }
- }
+ if (hw_p->first_init == 0)
+ hw_p->txbuf_ptr = malloc_aligned(MAL_ALLOC_SIZE,
+ L1_CACHE_BYTES);
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;
-#if 0
- printf ("TX_BUFF %d @ 0x%08lx\n", i,
- (ulong) hw_p->tx[i].data_ptr);
-#endif
+ debug("TX_BUFF %d @ 0x%08lx\n", i, (u32)hw_p->tx[i].data_ptr);
}
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];
+ 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;
-#if 0
- printf ("RX_BUFF %d @ 0x%08lx\n", i, (ulong) hw_p->rx[i].data_ptr);
-#endif
+ debug("RX_BUFF %d @ 0x%08lx\n", i, (u32)hw_p->rx[i].data_ptr);
}
reg = 0x00000000;
reg = reg << 8;
reg |= dev->enetaddr[1];
- out32 (EMAC_IAH + hw_p->hw_addr, reg);
+ out_be32((void *)EMAC_IAH + hw_p->hw_addr, reg);
reg = 0x00000000;
reg |= dev->enetaddr[2]; /* set low address */
reg = reg << 8;
reg |= dev->enetaddr[5];
- out32 (EMAC_IAL + hw_p->hw_addr, reg);
+ out_be32((void *)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);
+ mtdcr (maltxctp2r, hw_p->tx_phys);
#else
- mtdcr (maltxctp1r, hw_p->tx);
+ mtdcr (maltxctp1r, hw_p->tx_phys);
#endif
#if defined(CONFIG_440)
mtdcr (maltxbattr, 0x0);
mtdcr (malrxbattr, 0x0);
#endif
- mtdcr (malrxctp1r, hw_p->rx);
+
+#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:
/* setup MAL tx & rx channel pointers */
mtdcr (maltxbattr, 0x0);
mtdcr (malrxbattr, 0x0);
- mtdcr (maltxctp2r, hw_p->tx);
- mtdcr (malrxctp2r, hw_p->rx);
+ mtdcr (maltxctp2r, hw_p->tx_phys);
+ mtdcr (malrxctp2r, hw_p->rx_phys);
/* 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 (maltxctp3r, hw_p->tx_phys);
mtdcr (malrxbattr, 0x0);
- mtdcr (malrxctp3r, hw_p->rx);
+ mtdcr (malrxctp3r, hw_p->rx_phys);
/* set RX buffer size */
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 */
mtdcr (maltxbattr, 0x0);
mtdcr (malrxbattr, 0x0);
#endif
- mtdcr (maltxctp0r, hw_p->tx);
- mtdcr (malrxctp0r, hw_p->rx);
+ mtdcr (maltxctp0r, hw_p->tx_phys);
+ mtdcr (malrxctp0r, hw_p->rx_phys);
/* set RX buffer size */
mtdcr (malrcbs0, ENET_MAX_MTU_ALIGNED / 16);
break;
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);
+ out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_TXE | EMAC_M0_RXE);
+
+ mode_reg = in_be32((void *)EMAC_M1 + hw_p->hw_addr);
- /* 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 rx-/tx-fifo size */
+ mode_reg = (mode_reg & ~EMAC_MR1_FIFO_MASK) | EMAC_MR1_FIFO_SIZE;
/* set speed */
if (speed == _1000BASET) {
-#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
- defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE)
unsigned long pfc1;
mfsdr (sdr_pfc1, pfc1);
if (duplex == FULL)
mode_reg = mode_reg | 0x80000000 | EMAC_M1_IST;
- out32 (EMAC_M1 + hw_p->hw_addr, mode_reg);
+ out_be32((void *)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);
+ out_be32((void *)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 */
+ out_be32((void *)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);
+ out_be32((void *)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);
+ out_be32((void *)EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x0f002000);
#endif /* defined(CONFIG_440) */
- out32 (EMAC_TXM1 + hw_p->hw_addr, 0xf8640000);
+ out_be32((void *)EMAC_TXM1 + hw_p->hw_addr, 0xf8640000);
/* Set fifo limit entry in tx mode 0 */
- out32 (EMAC_TXM0 + hw_p->hw_addr, 0x00000003);
+ out_be32((void *)EMAC_TXM0 + hw_p->hw_addr, 0x00000003);
/* Frame gap set */
- out32 (EMAC_I_FRAME_GAP_REG + hw_p->hw_addr, 0x00000008);
+ out_be32((void *)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);
+ out_be32((void *)EMAC_ISR + hw_p->hw_addr, 0xffffffff); /* clear pending interrupts */
+ out_be32((void *)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);
+ irq_install_handler(ETH_IRQ_NUM(hw_p->devnum),
+ (interrupt_handler_t *) enetInt, dev);
}
mtmsr (msr); /* enable interrupts again */
hw_p->bis = bis;
hw_p->first_init = 1;
- return (1);
+ return 0;
}
/* memcpy ((void *) &tx_buff[tx_slot], (const void *) ptr, len); */
memcpy ((void *) hw_p->txbuf_ptr, (const void *) ptr, len);
+ flush_dcache_range((u32)hw_p->txbuf_ptr, (u32)hw_p->txbuf_ptr + len);
/*-----------------------------------------------------------------------+
* set TX Buffer busy, and send it
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();
- out32 (EMAC_TXM0 + hw_p->hw_addr,
- in32 (EMAC_TXM0 + hw_p->hw_addr) | EMAC_TXM0_GNP0);
+ out_be32((void *)EMAC_TXM0 + hw_p->hw_addr,
+ in_be32((void *)EMAC_TXM0 + hw_p->hw_addr) | EMAC_TXM0_GNP0);
#ifdef INFO_4XX_ENET
hw_p->stats.pkts_tx++;
#endif
*-----------------------------------------------------------------------*/
time_start = get_timer (0);
while (1) {
- temp_txm0 = in32 (EMAC_TXM0 + hw_p->hw_addr);
+ temp_txm0 = in_be32((void *)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 defined (CONFIG_440)
+#if defined (CONFIG_440) || defined(CONFIG_405EX)
#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
/*
*/
#define UIC0MSR uic1msr
#define UIC0SR uic1sr
+#define UIC1MSR uic1msr
+#define UIC1SR uic1sr
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+/*
+ * Hack: On 460EX/GT all enet irq sources are located on UIC2
+ * Needs some cleanup. --ag
+ */
+#define UIC0MSR uic2msr
+#define UIC0SR uic2sr
+#define UIC1MSR uic2msr
+#define UIC1SR uic2sr
#else
#define UIC0MSR uic0msr
#define UIC0SR uic0sr
+#define UIC1MSR uic1msr
+#define UIC1SR uic1sr
#endif
-#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_405EX)
#define UICMSR_ETHX uic0msr
#define UICSR_ETHX uic0sr
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UICMSR_ETHX uic2msr
+#define UICSR_ETHX uic2sr
#else
#define UICMSR_ETHX uic1msr
#define UICSR_ETHX uic1sr
serviced = 0;
my_uic0msr = mfdcr (UIC0MSR);
- my_uic1msr = mfdcr (uic1msr);
+ my_uic1msr = mfdcr (UIC1MSR);
#if defined(CONFIG_440GX)
my_uic2msr = mfdcr (uic2msr);
#endif
/* 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);
+ 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;
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 (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);
+ 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;
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 (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);
+ 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;
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 (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);
+ 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;
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 (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
mtdcr (uic2sr, UIC_ETH3);
return (rc); /* we had errors so get out */
}
/* 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 */
+ if ((mal_rx_eob &
+ (0x80000000 >> (hw_p->devnum * MAL_RX_CHAN_MUL)))
+ != 0) { /* call emac routine for channel x */
/* clear EOB
mtdcr(malrxeobisr, mal_rx_eob); */
enet_rcv (dev, emac_isr);
}
mtdcr (UIC0SR, UIC_MRE); /* Clear */
- mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
+ mtdcr (UIC1SR, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
switch (hw_p->devnum) {
case 0:
mtdcr (UICSR_ETHX, UIC_ETH0);
/* 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);
+ 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;
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);
+ out_be32((void *)EMAC_ISR + hw_p->hw_addr, isr);
}
/*-----------------------------------------------------------------------------+
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);
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 */
+ 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;
if (NUM_RX_BUFF == hw_p->rx_i_index)
hw_p->rx_i_index = 0;
+ hw_p->rx_slot++;
+ if (NUM_RX_BUFF == hw_p->rx_slot)
+ hw_p->rx_slot = 0;
+
/* AS.HARNOIS
* free receive buffer only when
* buffer has been handled (eth_rx)
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); */
/* NetReceive(NetRxPackets[i], length); */
+ invalidate_dcache_range((u32)hw_p->rx[user_index].data_ptr,
+ (u32)hw_p->rx[user_index].data_ptr +
+ length - 4);
NetReceive (NetRxPackets[user_index], length - 4);
/* Free Recv Buffer */
hw_p->rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY;
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
}
bis->bi_phynum[3] = CONFIG_PHY3_ADDR;
bis->bi_phymode[2] = 2;
bis->bi_phymode[3] = 2;
+#endif
+#if defined(CONFIG_440GX) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_405EX)
ppc_4xx_eth_setup_bridge(0, bis);
#endif
if (0 == virgin) {
/* set the MAL IER ??? names may change with new spec ??? */
-#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#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 |
MAL_IER_DE | MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE ;
#endif
#if defined(CONFIG_NET_MULTI)
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register (dev->name,
emac4xx_miiphy_read, emac4xx_miiphy_write);
#endif
#endif
} /* end for each supported device */
- return (1);
+
+ return 0;
}
#if !defined(CONFIG_NET_MULTI)
int emac4xx_miiphy_initialize (bd_t * bis)
{
-#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register ("ppc_4xx_eth0",
emac4xx_miiphy_read, emac4xx_miiphy_write);
#endif
}
#endif /* !defined(CONFIG_NET_MULTI) */
-#endif /* #if (CONFIG_COMMANDS & CFG_CMD_NET) */
+#endif