1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Applied Micro X-Gene SoC Ethernet v2 Driver
5 * Copyright (c) 2017, Applied Micro Circuits Corporation
6 * Author(s): Iyappan Subramanian <isubramanian@apm.com>
7 * Keyur Chudgar <kchudgar@apm.com>
12 static int xge_mdio_write(struct mii_bus
*bus
, int phy_id
, int reg
, u16 data
)
14 struct xge_pdata
*pdata
= bus
->priv
;
18 SET_REG_BITS(&val
, PHY_ADDR
, phy_id
);
19 SET_REG_BITS(&val
, REG_ADDR
, reg
);
20 xge_wr_csr(pdata
, MII_MGMT_ADDRESS
, val
);
22 xge_wr_csr(pdata
, MII_MGMT_CONTROL
, data
);
25 done
= xge_rd_csr(pdata
, MII_MGMT_INDICATORS
);
26 } while ((done
& MII_MGMT_BUSY
) && wait
--);
28 if (done
& MII_MGMT_BUSY
) {
29 dev_err(&bus
->dev
, "MII_MGMT write failed\n");
36 static int xge_mdio_read(struct mii_bus
*bus
, int phy_id
, int reg
)
38 struct xge_pdata
*pdata
= bus
->priv
;
39 u32 data
, done
, val
= 0;
42 SET_REG_BITS(&val
, PHY_ADDR
, phy_id
);
43 SET_REG_BITS(&val
, REG_ADDR
, reg
);
44 xge_wr_csr(pdata
, MII_MGMT_ADDRESS
, val
);
46 xge_wr_csr(pdata
, MII_MGMT_COMMAND
, MII_READ_CYCLE
);
49 done
= xge_rd_csr(pdata
, MII_MGMT_INDICATORS
);
50 } while ((done
& MII_MGMT_BUSY
) && wait
--);
52 if (done
& MII_MGMT_BUSY
) {
53 dev_err(&bus
->dev
, "MII_MGMT read failed\n");
57 data
= xge_rd_csr(pdata
, MII_MGMT_STATUS
);
58 xge_wr_csr(pdata
, MII_MGMT_COMMAND
, 0);
63 static void xge_adjust_link(struct net_device
*ndev
)
65 struct xge_pdata
*pdata
= netdev_priv(ndev
);
66 struct phy_device
*phydev
= ndev
->phydev
;
69 if (pdata
->phy_speed
!= phydev
->speed
) {
70 pdata
->phy_speed
= phydev
->speed
;
71 xge_mac_set_speed(pdata
);
72 xge_mac_enable(pdata
);
73 phy_print_status(phydev
);
76 if (pdata
->phy_speed
!= SPEED_UNKNOWN
) {
77 pdata
->phy_speed
= SPEED_UNKNOWN
;
78 xge_mac_disable(pdata
);
79 phy_print_status(phydev
);
84 void xge_mdio_remove(struct net_device
*ndev
)
86 struct xge_pdata
*pdata
= netdev_priv(ndev
);
87 struct mii_bus
*mdio_bus
= pdata
->mdio_bus
;
90 phy_disconnect(ndev
->phydev
);
92 if (mdio_bus
->state
== MDIOBUS_REGISTERED
)
93 mdiobus_unregister(mdio_bus
);
95 mdiobus_free(mdio_bus
);
98 int xge_mdio_config(struct net_device
*ndev
)
100 __ETHTOOL_DECLARE_LINK_MODE_MASK(mask
) = { 0, };
101 struct xge_pdata
*pdata
= netdev_priv(ndev
);
102 struct device
*dev
= &pdata
->pdev
->dev
;
103 struct mii_bus
*mdio_bus
;
104 struct phy_device
*phydev
;
107 mdio_bus
= mdiobus_alloc();
111 mdio_bus
->name
= "APM X-Gene Ethernet (v2) MDIO Bus";
112 mdio_bus
->read
= xge_mdio_read
;
113 mdio_bus
->write
= xge_mdio_write
;
114 mdio_bus
->priv
= pdata
;
115 mdio_bus
->parent
= dev
;
116 snprintf(mdio_bus
->id
, MII_BUS_ID_SIZE
, "%s-mii", dev_name(dev
));
117 pdata
->mdio_bus
= mdio_bus
;
119 mdio_bus
->phy_mask
= 0x1;
120 ret
= mdiobus_register(mdio_bus
);
124 phydev
= phy_find_first(mdio_bus
);
126 dev_err(dev
, "no PHY found\n");
130 phydev
= phy_connect(ndev
, phydev_name(phydev
),
132 pdata
->resources
.phy_mode
);
134 if (IS_ERR(phydev
)) {
135 netdev_err(ndev
, "Could not attach to PHY\n");
136 ret
= PTR_ERR(phydev
);
140 linkmode_set_bit_array(phy_10_100_features_array
,
141 ARRAY_SIZE(phy_10_100_features_array
),
143 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT
, mask
);
144 linkmode_set_bit(ETHTOOL_LINK_MODE_AUI_BIT
, mask
);
145 linkmode_set_bit(ETHTOOL_LINK_MODE_MII_BIT
, mask
);
146 linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT
, mask
);
147 linkmode_set_bit(ETHTOOL_LINK_MODE_BNC_BIT
, mask
);
149 linkmode_andnot(phydev
->supported
, phydev
->supported
, mask
);
150 linkmode_copy(phydev
->advertising
, phydev
->supported
);
151 pdata
->phy_speed
= SPEED_UNKNOWN
;
155 xge_mdio_remove(ndev
);