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: ...@@ -9,8 +9,6 @@ Required Properties:
- "mediatek,mt7622-sgmiisys", "syscon" - "mediatek,mt7622-sgmiisys", "syscon"
- "mediatek,mt7629-sgmiisys", "syscon" - "mediatek,mt7629-sgmiisys", "syscon"
- #clock-cells: Must be 1 - #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 The SGMIISYS controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt Documentation/devicetree/bindings/clock/clock-bindings.txt
......
...@@ -115,24 +115,34 @@ &cir { ...@@ -115,24 +115,34 @@ &cir {
}; };
&eth { &eth {
pinctrl-names = "default";
pinctrl-0 = <&eth_pins>;
status = "okay"; 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 { gmac1: mac@1 {
compatible = "mediatek,eth-mac"; compatible = "mediatek,eth-mac";
reg = <1>; reg = <1>;
phy-handle = <&phy5>; phy-mode = "rgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
}; };
mdio-bus { mdio: mdio-bus {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
phy5: ethernet-phy@5 {
reg = <5>;
phy-mode = "sgmii";
};
}; };
}; };
......
...@@ -931,6 +931,5 @@ sgmiisys: sgmiisys@1b128000 { ...@@ -931,6 +931,5 @@ sgmiisys: sgmiisys@1b128000 {
"syscon"; "syscon";
reg = <0 0x1b128000 0 0x3000>; reg = <0 0x1b128000 0 0x3000>;
#clock-cells = <1>; #clock-cells = <1>;
mediatek,physpeed = "2500";
}; };
}; };
...@@ -9,7 +9,7 @@ if NET_VENDOR_MEDIATEK ...@@ -9,7 +9,7 @@ if NET_VENDOR_MEDIATEK
config NET_MEDIATEK_SOC config NET_MEDIATEK_SOC
tristate "MediaTek SoC Gigabit Ethernet support" tristate "MediaTek SoC Gigabit Ethernet support"
select PHYLIB select PHYLINK
---help--- ---help---
This driver supports the gigabit ethernet MACs in the This driver supports the gigabit ethernet MACs in the
MediaTek SoC family. MediaTek SoC family.
......
...@@ -239,10 +239,9 @@ static int mtk_eth_mux_setup(struct mtk_eth *eth, int path) ...@@ -239,10 +239,9 @@ static int mtk_eth_mux_setup(struct mtk_eth *eth, int path)
return err; 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 err, path;
int sid, err, path;
path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII : path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII :
MTK_ETH_PATH_GMAC2_SGMII; MTK_ETH_PATH_GMAC2_SGMII;
...@@ -252,33 +251,10 @@ static int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id) ...@@ -252,33 +251,10 @@ static int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
if (err) if (err)
return 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; 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; int err, path = 0;
...@@ -296,7 +272,7 @@ static int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id) ...@@ -296,7 +272,7 @@ static int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
return 0; 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; int err, path;
...@@ -311,46 +287,3 @@ static int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id) ...@@ -311,46 +287,3 @@ static int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
return 0; 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 @@ ...@@ -14,6 +14,7 @@
#include <linux/of_net.h> #include <linux/of_net.h>
#include <linux/u64_stats_sync.h> #include <linux/u64_stats_sync.h>
#include <linux/refcount.h> #include <linux/refcount.h>
#include <linux/phylink.h>
#define MTK_QDMA_PAGE_SIZE 2048 #define MTK_QDMA_PAGE_SIZE 2048
#define MTK_MAX_RX_LENGTH 1536 #define MTK_MAX_RX_LENGTH 1536
...@@ -330,12 +331,19 @@ ...@@ -330,12 +331,19 @@
#define MAC_MCR_SPEED_100 BIT(2) #define MAC_MCR_SPEED_100 BIT(2)
#define MAC_MCR_FORCE_DPX BIT(1) #define MAC_MCR_FORCE_DPX BIT(1)
#define MAC_MCR_FORCE_LINK BIT(0) #define MAC_MCR_FORCE_LINK BIT(0)
#define MAC_MCR_FIXED_LINK (MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG | \ #define MAC_MCR_FORCE_LINK_DOWN (MAC_MCR_FORCE_MODE)
MAC_MCR_FORCE_MODE | MAC_MCR_TX_EN | \
MAC_MCR_RX_EN | MAC_MCR_BACKOFF_EN | \ /* Mac status registers */
MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_RX_FC | \ #define MTK_MAC_MSR(x) (0x10108 + (x * 0x100))
MAC_MCR_FORCE_TX_FC | MAC_MCR_SPEED_1000 | \ #define MAC_MSR_EEE1G BIT(7)
MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_LINK) #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 */ /* TRGMII RXC control register */
#define TRGMII_RCK_CTRL 0x10300 #define TRGMII_RCK_CTRL 0x10300
...@@ -404,14 +412,38 @@ ...@@ -404,14 +412,38 @@
/* Register to auto-negotiation restart */ /* Register to auto-negotiation restart */
#define SGMSYS_PCS_CONTROL_1 0x0 #define SGMSYS_PCS_CONTROL_1 0x0
#define SGMII_AN_RESTART BIT(9) #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 */ /* Register to programmable link timer, the unit in 2 * 8ns */
#define SGMSYS_PCS_LINK_TIMER 0x18 #define SGMSYS_PCS_LINK_TIMER 0x18
#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & GENMASK(19, 0)) #define SGMII_LINK_TIMER_DEFAULT (0x186a0 & GENMASK(19, 0))
/* Register to control remote fault */ /* Register to control remote fault */
#define SGMSYS_SGMII_MODE 0x20 #define SGMSYS_SGMII_MODE 0x20
#define SGMII_REMOTE_FAULT_DIS BIT(8) #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 */ /* Register to power up QPHY */
#define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8 #define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8
...@@ -858,22 +890,23 @@ struct mtk_eth { ...@@ -858,22 +890,23 @@ struct mtk_eth {
/* struct mtk_mac - the structure that holds the info about the MACs of the /* struct mtk_mac - the structure that holds the info about the MACs of the
* SoC * SoC
* @id: The number of the MAC * @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 * @of_node: Our devicetree node
* @hw: Backpointer to our main datastruture * @hw: Backpointer to our main datastruture
* @hw_stats: Packet statistics counter * @hw_stats: Packet statistics counter
* @trgmii Indicate if the MAC uses TRGMII connected to internal
switch
*/ */
struct mtk_mac { struct mtk_mac {
int id; int id;
int ge_mode; phy_interface_t interface;
unsigned int mode;
int speed;
struct device_node *of_node; struct device_node *of_node;
struct phylink *phylink;
struct phylink_config phylink_config;
struct mtk_eth *hw; struct mtk_eth *hw;
struct mtk_hw_stats *hw_stats; struct mtk_hw_stats *hw_stats;
__be32 hwlro_ip[MTK_MAX_LRO_IP_CNT]; __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT];
int hwlro_ip_cnt; int hwlro_ip_cnt;
bool trgmii;
}; };
/* the struct describing the SoC. these are declared in the soc_xyz.c files */ /* 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); ...@@ -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, int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np,
u32 ana_rgc3); u32 ana_rgc3);
int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id); 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_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
int mtk_setup_hw_path(struct mtk_eth *eth, int mac_id, int phymode); 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 */ #endif /* MTK_ETH_H */
...@@ -16,8 +16,7 @@ ...@@ -16,8 +16,7 @@
int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3) int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
{ {
struct device_node *np; struct device_node *np;
const char *str; int i;
int i, err;
ss->ana_rgc3 = ana_rgc3; ss->ana_rgc3 = ana_rgc3;
...@@ -29,19 +28,6 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 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); ss->regmap[i] = syscon_node_to_regmap(np);
if (IS_ERR(ss->regmap[i])) if (IS_ERR(ss->regmap[i]))
return PTR_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; return 0;
...@@ -73,27 +59,45 @@ int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id) ...@@ -73,27 +59,45 @@ int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id)
return 0; 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; unsigned int val;
int mode;
if (!ss->regmap[id]) if (!ss->regmap[id])
return -EINVAL; return -EINVAL;
regmap_read(ss->regmap[id], ss->ana_rgc3, &val); regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
val &= ~GENMASK(3, 2); val &= ~RG_PHY_SPEED_MASK;
mode = ss->flags[id] & MTK_SGMII_PHYSPEED_MASK; if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
val |= (mode == MTK_SGMII_PHYSPEED_1000) ? 0 : BIT(2); val |= RG_PHY_SPEED_3_125G;
regmap_write(ss->regmap[id], ss->ana_rgc3, val); regmap_write(ss->regmap[id], ss->ana_rgc3, val);
/* Disable SGMII AN */ /* Disable SGMII AN */
regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val); 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); regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
/* SGMII force mode setting */ /* 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); regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
/* Release PHYA power down state */ /* Release PHYA power down state */
...@@ -103,3 +107,20 @@ int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id) ...@@ -103,3 +107,20 @@ int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id)
return 0; 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