[U-Boot-Users] [RFC PATCH] TSEC internal TBI and SGMII support.
Ed Swarthout
ed.swarthout at hwdebug.com
Fri Aug 3 10:23:00 CEST 2007
From: Ed Swarthout <Ed.Swarthout at 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 at 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
--
1.5.2.2.279.gf366
More information about the U-Boot
mailing list