Commit 147c50ac authored by David S. Miller's avatar David S. Miller

Merge branch 'lan9303-phylink'

Jerry Ray says:

====================
dsa: lan9303: Move to PHYLINK

This patch series moves the lan9303 driver to use the phylink
api away from phylib.

Migrating to phylink means removing the .adjust_link api. The
functionality from the adjust_link is moved to the phylink_mac_link_up
api.  The code being removed only affected the cpu port.  The other
ports on the LAN9303 do not need anything from the phylink_mac_link_up
api.

Patches:
 0001 - Whitespace only change aligning the dsa_switch_ops members.
	No code changes.
 0002 - Moves the Turbo bit initialization out of the adjust_link api and
	places it in a driver initialization execution path. It only needs
	to be initialized once, it is never changed, and it is not a
	per-port flag.
 0003 - Adds exception handling logic in the extremely unlikely event that
	the read of the device fails.
 0004 - Performance optimization that skips a slow register write if there
	is no need to perform it.
 0005 - Change the way we identify the xMII port as phydev will be NULL
	when this logic is moved into phylink_mac_link_up.
 0006 - Removes adjust_link and begins using the phylink dsa_switch_ops
	apis.
 0007 - Adds XMII port flow control settings in the phylink_mac_link_up()
	api while cleaning up the ANEG / speed / duplex implementation.
---
v6->v7:
  - Moved the initialization of the Turbo bit into lan9303_setup().
  - Added a macro for determining is a port is an XMII port.
  - Added setting the XMII flow control in the phylink_mac_link_up() API.
  - removed unnecessary error handling and cleaned up the code flow in
    phylink_mac_link_up().
v5->v6:
  - Moved to using port number to identify xMII port for the LAN9303.
v4->v5:
  - Created prep patches to better show how things migrate.
  - cleaned up comments.
v3->v4:
  - Addressed whitespace issues as a separate patch.
  - Removed port_max_mtu api patch as it is unrelated to phylink migration.
  - Reworked the implementation to preserve the adjust_link functionality
    by including it in the phylink_mac_link_up api.
v2->v3:
  Added back in disabling Turbo Mode on the CPU MII interface.
  Removed the unnecessary clearing of the phy supported interfaces.
v1->v2:
  corrected the reported mtu size, removing ETH_HLEN and ETH_FCS_LEN
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cff9b79e 87523986
......@@ -15,6 +15,9 @@
#include "lan9303.h"
/* For the LAN9303 and LAN9354, only port 0 is an XMII port. */
#define IS_PORT_XMII(port) ((port) == 0)
#define LAN9303_NUM_PORTS 3
/* 13.2 System Control and Status Registers
......@@ -50,6 +53,9 @@
#define LAN9303_MANUAL_FC_1 0x68
#define LAN9303_MANUAL_FC_2 0x69
#define LAN9303_MANUAL_FC_0 0x6a
# define LAN9303_BP_EN BIT(6)
# define LAN9303_RX_FC_EN BIT(2)
# define LAN9303_TX_FC_EN BIT(1)
#define LAN9303_SWITCH_CSR_DATA 0x6b
#define LAN9303_SWITCH_CSR_CMD 0x6c
#define LAN9303_SWITCH_CSR_CMD_BUSY BIT(31)
......@@ -225,6 +231,13 @@ const struct regmap_access_table lan9303_register_set = {
};
EXPORT_SYMBOL(lan9303_register_set);
/* Flow Control registers indexed by port number */
static unsigned int flow_ctl_reg[] = {
LAN9303_MANUAL_FC_0,
LAN9303_MANUAL_FC_1,
LAN9303_MANUAL_FC_2
};
static int lan9303_read(struct regmap *regmap, unsigned int offset, u32 *reg)
{
int ret, i;
......@@ -902,6 +915,7 @@ static int lan9303_setup(struct dsa_switch *ds)
{
struct lan9303 *chip = ds->priv;
int ret;
u32 reg;
/* Make sure that port 0 is the cpu port */
if (!dsa_is_cpu_port(ds, 0)) {
......@@ -909,6 +923,17 @@ static int lan9303_setup(struct dsa_switch *ds)
return -EINVAL;
}
/* Virtual Phy: Remove Turbo 200Mbit mode */
ret = lan9303_read(chip->regmap, LAN9303_VIRT_SPECIAL_CTRL, &reg);
if (ret)
return (ret);
/* Clear the TURBO Mode bit if it was set. */
if (reg & LAN9303_VIRT_SPECIAL_TURBO) {
reg &= ~LAN9303_VIRT_SPECIAL_TURBO;
regmap_write(chip->regmap, LAN9303_VIRT_SPECIAL_CTRL, reg);
}
ret = lan9303_setup_tagging(chip);
if (ret)
dev_err(chip->dev, "failed to setup port tagging %d\n", ret);
......@@ -1049,42 +1074,6 @@ static int lan9303_phy_write(struct dsa_switch *ds, int phy, int regnum,
return chip->ops->phy_write(chip, phy, regnum, val);
}
static void lan9303_adjust_link(struct dsa_switch *ds, int port,
struct phy_device *phydev)
{
struct lan9303 *chip = ds->priv;
int ctl;
if (!phy_is_pseudo_fixed_link(phydev))
return;
ctl = lan9303_phy_read(ds, port, MII_BMCR);
ctl &= ~BMCR_ANENABLE;
if (phydev->speed == SPEED_100)
ctl |= BMCR_SPEED100;
else if (phydev->speed == SPEED_10)
ctl &= ~BMCR_SPEED100;
else
dev_err(ds->dev, "unsupported speed: %d\n", phydev->speed);
if (phydev->duplex == DUPLEX_FULL)
ctl |= BMCR_FULLDPLX;
else
ctl &= ~BMCR_FULLDPLX;
lan9303_phy_write(ds, port, MII_BMCR, ctl);
if (port == chip->phy_addr_base) {
/* Virtual Phy: Remove Turbo 200Mbit mode */
lan9303_read(chip->regmap, LAN9303_VIRT_SPECIAL_CTRL, &ctl);
ctl &= ~LAN9303_VIRT_SPECIAL_TURBO;
regmap_write(chip->regmap, LAN9303_VIRT_SPECIAL_CTRL, ctl);
}
}
static int lan9303_port_enable(struct dsa_switch *ds, int port,
struct phy_device *phy)
{
......@@ -1281,26 +1270,96 @@ static int lan9303_port_mdb_del(struct dsa_switch *ds, int port,
return 0;
}
static void lan9303_phylink_get_caps(struct dsa_switch *ds, int port,
struct phylink_config *config)
{
struct lan9303 *chip = ds->priv;
dev_dbg(chip->dev, "%s(%d) entered.", __func__, port);
config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE |
MAC_SYM_PAUSE;
if (port == 0) {
__set_bit(PHY_INTERFACE_MODE_RMII,
config->supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_MII,
config->supported_interfaces);
} else {
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
config->supported_interfaces);
/* Compatibility for phylib's default interface type when the
* phy-mode property is absent
*/
__set_bit(PHY_INTERFACE_MODE_GMII,
config->supported_interfaces);
}
/* This driver does not make use of the speed, duplex, pause or the
* advertisement in its mac_config, so it is safe to mark this driver
* as non-legacy.
*/
config->legacy_pre_march2020 = false;
}
static void lan9303_phylink_mac_link_up(struct dsa_switch *ds, int port,
unsigned int mode,
phy_interface_t interface,
struct phy_device *phydev, int speed,
int duplex, bool tx_pause,
bool rx_pause)
{
struct lan9303 *chip = ds->priv;
u32 ctl;
u32 reg;
/* On this device, we are only interested in doing something here if
* this is the xMII port. All other ports are 10/100 phys using MDIO
* to control there link settings.
*/
if (!IS_PORT_XMII(port))
return;
/* Disable auto-negotiation and force the speed/duplex settings. */
ctl = lan9303_phy_read(ds, port, MII_BMCR);
ctl &= ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
if (speed == SPEED_100)
ctl |= BMCR_SPEED100;
if (duplex == DUPLEX_FULL)
ctl |= BMCR_FULLDPLX;
lan9303_phy_write(ds, port, MII_BMCR, ctl);
/* Force the flow control settings. */
lan9303_read(chip->regmap, flow_ctl_reg[port], &reg);
reg &= ~(LAN9303_BP_EN | LAN9303_RX_FC_EN | LAN9303_TX_FC_EN);
if (rx_pause)
reg |= (LAN9303_RX_FC_EN | LAN9303_BP_EN);
if (tx_pause)
reg |= LAN9303_TX_FC_EN;
regmap_write(chip->regmap, flow_ctl_reg[port], reg);
}
static const struct dsa_switch_ops lan9303_switch_ops = {
.get_tag_protocol = lan9303_get_tag_protocol,
.setup = lan9303_setup,
.get_strings = lan9303_get_strings,
.phy_read = lan9303_phy_read,
.phy_write = lan9303_phy_write,
.adjust_link = lan9303_adjust_link,
.get_ethtool_stats = lan9303_get_ethtool_stats,
.get_sset_count = lan9303_get_sset_count,
.port_enable = lan9303_port_enable,
.port_disable = lan9303_port_disable,
.port_bridge_join = lan9303_port_bridge_join,
.port_bridge_leave = lan9303_port_bridge_leave,
.port_stp_state_set = lan9303_port_stp_state_set,
.port_fast_age = lan9303_port_fast_age,
.port_fdb_add = lan9303_port_fdb_add,
.port_fdb_del = lan9303_port_fdb_del,
.port_fdb_dump = lan9303_port_fdb_dump,
.port_mdb_add = lan9303_port_mdb_add,
.port_mdb_del = lan9303_port_mdb_del,
.get_tag_protocol = lan9303_get_tag_protocol,
.setup = lan9303_setup,
.get_strings = lan9303_get_strings,
.phy_read = lan9303_phy_read,
.phy_write = lan9303_phy_write,
.phylink_get_caps = lan9303_phylink_get_caps,
.phylink_mac_link_up = lan9303_phylink_mac_link_up,
.get_ethtool_stats = lan9303_get_ethtool_stats,
.get_sset_count = lan9303_get_sset_count,
.port_enable = lan9303_port_enable,
.port_disable = lan9303_port_disable,
.port_bridge_join = lan9303_port_bridge_join,
.port_bridge_leave = lan9303_port_bridge_leave,
.port_stp_state_set = lan9303_port_stp_state_set,
.port_fast_age = lan9303_port_fast_age,
.port_fdb_add = lan9303_port_fdb_add,
.port_fdb_del = lan9303_port_fdb_del,
.port_fdb_dump = lan9303_port_fdb_dump,
.port_mdb_add = lan9303_port_mdb_add,
.port_mdb_del = lan9303_port_mdb_del,
};
static int lan9303_register_switch(struct lan9303 *chip)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment