Commit 1ddc5d94 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-ethernet-mediatek-convert-to-PHYLINK'

René van Dorst says:

====================
net: ethernet: mediatek: convert to PHYLINK

These patches converts mediatek driver to PHYLINK API.

v3->v4:
* Phylink improvements and clean-ups after review
v2->v3:
* Phylink improvements and clean-ups after review
v1->v2:
* Rebase for mt76x8 changes
* Phylink improvements and clean-ups after review
* SGMII port doesn't support 2.5Gbit in SGMII mode only in BASE-X mode.
  Refactor the code.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cb6ec975 bd69baaa
......@@ -9,8 +9,6 @@ Required Properties:
- "mediatek,mt7622-sgmiisys", "syscon"
- "mediatek,mt7629-sgmiisys", "syscon"
- #clock-cells: Must be 1
- mediatek,physpeed: Should be one of "auto", "1000" or "2500" to match up
the capability of the target PHY.
The SGMIISYS controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
......
......@@ -115,24 +115,34 @@ &cir {
};
&eth {
pinctrl-names = "default";
pinctrl-0 = <&eth_pins>;
status = "okay";
gmac0: mac@0 {
compatible = "mediatek,eth-mac";
reg = <0>;
phy-mode = "2500base-x";
fixed-link {
speed = <2500>;
full-duplex;
pause;
};
};
gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
phy-handle = <&phy5>;
phy-mode = "rgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};
mdio-bus {
mdio: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
phy5: ethernet-phy@5 {
reg = <5>;
phy-mode = "sgmii";
};
};
};
......
......@@ -931,6 +931,5 @@ sgmiisys: sgmiisys@1b128000 {
"syscon";
reg = <0 0x1b128000 0 0x3000>;
#clock-cells = <1>;
mediatek,physpeed = "2500";
};
};
......@@ -9,7 +9,7 @@ if NET_VENDOR_MEDIATEK
config NET_MEDIATEK_SOC
tristate "MediaTek SoC Gigabit Ethernet support"
select PHYLIB
select PHYLINK
---help---
This driver supports the gigabit ethernet MACs in the
MediaTek SoC family.
......
......@@ -239,10 +239,9 @@ static int mtk_eth_mux_setup(struct mtk_eth *eth, int path)
return err;
}
static int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
{
unsigned int val = 0;
int sid, err, path;
int err, path;
path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII :
MTK_ETH_PATH_GMAC2_SGMII;
......@@ -252,33 +251,10 @@ static int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
if (err)
return err;
/* The path GMAC to SGMII will be enabled once the SGMIISYS is being
* setup done.
*/
regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
SYSCFG0_SGMII_MASK, ~(u32)SYSCFG0_SGMII_MASK);
/* Decide how GMAC and SGMIISYS be mapped */
sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? 0 : mac_id;
/* Setup SGMIISYS with the determined property */
if (MTK_HAS_FLAGS(eth->sgmii->flags[sid], MTK_SGMII_PHYSPEED_AN))
err = mtk_sgmii_setup_mode_an(eth->sgmii, sid);
else
err = mtk_sgmii_setup_mode_force(eth->sgmii, sid);
if (err)
return err;
regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
SYSCFG0_SGMII_MASK, val);
return 0;
}
static int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
{
int err, path = 0;
......@@ -296,7 +272,7 @@ static int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
return 0;
}
static int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
{
int err, path;
......@@ -311,46 +287,3 @@ static int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
return 0;
}
int mtk_setup_hw_path(struct mtk_eth *eth, int mac_id, int phymode)
{
int err;
/* No mux'ing for MT7628/88 */
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
return 0;
switch (phymode) {
case PHY_INTERFACE_MODE_TRGMII:
case PHY_INTERFACE_MODE_RGMII_TXID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_MII:
case PHY_INTERFACE_MODE_REVMII:
case PHY_INTERFACE_MODE_RMII:
if (MTK_HAS_CAPS(eth->soc->caps, MTK_RGMII)) {
err = mtk_gmac_rgmii_path_setup(eth, mac_id);
if (err)
return err;
}
break;
case PHY_INTERFACE_MODE_SGMII:
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
err = mtk_gmac_sgmii_path_setup(eth, mac_id);
if (err)
return err;
}
break;
case PHY_INTERFACE_MODE_GMII:
if (MTK_HAS_CAPS(eth->soc->caps, MTK_GEPHY)) {
err = mtk_gmac_gephy_path_setup(eth, mac_id);
if (err)
return err;
}
break;
default:
break;
}
return 0;
}
This diff is collapsed.
......@@ -14,6 +14,7 @@
#include <linux/of_net.h>
#include <linux/u64_stats_sync.h>
#include <linux/refcount.h>
#include <linux/phylink.h>
#define MTK_QDMA_PAGE_SIZE 2048
#define MTK_MAX_RX_LENGTH 1536
......@@ -330,12 +331,19 @@
#define MAC_MCR_SPEED_100 BIT(2)
#define MAC_MCR_FORCE_DPX BIT(1)
#define MAC_MCR_FORCE_LINK BIT(0)
#define MAC_MCR_FIXED_LINK (MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG | \
MAC_MCR_FORCE_MODE | MAC_MCR_TX_EN | \
MAC_MCR_RX_EN | MAC_MCR_BACKOFF_EN | \
MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_RX_FC | \
MAC_MCR_FORCE_TX_FC | MAC_MCR_SPEED_1000 | \
MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_LINK)
#define MAC_MCR_FORCE_LINK_DOWN (MAC_MCR_FORCE_MODE)
/* Mac status registers */
#define MTK_MAC_MSR(x) (0x10108 + (x * 0x100))
#define MAC_MSR_EEE1G BIT(7)
#define MAC_MSR_EEE100M BIT(6)
#define MAC_MSR_RX_FC BIT(5)
#define MAC_MSR_TX_FC BIT(4)
#define MAC_MSR_SPEED_1000 BIT(3)
#define MAC_MSR_SPEED_100 BIT(2)
#define MAC_MSR_SPEED_MASK (MAC_MSR_SPEED_1000 | MAC_MSR_SPEED_100)
#define MAC_MSR_DPX BIT(1)
#define MAC_MSR_LINK BIT(0)
/* TRGMII RXC control register */
#define TRGMII_RCK_CTRL 0x10300
......@@ -404,14 +412,38 @@
/* Register to auto-negotiation restart */
#define SGMSYS_PCS_CONTROL_1 0x0
#define SGMII_AN_RESTART BIT(9)
#define SGMII_ISOLATE BIT(10)
#define SGMII_AN_ENABLE BIT(12)
#define SGMII_LINK_STATYS BIT(18)
#define SGMII_AN_ABILITY BIT(19)
#define SGMII_AN_COMPLETE BIT(21)
#define SGMII_PCS_FAULT BIT(23)
#define SGMII_AN_EXPANSION_CLR BIT(30)
/* Register to programmable link timer, the unit in 2 * 8ns */
#define SGMSYS_PCS_LINK_TIMER 0x18
#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & GENMASK(19, 0))
/* Register to control remote fault */
#define SGMSYS_SGMII_MODE 0x20
#define SGMII_REMOTE_FAULT_DIS BIT(8)
#define SGMSYS_SGMII_MODE 0x20
#define SGMII_IF_MODE_BIT0 BIT(0)
#define SGMII_SPEED_DUPLEX_AN BIT(1)
#define SGMII_SPEED_10 0x0
#define SGMII_SPEED_100 BIT(2)
#define SGMII_SPEED_1000 BIT(3)
#define SGMII_DUPLEX_FULL BIT(4)
#define SGMII_IF_MODE_BIT5 BIT(5)
#define SGMII_REMOTE_FAULT_DIS BIT(8)
#define SGMII_CODE_SYNC_SET_VAL BIT(9)
#define SGMII_CODE_SYNC_SET_EN BIT(10)
#define SGMII_SEND_AN_ERROR_EN BIT(11)
#define SGMII_IF_MODE_MASK GENMASK(5, 1)
/* Register to set SGMII speed, ANA RG_ Control Signals III*/
#define SGMSYS_ANA_RG_CS3 0x2028
#define RG_PHY_SPEED_MASK (BIT(2) | BIT(3))
#define RG_PHY_SPEED_1_25G 0x0
#define RG_PHY_SPEED_3_125G BIT(2)
/* Register to power up QPHY */
#define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8
......@@ -858,22 +890,23 @@ struct mtk_eth {
/* struct mtk_mac - the structure that holds the info about the MACs of the
* SoC
* @id: The number of the MAC
* @ge_mode: Interface mode kept for setup restoring
* @interface: Interface mode kept for detecting change in hw settings
* @of_node: Our devicetree node
* @hw: Backpointer to our main datastruture
* @hw_stats: Packet statistics counter
* @trgmii Indicate if the MAC uses TRGMII connected to internal
switch
*/
struct mtk_mac {
int id;
int ge_mode;
phy_interface_t interface;
unsigned int mode;
int speed;
struct device_node *of_node;
struct phylink *phylink;
struct phylink_config phylink_config;
struct mtk_eth *hw;
struct mtk_hw_stats *hw_stats;
__be32 hwlro_ip[MTK_MAX_LRO_IP_CNT];
int hwlro_ip_cnt;
bool trgmii;
};
/* the struct describing the SoC. these are declared in the soc_xyz.c files */
......@@ -888,7 +921,12 @@ u32 mtk_r32(struct mtk_eth *eth, unsigned reg);
int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np,
u32 ana_rgc3);
int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id);
int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id);
int mtk_setup_hw_path(struct mtk_eth *eth, int mac_id, int phymode);
int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
const struct phylink_link_state *state);
void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id);
int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id);
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id);
int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id);
#endif /* MTK_ETH_H */
......@@ -16,8 +16,7 @@
int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
{
struct device_node *np;
const char *str;
int i, err;
int i;
ss->ana_rgc3 = ana_rgc3;
......@@ -29,19 +28,6 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
ss->regmap[i] = syscon_node_to_regmap(np);
if (IS_ERR(ss->regmap[i]))
return PTR_ERR(ss->regmap[i]);
err = of_property_read_string(np, "mediatek,physpeed", &str);
if (err)
return err;
if (!strcmp(str, "2500"))
ss->flags[i] |= MTK_SGMII_PHYSPEED_2500;
else if (!strcmp(str, "1000"))
ss->flags[i] |= MTK_SGMII_PHYSPEED_1000;
else if (!strcmp(str, "auto"))
ss->flags[i] |= MTK_SGMII_PHYSPEED_AN;
else
return -EINVAL;
}
return 0;
......@@ -73,27 +59,45 @@ int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id)
return 0;
}
int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id)
int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
const struct phylink_link_state *state)
{
unsigned int val;
int mode;
if (!ss->regmap[id])
return -EINVAL;
regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
val &= ~GENMASK(3, 2);
mode = ss->flags[id] & MTK_SGMII_PHYSPEED_MASK;
val |= (mode == MTK_SGMII_PHYSPEED_1000) ? 0 : BIT(2);
val &= ~RG_PHY_SPEED_MASK;
if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
val |= RG_PHY_SPEED_3_125G;
regmap_write(ss->regmap[id], ss->ana_rgc3, val);
/* Disable SGMII AN */
regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
val &= ~BIT(12);
val &= ~SGMII_AN_ENABLE;
regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
/* SGMII force mode setting */
val = 0x31120019;
regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
val &= ~SGMII_IF_MODE_MASK;
switch (state->speed) {
case SPEED_10:
val |= SGMII_SPEED_10;
break;
case SPEED_100:
val |= SGMII_SPEED_100;
break;
case SPEED_2500:
case SPEED_1000:
val |= SGMII_SPEED_1000;
break;
};
if (state->duplex == DUPLEX_FULL)
val |= SGMII_DUPLEX_FULL;
regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
/* Release PHYA power down state */
......@@ -103,3 +107,20 @@ int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id)
return 0;
}
void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id)
{
struct mtk_sgmii *ss = eth->sgmii;
unsigned int val, sid;
/* Decide how GMAC and SGMIISYS be mapped */
sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
0 : mac_id;
if (!ss->regmap[sid])
return;
regmap_read(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, &val);
val |= SGMII_AN_RESTART;
regmap_write(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, val);
}
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