aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTanli Chang <tanli.chang@sun.com>2009-05-26 23:45:50 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-26 23:45:50 -0400
commit9c5cd6708008fcc3dbced6e4b97aa5ecd0634a85 (patch)
treefeb040e38dd505819da5f7264e8c133d4ad643c0
parent8ca783ab78e3fa518885c4fef93d0972e450a4de (diff)
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: Tanli Chang <tanli.chang@sun.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/niu.c57
1 files changed, 47 insertions, 10 deletions
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index 2b1745328cf7..0d9de5ac4130 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -1317,7 +1317,7 @@ static int bcm8704_reset(struct niu *np)
1317 1317
1318 err = mdio_read(np, np->phy_addr, 1318 err = mdio_read(np, np->phy_addr,
1319 BCM8704_PHYXS_DEV_ADDR, MII_BMCR); 1319 BCM8704_PHYXS_DEV_ADDR, MII_BMCR);
1320 if (err < 0) 1320 if (err < 0 || err == 0xffff)
1321 return err; 1321 return err;
1322 err |= BMCR_RESET; 1322 err |= BMCR_RESET;
1323 err = mdio_write(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR, 1323 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 2042
2043 err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR, 2043 err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
2044 BCM8704_PMD_RCV_SIGDET); 2044 BCM8704_PMD_RCV_SIGDET);
2045 if (err < 0) 2045 if (err < 0 || err == 0xffff)
2046 goto out; 2046 goto out;
2047 if (!(err & PMD_RCV_SIGDET_GLOBAL)) { 2047 if (!(err & PMD_RCV_SIGDET_GLOBAL)) {
2048 err = 0; 2048 err = 0;
@@ -2083,8 +2083,6 @@ static int link_status_10g_bcm8706(struct niu *np, int *link_up_p)
2083 2083
2084out: 2084out:
2085 *link_up_p = link_up; 2085 *link_up_p = link_up;
2086 if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
2087 err = 0;
2088 return err; 2086 return err;
2089} 2087}
2090 2088
@@ -2220,10 +2218,17 @@ static int link_status_10g_hotplug(struct niu *np, int *link_up_p)
2220 if (phy_present != phy_present_prev) { 2218 if (phy_present != phy_present_prev) {
2221 /* state change */ 2219 /* state change */
2222 if (phy_present) { 2220 if (phy_present) {
2221 /* A NEM was just plugged in */
2223 np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT; 2222 np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
2224 if (np->phy_ops->xcvr_init) 2223 if (np->phy_ops->xcvr_init)
2225 err = np->phy_ops->xcvr_init(np); 2224 err = np->phy_ops->xcvr_init(np);
2226 if (err) { 2225 if (err) {
2226 err = mdio_read(np, np->phy_addr,
2227 BCM8704_PHYXS_DEV_ADDR, MII_BMCR);
2228 if (err == 0xffff) {
2229 /* No mdio, back-to-back XAUI */
2230 goto out;
2231 }
2227 /* debounce */ 2232 /* debounce */
2228 np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT; 2233 np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
2229 } 2234 }
@@ -2234,13 +2239,21 @@ static int link_status_10g_hotplug(struct niu *np, int *link_up_p)
2234 np->dev->name); 2239 np->dev->name);
2235 } 2240 }
2236 } 2241 }
2237 if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) 2242out:
2243 if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) {
2238 err = link_status_10g_bcm8706(np, link_up_p); 2244 err = link_status_10g_bcm8706(np, link_up_p);
2245 if (err == 0xffff) {
2246 /* No mdio, back-to-back XAUI: it is C10NEM */
2247 *link_up_p = 1;
2248 np->link_config.active_speed = SPEED_10000;
2249 np->link_config.active_duplex = DUPLEX_FULL;
2250 }
2251 }
2239 } 2252 }
2240 2253
2241 spin_unlock_irqrestore(&np->lock, flags); 2254 spin_unlock_irqrestore(&np->lock, flags);
2242 2255
2243 return err; 2256 return 0;
2244} 2257}
2245 2258
2246static int niu_link_status(struct niu *np, int *link_up_p) 2259static 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 .link_status = link_status_10g_hotplug, 2325 .link_status = link_status_10g_hotplug,
2313}; 2326};
2314 2327
2328static const struct niu_phy_ops phy_ops_niu_10g_hotplug = {
2329 .serdes_init = serdes_init_niu_10g_fiber,
2330 .xcvr_init = xcvr_init_10g_bcm8706,
2331 .link_status = link_status_10g_hotplug,
2332};
2333
2315static const struct niu_phy_ops phy_ops_10g_copper = { 2334static const struct niu_phy_ops phy_ops_10g_copper = {
2316 .serdes_init = serdes_init_10g, 2335 .serdes_init = serdes_init_10g,
2317 .link_status = link_status_10g, /* XXX */ 2336 .link_status = link_status_10g, /* XXX */
@@ -2358,6 +2377,11 @@ static const struct niu_phy_template phy_template_10g_fiber_hotplug = {
2358 .phy_addr_base = 8, 2377 .phy_addr_base = 8,
2359}; 2378};
2360 2379
2380static const struct niu_phy_template phy_template_niu_10g_hotplug = {
2381 .ops = &phy_ops_niu_10g_hotplug,
2382 .phy_addr_base = 8,
2383};
2384
2361static const struct niu_phy_template phy_template_10g_copper = { 2385static const struct niu_phy_template phy_template_10g_copper = {
2362 .ops = &phy_ops_10g_copper, 2386 .ops = &phy_ops_10g_copper,
2363 .phy_addr_base = 10, 2387 .phy_addr_base = 10,
@@ -2542,8 +2566,16 @@ static int niu_determine_phy_disposition(struct niu *np)
2542 case NIU_FLAGS_10G | NIU_FLAGS_FIBER: 2566 case NIU_FLAGS_10G | NIU_FLAGS_FIBER:
2543 /* 10G Fiber */ 2567 /* 10G Fiber */
2544 default: 2568 default:
2545 tp = &phy_template_niu_10g_fiber; 2569 if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
2546 phy_addr_off += np->port; 2570 tp = &phy_template_niu_10g_hotplug;
2571 if (np->port == 0)
2572 phy_addr_off = 8;
2573 if (np->port == 1)
2574 phy_addr_off = 12;
2575 } else {
2576 tp = &phy_template_niu_10g_fiber;
2577 phy_addr_off += np->port;
2578 }
2547 break; 2579 break;
2548 } 2580 }
2549 } else { 2581 } else {
@@ -2630,11 +2662,11 @@ static int niu_init_link(struct niu *np)
2630 msleep(200); 2662 msleep(200);
2631 } 2663 }
2632 err = niu_serdes_init(np); 2664 err = niu_serdes_init(np);
2633 if (err) 2665 if (err && !(np->flags & NIU_FLAGS_HOTPLUG_PHY))
2634 return err; 2666 return err;
2635 msleep(200); 2667 msleep(200);
2636 err = niu_xcvr_init(np); 2668 err = niu_xcvr_init(np);
2637 if (!err) 2669 if (!err || (np->flags & NIU_FLAGS_HOTPLUG_PHY))
2638 niu_link_status(np, &ignore); 2670 niu_link_status(np, &ignore);
2639 return 0; 2671 return 0;
2640} 2672}
@@ -9346,6 +9378,11 @@ static int __devinit niu_get_of_props(struct niu *np)
9346 if (model) 9378 if (model)
9347 strcpy(np->vpd.model, model); 9379 strcpy(np->vpd.model, model);
9348 9380
9381 if (of_find_property(dp, "hot-swappable-phy", &prop_len)) {
9382 np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER |
9383 NIU_FLAGS_HOTPLUG_PHY);
9384 }
9385
9349 return 0; 9386 return 0;
9350#else 9387#else
9351 return -EINVAL; 9388 return -EINVAL;