niu: Add support for Neptune FEM/NEM cards for C10 server blades
[ Minor coding style and whitespace corrections, also bump driver version and release date. -DaveM ] Signed-off-by: Matheos Worku <matheos.worku@sun.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7f7c4072ea
commit
a5d6ab56da
2 changed files with 277 additions and 30 deletions
|
@ -33,8 +33,8 @@
|
|||
|
||||
#define DRV_MODULE_NAME "niu"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "0.7"
|
||||
#define DRV_MODULE_RELDATE "February 18, 2008"
|
||||
#define DRV_MODULE_VERSION "0.8"
|
||||
#define DRV_MODULE_RELDATE "April 24, 2008"
|
||||
|
||||
static char version[] __devinitdata =
|
||||
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
|
||||
|
@ -673,11 +673,16 @@ static int serdes_init_10g(struct niu *np)
|
|||
}
|
||||
|
||||
if ((sig & mask) != val) {
|
||||
if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
|
||||
np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
|
||||
return 0;
|
||||
}
|
||||
dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
|
||||
"[%08x]\n", np->port, (int) (sig & mask), (int) val);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
|
||||
np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -998,6 +1003,28 @@ static int bcm8704_user_dev3_readback(struct niu *np, int reg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bcm8706_init_user_dev3(struct niu *np)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
||||
err = mdio_read(np, np->phy_addr, BCM8704_USER_DEV3_ADDR,
|
||||
BCM8704_USER_OPT_DIGITAL_CTRL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err &= ~USER_ODIG_CTRL_GPIOS;
|
||||
err |= (0x3 << USER_ODIG_CTRL_GPIOS_SHIFT);
|
||||
err |= USER_ODIG_CTRL_RESV2;
|
||||
err = mdio_write(np, np->phy_addr, BCM8704_USER_DEV3_ADDR,
|
||||
BCM8704_USER_OPT_DIGITAL_CTRL, err);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mdelay(1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm8704_init_user_dev3(struct niu *np)
|
||||
{
|
||||
int err;
|
||||
|
@ -1127,33 +1154,11 @@ static int xcvr_init_10g_mrvl88x2011(struct niu *np)
|
|||
MRVL88X2011_10G_PMD_TX_DIS, MRVL88X2011_ENA_PMDTX);
|
||||
}
|
||||
|
||||
static int xcvr_init_10g_bcm8704(struct niu *np)
|
||||
|
||||
static int xcvr_diag_bcm870x(struct niu *np)
|
||||
{
|
||||
struct niu_link_config *lp = &np->link_config;
|
||||
u16 analog_stat0, tx_alarm_status;
|
||||
int err;
|
||||
|
||||
err = bcm8704_reset(np);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = bcm8704_init_user_dev3(np);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
|
||||
MII_BMCR);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err &= ~BMCR_LOOPBACK;
|
||||
|
||||
if (lp->loopback_mode == LOOPBACK_MAC)
|
||||
err |= BMCR_LOOPBACK;
|
||||
|
||||
err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
|
||||
MII_BMCR, err);
|
||||
if (err)
|
||||
return err;
|
||||
int err = 0;
|
||||
|
||||
#if 1
|
||||
err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
|
||||
|
@ -1211,6 +1216,89 @@ static int xcvr_init_10g_bcm8704(struct niu *np)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int xcvr_10g_set_lb_bcm870x(struct niu *np)
|
||||
{
|
||||
struct niu_link_config *lp = &np->link_config;
|
||||
int err;
|
||||
|
||||
err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
|
||||
MII_BMCR);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err &= ~BMCR_LOOPBACK;
|
||||
|
||||
if (lp->loopback_mode == LOOPBACK_MAC)
|
||||
err |= BMCR_LOOPBACK;
|
||||
|
||||
err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
|
||||
MII_BMCR, err);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xcvr_init_10g_bcm8706(struct niu *np)
|
||||
{
|
||||
int err = 0;
|
||||
u64 val;
|
||||
|
||||
if ((np->flags & NIU_FLAGS_HOTPLUG_PHY) &&
|
||||
(np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) == 0)
|
||||
return err;
|
||||
|
||||
val = nr64_mac(XMAC_CONFIG);
|
||||
val &= ~XMAC_CONFIG_LED_POLARITY;
|
||||
val |= XMAC_CONFIG_FORCE_LED_ON;
|
||||
nw64_mac(XMAC_CONFIG, val);
|
||||
|
||||
val = nr64(MIF_CONFIG);
|
||||
val |= MIF_CONFIG_INDIRECT_MODE;
|
||||
nw64(MIF_CONFIG, val);
|
||||
|
||||
err = bcm8704_reset(np);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = xcvr_10g_set_lb_bcm870x(np);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = bcm8706_init_user_dev3(np);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = xcvr_diag_bcm870x(np);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xcvr_init_10g_bcm8704(struct niu *np)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bcm8704_reset(np);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = bcm8704_init_user_dev3(np);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = xcvr_10g_set_lb_bcm870x(np);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = xcvr_diag_bcm870x(np);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xcvr_init_10g(struct niu *np)
|
||||
{
|
||||
int phy_id, err;
|
||||
|
@ -1548,6 +1636,59 @@ static int link_status_10g_mrvl(struct niu *np, int *link_up_p)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int link_status_10g_bcm8706(struct niu *np, int *link_up_p)
|
||||
{
|
||||
int err, link_up;
|
||||
link_up = 0;
|
||||
|
||||
err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
|
||||
BCM8704_PMD_RCV_SIGDET);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
if (!(err & PMD_RCV_SIGDET_GLOBAL)) {
|
||||
err = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
|
||||
BCM8704_PCS_10G_R_STATUS);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
if (!(err & PCS_10G_R_STATUS_BLK_LOCK)) {
|
||||
err = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = mdio_read(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR,
|
||||
BCM8704_PHYXS_XGXS_LANE_STAT);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
if (err != (PHYXS_XGXS_LANE_STAT_ALINGED |
|
||||
PHYXS_XGXS_LANE_STAT_MAGIC |
|
||||
PHYXS_XGXS_LANE_STAT_PATTEST |
|
||||
PHYXS_XGXS_LANE_STAT_LANE3 |
|
||||
PHYXS_XGXS_LANE_STAT_LANE2 |
|
||||
PHYXS_XGXS_LANE_STAT_LANE1 |
|
||||
PHYXS_XGXS_LANE_STAT_LANE0)) {
|
||||
err = 0;
|
||||
np->link_config.active_speed = SPEED_INVALID;
|
||||
np->link_config.active_duplex = DUPLEX_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
link_up = 1;
|
||||
np->link_config.active_speed = SPEED_10000;
|
||||
np->link_config.active_duplex = DUPLEX_FULL;
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
*link_up_p = link_up;
|
||||
if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
|
||||
err = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int link_status_10g_bcom(struct niu *np, int *link_up_p)
|
||||
{
|
||||
int err, link_up;
|
||||
|
@ -1627,6 +1768,82 @@ static int link_status_10g(struct niu *np, int *link_up_p)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int niu_10g_phy_present(struct niu *np)
|
||||
{
|
||||
u64 sig, mask, val;
|
||||
|
||||
sig = nr64(ESR_INT_SIGNALS);
|
||||
switch (np->port) {
|
||||
case 0:
|
||||
mask = ESR_INT_SIGNALS_P0_BITS;
|
||||
val = (ESR_INT_SRDY0_P0 |
|
||||
ESR_INT_DET0_P0 |
|
||||
ESR_INT_XSRDY_P0 |
|
||||
ESR_INT_XDP_P0_CH3 |
|
||||
ESR_INT_XDP_P0_CH2 |
|
||||
ESR_INT_XDP_P0_CH1 |
|
||||
ESR_INT_XDP_P0_CH0);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
mask = ESR_INT_SIGNALS_P1_BITS;
|
||||
val = (ESR_INT_SRDY0_P1 |
|
||||
ESR_INT_DET0_P1 |
|
||||
ESR_INT_XSRDY_P1 |
|
||||
ESR_INT_XDP_P1_CH3 |
|
||||
ESR_INT_XDP_P1_CH2 |
|
||||
ESR_INT_XDP_P1_CH1 |
|
||||
ESR_INT_XDP_P1_CH0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((sig & mask) != val)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_status_10g_hotplug(struct niu *np, int *link_up_p)
|
||||
{
|
||||
unsigned long flags;
|
||||
int err = 0;
|
||||
int phy_present;
|
||||
int phy_present_prev;
|
||||
|
||||
spin_lock_irqsave(&np->lock, flags);
|
||||
|
||||
if (np->link_config.loopback_mode == LOOPBACK_DISABLED) {
|
||||
phy_present_prev = (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) ?
|
||||
1 : 0;
|
||||
phy_present = niu_10g_phy_present(np);
|
||||
if (phy_present != phy_present_prev) {
|
||||
/* state change */
|
||||
if (phy_present) {
|
||||
np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
|
||||
if (np->phy_ops->xcvr_init)
|
||||
err = np->phy_ops->xcvr_init(np);
|
||||
if (err) {
|
||||
/* debounce */
|
||||
np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
|
||||
}
|
||||
} else {
|
||||
np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
|
||||
*link_up_p = 0;
|
||||
niuwarn(LINK, "%s: Hotplug PHY Removed\n",
|
||||
np->dev->name);
|
||||
}
|
||||
}
|
||||
if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT)
|
||||
err = link_status_10g_bcm8706(np, link_up_p);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&np->lock, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int link_status_1g(struct niu *np, int *link_up_p)
|
||||
{
|
||||
struct niu_link_config *lp = &np->link_config;
|
||||
|
@ -1761,6 +1978,12 @@ static const struct niu_phy_ops phy_ops_10g_fiber = {
|
|||
.link_status = link_status_10g,
|
||||
};
|
||||
|
||||
static const struct niu_phy_ops phy_ops_10g_fiber_hotplug = {
|
||||
.serdes_init = serdes_init_10g,
|
||||
.xcvr_init = xcvr_init_10g_bcm8706,
|
||||
.link_status = link_status_10g_hotplug,
|
||||
};
|
||||
|
||||
static const struct niu_phy_ops phy_ops_10g_copper = {
|
||||
.serdes_init = serdes_init_10g,
|
||||
.link_status = link_status_10g, /* XXX */
|
||||
|
@ -1792,6 +2015,11 @@ static const struct niu_phy_template phy_template_10g_fiber = {
|
|||
.phy_addr_base = 8,
|
||||
};
|
||||
|
||||
static const struct niu_phy_template phy_template_10g_fiber_hotplug = {
|
||||
.ops = &phy_ops_10g_fiber_hotplug,
|
||||
.phy_addr_base = 8,
|
||||
};
|
||||
|
||||
static const struct niu_phy_template phy_template_10g_copper = {
|
||||
.ops = &phy_ops_10g_copper,
|
||||
.phy_addr_base = 10,
|
||||
|
@ -1996,6 +2224,13 @@ static int niu_determine_phy_disposition(struct niu *np)
|
|||
plat_type == PLAT_TYPE_VF_P1)
|
||||
phy_addr_off = 8;
|
||||
phy_addr_off += np->port;
|
||||
if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
|
||||
tp = &phy_template_10g_fiber_hotplug;
|
||||
if (np->port == 0)
|
||||
phy_addr_off = 8;
|
||||
if (np->port == 1)
|
||||
phy_addr_off = 12;
|
||||
}
|
||||
break;
|
||||
|
||||
case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES:
|
||||
|
@ -6830,6 +7065,9 @@ static void __devinit niu_pci_vpd_validate(struct niu *np)
|
|||
}
|
||||
if (np->flags & NIU_FLAGS_10G)
|
||||
np->mac_xcvr = MAC_XCVR_XPCS;
|
||||
} else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) {
|
||||
np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER |
|
||||
NIU_FLAGS_HOTPLUG_PHY);
|
||||
} else if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) {
|
||||
dev_err(np->device, PFX "Illegal phy string [%s].\n",
|
||||
np->vpd.phy_type);
|
||||
|
@ -7052,7 +7290,8 @@ static int __devinit phy_record(struct niu_parent *parent,
|
|||
return 0;
|
||||
if (type == PHY_TYPE_PMA_PMD || type == PHY_TYPE_PCS) {
|
||||
if (((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) &&
|
||||
((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011))
|
||||
((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011) &&
|
||||
((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8706))
|
||||
return 0;
|
||||
} else {
|
||||
if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM5464R)
|
||||
|
@ -7299,7 +7538,6 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
|
|||
u32 val;
|
||||
int err;
|
||||
|
||||
|
||||
if (!strcmp(np->vpd.model, "SUNW,CP3220") ||
|
||||
!strcmp(np->vpd.model, "SUNW,CP3260")) {
|
||||
num_10g = 0;
|
||||
|
@ -7310,6 +7548,12 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
|
|||
phy_encode(PORT_TYPE_1G, 1) |
|
||||
phy_encode(PORT_TYPE_1G, 2) |
|
||||
phy_encode(PORT_TYPE_1G, 3));
|
||||
} else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) {
|
||||
num_10g = 2;
|
||||
num_1g = 0;
|
||||
parent->num_ports = 2;
|
||||
val = (phy_encode(PORT_TYPE_10G, 0) |
|
||||
phy_encode(PORT_TYPE_10G, 1));
|
||||
} else {
|
||||
err = fill_phy_probe_info(np, parent, info);
|
||||
if (err)
|
||||
|
|
|
@ -2537,6 +2537,7 @@ struct fcram_hash_ipv6 {
|
|||
|
||||
#define NIU_PHY_ID_MASK 0xfffff0f0
|
||||
#define NIU_PHY_ID_BCM8704 0x00206030
|
||||
#define NIU_PHY_ID_BCM8706 0x00206035
|
||||
#define NIU_PHY_ID_BCM5464R 0x002060b0
|
||||
#define NIU_PHY_ID_MRVL88X2011 0x01410020
|
||||
|
||||
|
@ -3208,6 +3209,8 @@ struct niu {
|
|||
struct niu_parent *parent;
|
||||
|
||||
u32 flags;
|
||||
#define NIU_FLAGS_HOTPLUG_PHY_PRESENT 0x02000000 /* Removebale PHY detected*/
|
||||
#define NIU_FLAGS_HOTPLUG_PHY 0x01000000 /* Removebale PHY */
|
||||
#define NIU_FLAGS_VPD_VALID 0x00800000 /* VPD has valid version */
|
||||
#define NIU_FLAGS_MSIX 0x00400000 /* MSI-X in use */
|
||||
#define NIU_FLAGS_MCAST 0x00200000 /* multicast filter enabled */
|
||||
|
|
Loading…
Reference in a new issue