Commit 9c5cd670 authored by Tanli Chang's avatar Tanli Chang Committed by David S. Miller

niu: Add support for C10NEM

This patch is for supporting C10NEM. C10NEM is a switch module, which
has back-to-back XAUI link connected to blades.
Signed-off-by: default avatarTanli Chang <tanli.chang@sun.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8ca783ab
...@@ -1317,7 +1317,7 @@ static int bcm8704_reset(struct niu *np) ...@@ -1317,7 +1317,7 @@ static int bcm8704_reset(struct niu *np)
err = mdio_read(np, np->phy_addr, err = mdio_read(np, np->phy_addr,
BCM8704_PHYXS_DEV_ADDR, MII_BMCR); BCM8704_PHYXS_DEV_ADDR, MII_BMCR);
if (err < 0) if (err < 0 || err == 0xffff)
return err; return err;
err |= BMCR_RESET; err |= BMCR_RESET;
err = mdio_write(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR, err = mdio_write(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR,
...@@ -2042,7 +2042,7 @@ static int link_status_10g_bcm8706(struct niu *np, int *link_up_p) ...@@ -2042,7 +2042,7 @@ static int link_status_10g_bcm8706(struct niu *np, int *link_up_p)
err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR, err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
BCM8704_PMD_RCV_SIGDET); BCM8704_PMD_RCV_SIGDET);
if (err < 0) if (err < 0 || err == 0xffff)
goto out; goto out;
if (!(err & PMD_RCV_SIGDET_GLOBAL)) { if (!(err & PMD_RCV_SIGDET_GLOBAL)) {
err = 0; err = 0;
...@@ -2083,8 +2083,6 @@ static int link_status_10g_bcm8706(struct niu *np, int *link_up_p) ...@@ -2083,8 +2083,6 @@ static int link_status_10g_bcm8706(struct niu *np, int *link_up_p)
out: out:
*link_up_p = link_up; *link_up_p = link_up;
if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
err = 0;
return err; return err;
} }
...@@ -2220,10 +2218,17 @@ static int link_status_10g_hotplug(struct niu *np, int *link_up_p) ...@@ -2220,10 +2218,17 @@ static int link_status_10g_hotplug(struct niu *np, int *link_up_p)
if (phy_present != phy_present_prev) { if (phy_present != phy_present_prev) {
/* state change */ /* state change */
if (phy_present) { if (phy_present) {
/* A NEM was just plugged in */
np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT; np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
if (np->phy_ops->xcvr_init) if (np->phy_ops->xcvr_init)
err = np->phy_ops->xcvr_init(np); err = np->phy_ops->xcvr_init(np);
if (err) { if (err) {
err = mdio_read(np, np->phy_addr,
BCM8704_PHYXS_DEV_ADDR, MII_BMCR);
if (err == 0xffff) {
/* No mdio, back-to-back XAUI */
goto out;
}
/* debounce */ /* debounce */
np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT; np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
} }
...@@ -2234,13 +2239,21 @@ static int link_status_10g_hotplug(struct niu *np, int *link_up_p) ...@@ -2234,13 +2239,21 @@ static int link_status_10g_hotplug(struct niu *np, int *link_up_p)
np->dev->name); np->dev->name);
} }
} }
if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) out:
if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) {
err = link_status_10g_bcm8706(np, link_up_p); err = link_status_10g_bcm8706(np, link_up_p);
if (err == 0xffff) {
/* No mdio, back-to-back XAUI: it is C10NEM */
*link_up_p = 1;
np->link_config.active_speed = SPEED_10000;
np->link_config.active_duplex = DUPLEX_FULL;
}
}
} }
spin_unlock_irqrestore(&np->lock, flags); spin_unlock_irqrestore(&np->lock, flags);
return err; return 0;
} }
static int niu_link_status(struct niu *np, int *link_up_p) static int niu_link_status(struct niu *np, int *link_up_p)
...@@ -2312,6 +2325,12 @@ static const struct niu_phy_ops phy_ops_10g_fiber_hotplug = { ...@@ -2312,6 +2325,12 @@ static const struct niu_phy_ops phy_ops_10g_fiber_hotplug = {
.link_status = link_status_10g_hotplug, .link_status = link_status_10g_hotplug,
}; };
static const struct niu_phy_ops phy_ops_niu_10g_hotplug = {
.serdes_init = serdes_init_niu_10g_fiber,
.xcvr_init = xcvr_init_10g_bcm8706,
.link_status = link_status_10g_hotplug,
};
static const struct niu_phy_ops phy_ops_10g_copper = { static const struct niu_phy_ops phy_ops_10g_copper = {
.serdes_init = serdes_init_10g, .serdes_init = serdes_init_10g,
.link_status = link_status_10g, /* XXX */ .link_status = link_status_10g, /* XXX */
...@@ -2358,6 +2377,11 @@ static const struct niu_phy_template phy_template_10g_fiber_hotplug = { ...@@ -2358,6 +2377,11 @@ static const struct niu_phy_template phy_template_10g_fiber_hotplug = {
.phy_addr_base = 8, .phy_addr_base = 8,
}; };
static const struct niu_phy_template phy_template_niu_10g_hotplug = {
.ops = &phy_ops_niu_10g_hotplug,
.phy_addr_base = 8,
};
static const struct niu_phy_template phy_template_10g_copper = { static const struct niu_phy_template phy_template_10g_copper = {
.ops = &phy_ops_10g_copper, .ops = &phy_ops_10g_copper,
.phy_addr_base = 10, .phy_addr_base = 10,
...@@ -2542,8 +2566,16 @@ static int niu_determine_phy_disposition(struct niu *np) ...@@ -2542,8 +2566,16 @@ static int niu_determine_phy_disposition(struct niu *np)
case NIU_FLAGS_10G | NIU_FLAGS_FIBER: case NIU_FLAGS_10G | NIU_FLAGS_FIBER:
/* 10G Fiber */ /* 10G Fiber */
default: default:
if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
tp = &phy_template_niu_10g_hotplug;
if (np->port == 0)
phy_addr_off = 8;
if (np->port == 1)
phy_addr_off = 12;
} else {
tp = &phy_template_niu_10g_fiber; tp = &phy_template_niu_10g_fiber;
phy_addr_off += np->port; phy_addr_off += np->port;
}
break; break;
} }
} else { } else {
...@@ -2630,11 +2662,11 @@ static int niu_init_link(struct niu *np) ...@@ -2630,11 +2662,11 @@ static int niu_init_link(struct niu *np)
msleep(200); msleep(200);
} }
err = niu_serdes_init(np); err = niu_serdes_init(np);
if (err) if (err && !(np->flags & NIU_FLAGS_HOTPLUG_PHY))
return err; return err;
msleep(200); msleep(200);
err = niu_xcvr_init(np); err = niu_xcvr_init(np);
if (!err) if (!err || (np->flags & NIU_FLAGS_HOTPLUG_PHY))
niu_link_status(np, &ignore); niu_link_status(np, &ignore);
return 0; return 0;
} }
...@@ -9346,6 +9378,11 @@ static int __devinit niu_get_of_props(struct niu *np) ...@@ -9346,6 +9378,11 @@ static int __devinit niu_get_of_props(struct niu *np)
if (model) if (model)
strcpy(np->vpd.model, model); strcpy(np->vpd.model, model);
if (of_find_property(dp, "hot-swappable-phy", &prop_len)) {
np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER |
NIU_FLAGS_HOTPLUG_PHY);
}
return 0; return 0;
#else #else
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment