* [U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY
@ 2008-08-30 6:20 Victor Gallardo
2008-08-30 9:18 ` Stefan Roese
2008-08-30 16:34 ` Ben Warren
0 siblings, 2 replies; 8+ messages in thread
From: Victor Gallardo @ 2008-08-30 6:20 UTC (permalink / raw)
To: u-boot
This patch adds GPCS, SGMII and M88E1112 PHY support
for the AMCC PPC460GT/EX processors.
Signed-off-by: Victor Gallardo <vgallardo@amcc.com>
---
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, ®_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, ®_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
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY
2008-08-30 6:20 [U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY Victor Gallardo
@ 2008-08-30 9:18 ` Stefan Roese
2008-08-30 16:34 ` Ben Warren
1 sibling, 0 replies; 8+ messages in thread
From: Stefan Roese @ 2008-08-30 9:18 UTC (permalink / raw)
To: u-boot
Victor,
On Saturday 30 August 2008, Victor Gallardo wrote:
> This patch adds GPCS, SGMII and M88E1112 PHY support
> for the AMCC PPC460GT/EX processors.
Please find some comments below.
> Signed-off-by: Victor Gallardo <vgallardo@amcc.com>
> ---
> 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
Could you please explain this PHY_LESS mode and especially the CONFIG_PHY_LESS
define a little more. To what value will this be defined for Arches for
example?
> +
>
> /*-------------------------------------------------------------------------
>----+ * 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 */
> +}
Make this a little simpler and drop the brackets (for single line statements):
if ((eth_cfg & SDR0_ETH_CFG_SGMII0_ENABLE) &&
(eth_cfg & SDR0_ETH_CFG_SGMII1_ENABLE))
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 */
> +}
Same here please.
> #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);
Please add some comments for those "magic number" above.
> + }
> +#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;
Don't use uppercase names for labels.
> +
> #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, ®_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, ®_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;
Nitpick: Please add empty line after variable declarations.
> + 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)
Please clean up and resubmit.
Thanks.
Best regards,
Stefan
=====================================================================
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: office at denx.de
=====================================================================
^ permalink raw reply [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY
@ 2008-08-30 11:08 Victor Gallardo
0 siblings, 0 replies; 8+ messages in thread
From: Victor Gallardo @ 2008-08-30 11:08 UTC (permalink / raw)
To: u-boot
This patch adds GPCS, SGMII and M88E1112 PHY support
for the AMCC PPC460GT/EX processors.
Signed-off-by: Victor Gallardo <vgallardo@amcc.com>
---
cpu/ppc4xx/4xx_enet.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++-
cpu/ppc4xx/miiphy.c | 41 +++++++++++++++-
include/ppc4xx_enet.h | 3 +
3 files changed, 161 insertions(+), 5 deletions(-)
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index 8a38335..f6cbf2b 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,20 @@
#define MAL_RX_CHAN_MUL 1
#endif
+/*
+ * Some boards do not have a PHY for each ethernet port.
+ * For example on Arches board (2 CPU system) eth0 does not have
+ * a PHY, both CPU's are wired directly together (AC coupled)
+ * using SGMII0. In these cases set the appropriate
+ * CONFIG_PHY_ADDR equal to CONFIG_PHY_LESS to detect that
+ * the specified ethernet port does not have a PHY.
+ */
+#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 +626,17 @@ 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 +659,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 +787,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 +985,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 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
@@ -974,6 +1056,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 +1071,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, ®_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, ®_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 +1192,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..d303598 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,39 @@ 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 +297,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 +346,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..00669a7 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,8 @@ 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
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY
2008-08-30 6:20 [U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY Victor Gallardo
2008-08-30 9:18 ` Stefan Roese
@ 2008-08-30 16:34 ` Ben Warren
2008-08-30 17:56 ` Stefan Roese
2008-09-02 17:52 ` Victor Gallardo
1 sibling, 2 replies; 8+ messages in thread
From: Ben Warren @ 2008-08-30 16:34 UTC (permalink / raw)
To: u-boot
On Fri, Aug 29, 2008 at 11:20 PM, Victor Gallardo <vgallardo@amcc.com> wrote:
> This patch adds GPCS, SGMII and M88E1112 PHY support
> for the AMCC PPC460GT/EX processors.
>
> Signed-off-by: Victor Gallardo <vgallardo@amcc.com>
> ---
> 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
> +
Sorry, but this is not scalable. There are many real-world examples
of boards where one controller is connected to a PHY, and another has
a FIXED link to a switch or something else. This driver is already an
unwieldy mess and adding this sort of thing only makes it worse. If
you want to add fixed-link capabilities, please re-direct your efforts
towards a more generic, scalable solution.
regards,
Ben
^ permalink raw reply [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY
2008-08-30 16:34 ` Ben Warren
@ 2008-08-30 17:56 ` Stefan Roese
2008-08-30 20:33 ` Ben Warren
2008-09-02 17:52 ` Victor Gallardo
1 sibling, 1 reply; 8+ messages in thread
From: Stefan Roese @ 2008-08-30 17:56 UTC (permalink / raw)
To: u-boot
Ben,
On Saturday 30 August 2008, Ben Warren wrote:
> > +#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
> > +
>
> Sorry, but this is not scalable. There are many real-world examples
> of boards where one controller is connected to a PHY, and another has
> a FIXED link to a switch or something else. This driver is already an
> unwieldy mess and adding this sort of thing only makes it worse. If
> you want to add fixed-link capabilities, please re-direct your efforts
> towards a more generic, scalable solution.
Yes, this was my first fear too. But take a look at the commet Victor added in
his 2nd patch version (I asked specifically for this comment to learn how
this should work):
+/*
+ * Some boards do not have a PHY for each ethernet port.
+ * For example on Arches board (2 CPU system) eth0 does not have
+ * a PHY, both CPU's are wired directly together (AC coupled)
+ * using SGMII0. In these cases set the appropriate
+ * CONFIG_PHY_ADDR equal to CONFIG_PHY_LESS to detect that
+ * the specified ethernet port does not have a PHY.
+ */
+#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
So it's a per ethernet-interface selectable define of the CONFIG_PHY_ADDR and
it kind of scales. It's not perfect but at least it's a way to support boards
with interfaces connected to PHY's and other without PHY connection.
What do you think? Is this acceptable? Or what other solution would be
acceptable?
Thanks.
Best regards,
Stefan
=====================================================================
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: office at denx.de
=====================================================================
^ permalink raw reply [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY
2008-08-30 17:56 ` Stefan Roese
@ 2008-08-30 20:33 ` Ben Warren
0 siblings, 0 replies; 8+ messages in thread
From: Ben Warren @ 2008-08-30 20:33 UTC (permalink / raw)
To: u-boot
Hi Stefan,
On Sat, Aug 30, 2008 at 10:56 AM, Stefan Roese <sr@denx.de> wrote:
> Ben,
>
> On Saturday 30 August 2008, Ben Warren wrote:
>> > +#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
>> > +
>>
>> Sorry, but this is not scalable. There are many real-world examples
>> of boards where one controller is connected to a PHY, and another has
>> a FIXED link to a switch or something else. This driver is already an
>> unwieldy mess and adding this sort of thing only makes it worse. If
>> you want to add fixed-link capabilities, please re-direct your efforts
>> towards a more generic, scalable solution.
>
> Yes, this was my first fear too. But take a look at the commet Victor added in
> his 2nd patch version (I asked specifically for this comment to learn how
> this should work):
>
> +/*
> + * Some boards do not have a PHY for each ethernet port.
> + * For example on Arches board (2 CPU system) eth0 does not have
> + * a PHY, both CPU's are wired directly together (AC coupled)
> + * using SGMII0. In these cases set the appropriate
> + * CONFIG_PHY_ADDR equal to CONFIG_PHY_LESS to detect that
> + * the specified ethernet port does not have a PHY.
> + */
> +#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
>
> So it's a per ethernet-interface selectable define of the CONFIG_PHY_ADDR and
> it kind of scales. It's not perfect but at least it's a way to support boards
> with interfaces connected to PHY's and other without PHY connection.
>
> What do you think? Is this acceptable? Or what other solution would be
> acceptable?
>
I guess this falls into the category of one of those things that's
probably OK for now but is ripe for being gutted at a later date. The
right solution is to find a way to pass parametric information on a
per-controller basis, but we're a long way from that now.
If you're OK with the understanding that this is temporary, let's pull
it in. I don't want to stand in the way of being able to support a
major eval board.
regards,
Ben
^ permalink raw reply [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY
2008-08-30 16:34 ` Ben Warren
2008-08-30 17:56 ` Stefan Roese
@ 2008-09-02 17:52 ` Victor Gallardo
1 sibling, 0 replies; 8+ messages in thread
From: Victor Gallardo @ 2008-09-02 17:52 UTC (permalink / raw)
To: u-boot
Hi Ben,
OK. You are correct. I will update this area and resubmit.
-Victor Gallardo
-----Original Message-----
From: Ben Warren [mailto:biggerbadderben at gmail.com]
Sent: Saturday, August 30, 2008 9:34 AM
To: Victor Gallardo
Cc: u-boot at lists.denx.de
Subject: Re: [U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII
and M88E1112 PHY
On Fri, Aug 29, 2008 at 11:20 PM, Victor Gallardo <vgallardo@amcc.com>
wrote:
> This patch adds GPCS, SGMII and M88E1112 PHY support for the AMCC
> PPC460GT/EX processors.
>
> Signed-off-by: Victor Gallardo <vgallardo@amcc.com>
> ---
> 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
> +
Sorry, but this is not scalable. There are many real-world examples of
boards where one controller is connected to a PHY, and another has a
FIXED link to a switch or something else. This driver is already an
unwieldy mess and adding this sort of thing only makes it worse. If you
want to add fixed-link capabilities, please re-direct your efforts
towards a more generic, scalable solution.
regards,
Ben
^ permalink raw reply [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY
@ 2008-09-05 6:47 Victor Gallardo
0 siblings, 0 replies; 8+ messages in thread
From: Victor Gallardo @ 2008-09-05 6:47 UTC (permalink / raw)
To: u-boot
This patch adds GPCS, SGMII and M88E1112 PHY support
for the AMCC PPC460GT/EX processors.
Signed-off-by: Victor Gallardo <vgallardo@amcc.com>
---
v2:
- Added comments to GPCS PHY setup
- Minor coding style cleanup
v3:
- Generalized the PHY-less configuration even more
v4:
- Change "PHY-less" to "Fixed PHY" to standardize
cpu/ppc4xx/4xx_enet.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++-
cpu/ppc4xx/miiphy.c | 41 ++++++++++++-
include/ppc4xx_enet.h | 3 +
3 files changed, 198 insertions(+), 5 deletions(-)
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index 8a38335..071ac0a 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,52 @@
#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 CFG_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 CFG_FIXED_PHY_PORT(devnum,speed,duplex) \
+ * {devnum, speed, duplex},
+ *
+ * #define CFG_FIXED_PHY_PORTS \
+ * CFG_FIXED_PHY_PORT(0,1000,FULL) \
+ * CFG_FIXED_PHY_PORT(2,100,HALF)
+ */
+
+#ifndef CONFIG_FIXED_PHY
+#define CONFIG_FIXED_PHY 0xFFFFFFFF /* Fixed PHY (PHY-less) */
+#endif
+
+#ifndef CFG_FIXED_PHY_PORTS
+#define CFG_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[] = {
+ CFG_FIXED_PHY_PORTS /* defined in board configuration file */
+};
+
/*-----------------------------------------------------------------------------+
* Global variables. TX and RX descriptors and buffers.
*-----------------------------------------------------------------------------*/
@@ -611,8 +658,17 @@ 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 +691,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 +819,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 +1017,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 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
@@ -974,6 +1088,9 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
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
@@ -986,6 +1103,27 @@ 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, 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) || \
@@ -1080,8 +1218,25 @@ 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_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;
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c
index c882720..d303598 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,39 @@ 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 +297,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 +346,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..00669a7 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,8 @@ 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
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2008-09-05 6:47 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-30 6:20 [U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY Victor Gallardo
2008-08-30 9:18 ` Stefan Roese
2008-08-30 16:34 ` Ben Warren
2008-08-30 17:56 ` Stefan Roese
2008-08-30 20:33 ` Ben Warren
2008-09-02 17:52 ` Victor Gallardo
-- strict thread matches above, loose matches on Subject: below --
2008-08-30 11:08 Victor Gallardo
2008-09-05 6:47 Victor Gallardo
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.