From: Ed Swarthout <ed.swarthout@hwdebug.com>
To: u-boot@lists.denx.de
Subject: [U-Boot-Users] [RFC PATCH] TSEC internal TBI and SGMII support.
Date: Fri, 3 Aug 2007 03:23:00 -0500 [thread overview]
Message-ID: <11861293802449-git-send-email-ed.swarthout@hwdebug.com> (raw)
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
--
1.5.2.2.279.gf366
next reply other threads:[~2007-08-03 8:23 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-08-03 8:23 Ed Swarthout [this message]
2007-08-14 7:15 ` [U-Boot-Users] [RFC PATCH] TSEC internal TBI and SGMII support Andy Fleming
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=11861293802449-git-send-email-ed.swarthout@hwdebug.com \
--to=ed.swarthout@hwdebug.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.