Skip to content

Commit ca366d6

Browse files
vDorstdavem330
authored andcommitted
net: dsa: mt7530: Convert to PHYLINK API
Convert mt7530 to PHYLINK API Signed-off-by: René van Dorst <opensource@vdorst.com> Tested-by: Frank Wunderlich <frank-w@public-files.de> Acked-by: Russell King <rmk+kernel@armlinux.org.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 771efed commit ca366d6

File tree

2 files changed

+211
-87
lines changed

2 files changed

+211
-87
lines changed

drivers/net/dsa/mt7530.c

Lines changed: 197 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include <linux/of_mdio.h>
1414
#include <linux/of_net.h>
1515
#include <linux/of_platform.h>
16-
#include <linux/phy.h>
16+
#include <linux/phylink.h>
1717
#include <linux/regmap.h>
1818
#include <linux/regulator/consumer.h>
1919
#include <linux/reset.h>
@@ -633,63 +633,6 @@ mt7530_get_sset_count(struct dsa_switch *ds, int port, int sset)
633633
return ARRAY_SIZE(mt7530_mib);
634634
}
635635

636-
static void mt7530_adjust_link(struct dsa_switch *ds, int port,
637-
struct phy_device *phydev)
638-
{
639-
struct mt7530_priv *priv = ds->priv;
640-
641-
if (phy_is_pseudo_fixed_link(phydev)) {
642-
dev_dbg(priv->dev, "phy-mode for master device = %x\n",
643-
phydev->interface);
644-
645-
/* Setup TX circuit incluing relevant PAD and driving */
646-
mt7530_pad_clk_setup(ds, phydev->interface);
647-
648-
if (priv->id == ID_MT7530) {
649-
/* Setup RX circuit, relevant PAD and driving on the
650-
* host which must be placed after the setup on the
651-
* device side is all finished.
652-
*/
653-
mt7623_pad_clk_setup(ds);
654-
}
655-
} else {
656-
u16 lcl_adv = 0, rmt_adv = 0;
657-
u8 flowctrl;
658-
u32 mcr = PMCR_USERP_LINK | PMCR_FORCE_MODE;
659-
660-
switch (phydev->speed) {
661-
case SPEED_1000:
662-
mcr |= PMCR_FORCE_SPEED_1000;
663-
break;
664-
case SPEED_100:
665-
mcr |= PMCR_FORCE_SPEED_100;
666-
break;
667-
}
668-
669-
if (phydev->link)
670-
mcr |= PMCR_FORCE_LNK;
671-
672-
if (phydev->duplex) {
673-
mcr |= PMCR_FORCE_FDX;
674-
675-
if (phydev->pause)
676-
rmt_adv = LPA_PAUSE_CAP;
677-
if (phydev->asym_pause)
678-
rmt_adv |= LPA_PAUSE_ASYM;
679-
680-
lcl_adv = linkmode_adv_to_lcl_adv_t(
681-
phydev->advertising);
682-
flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
683-
684-
if (flowctrl & FLOW_CTRL_TX)
685-
mcr |= PMCR_TX_FC_EN;
686-
if (flowctrl & FLOW_CTRL_RX)
687-
mcr |= PMCR_RX_FC_EN;
688-
}
689-
mt7530_write(priv, MT7530_PMCR_P(port), mcr);
690-
}
691-
}
692-
693636
static int
694637
mt7530_cpu_port_enable(struct mt7530_priv *priv,
695638
int port)
@@ -698,9 +641,6 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv,
698641
mt7530_write(priv, MT7530_PVC_P(port),
699642
PORT_SPEC_TAG);
700643

701-
/* Setup the MAC by default for the cpu port */
702-
mt7530_write(priv, MT7530_PMCR_P(port), PMCR_CPUP_LINK);
703-
704644
/* Disable auto learning on the cpu port */
705645
mt7530_set(priv, MT7530_PSC_P(port), SA_DIS);
706646

@@ -731,9 +671,6 @@ mt7530_port_enable(struct dsa_switch *ds, int port,
731671

732672
mutex_lock(&priv->reg_mutex);
733673

734-
/* Setup the MAC for the user port */
735-
mt7530_write(priv, MT7530_PMCR_P(port), PMCR_USERP_LINK);
736-
737674
/* Allow the user port gets connected to the cpu port and also
738675
* restore the port matrix if the port is the member of a certain
739676
* bridge.
@@ -742,7 +679,7 @@ mt7530_port_enable(struct dsa_switch *ds, int port,
742679
priv->ports[port].enable = true;
743680
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
744681
priv->ports[port].pm);
745-
mt7530_port_set_status(priv, port, 1);
682+
mt7530_port_set_status(priv, port, 0);
746683

747684
mutex_unlock(&priv->reg_mutex);
748685

@@ -1232,10 +1169,10 @@ static int
12321169
mt7530_setup(struct dsa_switch *ds)
12331170
{
12341171
struct mt7530_priv *priv = ds->priv;
1235-
int ret, i;
1236-
u32 id, val;
1237-
struct device_node *dn;
12381172
struct mt7530_dummy_poll p;
1173+
struct device_node *dn;
1174+
u32 id, val;
1175+
int ret, i;
12391176

12401177
/* The parent node of master netdev which holds the common system
12411178
* controller also is the container for two GMACs nodes representing
@@ -1305,6 +1242,8 @@ mt7530_setup(struct dsa_switch *ds)
13051242
val |= MHWTRAP_MANUAL;
13061243
mt7530_write(priv, MT7530_MHWTRAP, val);
13071244

1245+
priv->p6_interface = PHY_INTERFACE_MODE_NA;
1246+
13081247
/* Enable and reset MIB counters */
13091248
mt7530_mib_reset(ds);
13101249

@@ -1329,6 +1268,191 @@ mt7530_setup(struct dsa_switch *ds)
13291268
return 0;
13301269
}
13311270

1271+
static void mt7530_phylink_mac_config(struct dsa_switch *ds, int port,
1272+
unsigned int mode,
1273+
const struct phylink_link_state *state)
1274+
{
1275+
struct mt7530_priv *priv = ds->priv;
1276+
u32 mcr_cur, mcr_new;
1277+
1278+
switch (port) {
1279+
case 0: /* Internal phy */
1280+
case 1:
1281+
case 2:
1282+
case 3:
1283+
case 4:
1284+
if (state->interface != PHY_INTERFACE_MODE_GMII)
1285+
return;
1286+
break;
1287+
/* case 5: Port 5 is not supported! */
1288+
case 6: /* 1st cpu port */
1289+
if (priv->p6_interface == state->interface)
1290+
break;
1291+
1292+
if (state->interface != PHY_INTERFACE_MODE_RGMII &&
1293+
state->interface != PHY_INTERFACE_MODE_TRGMII)
1294+
return;
1295+
1296+
/* Setup TX circuit incluing relevant PAD and driving */
1297+
mt7530_pad_clk_setup(ds, state->interface);
1298+
1299+
if (priv->id == ID_MT7530) {
1300+
/* Setup RX circuit, relevant PAD and driving on the
1301+
* host which must be placed after the setup on the
1302+
* device side is all finished.
1303+
*/
1304+
mt7623_pad_clk_setup(ds);
1305+
}
1306+
1307+
priv->p6_interface = state->interface;
1308+
break;
1309+
default:
1310+
dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
1311+
return;
1312+
}
1313+
1314+
if (phylink_autoneg_inband(mode)) {
1315+
dev_err(ds->dev, "%s: in-band negotiation unsupported\n",
1316+
__func__);
1317+
return;
1318+
}
1319+
1320+
mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port));
1321+
mcr_new = mcr_cur;
1322+
mcr_new &= ~(PMCR_FORCE_SPEED_1000 | PMCR_FORCE_SPEED_100 |
1323+
PMCR_FORCE_FDX | PMCR_TX_FC_EN | PMCR_RX_FC_EN);
1324+
mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN |
1325+
PMCR_BACKPR_EN | PMCR_FORCE_MODE | PMCR_FORCE_LNK;
1326+
1327+
switch (state->speed) {
1328+
case SPEED_1000:
1329+
mcr_new |= PMCR_FORCE_SPEED_1000;
1330+
break;
1331+
case SPEED_100:
1332+
mcr_new |= PMCR_FORCE_SPEED_100;
1333+
break;
1334+
}
1335+
if (state->duplex == DUPLEX_FULL) {
1336+
mcr_new |= PMCR_FORCE_FDX;
1337+
if (state->pause & MLO_PAUSE_TX)
1338+
mcr_new |= PMCR_TX_FC_EN;
1339+
if (state->pause & MLO_PAUSE_RX)
1340+
mcr_new |= PMCR_RX_FC_EN;
1341+
}
1342+
1343+
if (mcr_new != mcr_cur)
1344+
mt7530_write(priv, MT7530_PMCR_P(port), mcr_new);
1345+
}
1346+
1347+
static void mt7530_phylink_mac_link_down(struct dsa_switch *ds, int port,
1348+
unsigned int mode,
1349+
phy_interface_t interface)
1350+
{
1351+
struct mt7530_priv *priv = ds->priv;
1352+
1353+
mt7530_port_set_status(priv, port, 0);
1354+
}
1355+
1356+
static void mt7530_phylink_mac_link_up(struct dsa_switch *ds, int port,
1357+
unsigned int mode,
1358+
phy_interface_t interface,
1359+
struct phy_device *phydev)
1360+
{
1361+
struct mt7530_priv *priv = ds->priv;
1362+
1363+
mt7530_port_set_status(priv, port, 1);
1364+
}
1365+
1366+
static void mt7530_phylink_validate(struct dsa_switch *ds, int port,
1367+
unsigned long *supported,
1368+
struct phylink_link_state *state)
1369+
{
1370+
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
1371+
1372+
switch (port) {
1373+
case 0: /* Internal phy */
1374+
case 1:
1375+
case 2:
1376+
case 3:
1377+
case 4:
1378+
if (state->interface != PHY_INTERFACE_MODE_NA &&
1379+
state->interface != PHY_INTERFACE_MODE_GMII)
1380+
goto unsupported;
1381+
break;
1382+
/* case 5: Port 5 not supported! */
1383+
case 6: /* 1st cpu port */
1384+
if (state->interface != PHY_INTERFACE_MODE_NA &&
1385+
state->interface != PHY_INTERFACE_MODE_RGMII &&
1386+
state->interface != PHY_INTERFACE_MODE_TRGMII)
1387+
goto unsupported;
1388+
break;
1389+
default:
1390+
dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
1391+
unsupported:
1392+
linkmode_zero(supported);
1393+
return;
1394+
}
1395+
1396+
phylink_set_port_modes(mask);
1397+
phylink_set(mask, Autoneg);
1398+
1399+
if (state->interface != PHY_INTERFACE_MODE_TRGMII) {
1400+
phylink_set(mask, 10baseT_Half);
1401+
phylink_set(mask, 10baseT_Full);
1402+
phylink_set(mask, 100baseT_Half);
1403+
phylink_set(mask, 100baseT_Full);
1404+
phylink_set(mask, 1000baseT_Half);
1405+
}
1406+
1407+
phylink_set(mask, 1000baseT_Full);
1408+
1409+
phylink_set(mask, Pause);
1410+
phylink_set(mask, Asym_Pause);
1411+
1412+
linkmode_and(supported, supported, mask);
1413+
linkmode_and(state->advertising, state->advertising, mask);
1414+
}
1415+
1416+
static int
1417+
mt7530_phylink_mac_link_state(struct dsa_switch *ds, int port,
1418+
struct phylink_link_state *state)
1419+
{
1420+
struct mt7530_priv *priv = ds->priv;
1421+
u32 pmsr;
1422+
1423+
if (port < 0 || port >= MT7530_NUM_PORTS)
1424+
return -EINVAL;
1425+
1426+
pmsr = mt7530_read(priv, MT7530_PMSR_P(port));
1427+
1428+
state->link = (pmsr & PMSR_LINK);
1429+
state->an_complete = state->link;
1430+
state->duplex = !!(pmsr & PMSR_DPX);
1431+
1432+
switch (pmsr & PMSR_SPEED_MASK) {
1433+
case PMSR_SPEED_10:
1434+
state->speed = SPEED_10;
1435+
break;
1436+
case PMSR_SPEED_100:
1437+
state->speed = SPEED_100;
1438+
break;
1439+
case PMSR_SPEED_1000:
1440+
state->speed = SPEED_1000;
1441+
break;
1442+
default:
1443+
state->speed = SPEED_UNKNOWN;
1444+
break;
1445+
}
1446+
1447+
state->pause &= ~(MLO_PAUSE_RX | MLO_PAUSE_TX);
1448+
if (pmsr & PMSR_RX_FC)
1449+
state->pause |= MLO_PAUSE_RX;
1450+
if (pmsr & PMSR_TX_FC)
1451+
state->pause |= MLO_PAUSE_TX;
1452+
1453+
return 1;
1454+
}
1455+
13321456
static const struct dsa_switch_ops mt7530_switch_ops = {
13331457
.get_tag_protocol = mtk_get_tag_protocol,
13341458
.setup = mt7530_setup,
@@ -1337,7 +1461,6 @@ static const struct dsa_switch_ops mt7530_switch_ops = {
13371461
.phy_write = mt7530_phy_write,
13381462
.get_ethtool_stats = mt7530_get_ethtool_stats,
13391463
.get_sset_count = mt7530_get_sset_count,
1340-
.adjust_link = mt7530_adjust_link,
13411464
.port_enable = mt7530_port_enable,
13421465
.port_disable = mt7530_port_disable,
13431466
.port_stp_state_set = mt7530_stp_state_set,
@@ -1350,6 +1473,11 @@ static const struct dsa_switch_ops mt7530_switch_ops = {
13501473
.port_vlan_prepare = mt7530_port_vlan_prepare,
13511474
.port_vlan_add = mt7530_port_vlan_add,
13521475
.port_vlan_del = mt7530_port_vlan_del,
1476+
.phylink_validate = mt7530_phylink_validate,
1477+
.phylink_mac_link_state = mt7530_phylink_mac_link_state,
1478+
.phylink_mac_config = mt7530_phylink_mac_config,
1479+
.phylink_mac_link_down = mt7530_phylink_mac_link_down,
1480+
.phylink_mac_link_up = mt7530_phylink_mac_link_up,
13531481
};
13541482

13551483
static const struct of_device_id mt7530_of_match[] = {

drivers/net/dsa/mt7530.h

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -198,26 +198,20 @@ enum mt7530_vlan_port_attr {
198198
#define PMCR_FORCE_SPEED_100 BIT(2)
199199
#define PMCR_FORCE_FDX BIT(1)
200200
#define PMCR_FORCE_LNK BIT(0)
201-
#define PMCR_COMMON_LINK (PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \
202-
PMCR_BACKOFF_EN | PMCR_BACKPR_EN | \
203-
PMCR_TX_EN | PMCR_RX_EN | \
204-
PMCR_TX_FC_EN | PMCR_RX_FC_EN)
205-
#define PMCR_CPUP_LINK (PMCR_COMMON_LINK | PMCR_FORCE_MODE | \
206-
PMCR_FORCE_SPEED_1000 | \
207-
PMCR_FORCE_FDX | \
208-
PMCR_FORCE_LNK)
209-
#define PMCR_USERP_LINK PMCR_COMMON_LINK
210-
#define PMCR_FIXED_LINK (PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \
211-
PMCR_FORCE_MODE | PMCR_TX_EN | \
212-
PMCR_RX_EN | PMCR_BACKPR_EN | \
213-
PMCR_BACKOFF_EN | \
214-
PMCR_FORCE_SPEED_1000 | \
215-
PMCR_FORCE_FDX | \
216-
PMCR_FORCE_LNK)
217-
#define PMCR_FIXED_LINK_FC (PMCR_FIXED_LINK | \
218-
PMCR_TX_FC_EN | PMCR_RX_FC_EN)
201+
#define PMCR_SPEED_MASK (PMCR_FORCE_SPEED_100 | \
202+
PMCR_FORCE_SPEED_1000)
219203

220204
#define MT7530_PMSR_P(x) (0x3008 + (x) * 0x100)
205+
#define PMSR_EEE1G BIT(7)
206+
#define PMSR_EEE100M BIT(6)
207+
#define PMSR_RX_FC BIT(5)
208+
#define PMSR_TX_FC BIT(4)
209+
#define PMSR_SPEED_1000 BIT(3)
210+
#define PMSR_SPEED_100 BIT(2)
211+
#define PMSR_SPEED_10 0x00
212+
#define PMSR_SPEED_MASK (PMSR_SPEED_100 | PMSR_SPEED_1000)
213+
#define PMSR_DPX BIT(1)
214+
#define PMSR_LINK BIT(0)
221215

222216
/* Register for MIB */
223217
#define MT7530_PORT_MIB_COUNTER(x) (0x4000 + (x) * 0x100)
@@ -423,6 +417,7 @@ struct mt7530_port {
423417
* @ports: Holding the state among ports
424418
* @reg_mutex: The lock for protecting among process accessing
425419
* registers
420+
* @p6_interface Holding the current port 6 interface
426421
*/
427422
struct mt7530_priv {
428423
struct device *dev;
@@ -435,6 +430,7 @@ struct mt7530_priv {
435430
struct gpio_desc *reset;
436431
unsigned int id;
437432
bool mcm;
433+
phy_interface_t p6_interface;
438434

439435
struct mt7530_port ports[MT7530_NUM_PORTS];
440436
/* protect among processes for registers access*/

0 commit comments

Comments
 (0)