Lines Matching refs:xpcs
11 #include <linux/pcs/pcs-xpcs.h>
17 #include "pcs-xpcs.h"
114 int (*pma_config)(struct dw_xpcs *xpcs);
124 xpcs_find_compat(struct dw_xpcs *xpcs, phy_interface_t interface)
128 for (compat = xpcs->desc->compat; compat->supported; compat++)
135 struct phylink_pcs *xpcs_to_phylink_pcs(struct dw_xpcs *xpcs)
137 return &xpcs->pcs;
141 int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
145 compat = xpcs_find_compat(xpcs, interface);
168 int xpcs_read(struct dw_xpcs *xpcs, int dev, u32 reg)
170 return mdiodev_c45_read(xpcs->mdiodev, dev, reg);
173 int xpcs_write(struct dw_xpcs *xpcs, int dev, u32 reg, u16 val)
175 return mdiodev_c45_write(xpcs->mdiodev, dev, reg, val);
178 int xpcs_modify(struct dw_xpcs *xpcs, int dev, u32 reg, u16 mask, u16 set)
180 return mdiodev_c45_modify(xpcs->mdiodev, dev, reg, mask, set);
183 static int xpcs_modify_changed(struct dw_xpcs *xpcs, int dev, u32 reg,
186 return mdiodev_c45_modify_changed(xpcs->mdiodev, dev, reg, mask, set);
189 static int xpcs_read_vendor(struct dw_xpcs *xpcs, int dev, u32 reg)
191 return xpcs_read(xpcs, dev, DW_VENDOR | reg);
194 static int xpcs_write_vendor(struct dw_xpcs *xpcs, int dev, int reg,
197 return xpcs_write(xpcs, dev, DW_VENDOR | reg, val);
200 static int xpcs_modify_vendor(struct dw_xpcs *xpcs, int dev, int reg, u16 mask,
203 return xpcs_modify(xpcs, dev, DW_VENDOR | reg, mask, set);
206 int xpcs_read_vpcs(struct dw_xpcs *xpcs, int reg)
208 return xpcs_read_vendor(xpcs, MDIO_MMD_PCS, reg);
211 int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val)
213 return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val);
216 static int xpcs_modify_vpcs(struct dw_xpcs *xpcs, int reg, u16 mask, u16 val)
218 return xpcs_modify_vendor(xpcs, MDIO_MMD_PCS, reg, mask, val);
221 static int xpcs_poll_reset(struct dw_xpcs *xpcs, int dev)
227 50000, 600000, true, xpcs, dev, MII_BMCR);
234 static int xpcs_soft_reset(struct dw_xpcs *xpcs,
253 ret = xpcs_write(xpcs, dev, MII_BMCR, BMCR_RESET);
257 return xpcs_poll_reset(xpcs, dev);
266 static int xpcs_read_fault_c73(struct dw_xpcs *xpcs,
273 xpcs_warn(xpcs, state, "Link fault condition detected!\n");
277 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT2);
282 xpcs_warn(xpcs, state, "Receiver fault detected!\n");
284 xpcs_warn(xpcs, state, "Transmitter fault detected!\n");
286 ret = xpcs_read_vendor(xpcs, MDIO_MMD_PCS, DW_VR_XS_PCS_DIG_STS);
291 xpcs_warn(xpcs, state, "FIFO fault condition detected!\n");
295 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1);
300 xpcs_warn(xpcs, state, "Link is not locked!\n");
302 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT2);
307 xpcs_warn(xpcs, state, "Link has errors!\n");
314 static void xpcs_link_up_usxgmii(struct dw_xpcs *xpcs, int speed)
342 ret = xpcs_modify_vpcs(xpcs, MDIO_CTRL1, DW_USXGMII_EN, DW_USXGMII_EN);
346 ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, MII_BMCR, DW_USXGMII_SS_MASK,
351 ret = xpcs_modify_vpcs(xpcs, MDIO_CTRL1, DW_USXGMII_RST,
359 dev_err(&xpcs->mdiodev->dev, "%s: XPCS access returned %pe\n",
363 static int _xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
381 ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV3, adv);
394 ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV2, adv);
405 return xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV1, adv);
408 static int xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
413 ret = _xpcs_config_aneg_c73(xpcs, compat);
417 return xpcs_modify(xpcs, MDIO_MMD_AN, MDIO_CTRL1,
422 static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
429 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA);
435 xpcs_config_aneg_c73(xpcs, compat);
445 static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs,
460 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA + i);
472 static int xpcs_get_max_xlgmii_speed(struct dw_xpcs *xpcs,
526 static void xpcs_resolve_pma(struct dw_xpcs *xpcs,
537 state->speed = xpcs_get_max_xlgmii_speed(xpcs, state);
550 struct dw_xpcs *xpcs;
553 xpcs = phylink_pcs_to_xpcs(pcs);
554 compat = xpcs_find_compat(xpcs, state->interface);
573 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
576 compat = xpcs_find_compat(xpcs, interface);
597 static void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
601 for (compat = xpcs->desc->compat; compat->supported; compat++)
605 static int xpcs_switch_interface_mode(struct dw_xpcs *xpcs,
610 if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
611 ret = txgbe_xpcs_switch_mode(xpcs, interface);
612 } else if (xpcs->interface != interface) {
614 xpcs->need_reset = true;
615 xpcs->interface = interface;
623 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
627 ret = xpcs_switch_interface_mode(xpcs, interface);
629 dev_err(&xpcs->mdiodev->dev, "switch interface failed: %pe\n",
632 if (!xpcs->need_reset)
635 compat = xpcs_find_compat(xpcs, interface);
637 dev_err(&xpcs->mdiodev->dev, "unsupported interface %s\n",
642 ret = xpcs_soft_reset(xpcs, compat);
644 dev_err(&xpcs->mdiodev->dev, "soft reset failed: %pe\n",
647 xpcs->need_reset = false;
650 static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs,
674 mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMCR);
679 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
689 if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
700 ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, mask, val);
710 if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
715 ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, mask, val);
720 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
726 static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs,
742 mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMCR);
747 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
757 if (!xpcs->pcs.poll) {
762 ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, mask, val);
772 ret = xpcs_modify_changed(xpcs, MDIO_MMD_VEND2,
781 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0);
786 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
795 static int xpcs_config_2500basex(struct dw_xpcs *xpcs)
799 ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1,
806 return xpcs_modify(xpcs, MDIO_MMD_VEND2, MII_BMCR,
811 static int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
818 compat = xpcs_find_compat(xpcs, interface);
822 if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
828 xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1,
837 ret = xpcs_config_aneg_c73(xpcs, compat);
843 ret = xpcs_config_aneg_c37_sgmii(xpcs, neg_mode);
848 ret = xpcs_config_aneg_c37_1000basex(xpcs, neg_mode,
854 ret = xpcs_config_2500basex(xpcs);
863 ret = compat->pma_config(xpcs);
876 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
878 return xpcs_do_config(xpcs, interface, advertising, neg_mode);
881 static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
894 pcs_stat1 = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
904 ret = xpcs_read_fault_c73(xpcs, state, pcs_stat1);
906 ret = xpcs_soft_reset(xpcs, compat);
912 return xpcs_do_config(xpcs, state->interface, NULL,
927 an_stat1 = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
933 state->an_complete = xpcs_aneg_done_c73(xpcs, state, compat,
940 ret = xpcs_read_lpa_c73(xpcs, state, an_stat1);
948 xpcs_resolve_pma(xpcs, state);
954 static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
968 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS);
994 speed = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMCR);
1006 duplex = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_ADVERTISE);
1015 xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0);
1021 static int xpcs_get_state_c37_1000basex(struct dw_xpcs *xpcs,
1032 lpa = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_LPA);
1036 bmsr = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMSR);
1041 if (!xpcs->pcs.poll) {
1044 an_intr = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS);
1047 xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, an_intr);
1057 static int xpcs_get_state_2500basex(struct dw_xpcs *xpcs,
1062 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_BMSR);
1082 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1086 compat = xpcs_find_compat(xpcs, state->interface);
1092 phylink_mii_c45_pcs_get_state(xpcs->mdiodev, state);
1095 ret = xpcs_get_state_c73(xpcs, state, compat);
1097 dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
1101 ret = xpcs_get_state_c37_sgmii(xpcs, state);
1103 dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
1107 ret = xpcs_get_state_c37_1000basex(xpcs, neg_mode, state);
1109 dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
1113 ret = xpcs_get_state_2500basex(xpcs, state);
1115 dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n",
1123 static void xpcs_link_up_sgmii_1000basex(struct dw_xpcs *xpcs,
1135 dev_err(&xpcs->mdiodev->dev,
1142 dev_err(&xpcs->mdiodev->dev,
1147 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR,
1150 dev_err(&xpcs->mdiodev->dev, "%s: xpcs_write returned %pe\n",
1157 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1161 xpcs_link_up_usxgmii(xpcs, speed);
1166 xpcs_link_up_sgmii_1000basex(xpcs, neg_mode, interface, speed,
1177 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1179 xpcs_modify(xpcs, MDIO_MMD_VEND2, MII_BMCR, BMCR_ANRESTART,
1183 static int xpcs_config_eee(struct dw_xpcs *xpcs, bool enable)
1198 xpcs->eee_mult_fact);
1202 ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, mask,
1207 return xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1,
1214 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1216 xpcs_config_eee(xpcs, false);
1221 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
1223 xpcs_config_eee(xpcs, true);
1228 * @xpcs: pointer to a &struct dw_xpcs instance
1234 void xpcs_config_eee_mult_fact(struct dw_xpcs *xpcs, u8 mult_fact)
1236 xpcs->eee_mult_fact = mult_fact;
1240 static int xpcs_read_ids(struct dw_xpcs *xpcs)
1248 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID1);
1254 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID2);
1265 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_PHYSID1);
1271 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_PHYSID2);
1279 if (xpcs->info.pcs == DW_XPCS_ID_NATIVE)
1280 xpcs->info.pcs = id;
1283 ret = xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_DEVID1);
1289 ret = xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_DEVID2);
1300 if (xpcs->info.pma == DW_XPCS_PMA_ID_NATIVE)
1301 xpcs->info.pma = id;
1392 static int xpcs_identify(struct dw_xpcs *xpcs)
1396 ret = xpcs_read_ids(xpcs);
1403 if ((xpcs->info.pcs & entry->mask) == entry->id) {
1404 xpcs->desc = entry;
1414 struct dw_xpcs *xpcs;
1416 xpcs = kzalloc(sizeof(*xpcs), GFP_KERNEL);
1417 if (!xpcs)
1421 xpcs->mdiodev = mdiodev;
1422 xpcs->pcs.ops = &xpcs_phylink_ops;
1423 xpcs->pcs.poll = true;
1425 return xpcs;
1428 static void xpcs_free_data(struct dw_xpcs *xpcs)
1430 mdio_device_put(xpcs->mdiodev);
1431 kfree(xpcs);
1434 static int xpcs_init_clks(struct dw_xpcs *xpcs)
1440 struct device *dev = &xpcs->mdiodev->dev;
1444 xpcs->clks[i].id = ids[i];
1446 ret = clk_bulk_get_optional(dev, DW_XPCS_NUM_CLKS, xpcs->clks);
1450 ret = clk_bulk_prepare_enable(DW_XPCS_NUM_CLKS, xpcs->clks);
1457 static void xpcs_clear_clks(struct dw_xpcs *xpcs)
1459 clk_bulk_disable_unprepare(DW_XPCS_NUM_CLKS, xpcs->clks);
1461 clk_bulk_put(DW_XPCS_NUM_CLKS, xpcs->clks);
1464 static int xpcs_init_id(struct dw_xpcs *xpcs)
1468 info = dev_get_platdata(&xpcs->mdiodev->dev);
1470 xpcs->info.pcs = DW_XPCS_ID_NATIVE;
1471 xpcs->info.pma = DW_XPCS_PMA_ID_NATIVE;
1473 xpcs->info = *info;
1476 return xpcs_identify(xpcs);
1481 struct dw_xpcs *xpcs;
1484 xpcs = xpcs_create_data(mdiodev);
1485 if (IS_ERR(xpcs))
1486 return xpcs;
1488 ret = xpcs_init_clks(xpcs);
1492 ret = xpcs_init_id(xpcs);
1496 xpcs_get_interfaces(xpcs, xpcs->pcs.supported_interfaces);
1498 if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID)
1499 xpcs->pcs.poll = false;
1501 xpcs->need_reset = true;
1503 return xpcs;
1506 xpcs_clear_clks(xpcs);
1509 xpcs_free_data(xpcs);
1526 struct dw_xpcs *xpcs;
1532 xpcs = xpcs_create(mdiodev);
1542 return xpcs;
1548 struct dw_xpcs *xpcs;
1550 xpcs = xpcs_create_mdiodev(bus, addr);
1551 if (IS_ERR(xpcs))
1552 return ERR_CAST(xpcs);
1554 return &xpcs->pcs;
1571 struct dw_xpcs *xpcs;
1580 xpcs = xpcs_create(mdiodev);
1590 return xpcs;
1594 void xpcs_destroy(struct dw_xpcs *xpcs)
1596 if (!xpcs)
1599 xpcs_clear_clks(xpcs);
1601 xpcs_free_data(xpcs);