
From: Ed Swarthout Ed.Swarthout@freescale.com
Only register one miiphy device and attach all phy's to it.
Option CONFIG_TSEC_TBI adds support to configure the internal TBI phy. The first TBI phy address is TBIPA_VALUE=0x11 and incremented for each tsec.
CONFIG_MII_DEFAULT_TSEC will allow any phy connected to the default MII bus to be read or written without being tied to a specific tsec.
Add vsc8234 phy support.
The FSL boards use a sgmii riser card with a 4-port phy at address range 0x1c-0x1f. The CONFIG_SGMII_RISER option adds TSEC1_SGMII_PHY_ADDR_OFFSET to phyaddr when that tsec is configured to sgmii mode by the por config switches.
Signed-off-by: Ed Swarthout Ed.Swarthout@freescale.com ---
This version makes all the phys appear to be on a single miiphy bus so "mii info" will find and shows all the phys.
drivers/tsec.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++--------- drivers/tsec.h | 22 ++++++++++- 2 files changed, 119 insertions(+), 20 deletions(-)
diff --git a/drivers/tsec.c b/drivers/tsec.c index 55334d6..0074630 100644 --- a/drivers/tsec.c +++ b/drivers/tsec.c @@ -97,11 +97,13 @@ static struct tsec_info_struct tsec_info[] = { #endif };
-#define MAXCONTROLLERS (4) +#define MAXCONTROLLERS (8) /* 4 external phys and 4 internal tbi phys */
static int relocated = 0; +static int miiphy_registered = 0; /* Only register one miiphy device */
static struct tsec_private *privlist[MAXCONTROLLERS]; +static int privlist_next = 0; /* next entry to use */
#ifdef __GNUC__ static RTXBD rtx __attribute__ ((aligned(8))); @@ -128,6 +130,20 @@ static int tsec_miiphy_write(char *devname, unsigned char addr, static int tsec_miiphy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value);
+#ifdef CONFIG_TSEC_TBI +static struct phy_cmd tbi_phy_config[] = (struct phy_cmd[]) { + {TBI_ANA, + TBIANA_ASYMMETRIC_PAUSE|TBIANA_SYMMETRIC_PAUSE|TBIANA_FULL_DUPLEX, + NULL}, + {TBI_TBICON, + TBICON_CLK_SELECT, NULL}, + {TBI_CR, + TBICR_PHY_RESET|TBICR_ANEG_ENABLE|TBICR_FULL_DUPLEX|TBICR_SPEED1_SET, + NULL}, + {miim_end,} +}; +#endif + /* Initialize device structure. Returns success if PHY * initialization succeeded (i.e. if it recognizes the PHY) */ @@ -149,13 +165,20 @@ int tsec_initialize(bd_t * bis, int index, char *devname) if (NULL == priv) return 0;
- privlist[index] = priv; + privlist[privlist_next++] = priv; priv->regs = (volatile tsec_t *)(TSEC_BASE_ADDR + index * TSEC_SIZE); priv->phyregs = (volatile tsec_t *)(TSEC_BASE_ADDR + tsec_info[index].phyregidx * TSEC_SIZE);
priv->phyaddr = tsec_info[index].phyaddr; +#ifdef CONFIG_SGMII_RISER + /* 8544DS board has two phys. rgmii at 0-1 and sgmii at 1c-1d. + * Pick based on POR configuration reflected in ecntrl + */ + if (priv->regs->ecntrl & ECNTRL_SGMII_MODE) + priv->phyaddr += TSEC1_SGMII_PHY_ADDR_OFFSET; +#endif priv->flags = tsec_info[index].flags;
sprintf(dev->name, devname); @@ -172,15 +195,36 @@ int tsec_initialize(bd_t * bis, int index, char *devname)
eth_register(dev);
- /* Reset the MAC */ - priv->regs->maccfg1 |= MACCFG1_SOFT_RESET; - priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET); + /* Assign a Physical address to the internal TBI phy */ + priv->regs->tbipa = TBIPA_VALUE + index;
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ && !defined(BITBANGMII) - miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write); + if (!miiphy_registered++) + miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write); +#endif + +#ifdef CONFIG_TSEC_TBI + /* Add a private structure for internal TBI devices to list */ + struct tsec_private *priv_tbi = \ + (struct tsec_private *)malloc(sizeof(struct tsec_private)); + privlist[privlist_next++] = priv_tbi; + priv_tbi->phyregs = priv->regs; + priv_tbi->phyaddr = TBIPA_VALUE + index; /* phyaddr must be unique */ + priv_tbi->flags = 0; + + /* for sgmii mode, this must be done before external mac reset */ + debug("Initialize TBI phy %x\n", priv_tbi->phyaddr); + phy_run_commands(priv_tbi, tbi_phy_config); #endif
+ /* Init MACCFG2. Defaults to GMII */ + priv->regs->maccfg2 = MACCFG2_INIT_SETTINGS; + + /* Reset the MAC */ + priv->regs->maccfg1 |= MACCFG1_SOFT_RESET; + priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET); + /* Try to initialize PHY here, and return */ return init_phy(dev); } @@ -293,13 +337,6 @@ static int init_phy(struct eth_device *dev) { struct tsec_private *priv = (struct tsec_private *)dev->priv; struct phy_info *curphy; - volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR); - - /* Assign a Physical address to the TBI */ - regs->tbipa = TBIPA_VALUE; - regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE); - regs->tbipa = TBIPA_VALUE; - asm("sync");
/* Reset MII (due to new addresses) */ priv->phyregs->miimcfg = MIIMCFG_RESET; @@ -592,10 +629,10 @@ uint mii_parse_cis8201(uint mii_reg, struct tsec_private * priv) return 0; }
-/* Parse the vsc8244's status register for speed and duplex +/* Parse the vsc8244/vsc8234's status register for speed and duplex * information */ -uint mii_parse_vsc8244(uint mii_reg, struct tsec_private * priv) +uint mii_parse_vsc82x4(uint mii_reg, struct tsec_private *priv) { uint speed;
@@ -740,7 +777,8 @@ static void adjust_link(struct eth_device *dev) /* Set R100 bit in all modes although * it is only used in RGMII mode */ - if (priv->speed == 100) + if ((priv->speed == 100) + && (priv->flags & TSEC_REDUCED)) regs->ecntrl |= ECNTRL_R100; else regs->ecntrl &= ~(ECNTRL_R100); @@ -1149,7 +1187,29 @@ struct phy_info phy_info_VSC8244 = { {MIIM_STATUS, miim_read, &mii_parse_sr}, /* Read the status */ {MIIM_VSC8244_AUX_CONSTAT, miim_read, - &mii_parse_vsc8244}, + &mii_parse_vsc82x4}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown */ + {miim_end,} + }, +}; + +struct phy_info phy_info_VSC8234 = { + 0xfc623 >> 6, /* 0x3f18 */ + "Vitesse VSC8234", + 6, + (struct phy_cmd[]){ /* config */ + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_INIT, NULL}, + {miim_end,} + }, + (struct phy_cmd[]){ /* startup */ + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_VSC8244_AUX_CONSTAT, miim_read, + &mii_parse_vsc82x4}, {miim_end,} }, (struct phy_cmd[]){ /* shutdown */ @@ -1324,6 +1384,7 @@ struct phy_info *phy_info[] = { &phy_info_dm9161, &phy_info_lxt971, &phy_info_VSC8244, + &phy_info_VSC8234, &phy_info_dp83865, &phy_info_generic, NULL @@ -1471,8 +1532,17 @@ static int tsec_miiphy_read(char *devname, unsigned char addr, struct tsec_private *priv = get_priv_for_phy(addr);
if (NULL == priv) { - printf("Can't read PHY at address %d\n", addr); +#ifdef CONFIG_MII_DEFAULT_TSEC + struct tsec_private temp_private; + priv = &temp_private; + priv->phyregs = (volatile tsec_t *)(TSEC_BASE_ADDR); + priv->phyaddr = addr; + priv->flags = 0; +#else + printf("No controller registered for PHY at address %d\n", + addr); return -1; +#endif }
ret = (unsigned short)read_phy_reg(priv, reg); @@ -1493,8 +1563,17 @@ static int tsec_miiphy_write(char *devname, unsigned char addr, struct tsec_private *priv = get_priv_for_phy(addr);
if (NULL == priv) { - printf("Can't write PHY at address %d\n", addr); +#ifdef CONFIG_MII_DEFAULT_TSEC + struct tsec_private temp_private; + priv = &temp_private; + priv->phyregs = (volatile tsec_t *)(TSEC_BASE_ADDR); + priv->phyaddr = addr; + priv->flags = 0; +#else + printf("No controller registered for PHY at address %d\n", + addr); return -1; +#endif }
write_phy_reg(priv, reg, value); diff --git a/drivers/tsec.h b/drivers/tsec.h index 7bf3dee..c4b507b 100644 --- a/drivers/tsec.h +++ b/drivers/tsec.h @@ -42,6 +42,26 @@
#define PHY_AUTONEGOTIATE_TIMEOUT 5000 /* in ms */
+/* TBI register addresses */ +#define TBI_CR 0x00 +#define TBI_SR 0x01 +#define TBI_ANA 0x04 +#define TBI_ANLPBPA 0x05 +#define TBI_ANEX 0x06 +#define TBI_TBICON 0x11 + +/* TBI MDIO register bit fields*/ +#define TBICON_CLK_SELECT 0x0020 +#define TBIANA_ASYMMETRIC_PAUSE 0x0100 +#define TBIANA_SYMMETRIC_PAUSE 0x0080 +#define TBIANA_HALF_DUPLEX 0x0040 +#define TBIANA_FULL_DUPLEX 0x0020 +#define TBICR_PHY_RESET 0x8000 +#define TBICR_ANEG_ENABLE 0x1000 +#define TBICR_RESTART_ANEG 0x0200 +#define TBICR_FULL_DUPLEX 0x0100 +#define TBICR_SPEED1_SET 0x0040 + /* MAC register bits */ #define MACCFG1_SOFT_RESET 0x80000000 #define MACCFG1_RESET_RX_MC 0x00080000 @@ -70,7 +90,7 @@ #define miim_end -2 #define miim_read -1
-#define TBIPA_VALUE 0x1f +#define TBIPA_VALUE 0x11 /* assigns 0x11-0x14 */ #define MIIMCFG_INIT_VALUE 0x00000003 #define MIIMCFG_RESET 0x80000000