|
@@ -801,22 +801,90 @@ static int bcm8704_init_user_dev3(struct niu *np)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int xcvr_init_10g(struct niu *np)
|
|
|
+static int mrvl88x2011_act_led(struct niu *np, int val)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV2_ADDR,
|
|
|
+ MRVL88X2011_LED_8_TO_11_CTL);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ err &= ~MRVL88X2011_LED(MRVL88X2011_LED_ACT,MRVL88X2011_LED_CTL_MASK);
|
|
|
+ err |= MRVL88X2011_LED(MRVL88X2011_LED_ACT,val);
|
|
|
+
|
|
|
+ return mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV2_ADDR,
|
|
|
+ MRVL88X2011_LED_8_TO_11_CTL, err);
|
|
|
+}
|
|
|
+
|
|
|
+static int mrvl88x2011_led_blink_rate(struct niu *np, int rate)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV2_ADDR,
|
|
|
+ MRVL88X2011_LED_BLINK_CTL);
|
|
|
+ if (err >= 0) {
|
|
|
+ err &= ~MRVL88X2011_LED_BLKRATE_MASK;
|
|
|
+ err |= (rate << 4);
|
|
|
+
|
|
|
+ err = mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV2_ADDR,
|
|
|
+ MRVL88X2011_LED_BLINK_CTL, err);
|
|
|
+ }
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static int xcvr_init_10g_mrvl88x2011(struct niu *np)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+
|
|
|
+ /* Set LED functions */
|
|
|
+ err = mrvl88x2011_led_blink_rate(np, MRVL88X2011_LED_BLKRATE_134MS);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ /* led activity */
|
|
|
+ err = mrvl88x2011_act_led(np, MRVL88X2011_LED_CTL_OFF);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV3_ADDR,
|
|
|
+ MRVL88X2011_GENERAL_CTL);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ err |= MRVL88X2011_ENA_XFPREFCLK;
|
|
|
+
|
|
|
+ err = mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV3_ADDR,
|
|
|
+ MRVL88X2011_GENERAL_CTL, err);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR,
|
|
|
+ MRVL88X2011_PMA_PMD_CTL_1);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ if (np->link_config.loopback_mode == LOOPBACK_MAC)
|
|
|
+ err |= MRVL88X2011_LOOPBACK;
|
|
|
+ else
|
|
|
+ err &= ~MRVL88X2011_LOOPBACK;
|
|
|
+
|
|
|
+ err = mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR,
|
|
|
+ MRVL88X2011_PMA_PMD_CTL_1, err);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ /* Enable PMD */
|
|
|
+ return mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR,
|
|
|
+ MRVL88X2011_10G_PMD_TX_DIS, MRVL88X2011_ENA_PMDTX);
|
|
|
+}
|
|
|
+
|
|
|
+static int xcvr_init_10g_bcm8704(struct niu *np)
|
|
|
{
|
|
|
struct niu_link_config *lp = &np->link_config;
|
|
|
u16 analog_stat0, tx_alarm_status;
|
|
|
int err;
|
|
|
- u64 val;
|
|
|
-
|
|
|
- val = nr64_mac(XMAC_CONFIG);
|
|
|
- val &= ~XMAC_CONFIG_LED_POLARITY;
|
|
|
- val |= XMAC_CONFIG_FORCE_LED_ON;
|
|
|
- nw64_mac(XMAC_CONFIG, val);
|
|
|
-
|
|
|
- /* XXX shared resource, lock parent XXX */
|
|
|
- val = nr64(MIF_CONFIG);
|
|
|
- val |= MIF_CONFIG_INDIRECT_MODE;
|
|
|
- nw64(MIF_CONFIG, val);
|
|
|
|
|
|
err = bcm8704_reset(np);
|
|
|
if (err)
|
|
@@ -896,6 +964,38 @@ static int xcvr_init_10g(struct niu *np)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int xcvr_init_10g(struct niu *np)
|
|
|
+{
|
|
|
+ int phy_id, err;
|
|
|
+ u64 val;
|
|
|
+
|
|
|
+ val = nr64_mac(XMAC_CONFIG);
|
|
|
+ val &= ~XMAC_CONFIG_LED_POLARITY;
|
|
|
+ val |= XMAC_CONFIG_FORCE_LED_ON;
|
|
|
+ nw64_mac(XMAC_CONFIG, val);
|
|
|
+
|
|
|
+ /* XXX shared resource, lock parent XXX */
|
|
|
+ val = nr64(MIF_CONFIG);
|
|
|
+ val |= MIF_CONFIG_INDIRECT_MODE;
|
|
|
+ nw64(MIF_CONFIG, val);
|
|
|
+
|
|
|
+ phy_id = phy_decode(np->parent->port_phy, np->port);
|
|
|
+ phy_id = np->parent->phy_probe_info.phy_id[phy_id][np->port];
|
|
|
+
|
|
|
+ /* handle different phy types */
|
|
|
+ switch (phy_id & NIU_PHY_ID_MASK) {
|
|
|
+ case NIU_PHY_ID_MRVL88X2011:
|
|
|
+ err = xcvr_init_10g_mrvl88x2011(np);
|
|
|
+ break;
|
|
|
+
|
|
|
+ default: /* bcom 8704 */
|
|
|
+ err = xcvr_init_10g_bcm8704(np);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int mii_reset(struct niu *np)
|
|
|
{
|
|
|
int limit, err;
|
|
@@ -1082,19 +1182,68 @@ static int niu_link_status_common(struct niu *np, int link_up)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int link_status_10g(struct niu *np, int *link_up_p)
|
|
|
+static int link_status_10g_mrvl(struct niu *np, int *link_up_p)
|
|
|
{
|
|
|
- unsigned long flags;
|
|
|
- int err, link_up;
|
|
|
+ int err, link_up, pma_status, pcs_status;
|
|
|
|
|
|
link_up = 0;
|
|
|
|
|
|
- spin_lock_irqsave(&np->lock, flags);
|
|
|
+ err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR,
|
|
|
+ MRVL88X2011_10G_PMD_STATUS_2);
|
|
|
+ if (err < 0)
|
|
|
+ goto out;
|
|
|
|
|
|
- err = -EINVAL;
|
|
|
- if (np->link_config.loopback_mode != LOOPBACK_DISABLED)
|
|
|
+ /* Check PMA/PMD Register: 1.0001.2 == 1 */
|
|
|
+ err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR,
|
|
|
+ MRVL88X2011_PMA_PMD_STATUS_1);
|
|
|
+ if (err < 0)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ pma_status = ((err & MRVL88X2011_LNK_STATUS_OK) ? 1 : 0);
|
|
|
+
|
|
|
+ /* Check PMC Register : 3.0001.2 == 1: read twice */
|
|
|
+ err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV3_ADDR,
|
|
|
+ MRVL88X2011_PMA_PMD_STATUS_1);
|
|
|
+ if (err < 0)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV3_ADDR,
|
|
|
+ MRVL88X2011_PMA_PMD_STATUS_1);
|
|
|
+ if (err < 0)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ pcs_status = ((err & MRVL88X2011_LNK_STATUS_OK) ? 1 : 0);
|
|
|
+
|
|
|
+ /* Check XGXS Register : 4.0018.[0-3,12] */
|
|
|
+ err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV4_ADDR,
|
|
|
+ MRVL88X2011_10G_XGXS_LANE_STAT);
|
|
|
+ if (err < 0)
|
|
|
goto out;
|
|
|
|
|
|
+ if (err == (PHYXS_XGXS_LANE_STAT_ALINGED | PHYXS_XGXS_LANE_STAT_LANE3 |
|
|
|
+ PHYXS_XGXS_LANE_STAT_LANE2 | PHYXS_XGXS_LANE_STAT_LANE1 |
|
|
|
+ PHYXS_XGXS_LANE_STAT_LANE0 | PHYXS_XGXS_LANE_STAT_MAGIC |
|
|
|
+ 0x800))
|
|
|
+ link_up = (pma_status && pcs_status) ? 1 : 0;
|
|
|
+
|
|
|
+ np->link_config.active_speed = SPEED_10000;
|
|
|
+ np->link_config.active_duplex = DUPLEX_FULL;
|
|
|
+ err = 0;
|
|
|
+out:
|
|
|
+ mrvl88x2011_act_led(np, (link_up ?
|
|
|
+ MRVL88X2011_LED_CTL_PCS_ACT :
|
|
|
+ MRVL88X2011_LED_CTL_OFF));
|
|
|
+
|
|
|
+ *link_up_p = link_up;
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static int link_status_10g_bcom(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)
|
|
@@ -1134,9 +1283,37 @@ static int link_status_10g(struct niu *np, int *link_up_p)
|
|
|
err = 0;
|
|
|
|
|
|
out:
|
|
|
+ *link_up_p = link_up;
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static int link_status_10g(struct niu *np, int *link_up_p)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ int err = -EINVAL;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&np->lock, flags);
|
|
|
+
|
|
|
+ if (np->link_config.loopback_mode == LOOPBACK_DISABLED) {
|
|
|
+ int phy_id;
|
|
|
+
|
|
|
+ phy_id = phy_decode(np->parent->port_phy, np->port);
|
|
|
+ phy_id = np->parent->phy_probe_info.phy_id[phy_id][np->port];
|
|
|
+
|
|
|
+ /* handle different phy types */
|
|
|
+ switch (phy_id & NIU_PHY_ID_MASK) {
|
|
|
+ case NIU_PHY_ID_MRVL88X2011:
|
|
|
+ err = link_status_10g_mrvl(np, link_up_p);
|
|
|
+ break;
|
|
|
+
|
|
|
+ default: /* bcom 8704 */
|
|
|
+ err = link_status_10g_bcom(np, link_up_p);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
spin_unlock_irqrestore(&np->lock, flags);
|
|
|
|
|
|
- *link_up_p = link_up;
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -6297,7 +6474,8 @@ static int __devinit phy_record(struct niu_parent *parent,
|
|
|
if (dev_id_1 < 0 || dev_id_2 < 0)
|
|
|
return 0;
|
|
|
if (type == PHY_TYPE_PMA_PMD || type == PHY_TYPE_PCS) {
|
|
|
- if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704)
|
|
|
+ if (((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) &&
|
|
|
+ ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011))
|
|
|
return 0;
|
|
|
} else {
|
|
|
if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM5464R)
|