mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
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>
This commit is contained in:
parent
771efeda39
commit
ca366d6c88
@ -13,7 +13,7 @@
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/phylink.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/reset.h>
|
||||
@ -633,63 +633,6 @@ mt7530_get_sset_count(struct dsa_switch *ds, int port, int sset)
|
||||
return ARRAY_SIZE(mt7530_mib);
|
||||
}
|
||||
|
||||
static void mt7530_adjust_link(struct dsa_switch *ds, int port,
|
||||
struct phy_device *phydev)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
|
||||
if (phy_is_pseudo_fixed_link(phydev)) {
|
||||
dev_dbg(priv->dev, "phy-mode for master device = %x\n",
|
||||
phydev->interface);
|
||||
|
||||
/* Setup TX circuit incluing relevant PAD and driving */
|
||||
mt7530_pad_clk_setup(ds, phydev->interface);
|
||||
|
||||
if (priv->id == ID_MT7530) {
|
||||
/* Setup RX circuit, relevant PAD and driving on the
|
||||
* host which must be placed after the setup on the
|
||||
* device side is all finished.
|
||||
*/
|
||||
mt7623_pad_clk_setup(ds);
|
||||
}
|
||||
} else {
|
||||
u16 lcl_adv = 0, rmt_adv = 0;
|
||||
u8 flowctrl;
|
||||
u32 mcr = PMCR_USERP_LINK | PMCR_FORCE_MODE;
|
||||
|
||||
switch (phydev->speed) {
|
||||
case SPEED_1000:
|
||||
mcr |= PMCR_FORCE_SPEED_1000;
|
||||
break;
|
||||
case SPEED_100:
|
||||
mcr |= PMCR_FORCE_SPEED_100;
|
||||
break;
|
||||
}
|
||||
|
||||
if (phydev->link)
|
||||
mcr |= PMCR_FORCE_LNK;
|
||||
|
||||
if (phydev->duplex) {
|
||||
mcr |= PMCR_FORCE_FDX;
|
||||
|
||||
if (phydev->pause)
|
||||
rmt_adv = LPA_PAUSE_CAP;
|
||||
if (phydev->asym_pause)
|
||||
rmt_adv |= LPA_PAUSE_ASYM;
|
||||
|
||||
lcl_adv = linkmode_adv_to_lcl_adv_t(
|
||||
phydev->advertising);
|
||||
flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
|
||||
|
||||
if (flowctrl & FLOW_CTRL_TX)
|
||||
mcr |= PMCR_TX_FC_EN;
|
||||
if (flowctrl & FLOW_CTRL_RX)
|
||||
mcr |= PMCR_RX_FC_EN;
|
||||
}
|
||||
mt7530_write(priv, MT7530_PMCR_P(port), mcr);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mt7530_cpu_port_enable(struct mt7530_priv *priv,
|
||||
int port)
|
||||
@ -698,9 +641,6 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv,
|
||||
mt7530_write(priv, MT7530_PVC_P(port),
|
||||
PORT_SPEC_TAG);
|
||||
|
||||
/* Setup the MAC by default for the cpu port */
|
||||
mt7530_write(priv, MT7530_PMCR_P(port), PMCR_CPUP_LINK);
|
||||
|
||||
/* Disable auto learning on the cpu port */
|
||||
mt7530_set(priv, MT7530_PSC_P(port), SA_DIS);
|
||||
|
||||
@ -731,9 +671,6 @@ mt7530_port_enable(struct dsa_switch *ds, int port,
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
/* Setup the MAC for the user port */
|
||||
mt7530_write(priv, MT7530_PMCR_P(port), PMCR_USERP_LINK);
|
||||
|
||||
/* Allow the user port gets connected to the cpu port and also
|
||||
* restore the port matrix if the port is the member of a certain
|
||||
* bridge.
|
||||
@ -742,7 +679,7 @@ mt7530_port_enable(struct dsa_switch *ds, int port,
|
||||
priv->ports[port].enable = true;
|
||||
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
|
||||
priv->ports[port].pm);
|
||||
mt7530_port_set_status(priv, port, 1);
|
||||
mt7530_port_set_status(priv, port, 0);
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
@ -1232,10 +1169,10 @@ static int
|
||||
mt7530_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
int ret, i;
|
||||
u32 id, val;
|
||||
struct device_node *dn;
|
||||
struct mt7530_dummy_poll p;
|
||||
struct device_node *dn;
|
||||
u32 id, val;
|
||||
int ret, i;
|
||||
|
||||
/* The parent node of master netdev which holds the common system
|
||||
* controller also is the container for two GMACs nodes representing
|
||||
@ -1305,6 +1242,8 @@ mt7530_setup(struct dsa_switch *ds)
|
||||
val |= MHWTRAP_MANUAL;
|
||||
mt7530_write(priv, MT7530_MHWTRAP, val);
|
||||
|
||||
priv->p6_interface = PHY_INTERFACE_MODE_NA;
|
||||
|
||||
/* Enable and reset MIB counters */
|
||||
mt7530_mib_reset(ds);
|
||||
|
||||
@ -1329,6 +1268,191 @@ mt7530_setup(struct dsa_switch *ds)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7530_phylink_mac_config(struct dsa_switch *ds, int port,
|
||||
unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
u32 mcr_cur, mcr_new;
|
||||
|
||||
switch (port) {
|
||||
case 0: /* Internal phy */
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
if (state->interface != PHY_INTERFACE_MODE_GMII)
|
||||
return;
|
||||
break;
|
||||
/* case 5: Port 5 is not supported! */
|
||||
case 6: /* 1st cpu port */
|
||||
if (priv->p6_interface == state->interface)
|
||||
break;
|
||||
|
||||
if (state->interface != PHY_INTERFACE_MODE_RGMII &&
|
||||
state->interface != PHY_INTERFACE_MODE_TRGMII)
|
||||
return;
|
||||
|
||||
/* Setup TX circuit incluing relevant PAD and driving */
|
||||
mt7530_pad_clk_setup(ds, state->interface);
|
||||
|
||||
if (priv->id == ID_MT7530) {
|
||||
/* Setup RX circuit, relevant PAD and driving on the
|
||||
* host which must be placed after the setup on the
|
||||
* device side is all finished.
|
||||
*/
|
||||
mt7623_pad_clk_setup(ds);
|
||||
}
|
||||
|
||||
priv->p6_interface = state->interface;
|
||||
break;
|
||||
default:
|
||||
dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
|
||||
return;
|
||||
}
|
||||
|
||||
if (phylink_autoneg_inband(mode)) {
|
||||
dev_err(ds->dev, "%s: in-band negotiation unsupported\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port));
|
||||
mcr_new = mcr_cur;
|
||||
mcr_new &= ~(PMCR_FORCE_SPEED_1000 | PMCR_FORCE_SPEED_100 |
|
||||
PMCR_FORCE_FDX | PMCR_TX_FC_EN | PMCR_RX_FC_EN);
|
||||
mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN |
|
||||
PMCR_BACKPR_EN | PMCR_FORCE_MODE | PMCR_FORCE_LNK;
|
||||
|
||||
switch (state->speed) {
|
||||
case SPEED_1000:
|
||||
mcr_new |= PMCR_FORCE_SPEED_1000;
|
||||
break;
|
||||
case SPEED_100:
|
||||
mcr_new |= PMCR_FORCE_SPEED_100;
|
||||
break;
|
||||
}
|
||||
if (state->duplex == DUPLEX_FULL) {
|
||||
mcr_new |= PMCR_FORCE_FDX;
|
||||
if (state->pause & MLO_PAUSE_TX)
|
||||
mcr_new |= PMCR_TX_FC_EN;
|
||||
if (state->pause & MLO_PAUSE_RX)
|
||||
mcr_new |= PMCR_RX_FC_EN;
|
||||
}
|
||||
|
||||
if (mcr_new != mcr_cur)
|
||||
mt7530_write(priv, MT7530_PMCR_P(port), mcr_new);
|
||||
}
|
||||
|
||||
static void mt7530_phylink_mac_link_down(struct dsa_switch *ds, int port,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
|
||||
mt7530_port_set_status(priv, port, 0);
|
||||
}
|
||||
|
||||
static void mt7530_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
||||
unsigned int mode,
|
||||
phy_interface_t interface,
|
||||
struct phy_device *phydev)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
|
||||
mt7530_port_set_status(priv, port, 1);
|
||||
}
|
||||
|
||||
static void mt7530_phylink_validate(struct dsa_switch *ds, int port,
|
||||
unsigned long *supported,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
|
||||
|
||||
switch (port) {
|
||||
case 0: /* Internal phy */
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
if (state->interface != PHY_INTERFACE_MODE_NA &&
|
||||
state->interface != PHY_INTERFACE_MODE_GMII)
|
||||
goto unsupported;
|
||||
break;
|
||||
/* case 5: Port 5 not supported! */
|
||||
case 6: /* 1st cpu port */
|
||||
if (state->interface != PHY_INTERFACE_MODE_NA &&
|
||||
state->interface != PHY_INTERFACE_MODE_RGMII &&
|
||||
state->interface != PHY_INTERFACE_MODE_TRGMII)
|
||||
goto unsupported;
|
||||
break;
|
||||
default:
|
||||
dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
|
||||
unsupported:
|
||||
linkmode_zero(supported);
|
||||
return;
|
||||
}
|
||||
|
||||
phylink_set_port_modes(mask);
|
||||
phylink_set(mask, Autoneg);
|
||||
|
||||
if (state->interface != PHY_INTERFACE_MODE_TRGMII) {
|
||||
phylink_set(mask, 10baseT_Half);
|
||||
phylink_set(mask, 10baseT_Full);
|
||||
phylink_set(mask, 100baseT_Half);
|
||||
phylink_set(mask, 100baseT_Full);
|
||||
phylink_set(mask, 1000baseT_Half);
|
||||
}
|
||||
|
||||
phylink_set(mask, 1000baseT_Full);
|
||||
|
||||
phylink_set(mask, Pause);
|
||||
phylink_set(mask, Asym_Pause);
|
||||
|
||||
linkmode_and(supported, supported, mask);
|
||||
linkmode_and(state->advertising, state->advertising, mask);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7530_phylink_mac_link_state(struct dsa_switch *ds, int port,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
u32 pmsr;
|
||||
|
||||
if (port < 0 || port >= MT7530_NUM_PORTS)
|
||||
return -EINVAL;
|
||||
|
||||
pmsr = mt7530_read(priv, MT7530_PMSR_P(port));
|
||||
|
||||
state->link = (pmsr & PMSR_LINK);
|
||||
state->an_complete = state->link;
|
||||
state->duplex = !!(pmsr & PMSR_DPX);
|
||||
|
||||
switch (pmsr & PMSR_SPEED_MASK) {
|
||||
case PMSR_SPEED_10:
|
||||
state->speed = SPEED_10;
|
||||
break;
|
||||
case PMSR_SPEED_100:
|
||||
state->speed = SPEED_100;
|
||||
break;
|
||||
case PMSR_SPEED_1000:
|
||||
state->speed = SPEED_1000;
|
||||
break;
|
||||
default:
|
||||
state->speed = SPEED_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
state->pause &= ~(MLO_PAUSE_RX | MLO_PAUSE_TX);
|
||||
if (pmsr & PMSR_RX_FC)
|
||||
state->pause |= MLO_PAUSE_RX;
|
||||
if (pmsr & PMSR_TX_FC)
|
||||
state->pause |= MLO_PAUSE_TX;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct dsa_switch_ops mt7530_switch_ops = {
|
||||
.get_tag_protocol = mtk_get_tag_protocol,
|
||||
.setup = mt7530_setup,
|
||||
@ -1337,7 +1461,6 @@ static const struct dsa_switch_ops mt7530_switch_ops = {
|
||||
.phy_write = mt7530_phy_write,
|
||||
.get_ethtool_stats = mt7530_get_ethtool_stats,
|
||||
.get_sset_count = mt7530_get_sset_count,
|
||||
.adjust_link = mt7530_adjust_link,
|
||||
.port_enable = mt7530_port_enable,
|
||||
.port_disable = mt7530_port_disable,
|
||||
.port_stp_state_set = mt7530_stp_state_set,
|
||||
@ -1350,6 +1473,11 @@ static const struct dsa_switch_ops mt7530_switch_ops = {
|
||||
.port_vlan_prepare = mt7530_port_vlan_prepare,
|
||||
.port_vlan_add = mt7530_port_vlan_add,
|
||||
.port_vlan_del = mt7530_port_vlan_del,
|
||||
.phylink_validate = mt7530_phylink_validate,
|
||||
.phylink_mac_link_state = mt7530_phylink_mac_link_state,
|
||||
.phylink_mac_config = mt7530_phylink_mac_config,
|
||||
.phylink_mac_link_down = mt7530_phylink_mac_link_down,
|
||||
.phylink_mac_link_up = mt7530_phylink_mac_link_up,
|
||||
};
|
||||
|
||||
static const struct of_device_id mt7530_of_match[] = {
|
||||
|
@ -198,26 +198,20 @@ enum mt7530_vlan_port_attr {
|
||||
#define PMCR_FORCE_SPEED_100 BIT(2)
|
||||
#define PMCR_FORCE_FDX BIT(1)
|
||||
#define PMCR_FORCE_LNK BIT(0)
|
||||
#define PMCR_COMMON_LINK (PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \
|
||||
PMCR_BACKOFF_EN | PMCR_BACKPR_EN | \
|
||||
PMCR_TX_EN | PMCR_RX_EN | \
|
||||
PMCR_TX_FC_EN | PMCR_RX_FC_EN)
|
||||
#define PMCR_CPUP_LINK (PMCR_COMMON_LINK | PMCR_FORCE_MODE | \
|
||||
PMCR_FORCE_SPEED_1000 | \
|
||||
PMCR_FORCE_FDX | \
|
||||
PMCR_FORCE_LNK)
|
||||
#define PMCR_USERP_LINK PMCR_COMMON_LINK
|
||||
#define PMCR_FIXED_LINK (PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \
|
||||
PMCR_FORCE_MODE | PMCR_TX_EN | \
|
||||
PMCR_RX_EN | PMCR_BACKPR_EN | \
|
||||
PMCR_BACKOFF_EN | \
|
||||
PMCR_FORCE_SPEED_1000 | \
|
||||
PMCR_FORCE_FDX | \
|
||||
PMCR_FORCE_LNK)
|
||||
#define PMCR_FIXED_LINK_FC (PMCR_FIXED_LINK | \
|
||||
PMCR_TX_FC_EN | PMCR_RX_FC_EN)
|
||||
#define PMCR_SPEED_MASK (PMCR_FORCE_SPEED_100 | \
|
||||
PMCR_FORCE_SPEED_1000)
|
||||
|
||||
#define MT7530_PMSR_P(x) (0x3008 + (x) * 0x100)
|
||||
#define PMSR_EEE1G BIT(7)
|
||||
#define PMSR_EEE100M BIT(6)
|
||||
#define PMSR_RX_FC BIT(5)
|
||||
#define PMSR_TX_FC BIT(4)
|
||||
#define PMSR_SPEED_1000 BIT(3)
|
||||
#define PMSR_SPEED_100 BIT(2)
|
||||
#define PMSR_SPEED_10 0x00
|
||||
#define PMSR_SPEED_MASK (PMSR_SPEED_100 | PMSR_SPEED_1000)
|
||||
#define PMSR_DPX BIT(1)
|
||||
#define PMSR_LINK BIT(0)
|
||||
|
||||
/* Register for MIB */
|
||||
#define MT7530_PORT_MIB_COUNTER(x) (0x4000 + (x) * 0x100)
|
||||
@ -423,6 +417,7 @@ struct mt7530_port {
|
||||
* @ports: Holding the state among ports
|
||||
* @reg_mutex: The lock for protecting among process accessing
|
||||
* registers
|
||||
* @p6_interface Holding the current port 6 interface
|
||||
*/
|
||||
struct mt7530_priv {
|
||||
struct device *dev;
|
||||
@ -435,6 +430,7 @@ struct mt7530_priv {
|
||||
struct gpio_desc *reset;
|
||||
unsigned int id;
|
||||
bool mcm;
|
||||
phy_interface_t p6_interface;
|
||||
|
||||
struct mt7530_port ports[MT7530_NUM_PORTS];
|
||||
/* protect among processes for registers access*/
|
||||
|
Loading…
Reference in New Issue
Block a user