summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDavid Updegraff <dave@cray.com>2007-04-20 14:34:48 -0500
committerAndrew Fleming-AFLEMING <afleming@freescale.com>2007-05-02 15:38:22 -0500
commitaf1c2b84bf27c8565baddc82d1abb93700d10e2e (patch)
tree2383ff1fe9c2c3f2b107949370008d4b159b7d03 /drivers
parent66ed6cca3f340f7a8a06d9272ae2ef8e96f0273d (diff)
Add support for treating unknown PHYs as generic PHYs.
When bringing up u-boot on new boards, PHY support sometimes gets neglected. Most PHYs don't really need any special support, though. By adding a generic entry that always matches if nothing else does, we can provide support for "unsupported" PHYs for the tsec. The generic PHY driver supports most PHYs, including gigabit. Signed-off-by: David Updegraff <dave@cray.com> Signed-off-by: Andy Fleming <afleming@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/tsec.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/drivers/tsec.c b/drivers/tsec.c
index ed35f227c1b..25566a73387 100644
--- a/drivers/tsec.c
+++ b/drivers/tsec.c
@@ -385,6 +385,76 @@ uint mii_parse_sr(uint mii_reg, struct tsec_private * priv)
return 0;
}
+/* Generic function which updates the speed and duplex. If
+ * autonegotiation is enabled, it uses the AND of the link
+ * partner's advertised capabilities and our advertised
+ * capabilities. If autonegotiation is disabled, we use the
+ * appropriate bits in the control register.
+ *
+ * Stolen from Linux's mii.c and phy_device.c
+ */
+uint mii_parse_link(uint mii_reg, struct tsec_private *priv)
+{
+ /* We're using autonegotiation */
+ if (mii_reg & PHY_BMSR_AUTN_ABLE) {
+ uint lpa = 0;
+ uint gblpa = 0;
+
+ /* Check for gigabit capability */
+ if (mii_reg & PHY_BMSR_EXT) {
+ /* We want a list of states supported by
+ * both PHYs in the link
+ */
+ gblpa = read_phy_reg(priv, PHY_1000BTSR);
+ gblpa &= read_phy_reg(priv, PHY_1000BTCR) << 2;
+ }
+
+ /* Set the baseline so we only have to set them
+ * if they're different
+ */
+ priv->speed = 10;
+ priv->duplexity = 0;
+
+ /* Check the gigabit fields */
+ if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) {
+ priv->speed = 1000;
+
+ if (gblpa & PHY_1000BTSR_1000FD)
+ priv->duplexity = 1;
+
+ /* We're done! */
+ return 0;
+ }
+
+ lpa = read_phy_reg(priv, PHY_ANAR);
+ lpa &= read_phy_reg(priv, PHY_ANLPAR);
+
+ if (lpa & (PHY_ANLPAR_TXFD | PHY_ANLPAR_TX)) {
+ priv->speed = 100;
+
+ if (lpa & PHY_ANLPAR_TXFD)
+ priv->duplexity = 1;
+
+ } else if (lpa & PHY_ANLPAR_10FD)
+ priv->duplexity = 1;
+ } else {
+ uint bmcr = read_phy_reg(priv, PHY_BMCR);
+
+ priv->speed = 10;
+ priv->duplexity = 0;
+
+ if (bmcr & PHY_BMCR_DPLX)
+ priv->duplexity = 1;
+
+ if (bmcr & PHY_BMCR_1000_MBPS)
+ priv->speed = 1000;
+ else if (bmcr & PHY_BMCR_100_MBPS)
+ priv->speed = 100;
+ }
+
+ return 0;
+}
+
/*
* Parse the BCM54xx status register for speed and duplex information.
* The linux sungem_phy has this information, but in a table format.
@@ -722,6 +792,7 @@ static void startup_tsec(struct eth_device *dev)
/* Start up the PHY */
if(priv->phyinfo)
phy_run_commands(priv, priv->phyinfo->startup);
+
adjust_link(dev);
/* Enable Transmit and Receive */
@@ -1092,6 +1163,27 @@ struct phy_info phy_info_dm9161 = {
{miim_end,}
},
};
+/* a generic flavor. */
+struct phy_info phy_info_generic = {
+ 0,
+ "Unknown/Generic PHY",
+ 32,
+ (struct phy_cmd[]) { /* config */
+ {PHY_BMCR, PHY_BMCR_RESET, NULL},
+ {PHY_BMCR, PHY_BMCR_AUTON|PHY_BMCR_RST_NEG, NULL},
+ {miim_end,}
+ },
+ (struct phy_cmd[]) { /* startup */
+ {PHY_BMSR, miim_read, NULL},
+ {PHY_BMSR, miim_read, &mii_parse_sr},
+ {PHY_BMSR, miim_read, &mii_parse_link},
+ {miim_end,}
+ },
+ (struct phy_cmd[]) { /* shutdown */
+ {miim_end,}
+ }
+};
+
uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
{
@@ -1207,6 +1299,7 @@ struct phy_info *phy_info[] = {
&phy_info_lxt971,
&phy_info_VSC8244,
&phy_info_dp83865,
+ &phy_info_generic,
NULL
};