This patch makes necessary changes in the Neptune driver to support
the new Marvell PHY. It also adds support for the LED blinking
on Neptune cards with Marvell PHY.
diff -uprN -X linux-2.6/Documentation/dontdiff
linux-2.6/drivers/net/niu.c linux-2.6-changed/drivers/net/niu.c
--- linux-2.6/drivers/net/niu.c 2007-12-10 14:14:04.000000000 +0100
+++ linux-2.6-changed/drivers/net/niu.c 2007-12-18 16:47:50.000000000
+0100
@@ -801,22 +801,65 @@ static int bcm8704_init_user_dev3(struct
return 0;
}
-static int xcvr_init_10g(struct niu *np)
+void mrvl88x2011_act_led(struct niu *np, int val)
{
- 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);
+#define MRVL88X2011_LED_ACT 1
+#define MRVL88X2011_LED(n,v) ((v)<<((n)*4))
+#define MRVL88X2011_LED_STAT(n,v) ((v)>>((n)*4))
- /* XXX shared resource, lock parent XXX */
- val = nr64(MIF_CONFIG);
- val |= MIF_CONFIG_INDIRECT_MODE;
- nw64(MIF_CONFIG, val);
+ err = mdio_read(np, np->phy_addr, 2, 0x8306);
+ err &= ~MRVL88X2011_LED(MRVL88X2011_LED_ACT,0x7);
+ err |= MRVL88X2011_LED(MRVL88X2011_LED_ACT,val);
+
+ (void) mdio_write(np, np->phy_addr, 2, 0x8306, err);
+}
+
+void mrvl88x2011_led_blink_rate(struct niu *np, int rate)
+{
+ int err;
+
+ err = mdio_read(np, np->phy_addr, 2, 0x8303);
+ if (err >= 0) {
+ err &= ~0x70;
+ err |= (rate << 4);
+
+ (void) mdio_write(np, np->phy_addr, 2, 0x8303, err);
+ }
+}
+
+static int xcvr_init_10g_mrvl88x2011(struct niu *np)
+{
+ int err;
+
+ /* Set LED functions */
+ mrvl88x2011_led_blink_rate(np, 2);
+ mrvl88x2011_act_led(np, 0); /* led activity */
+
+ err = mdio_read(np, np->phy_addr, 3, 0x8300);
+ if (err < 0) {
+ return(err);
+ }
+
+ err |= 0x0001;
+
+ err = mdio_write(np, np->phy_addr, 3, 0x8300, err);
+ if (err < 0) {
+ return(err);
+ }
+
+ /* Enable PMD */
+ err = mdio_write(np, np->phy_addr, 1, 0x0009, 0);
+
+ return (err);
+}
+
+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;
err = bcm8704_reset(np);
if (err)
@@ -896,6 +939,39 @@ static int xcvr_init_10g(struct niu *np)
return 0;
}
+static int xcvr_init_10g(struct niu *np)
+{
+ int err;
+ u64 val;
+ int phy_id;
+
+ 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,18 +1158,69 @@ static int niu_link_status_common(struct
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;
+ int link_up = 0;
+ int pma_status;
+ int pcs_status;
- link_up = 0;
- spin_lock_irqsave(&np->lock, flags);
+ err = mdio_read(np, np->phy_addr, 1, 0x0008);
+ 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, 1, 0x0001);
+ if (err < 0) {
+ goto out;
+ }
+
+ pma_status = ((err & 0x0004) ? 1:0);
+
+ /* Check PMC Register : 3.0001.2 == 1: read twice
+ */
+ err = mdio_read(np, np->phy_addr, 3, 0x0001);
+ if (err < 0) {
goto out;
+ }
+ err = mdio_read(np, np->phy_addr, 3, 0x0001);
+ if (err < 0) {
+ goto out;
+ }
+ pcs_status = ((err & 0x0004) ? 1 : 0);
+
+ /* Check XGXS Register : 4.0018.[0-3,12]
+ */
+ err = mdio_read(np, np->phy_addr, 4, 0x0018);
+ 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 ? 5:0);
+
+ *link_up_p = link_up;
+ return err;
+}
+
+static int link_status_10g_bcom(struct niu *np, int *link_up_p)
+{
+ int err;
+ int link_up = 0;
err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
BCM8704_PMD_RCV_SIGDET);
@@ -1134,12 +1261,42 @@ static int link_status_10g(struct niu *n
err = 0;
out:
- spin_unlock_irqrestore(&np->lock, flags);
-
*link_up_p = link_up;
return err;
}
+static int link_status_10g(struct niu *np, int *link_up_p)
+{
+ unsigned long flags;
+ int err;
+
+ 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);
+
+ return(err);
+}
+
static int link_status_1g(struct niu *np, int *link_up_p)
{
u16 current_speed, bmsr;
@@ -6281,8 +6438,10 @@ static int __devinit phy_record(struct n
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)
diff -uprN -X linux-2.6/Documentation/dontdiff
linux-2.6/drivers/net/niu.h linux-2.6-changed/drivers/net/niu.h
--- linux-2.6/drivers/net/niu.h 2007-12-10 14:14:04.000000000 +0100
+++ linux-2.6-changed/drivers/net/niu.h 2007-12-18 15:01:02.000000000
+0100
@@ -2538,6 +2538,7 @@ struct fcram_hash_ipv6 {
#define NIU_PHY_ID_MASK 0xfffff0f0
#define NIU_PHY_ID_BCM8704 0x00206030
#define NIU_PHY_ID_BCM5464R 0x002060b0
+#define NIU_PHY_ID_MRVL88X2011 0x01410020
#define BCM8704_PMA_PMD_DEV_ADDR 1
#define BCM8704_PCS_DEV_ADDR 2
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html