aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/niu.c
diff options
context:
space:
mode:
authorMirko Lindner <mlindner@marvell.com>2008-01-10 05:12:44 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-10 05:12:44 -0500
commitb0de8e402dc5d3ee04f4d0f669ae492a3e569933 (patch)
treee692537e3a834e1ed415beda87be1ce0d492827c /drivers/net/niu.c
parentfd0b45dfd1858c6b49d06355a460bcf36d654c06 (diff)
[NIU]: Support for Marvell PHY
From: Mirko Lindner <mlindner@marvell.com> 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. All registers are using defines in the niu.h header file as is already done for the BCM8704 registers. [ Coding style, etc. cleanups -DaveM ] Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/niu.c')
-rw-r--r--drivers/net/niu.c218
1 files changed, 198 insertions, 20 deletions
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index 9a0c6d3adfe9..3bbcea11329f 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -801,22 +801,90 @@ static int bcm8704_init_user_dev3(struct niu *np)
801 return 0; 801 return 0;
802} 802}
803 803
804static int xcvr_init_10g(struct niu *np) 804static int mrvl88x2011_act_led(struct niu *np, int val)
805{
806 int err;
807
808 err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV2_ADDR,
809 MRVL88X2011_LED_8_TO_11_CTL);
810 if (err < 0)
811 return err;
812
813 err &= ~MRVL88X2011_LED(MRVL88X2011_LED_ACT,MRVL88X2011_LED_CTL_MASK);
814 err |= MRVL88X2011_LED(MRVL88X2011_LED_ACT,val);
815
816 return mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV2_ADDR,
817 MRVL88X2011_LED_8_TO_11_CTL, err);
818}
819
820static int mrvl88x2011_led_blink_rate(struct niu *np, int rate)
821{
822 int err;
823
824 err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV2_ADDR,
825 MRVL88X2011_LED_BLINK_CTL);
826 if (err >= 0) {
827 err &= ~MRVL88X2011_LED_BLKRATE_MASK;
828 err |= (rate << 4);
829
830 err = mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV2_ADDR,
831 MRVL88X2011_LED_BLINK_CTL, err);
832 }
833
834 return err;
835}
836
837static int xcvr_init_10g_mrvl88x2011(struct niu *np)
838{
839 int err;
840
841 /* Set LED functions */
842 err = mrvl88x2011_led_blink_rate(np, MRVL88X2011_LED_BLKRATE_134MS);
843 if (err)
844 return err;
845
846 /* led activity */
847 err = mrvl88x2011_act_led(np, MRVL88X2011_LED_CTL_OFF);
848 if (err)
849 return err;
850
851 err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV3_ADDR,
852 MRVL88X2011_GENERAL_CTL);
853 if (err < 0)
854 return err;
855
856 err |= MRVL88X2011_ENA_XFPREFCLK;
857
858 err = mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV3_ADDR,
859 MRVL88X2011_GENERAL_CTL, err);
860 if (err < 0)
861 return err;
862
863 err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR,
864 MRVL88X2011_PMA_PMD_CTL_1);
865 if (err < 0)
866 return err;
867
868 if (np->link_config.loopback_mode == LOOPBACK_MAC)
869 err |= MRVL88X2011_LOOPBACK;
870 else
871 err &= ~MRVL88X2011_LOOPBACK;
872
873 err = mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR,
874 MRVL88X2011_PMA_PMD_CTL_1, err);
875 if (err < 0)
876 return err;
877
878 /* Enable PMD */
879 return mdio_write(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR,
880 MRVL88X2011_10G_PMD_TX_DIS, MRVL88X2011_ENA_PMDTX);
881}
882
883static int xcvr_init_10g_bcm8704(struct niu *np)
805{ 884{
806 struct niu_link_config *lp = &np->link_config; 885 struct niu_link_config *lp = &np->link_config;
807 u16 analog_stat0, tx_alarm_status; 886 u16 analog_stat0, tx_alarm_status;
808 int err; 887 int err;
809 u64 val;
810
811 val = nr64_mac(XMAC_CONFIG);
812 val &= ~XMAC_CONFIG_LED_POLARITY;
813 val |= XMAC_CONFIG_FORCE_LED_ON;
814 nw64_mac(XMAC_CONFIG, val);
815
816 /* XXX shared resource, lock parent XXX */
817 val = nr64(MIF_CONFIG);
818 val |= MIF_CONFIG_INDIRECT_MODE;
819 nw64(MIF_CONFIG, val);
820 888
821 err = bcm8704_reset(np); 889 err = bcm8704_reset(np);
822 if (err) 890 if (err)
@@ -896,6 +964,38 @@ static int xcvr_init_10g(struct niu *np)
896 return 0; 964 return 0;
897} 965}
898 966
967static int xcvr_init_10g(struct niu *np)
968{
969 int phy_id, err;
970 u64 val;
971
972 val = nr64_mac(XMAC_CONFIG);
973 val &= ~XMAC_CONFIG_LED_POLARITY;
974 val |= XMAC_CONFIG_FORCE_LED_ON;
975 nw64_mac(XMAC_CONFIG, val);
976
977 /* XXX shared resource, lock parent XXX */
978 val = nr64(MIF_CONFIG);
979 val |= MIF_CONFIG_INDIRECT_MODE;
980 nw64(MIF_CONFIG, val);
981
982 phy_id = phy_decode(np->parent->port_phy, np->port);
983 phy_id = np->parent->phy_probe_info.phy_id[phy_id][np->port];
984
985 /* handle different phy types */
986 switch (phy_id & NIU_PHY_ID_MASK) {
987 case NIU_PHY_ID_MRVL88X2011:
988 err = xcvr_init_10g_mrvl88x2011(np);
989 break;
990
991 default: /* bcom 8704 */
992 err = xcvr_init_10g_bcm8704(np);
993 break;
994 }
995
996 return 0;
997}
998
899static int mii_reset(struct niu *np) 999static int mii_reset(struct niu *np)
900{ 1000{
901 int limit, err; 1001 int limit, err;
@@ -1082,19 +1182,68 @@ static int niu_link_status_common(struct niu *np, int link_up)
1082 return 0; 1182 return 0;
1083} 1183}
1084 1184
1085static int link_status_10g(struct niu *np, int *link_up_p) 1185static int link_status_10g_mrvl(struct niu *np, int *link_up_p)
1086{ 1186{
1087 unsigned long flags; 1187 int err, link_up, pma_status, pcs_status;
1088 int err, link_up;
1089 1188
1090 link_up = 0; 1189 link_up = 0;
1091 1190
1092 spin_lock_irqsave(&np->lock, flags); 1191 err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR,
1192 MRVL88X2011_10G_PMD_STATUS_2);
1193 if (err < 0)
1194 goto out;
1093 1195
1094 err = -EINVAL; 1196 /* Check PMA/PMD Register: 1.0001.2 == 1 */
1095 if (np->link_config.loopback_mode != LOOPBACK_DISABLED) 1197 err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV1_ADDR,
1198 MRVL88X2011_PMA_PMD_STATUS_1);
1199 if (err < 0)
1200 goto out;
1201
1202 pma_status = ((err & MRVL88X2011_LNK_STATUS_OK) ? 1 : 0);
1203
1204 /* Check PMC Register : 3.0001.2 == 1: read twice */
1205 err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV3_ADDR,
1206 MRVL88X2011_PMA_PMD_STATUS_1);
1207 if (err < 0)
1208 goto out;
1209
1210 err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV3_ADDR,
1211 MRVL88X2011_PMA_PMD_STATUS_1);
1212 if (err < 0)
1213 goto out;
1214
1215 pcs_status = ((err & MRVL88X2011_LNK_STATUS_OK) ? 1 : 0);
1216
1217 /* Check XGXS Register : 4.0018.[0-3,12] */
1218 err = mdio_read(np, np->phy_addr, MRVL88X2011_USER_DEV4_ADDR,
1219 MRVL88X2011_10G_XGXS_LANE_STAT);
1220 if (err < 0)
1096 goto out; 1221 goto out;
1097 1222
1223 if (err == (PHYXS_XGXS_LANE_STAT_ALINGED | PHYXS_XGXS_LANE_STAT_LANE3 |
1224 PHYXS_XGXS_LANE_STAT_LANE2 | PHYXS_XGXS_LANE_STAT_LANE1 |
1225 PHYXS_XGXS_LANE_STAT_LANE0 | PHYXS_XGXS_LANE_STAT_MAGIC |
1226 0x800))
1227 link_up = (pma_status && pcs_status) ? 1 : 0;
1228
1229 np->link_config.active_speed = SPEED_10000;
1230 np->link_config.active_duplex = DUPLEX_FULL;
1231 err = 0;
1232out:
1233 mrvl88x2011_act_led(np, (link_up ?
1234 MRVL88X2011_LED_CTL_PCS_ACT :
1235 MRVL88X2011_LED_CTL_OFF));
1236
1237 *link_up_p = link_up;
1238 return err;
1239}
1240
1241static int link_status_10g_bcom(struct niu *np, int *link_up_p)
1242{
1243 int err, link_up;
1244
1245 link_up = 0;
1246
1098 err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR, 1247 err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
1099 BCM8704_PMD_RCV_SIGDET); 1248 BCM8704_PMD_RCV_SIGDET);
1100 if (err < 0) 1249 if (err < 0)
@@ -1134,9 +1283,37 @@ static int link_status_10g(struct niu *np, int *link_up_p)
1134 err = 0; 1283 err = 0;
1135 1284
1136out: 1285out:
1286 *link_up_p = link_up;
1287 return err;
1288}
1289
1290static int link_status_10g(struct niu *np, int *link_up_p)
1291{
1292 unsigned long flags;
1293 int err = -EINVAL;
1294
1295 spin_lock_irqsave(&np->lock, flags);
1296
1297 if (np->link_config.loopback_mode == LOOPBACK_DISABLED) {
1298 int phy_id;
1299
1300 phy_id = phy_decode(np->parent->port_phy, np->port);
1301 phy_id = np->parent->phy_probe_info.phy_id[phy_id][np->port];
1302
1303 /* handle different phy types */
1304 switch (phy_id & NIU_PHY_ID_MASK) {
1305 case NIU_PHY_ID_MRVL88X2011:
1306 err = link_status_10g_mrvl(np, link_up_p);
1307 break;
1308
1309 default: /* bcom 8704 */
1310 err = link_status_10g_bcom(np, link_up_p);
1311 break;
1312 }
1313 }
1314
1137 spin_unlock_irqrestore(&np->lock, flags); 1315 spin_unlock_irqrestore(&np->lock, flags);
1138 1316
1139 *link_up_p = link_up;
1140 return err; 1317 return err;
1141} 1318}
1142 1319
@@ -6297,7 +6474,8 @@ static int __devinit phy_record(struct niu_parent *parent,
6297 if (dev_id_1 < 0 || dev_id_2 < 0) 6474 if (dev_id_1 < 0 || dev_id_2 < 0)
6298 return 0; 6475 return 0;
6299 if (type == PHY_TYPE_PMA_PMD || type == PHY_TYPE_PCS) { 6476 if (type == PHY_TYPE_PMA_PMD || type == PHY_TYPE_PCS) {
6300 if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) 6477 if (((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) &&
6478 ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011))
6301 return 0; 6479 return 0;
6302 } else { 6480 } else {
6303 if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM5464R) 6481 if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM5464R)