This patch adds GPCS, SGMII and M88E1112 PHY support
for the AMCC PPC460GT/EX processors.

Signed-off-by: Victor Gallardo <[EMAIL PROTECTED]>
---
 cpu/ppc4xx/4xx_enet.c |  116 ++++++++++++++++++++++++++++++++++++++++++++++++-
 cpu/ppc4xx/miiphy.c   |   40 ++++++++++++++++-
 include/ppc4xx_enet.h |    4 ++
 3 files changed, 155 insertions(+), 5 deletions(-)

diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index 8a38335..4729800 100644
--- a/cpu/ppc4xx/4xx_enet.c
+++ b/cpu/ppc4xx/4xx_enet.c
@@ -198,6 +198,7 @@
 #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) || \
@@ -216,6 +217,12 @@
 #define MAL_RX_CHAN_MUL        1
 #endif
 
+#if !defined(CONFIG_PHY_LESS)
+#define CONFIG_PHY_LESS        0xFFFFFFFF /* PHY-less mode */
+#define CONFIG_PHY_LESS_SPEED  1000
+#define CONFIG_PHY_LESS_DUPLEX FULL
+#endif
+
 
/*-----------------------------------------------------------------------------+
  * Global variables. TX and RX descriptors and buffers.
  
*-----------------------------------------------------------------------------*/
@@ -611,8 +618,19 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
 
 #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:
@@ -635,6 +653,8 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
        /*
         * 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:
@@ -761,6 +781,20 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
                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;
        }
@@ -945,6 +979,48 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t 
* bis)
        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 the GPCS interface */
+               miiphy_reset(dev->name, reg);
+               miiphy_write(dev->name, reg, 0x04, 0x8120);
+               miiphy_write(dev->name, reg, 0x07, 0x2801);
+               miiphy_write(dev->name, reg, 0x00, 0x0140);
+       }
+#endif /* defined(CONFIG_GPCS_PHY_ADDR) */
+
        /* wait for PHY to complete auto negotiation */
        reg_short = 0;
 #ifndef CONFIG_CS8952_PHY
@@ -974,6 +1050,9 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t 
* bis)
 
        bis->bi_phynum[devnum] = reg;
 
+       if (reg == CONFIG_PHY_LESS)
+               goto GET_SPEED;
+
 #if defined(CONFIG_PHY_RESET)
        /*
         * Reset the phy, only if its the first time through
@@ -986,6 +1065,33 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t 
* bis)
                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, 0x10, &reg_short);
+                       reg_short &= ~0x0C00; /* Preferred Media MASK */
+                       reg_short |=  0x0800; /* Preferred Media Copper */
+                       reg_short &= ~0x0380; /* Mode Select MASK */
+                       reg_short |=  0x0280; /* Mode Select Copper only */
+                       miiphy_write(dev->name, reg, 0x10, reg_short);
+                       miiphy_read(dev->name, reg, 0x1a, &reg_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) || \
@@ -1080,8 +1186,14 @@ static int ppc_4xx_eth_init (struct eth_device *dev, 
bd_t * bis)
        }
 #endif /* #ifndef CONFIG_CS8952_PHY */
 
-       speed = miiphy_speed (dev->name, reg);
-       duplex = miiphy_duplex (dev->name, reg);
+GET_SPEED:
+       if (reg == CONFIG_PHY_LESS) {
+               speed = CONFIG_PHY_LESS_SPEED;
+               duplex = CONFIG_PHY_LESS_DUPLEX;
+       } else {
+               speed = miiphy_speed(dev->name, reg);
+               duplex = miiphy_duplex(dev->name, reg);
+       }
 
        if (hw_p->print_speed) {
                hw_p->print_speed = 0;
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c
index c882720..abc88f7 100644
--- a/cpu/ppc4xx/miiphy.c
+++ b/cpu/ppc4xx/miiphy.c
@@ -180,8 +180,10 @@ int phy_setup_aneg (char *devname, unsigned char addr)
  *
  * sr: Currently on 460EX only EMAC0 works with MDIO, so we always
  * return EMAC0 offset here
+ * vg: For 460EX/460GT if internal GPCS PHY address is specified
+ * return appropriate EMAC offset
  */
-unsigned int miiphy_getemac_offset (void)
+unsigned int miiphy_getemac_offset(u8 addr)
 {
 #if (defined(CONFIG_440) && \
     !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
@@ -233,6 +235,38 @@ unsigned int miiphy_getemac_offset (void)
                return 0x100;
 #endif
 
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+       u32 mode_reg;
+       u32 eoffset = 0;
+       switch (addr) {
+#if defined(CONFIG_HAS_ETH1) && defined(CONFIG_GPCS_PHY1_ADDR)
+       case CONFIG_GPCS_PHY1_ADDR:
+               mode_reg = in_be32((void *)EMAC_M1 + 0x100);
+               if (addr == EMAC_M1_IPPA_GET(mode_reg))
+                       eoffset = 0x100;
+               break;
+#endif
+#if defined(CONFIG_HAS_ETH2) && defined(CONFIG_GPCS_PHY2_ADDR)
+       case CONFIG_GPCS_PHY2_ADDR:
+               mode_reg = in_be32((void *)EMAC_M1 + 0x300);
+               if (addr == EMAC_M1_IPPA_GET(mode_reg))
+                       eoffset = 0x300;
+               break;
+#endif
+#if defined(CONFIG_HAS_ETH3) && defined(CONFIG_GPCS_PHY3_ADDR)
+       case CONFIG_GPCS_PHY3_ADDR:
+               mode_reg = in_be32((void *)EMAC_M1 + 0x400);
+               if (addr == EMAC_M1_IPPA_GET(mode_reg))
+                       eoffset = 0x400;
+               break;
+#endif
+       default:
+               eoffset = 0;
+               break;
+       }
+       return eoffset;
+#endif
+
        return 0;
 #endif
 }
@@ -262,7 +296,7 @@ static int emac_miiphy_command(u8 addr, u8 reg, int cmd, 
u16 value)
        u32 emac_reg;
        u32 sta_reg;
 
-       emac_reg = miiphy_getemac_offset();
+       emac_reg = miiphy_getemac_offset(addr);
 
        /* wait for completion */
        if (emac_miiphy_wait(emac_reg) != 0)
@@ -311,7 +345,7 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr, 
unsigned char reg,
        unsigned long sta_reg;
        unsigned long emac_reg;
 
-       emac_reg = miiphy_getemac_offset ();
+       emac_reg = miiphy_getemac_offset(addr);
 
        if (emac_miiphy_command(addr, reg, EMAC_STACR_READ, 0) != 0)
                return -1;
diff --git a/include/ppc4xx_enet.h b/include/ppc4xx_enet.h
index b74c6fc..689b056 100644
--- a/include/ppc4xx_enet.h
+++ b/include/ppc4xx_enet.h
@@ -376,6 +376,7 @@ typedef struct emac_4xx_hw_st {
 #define EMAC_M1_APP            (0x08000000)
 #define EMAC_M1_RSVD           (0x06000000)
 #define EMAC_M1_IST            (0x01000000)
+#define EMAC_M1_MF_1000GPCS    (0x00C00000)
 #define EMAC_M1_MF_1000MBPS    (0x00800000)    /* 0's for 10MBPS */
 #define EMAC_M1_MF_100MBPS     (0x00400000)
 #define EMAC_M1_RFS_MASK       (0x00380000)
@@ -394,6 +395,9 @@ typedef struct emac_4xx_hw_st {
 #define EMAC_M1_MWSW           (0x00007000)
 #define EMAC_M1_JUMBO_ENABLE   (0x00000800)
 #define EMAC_M1_IPPA           (0x000007c0)
+#define EMAC_M1_IPPA_SET(id)   (((id) & 0x1f) << 6)
+#define EMAC_M1_IPPA_GET(id)   (((id) >> 6) & 0x1f)
+
 #define EMAC_M1_OBCI_GT100     (0x00000020)
 #define EMAC_M1_OBCI_100       (0x00000018)
 #define EMAC_M1_OBCI_83                (0x00000010)
-- 
1.5.5

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to