Skip to content

Commit b3591c2

Browse files
u1f35cdavem330
authored andcommitted
net: dsa: qca8k: Switch to PHYLINK instead of PHYLIB
Update the driver to use the new PHYLINK callbacks, removing the legacy adjust_link callback. Signed-off-by: Jonathan McDowell <noodles@earth.li> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 2b3445e commit b3591c2

File tree

1 file changed

+210
-96
lines changed

1 file changed

+210
-96
lines changed

drivers/net/dsa/qca8k.c

Lines changed: 210 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/of_platform.h>
1515
#include <linux/if_bridge.h>
1616
#include <linux/mdio.h>
17+
#include <linux/phylink.h>
1718
#include <linux/gpio/consumer.h>
1819
#include <linux/etherdevice.h>
1920

@@ -418,55 +419,6 @@ qca8k_mib_init(struct qca8k_priv *priv)
418419
mutex_unlock(&priv->reg_mutex);
419420
}
420421

421-
static int
422-
qca8k_set_pad_ctrl(struct qca8k_priv *priv, int port, int mode)
423-
{
424-
u32 reg, val;
425-
426-
switch (port) {
427-
case 0:
428-
reg = QCA8K_REG_PORT0_PAD_CTRL;
429-
break;
430-
case 6:
431-
reg = QCA8K_REG_PORT6_PAD_CTRL;
432-
break;
433-
default:
434-
pr_err("Can't set PAD_CTRL on port %d\n", port);
435-
return -EINVAL;
436-
}
437-
438-
/* Configure a port to be directly connected to an external
439-
* PHY or MAC.
440-
*/
441-
switch (mode) {
442-
case PHY_INTERFACE_MODE_RGMII:
443-
/* RGMII mode means no delay so don't enable the delay */
444-
val = QCA8K_PORT_PAD_RGMII_EN;
445-
qca8k_write(priv, reg, val);
446-
break;
447-
case PHY_INTERFACE_MODE_RGMII_ID:
448-
/* RGMII_ID needs internal delay. This is enabled through
449-
* PORT5_PAD_CTRL for all ports, rather than individual port
450-
* registers
451-
*/
452-
qca8k_write(priv, reg,
453-
QCA8K_PORT_PAD_RGMII_EN |
454-
QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) |
455-
QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY));
456-
qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
457-
QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
458-
break;
459-
case PHY_INTERFACE_MODE_SGMII:
460-
qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN);
461-
break;
462-
default:
463-
pr_err("xMII mode %d not supported\n", mode);
464-
return -EINVAL;
465-
}
466-
467-
return 0;
468-
}
469-
470422
static void
471423
qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
472424
{
@@ -639,9 +591,7 @@ static int
639591
qca8k_setup(struct dsa_switch *ds)
640592
{
641593
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
642-
phy_interface_t phy_mode = PHY_INTERFACE_MODE_NA;
643594
int ret, i;
644-
u32 mask;
645595

646596
/* Make sure that port 0 is the cpu port */
647597
if (!dsa_is_cpu_port(ds, 0)) {
@@ -661,24 +611,9 @@ qca8k_setup(struct dsa_switch *ds)
661611
if (ret)
662612
return ret;
663613

664-
/* Initialize CPU port pad mode (xMII type, delays...) */
665-
ret = of_get_phy_mode(dsa_to_port(ds, QCA8K_CPU_PORT)->dn, &phy_mode);
666-
if (ret) {
667-
pr_err("Can't find phy-mode for master device\n");
668-
return ret;
669-
}
670-
ret = qca8k_set_pad_ctrl(priv, QCA8K_CPU_PORT, phy_mode);
671-
if (ret < 0)
672-
return ret;
673-
674-
/* Enable CPU Port, force it to maximum bandwidth and full-duplex */
675-
mask = QCA8K_PORT_STATUS_SPEED_1000 | QCA8K_PORT_STATUS_TXFLOW |
676-
QCA8K_PORT_STATUS_RXFLOW | QCA8K_PORT_STATUS_DUPLEX;
677-
qca8k_write(priv, QCA8K_REG_PORT_STATUS(QCA8K_CPU_PORT), mask);
614+
/* Enable CPU Port */
678615
qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
679616
QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
680-
qca8k_port_set_status(priv, QCA8K_CPU_PORT, 1);
681-
priv->port_sts[QCA8K_CPU_PORT].enabled = 1;
682617

683618
/* Enable MIB counters */
684619
qca8k_mib_init(priv);
@@ -693,10 +628,9 @@ qca8k_setup(struct dsa_switch *ds)
693628
qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
694629
QCA8K_PORT_LOOKUP_MEMBER, 0);
695630

696-
/* Disable MAC by default on all user ports */
631+
/* Disable MAC by default on all ports */
697632
for (i = 1; i < QCA8K_NUM_PORTS; i++)
698-
if (dsa_is_user_port(ds, i))
699-
qca8k_port_set_status(priv, i, 0);
633+
qca8k_port_set_status(priv, i, 0);
700634

701635
/* Forward all unknown frames to CPU port for Linux processing */
702636
qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
@@ -743,44 +677,222 @@ qca8k_setup(struct dsa_switch *ds)
743677
}
744678

745679
static void
746-
qca8k_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phy)
680+
qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
681+
const struct phylink_link_state *state)
747682
{
748683
struct qca8k_priv *priv = ds->priv;
749684
u32 reg;
750685

751-
/* Force fixed-link setting for CPU port, skip others. */
752-
if (!phy_is_pseudo_fixed_link(phy))
686+
switch (port) {
687+
case 0: /* 1st CPU port */
688+
if (state->interface != PHY_INTERFACE_MODE_RGMII &&
689+
state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
690+
state->interface != PHY_INTERFACE_MODE_SGMII)
691+
return;
692+
693+
reg = QCA8K_REG_PORT0_PAD_CTRL;
694+
break;
695+
case 1:
696+
case 2:
697+
case 3:
698+
case 4:
699+
case 5:
700+
/* Internal PHY, nothing to do */
701+
return;
702+
case 6: /* 2nd CPU port / external PHY */
703+
if (state->interface != PHY_INTERFACE_MODE_RGMII &&
704+
state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
705+
state->interface != PHY_INTERFACE_MODE_SGMII &&
706+
state->interface != PHY_INTERFACE_MODE_1000BASEX)
707+
return;
708+
709+
reg = QCA8K_REG_PORT6_PAD_CTRL;
710+
break;
711+
default:
712+
dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
713+
return;
714+
}
715+
716+
if (port != 6 && phylink_autoneg_inband(mode)) {
717+
dev_err(ds->dev, "%s: in-band negotiation unsupported\n",
718+
__func__);
719+
return;
720+
}
721+
722+
switch (state->interface) {
723+
case PHY_INTERFACE_MODE_RGMII:
724+
/* RGMII mode means no delay so don't enable the delay */
725+
qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN);
726+
break;
727+
case PHY_INTERFACE_MODE_RGMII_ID:
728+
/* RGMII_ID needs internal delay. This is enabled through
729+
* PORT5_PAD_CTRL for all ports, rather than individual port
730+
* registers
731+
*/
732+
qca8k_write(priv, reg,
733+
QCA8K_PORT_PAD_RGMII_EN |
734+
QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) |
735+
QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY));
736+
qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
737+
QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
738+
break;
739+
case PHY_INTERFACE_MODE_SGMII:
740+
case PHY_INTERFACE_MODE_1000BASEX:
741+
/* Enable SGMII on the port */
742+
qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN);
743+
break;
744+
default:
745+
dev_err(ds->dev, "xMII mode %s not supported for port %d\n",
746+
phy_modes(state->interface), port);
753747
return;
748+
}
749+
}
754750

755-
/* Set port speed */
756-
switch (phy->speed) {
757-
case 10:
758-
reg = QCA8K_PORT_STATUS_SPEED_10;
751+
static void
752+
qca8k_phylink_validate(struct dsa_switch *ds, int port,
753+
unsigned long *supported,
754+
struct phylink_link_state *state)
755+
{
756+
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
757+
758+
switch (port) {
759+
case 0: /* 1st CPU port */
760+
if (state->interface != PHY_INTERFACE_MODE_NA &&
761+
state->interface != PHY_INTERFACE_MODE_RGMII &&
762+
state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
763+
state->interface != PHY_INTERFACE_MODE_SGMII)
764+
goto unsupported;
759765
break;
760-
case 100:
761-
reg = QCA8K_PORT_STATUS_SPEED_100;
766+
case 1:
767+
case 2:
768+
case 3:
769+
case 4:
770+
case 5:
771+
/* Internal PHY */
772+
if (state->interface != PHY_INTERFACE_MODE_NA &&
773+
state->interface != PHY_INTERFACE_MODE_GMII)
774+
goto unsupported;
762775
break;
763-
case 1000:
764-
reg = QCA8K_PORT_STATUS_SPEED_1000;
776+
case 6: /* 2nd CPU port / external PHY */
777+
if (state->interface != PHY_INTERFACE_MODE_NA &&
778+
state->interface != PHY_INTERFACE_MODE_RGMII &&
779+
state->interface != PHY_INTERFACE_MODE_RGMII_ID &&
780+
state->interface != PHY_INTERFACE_MODE_SGMII &&
781+
state->interface != PHY_INTERFACE_MODE_1000BASEX)
782+
goto unsupported;
765783
break;
766784
default:
767-
dev_dbg(priv->dev, "port%d link speed %dMbps not supported.\n",
768-
port, phy->speed);
785+
unsupported:
786+
linkmode_zero(supported);
769787
return;
770788
}
771789

772-
/* Set duplex mode */
773-
if (phy->duplex == DUPLEX_FULL)
774-
reg |= QCA8K_PORT_STATUS_DUPLEX;
790+
phylink_set_port_modes(mask);
791+
phylink_set(mask, Autoneg);
792+
793+
phylink_set(mask, 1000baseT_Full);
794+
phylink_set(mask, 10baseT_Half);
795+
phylink_set(mask, 10baseT_Full);
796+
phylink_set(mask, 100baseT_Half);
797+
phylink_set(mask, 100baseT_Full);
798+
799+
if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
800+
phylink_set(mask, 1000baseX_Full);
801+
802+
phylink_set(mask, Pause);
803+
phylink_set(mask, Asym_Pause);
804+
805+
linkmode_and(supported, supported, mask);
806+
linkmode_and(state->advertising, state->advertising, mask);
807+
}
808+
809+
static int
810+
qca8k_phylink_mac_link_state(struct dsa_switch *ds, int port,
811+
struct phylink_link_state *state)
812+
{
813+
struct qca8k_priv *priv = ds->priv;
814+
u32 reg;
775815

776-
/* Force flow control */
777-
if (dsa_is_cpu_port(ds, port))
778-
reg |= QCA8K_PORT_STATUS_RXFLOW | QCA8K_PORT_STATUS_TXFLOW;
816+
reg = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port));
817+
818+
state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP);
819+
state->an_complete = state->link;
820+
state->an_enabled = !!(reg & QCA8K_PORT_STATUS_LINK_AUTO);
821+
state->duplex = (reg & QCA8K_PORT_STATUS_DUPLEX) ? DUPLEX_FULL :
822+
DUPLEX_HALF;
823+
824+
switch (reg & QCA8K_PORT_STATUS_SPEED) {
825+
case QCA8K_PORT_STATUS_SPEED_10:
826+
state->speed = SPEED_10;
827+
break;
828+
case QCA8K_PORT_STATUS_SPEED_100:
829+
state->speed = SPEED_100;
830+
break;
831+
case QCA8K_PORT_STATUS_SPEED_1000:
832+
state->speed = SPEED_1000;
833+
break;
834+
default:
835+
state->speed = SPEED_UNKNOWN;
836+
break;
837+
}
838+
839+
state->pause = MLO_PAUSE_NONE;
840+
if (reg & QCA8K_PORT_STATUS_RXFLOW)
841+
state->pause |= MLO_PAUSE_RX;
842+
if (reg & QCA8K_PORT_STATUS_TXFLOW)
843+
state->pause |= MLO_PAUSE_TX;
844+
845+
return 1;
846+
}
847+
848+
static void
849+
qca8k_phylink_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
850+
phy_interface_t interface)
851+
{
852+
struct qca8k_priv *priv = ds->priv;
779853

780-
/* Force link down before changing MAC options */
781854
qca8k_port_set_status(priv, port, 0);
855+
}
856+
857+
static void
858+
qca8k_phylink_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
859+
phy_interface_t interface, struct phy_device *phydev,
860+
int speed, int duplex, bool tx_pause, bool rx_pause)
861+
{
862+
struct qca8k_priv *priv = ds->priv;
863+
u32 reg;
864+
865+
if (phylink_autoneg_inband(mode)) {
866+
reg = QCA8K_PORT_STATUS_LINK_AUTO;
867+
} else {
868+
switch (speed) {
869+
case SPEED_10:
870+
reg = QCA8K_PORT_STATUS_SPEED_10;
871+
break;
872+
case SPEED_100:
873+
reg = QCA8K_PORT_STATUS_SPEED_100;
874+
break;
875+
case SPEED_1000:
876+
reg = QCA8K_PORT_STATUS_SPEED_1000;
877+
break;
878+
default:
879+
reg = QCA8K_PORT_STATUS_LINK_AUTO;
880+
break;
881+
}
882+
883+
if (duplex == DUPLEX_FULL)
884+
reg |= QCA8K_PORT_STATUS_DUPLEX;
885+
886+
if (rx_pause || dsa_is_cpu_port(ds, port))
887+
reg |= QCA8K_PORT_STATUS_RXFLOW;
888+
889+
if (tx_pause || dsa_is_cpu_port(ds, port))
890+
reg |= QCA8K_PORT_STATUS_TXFLOW;
891+
}
892+
893+
reg |= QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC;
894+
782895
qca8k_write(priv, QCA8K_REG_PORT_STATUS(port), reg);
783-
qca8k_port_set_status(priv, port, 1);
784896
}
785897

786898
static void
@@ -937,13 +1049,11 @@ qca8k_port_enable(struct dsa_switch *ds, int port,
9371049
{
9381050
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
9391051

940-
if (!dsa_is_user_port(ds, port))
941-
return 0;
942-
9431052
qca8k_port_set_status(priv, port, 1);
9441053
priv->port_sts[port].enabled = 1;
9451054

946-
phy_support_asym_pause(phy);
1055+
if (dsa_is_user_port(ds, port))
1056+
phy_support_asym_pause(phy);
9471057

9481058
return 0;
9491059
}
@@ -1026,7 +1136,6 @@ qca8k_get_tag_protocol(struct dsa_switch *ds, int port,
10261136
static const struct dsa_switch_ops qca8k_switch_ops = {
10271137
.get_tag_protocol = qca8k_get_tag_protocol,
10281138
.setup = qca8k_setup,
1029-
.adjust_link = qca8k_adjust_link,
10301139
.get_strings = qca8k_get_strings,
10311140
.get_ethtool_stats = qca8k_get_ethtool_stats,
10321141
.get_sset_count = qca8k_get_sset_count,
@@ -1040,6 +1149,11 @@ static const struct dsa_switch_ops qca8k_switch_ops = {
10401149
.port_fdb_add = qca8k_port_fdb_add,
10411150
.port_fdb_del = qca8k_port_fdb_del,
10421151
.port_fdb_dump = qca8k_port_fdb_dump,
1152+
.phylink_validate = qca8k_phylink_validate,
1153+
.phylink_mac_link_state = qca8k_phylink_mac_link_state,
1154+
.phylink_mac_config = qca8k_phylink_mac_config,
1155+
.phylink_mac_link_down = qca8k_phylink_mac_link_down,
1156+
.phylink_mac_link_up = qca8k_phylink_mac_link_up,
10431157
};
10441158

10451159
static int

0 commit comments

Comments
 (0)