aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2022-12-06 14:38:53 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2022-12-06 14:38:53 -0800
commit5ab0127c2b72f4ce1289f7125df41f2bf6e94c3b (patch)
treeaf0752d356b26715937df902b4674120c75a2803
parent74b331d03c33a2037ad3ecf8607e155eb51ce0a9 (diff)
parentacc4fee245443de91f324aafa88d296ead452a2c (diff)
Merge "net: stmmac: add support for marvel phy" into wip-er12
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c89
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c22
-rw-r--r--include/linux/stmmac.h1
4 files changed, 99 insertions, 16 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index b8548bf5676aa..b41ffae556b5d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -89,14 +89,21 @@
#define MII_BUSY 0x00000001
#define MII_WRITE 0x00000002
-#define DWC_ETH_QOS_PHY_INTR_STATUS 0x0013
-
#define LINK_UP 1
#define LINK_DOWN 0
#define LINK_DOWN_STATE 0x800
#define LINK_UP_STATE 0x400
+#define DWC_ETH_QOS_PHY_INTR_STATUS 0x0013
+#define DWC_ETH_QOS_BASIC_STATUS 0x0001
+#define LINK_STATE_MASK 0x4
+#define AUTONEG_STATE_MASK 0x20
+
+#define MARVEL_PHY_INTCS 0x13
+#define MARVEL_PHY_STATUS 0x11
+#define MARVEL_LINK_UP_STATUS BIT(10)
+
struct emac_emb_smmu_cb_ctx emac_emb_smmu_ctx = {0};
struct plat_stmmacenet_data *plat_dat;
@@ -308,7 +315,8 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
0, RGMII_IO_MACRO_CONFIG2);
- if (priv->plat->mac2mac_88Q5072)
+ if (priv->plat->mac2mac_88Q5072 ||
+ (priv->phydev && priv->phydev->phy_id == MARVEL_PHY_ID))
rgmii_updatel(ethqos,
RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
0, RGMII_IO_MACRO_CONFIG2);
@@ -355,9 +363,16 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
0, RGMII_IO_MACRO_CONFIG);
rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
0, RGMII_IO_MACRO_CONFIG2);
- rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- RGMII_IO_MACRO_CONFIG2);
+ if (priv->plat->mac2mac_88Q5072 ||
+ (priv->phydev && priv->phydev->phy_id == MARVEL_PHY_ID))
+ rgmii_updatel(ethqos,
+ RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
+ 0, RGMII_IO_MACRO_CONFIG2);
+ else
+ rgmii_updatel(ethqos,
+ RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
+ RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
+ RGMII_IO_MACRO_CONFIG2);
rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2,
BIT(6), RGMII_IO_MACRO_CONFIG);
rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
@@ -403,15 +418,17 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
0, RGMII_IO_MACRO_CONFIG2);
- if (ethqos->emac_ver == EMAC_HW_v3_0_0_RG)
+ if (ethqos->emac_ver != EMAC_HW_v3_0_0_RG ||
+ priv->plat->mac2mac_88Q5072 ||
+ (priv->phydev && priv->phydev->phy_id == MARVEL_PHY_ID))
rgmii_updatel(ethqos,
RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- RGMII_IO_MACRO_CONFIG2);
+ 0, RGMII_IO_MACRO_CONFIG2);
else
rgmii_updatel(ethqos,
RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- 0, RGMII_IO_MACRO_CONFIG2);
+ RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
+ RGMII_IO_MACRO_CONFIG2);
rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9,
BIT(12) | GENMASK(9, 8),
RGMII_IO_MACRO_CONFIG);
@@ -589,13 +606,50 @@ static void ethqos_handle_phy_interrupt(struct qcom_ethqos *ethqos)
struct net_device *dev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(dev);
+ int marvel_intr_status = 0;
+ int marvel_status = 0;
+ int phy_id = 0;
+
+ if (!priv->phydev)
+ return;
+
+ phy_id = priv->phydev->phy_id & priv->phydev->drv->phy_id_mask;
+
+ if (phy_id == MARVEL_PHY_ID) {
+ marvel_intr_status =
+ ethqos_mdio_read(priv,
+ priv->plat->phy_addr,
+ MARVEL_PHY_INTCS);
+ marvel_status = ethqos_mdio_read(priv,
+ priv->plat->phy_addr,
+ MARVEL_PHY_STATUS);
+
+ /* Interrupt received for link state change */
+ phy_intr_status = ethqos_mdio_read(priv,
+ priv->plat->phy_addr,
+ DWC_ETH_QOS_BASIC_STATUS);
+ ETHQOSDBG("Basic Status Reg (%#x) = %#x\n",
+ DWC_ETH_QOS_BASIC_STATUS, phy_intr_status);
+
+ if (phy_intr_status & LINK_STATE_MASK) {
+ if (marvel_status & MARVEL_LINK_UP_STATUS)
+ ETHQOSDBG("Intr for link UP state\n");
+ phy_mac_interrupt(priv->phydev);
+ } else if (!(phy_intr_status & LINK_STATE_MASK)) {
+ ETHQOSDBG("Intr for link DOWN state\n");
+ phy_mac_interrupt(priv->phydev);
+ } else if (!(phy_intr_status & AUTONEG_STATE_MASK)) {
+ ETHQOSDBG("Intr for link down with auto-neg err\n");
+ }
+ } else {
+ phy_intr_status =
+ ethqos_mdio_read(priv, priv->plat->phy_addr,
+ DWC_ETH_QOS_PHY_INTR_STATUS);
- phy_intr_status = ethqos_mdio_read(priv, priv->plat->phy_addr,
- DWC_ETH_QOS_PHY_INTR_STATUS);
-
- if ((phy_intr_status & LINK_UP_STATE) ||
- (phy_intr_status & LINK_DOWN_STATE))
- phy_mac_interrupt(priv->phydev);
+ if ((phy_intr_status & LINK_UP_STATE) ||
+ (phy_intr_status & LINK_DOWN_STATE))
+ phy_mac_interrupt(priv->phydev);
+ }
}
static void ethqos_defer_phy_isr_work(struct work_struct *work)
@@ -763,6 +817,9 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
plat_dat->mac2mac_88Q5072 =
of_property_read_bool(np, "mac2mac-88Q5072");
+ plat_dat->phy_fixed_link =
+ of_property_read_bool(np, "phy-fixed-link");
+
if (of_property_read_bool(pdev->dev.of_node,
"emac-core-version")) {
/* Read emac core version value from dtsi */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index b7626aebe5975..b9944d5046d36 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -24,6 +24,9 @@
#include <linux/reset.h>
#include <net/page_pool.h>
+#define MARVELL_PHY_ID_88EA1512 0x01410dd4
+#define MARVEL_PHY_ID MARVELL_PHY_ID_88EA1512
+
struct stmmac_resources {
void __iomem *addr;
u8 mac[ETH_ALEN];
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 6e57513b94656..cfa4cb8805e86 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1023,6 +1023,14 @@ static void stmmac_validate(struct phylink_config *config,
/* If PCS is supported, check which modes it supports. */
if (priv->hw->xpcs)
xpcs_validate(priv->hw->xpcs, supported, state);
+
+ if (priv->plat->phy_fixed_link) {
+ state->link = 1;
+ state->duplex = DUPLEX_FULL;
+ state->speed = SPEED_1000;
+ if (priv->phydev)
+ priv->phydev->autoneg = AUTONEG_DISABLE;
+ }
}
static void stmmac_mac_config(struct phylink_config *config, unsigned int mode,
@@ -1204,6 +1212,7 @@ static int stmmac_init_phy(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
struct device_node *node;
+ int phy_id = 0;
int ret;
node = priv->plat->phylink_node;
@@ -1223,6 +1232,19 @@ static int stmmac_init_phy(struct net_device *dev)
return -ENODEV;
}
+ phy_id = priv->phydev->phy_id & priv->phydev->drv->phy_id_mask;
+ if (phy_id == MARVEL_PHY_ID && !priv->plat->phy_intr_en) {
+ pr_info(" %s phy_id = %#x, phy_id_mask = %#x\n",
+ __func__, priv->phydev->phy_id,
+ priv->phydev->drv->phy_id_mask);
+ ret = priv->plat->phy_intr_enable(priv);
+ if (ret)
+ pr_err("%s: Unable to enable PHY interrupt\n",
+ __func__);
+ else
+ priv->plat->phy_intr_en = true;
+ }
+
if (priv->plat->phy_intr_en_extn_stm &&
priv->plat->phy_intr_en) {
priv->phydev->irq = PHY_MAC_INTERRUPT;
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index e6bd4e4d8e876..d8a97f4b741c8 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -285,6 +285,7 @@ struct plat_stmmacenet_data {
bool mac2mac_en;
int mac2mac_link;
bool mac2mac_88Q5072;
+ bool phy_fixed_link;
struct emac_emb_smmu_cb_ctx stmmac_emb_smmu_ctx;
bool phy_intr_en_extn_stm;
bool phy_intr_en;