[U-Boot-Users] [RFC PATCH] TSEC internal TBI and SGMII support.

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

On 8/3/07, Ed Swarthout ed.swarthout@hwdebug.com wrote:
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.
Ed, I'm sorry but I'm going to have to NACK this, after all.
1) It no longer applies to my tree (not your fault, another patch got in the way)
2) It's far too fragile to have a software requirement that all boards with a TSEC leave 4 consecutive PHY addresses empty. We have boards that put addressable PHYs all around the address space, and it's only a matter of time before a board gets created which breaks this requirement.
3) We have to break out the 8234 support into a separate patch
4) SGMII support should probably *also* be separate
5) I think it's also wrong to assume that all SGMII PHYs will be a simple offset from the normal PHY addresses. Honestly, I believe the common case is that the PHYs will be SGMII or not. Our riser card is probably the exception, rather than the rule, but I feel certain someone will want to put the PHYs at odd addresses in the future. My inclination is still to hard-code the addresses, but I understand why you don't like that idea (and I agree, really).
I think we need to sit down and figure out what the requirements are, and then design a solution to fit those requirements.
Andy
participants (2)
-
Andy Fleming
-
Ed Swarthout