aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/niu.c
diff options
context:
space:
mode:
authorSantwona Behera <santwona.behera@sun.com>2008-11-14 17:44:08 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-14 17:44:08 -0500
commite3e081e1d5c4791f4416ed57b7a2f143ab9e5b09 (patch)
tree58bdc7dea3f3d1e3b68c8a3dac90db8f60bab584 /drivers/net/niu.c
parente8f6fbf62de37cbc2e179176ac7010d5f4396b67 (diff)
NIU: Add Sun CP3260 ATCA blade support
This patch adds support for the Sun CP3260 ATCA blade which is a N2 based ATCA blade with 2 NIU ports. The NIU ports do not have on-board PHY. Signed-off-by: Santwona Behera <santwona.behera@sun.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/niu.c')
-rw-r--r--drivers/net/niu.c286
1 files changed, 280 insertions, 6 deletions
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index d8463b1c3df3..be6b4d7e2bb4 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -406,7 +406,7 @@ static int esr2_set_rx_cfg(struct niu *np, unsigned long channel, u32 val)
406} 406}
407 407
408/* Mode is always 10G fiber. */ 408/* Mode is always 10G fiber. */
409static int serdes_init_niu(struct niu *np) 409static int serdes_init_niu_10g_fiber(struct niu *np)
410{ 410{
411 struct niu_link_config *lp = &np->link_config; 411 struct niu_link_config *lp = &np->link_config;
412 u32 tx_cfg, rx_cfg; 412 u32 tx_cfg, rx_cfg;
@@ -443,6 +443,223 @@ static int serdes_init_niu(struct niu *np)
443 return 0; 443 return 0;
444} 444}
445 445
446static int serdes_init_niu_1g_serdes(struct niu *np)
447{
448 struct niu_link_config *lp = &np->link_config;
449 u16 pll_cfg, pll_sts;
450 int max_retry = 100;
451 u64 sig, mask, val;
452 u32 tx_cfg, rx_cfg;
453 unsigned long i;
454 int err;
455
456 tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV |
457 PLL_TX_CFG_RATE_HALF);
458 rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT |
459 PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH |
460 PLL_RX_CFG_RATE_HALF);
461
462 if (np->port == 0)
463 rx_cfg |= PLL_RX_CFG_EQ_LP_ADAPTIVE;
464
465 if (lp->loopback_mode == LOOPBACK_PHY) {
466 u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS;
467
468 mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
469 ESR2_TI_PLL_TEST_CFG_L, test_cfg);
470
471 tx_cfg |= PLL_TX_CFG_ENTEST;
472 rx_cfg |= PLL_RX_CFG_ENTEST;
473 }
474
475 /* Initialize PLL for 1G */
476 pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_8X);
477
478 err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
479 ESR2_TI_PLL_CFG_L, pll_cfg);
480 if (err) {
481 dev_err(np->device, PFX "NIU Port %d "
482 "serdes_init_niu_1g_serdes: "
483 "mdio write to ESR2_TI_PLL_CFG_L failed", np->port);
484 return err;
485 }
486
487 pll_sts = PLL_CFG_ENPLL;
488
489 err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
490 ESR2_TI_PLL_STS_L, pll_sts);
491 if (err) {
492 dev_err(np->device, PFX "NIU Port %d "
493 "serdes_init_niu_1g_serdes: "
494 "mdio write to ESR2_TI_PLL_STS_L failed", np->port);
495 return err;
496 }
497
498 udelay(200);
499
500 /* Initialize all 4 lanes of the SERDES. */
501 for (i = 0; i < 4; i++) {
502 err = esr2_set_tx_cfg(np, i, tx_cfg);
503 if (err)
504 return err;
505 }
506
507 for (i = 0; i < 4; i++) {
508 err = esr2_set_rx_cfg(np, i, rx_cfg);
509 if (err)
510 return err;
511 }
512
513 switch (np->port) {
514 case 0:
515 val = (ESR_INT_SRDY0_P0 | ESR_INT_DET0_P0);
516 mask = val;
517 break;
518
519 case 1:
520 val = (ESR_INT_SRDY0_P1 | ESR_INT_DET0_P1);
521 mask = val;
522 break;
523
524 default:
525 return -EINVAL;
526 }
527
528 while (max_retry--) {
529 sig = nr64(ESR_INT_SIGNALS);
530 if ((sig & mask) == val)
531 break;
532
533 mdelay(500);
534 }
535
536 if ((sig & mask) != val) {
537 dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
538 "[%08x]\n", np->port, (int) (sig & mask), (int) val);
539 return -ENODEV;
540 }
541
542 return 0;
543}
544
545static int serdes_init_niu_10g_serdes(struct niu *np)
546{
547 struct niu_link_config *lp = &np->link_config;
548 u32 tx_cfg, rx_cfg, pll_cfg, pll_sts;
549 int max_retry = 100;
550 u64 sig, mask, val;
551 unsigned long i;
552 int err;
553
554 tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV);
555 rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT |
556 PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH |
557 PLL_RX_CFG_EQ_LP_ADAPTIVE);
558
559 if (lp->loopback_mode == LOOPBACK_PHY) {
560 u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS;
561
562 mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
563 ESR2_TI_PLL_TEST_CFG_L, test_cfg);
564
565 tx_cfg |= PLL_TX_CFG_ENTEST;
566 rx_cfg |= PLL_RX_CFG_ENTEST;
567 }
568
569 /* Initialize PLL for 10G */
570 pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_10X);
571
572 err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
573 ESR2_TI_PLL_CFG_L, pll_cfg & 0xffff);
574 if (err) {
575 dev_err(np->device, PFX "NIU Port %d "
576 "serdes_init_niu_10g_serdes: "
577 "mdio write to ESR2_TI_PLL_CFG_L failed", np->port);
578 return err;
579 }
580
581 pll_sts = PLL_CFG_ENPLL;
582
583 err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR,
584 ESR2_TI_PLL_STS_L, pll_sts & 0xffff);
585 if (err) {
586 dev_err(np->device, PFX "NIU Port %d "
587 "serdes_init_niu_10g_serdes: "
588 "mdio write to ESR2_TI_PLL_STS_L failed", np->port);
589 return err;
590 }
591
592 udelay(200);
593
594 /* Initialize all 4 lanes of the SERDES. */
595 for (i = 0; i < 4; i++) {
596 err = esr2_set_tx_cfg(np, i, tx_cfg);
597 if (err)
598 return err;
599 }
600
601 for (i = 0; i < 4; i++) {
602 err = esr2_set_rx_cfg(np, i, rx_cfg);
603 if (err)
604 return err;
605 }
606
607 /* check if serdes is ready */
608
609 switch (np->port) {
610 case 0:
611 mask = ESR_INT_SIGNALS_P0_BITS;
612 val = (ESR_INT_SRDY0_P0 |
613 ESR_INT_DET0_P0 |
614 ESR_INT_XSRDY_P0 |
615 ESR_INT_XDP_P0_CH3 |
616 ESR_INT_XDP_P0_CH2 |
617 ESR_INT_XDP_P0_CH1 |
618 ESR_INT_XDP_P0_CH0);
619 break;
620
621 case 1:
622 mask = ESR_INT_SIGNALS_P1_BITS;
623 val = (ESR_INT_SRDY0_P1 |
624 ESR_INT_DET0_P1 |
625 ESR_INT_XSRDY_P1 |
626 ESR_INT_XDP_P1_CH3 |
627 ESR_INT_XDP_P1_CH2 |
628 ESR_INT_XDP_P1_CH1 |
629 ESR_INT_XDP_P1_CH0);
630 break;
631
632 default:
633 return -EINVAL;
634 }
635
636 while (max_retry--) {
637 sig = nr64(ESR_INT_SIGNALS);
638 if ((sig & mask) == val)
639 break;
640
641 mdelay(500);
642 }
643
644 if ((sig & mask) != val) {
645 pr_info(PFX "NIU Port %u signal bits [%08x] are not "
646 "[%08x] for 10G...trying 1G\n",
647 np->port, (int) (sig & mask), (int) val);
648
649 /* 10G failed, try initializing at 1G */
650 err = serdes_init_niu_1g_serdes(np);
651 if (!err) {
652 np->flags &= ~NIU_FLAGS_10G;
653 np->mac_xcvr = MAC_XCVR_PCS;
654 } else {
655 dev_err(np->device, PFX "Port %u 10G/1G SERDES "
656 "Link Failed \n", np->port);
657 return -ENODEV;
658 }
659 }
660 return 0;
661}
662
446static int esr_read_rxtx_ctrl(struct niu *np, unsigned long chan, u32 *val) 663static int esr_read_rxtx_ctrl(struct niu *np, unsigned long chan, u32 *val)
447{ 664{
448 int err; 665 int err;
@@ -1954,13 +2171,23 @@ static const struct niu_phy_ops phy_ops_10g_serdes = {
1954 .link_status = link_status_10g_serdes, 2171 .link_status = link_status_10g_serdes,
1955}; 2172};
1956 2173
2174static const struct niu_phy_ops phy_ops_10g_serdes_niu = {
2175 .serdes_init = serdes_init_niu_10g_serdes,
2176 .link_status = link_status_10g_serdes,
2177};
2178
2179static const struct niu_phy_ops phy_ops_1g_serdes_niu = {
2180 .serdes_init = serdes_init_niu_1g_serdes,
2181 .link_status = link_status_1g_serdes,
2182};
2183
1957static const struct niu_phy_ops phy_ops_1g_rgmii = { 2184static const struct niu_phy_ops phy_ops_1g_rgmii = {
1958 .xcvr_init = xcvr_init_1g_rgmii, 2185 .xcvr_init = xcvr_init_1g_rgmii,
1959 .link_status = link_status_1g_rgmii, 2186 .link_status = link_status_1g_rgmii,
1960}; 2187};
1961 2188
1962static const struct niu_phy_ops phy_ops_10g_fiber_niu = { 2189static const struct niu_phy_ops phy_ops_10g_fiber_niu = {
1963 .serdes_init = serdes_init_niu, 2190 .serdes_init = serdes_init_niu_10g_fiber,
1964 .xcvr_init = xcvr_init_10g, 2191 .xcvr_init = xcvr_init_10g,
1965 .link_status = link_status_10g, 2192 .link_status = link_status_10g,
1966}; 2193};
@@ -1998,11 +2225,21 @@ struct niu_phy_template {
1998 u32 phy_addr_base; 2225 u32 phy_addr_base;
1999}; 2226};
2000 2227
2001static const struct niu_phy_template phy_template_niu = { 2228static const struct niu_phy_template phy_template_niu_10g_fiber = {
2002 .ops = &phy_ops_10g_fiber_niu, 2229 .ops = &phy_ops_10g_fiber_niu,
2003 .phy_addr_base = 16, 2230 .phy_addr_base = 16,
2004}; 2231};
2005 2232
2233static const struct niu_phy_template phy_template_niu_10g_serdes = {
2234 .ops = &phy_ops_10g_serdes_niu,
2235 .phy_addr_base = 0,
2236};
2237
2238static const struct niu_phy_template phy_template_niu_1g_serdes = {
2239 .ops = &phy_ops_1g_serdes_niu,
2240 .phy_addr_base = 0,
2241};
2242
2006static const struct niu_phy_template phy_template_10g_fiber = { 2243static const struct niu_phy_template phy_template_10g_fiber = {
2007 .ops = &phy_ops_10g_fiber, 2244 .ops = &phy_ops_10g_fiber,
2008 .phy_addr_base = 8, 2245 .phy_addr_base = 8,
@@ -2182,8 +2419,25 @@ static int niu_determine_phy_disposition(struct niu *np)
2182 u32 phy_addr_off = 0; 2419 u32 phy_addr_off = 0;
2183 2420
2184 if (plat_type == PLAT_TYPE_NIU) { 2421 if (plat_type == PLAT_TYPE_NIU) {
2185 tp = &phy_template_niu; 2422 switch (np->flags &
2186 phy_addr_off += np->port; 2423 (NIU_FLAGS_10G |
2424 NIU_FLAGS_FIBER |
2425 NIU_FLAGS_XCVR_SERDES)) {
2426 case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES:
2427 /* 10G Serdes */
2428 tp = &phy_template_niu_10g_serdes;
2429 break;
2430 case NIU_FLAGS_XCVR_SERDES:
2431 /* 1G Serdes */
2432 tp = &phy_template_niu_1g_serdes;
2433 break;
2434 case NIU_FLAGS_10G | NIU_FLAGS_FIBER:
2435 /* 10G Fiber */
2436 default:
2437 tp = &phy_template_niu_10g_fiber;
2438 phy_addr_off += np->port;
2439 break;
2440 }
2187 } else { 2441 } else {
2188 switch (np->flags & 2442 switch (np->flags &
2189 (NIU_FLAGS_10G | 2443 (NIU_FLAGS_10G |
@@ -7213,6 +7467,12 @@ static int __devinit niu_phy_type_prop_decode(struct niu *np,
7213 np->flags |= NIU_FLAGS_10G; 7467 np->flags |= NIU_FLAGS_10G;
7214 np->flags &= ~NIU_FLAGS_FIBER; 7468 np->flags &= ~NIU_FLAGS_FIBER;
7215 np->mac_xcvr = MAC_XCVR_XPCS; 7469 np->mac_xcvr = MAC_XCVR_XPCS;
7470 } else if (!strcmp(phy_prop, "xgsd") || !strcmp(phy_prop, "gsd")) {
7471 /* 10G Serdes or 1G Serdes, default to 10G */
7472 np->flags |= NIU_FLAGS_10G;
7473 np->flags &= ~NIU_FLAGS_FIBER;
7474 np->flags |= NIU_FLAGS_XCVR_SERDES;
7475 np->mac_xcvr = MAC_XCVR_XPCS;
7216 } else { 7476 } else {
7217 return -EINVAL; 7477 return -EINVAL;
7218 } 7478 }
@@ -7741,6 +8001,8 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
7741 u32 val; 8001 u32 val;
7742 int err; 8002 int err;
7743 8003
8004 num_10g = num_1g = 0;
8005
7744 if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) || 8006 if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) ||
7745 !strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) { 8007 !strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) {
7746 num_10g = 0; 8008 num_10g = 0;
@@ -7757,6 +8019,16 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
7757 parent->num_ports = 2; 8019 parent->num_ports = 2;
7758 val = (phy_encode(PORT_TYPE_10G, 0) | 8020 val = (phy_encode(PORT_TYPE_10G, 0) |
7759 phy_encode(PORT_TYPE_10G, 1)); 8021 phy_encode(PORT_TYPE_10G, 1));
8022 } else if ((np->flags & NIU_FLAGS_XCVR_SERDES) &&
8023 (parent->plat_type == PLAT_TYPE_NIU)) {
8024 /* this is the Monza case */
8025 if (np->flags & NIU_FLAGS_10G) {
8026 val = (phy_encode(PORT_TYPE_10G, 0) |
8027 phy_encode(PORT_TYPE_10G, 1));
8028 } else {
8029 val = (phy_encode(PORT_TYPE_1G, 0) |
8030 phy_encode(PORT_TYPE_1G, 1));
8031 }
7760 } else { 8032 } else {
7761 err = fill_phy_probe_info(np, parent, info); 8033 err = fill_phy_probe_info(np, parent, info);
7762 if (err) 8034 if (err)
@@ -8656,7 +8928,9 @@ static void __devinit niu_device_announce(struct niu *np)
8656 dev->name, 8928 dev->name,
8657 (np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"), 8929 (np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"),
8658 (np->flags & NIU_FLAGS_10G ? "10G" : "1G"), 8930 (np->flags & NIU_FLAGS_10G ? "10G" : "1G"),
8659 (np->flags & NIU_FLAGS_FIBER ? "FIBER" : "COPPER"), 8931 (np->flags & NIU_FLAGS_FIBER ? "FIBER" :
8932 (np->flags & NIU_FLAGS_XCVR_SERDES ? "SERDES" :
8933 "COPPER")),
8660 (np->mac_xcvr == MAC_XCVR_MII ? "MII" : 8934 (np->mac_xcvr == MAC_XCVR_MII ? "MII" :
8661 (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")), 8935 (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")),
8662 np->vpd.phy_type); 8936 np->vpd.phy_type);