[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <88a8839c7cd46a177fb47288d777d89ee44a3db2.1691047285.git.chenfeiyang@loongson.cn>
Date: Thu, 3 Aug 2023 19:30:37 +0800
From: Feiyang Chen <chenfeiyang@...ngson.cn>
To: andrew@...n.ch,
hkallweit1@...il.com,
peppe.cavallaro@...com,
alexandre.torgue@...s.st.com,
joabreu@...opsys.com,
chenhuacai@...ngson.cn
Cc: Feiyang Chen <chenfeiyang@...ngson.cn>,
linux@...linux.org.uk,
dongbiao@...ngson.cn,
loongson-kernel@...ts.loongnix.cn,
netdev@...r.kernel.org,
loongarch@...ts.linux.dev,
chris.chenfeiyang@...il.com
Subject: [PATCH v3 16/16] net: stmmac: dwmac-loongson: Add GNET support
Add GNET support. Current GNET does not support half duplex mode.
and GNET on LS7A only supports ANE when speed is set to 1000M, and
GNET on LS2K should use single queue.
Signed-off-by: Feiyang Chen <chenfeiyang@...ngson.cn>
---
.../ethernet/stmicro/stmmac/dwmac-loongson.c | 67 +++++++++++++++++++
.../ethernet/stmicro/stmmac/stmmac_ethtool.c | 6 ++
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +-
include/linux/stmmac.h | 2 +
4 files changed, 76 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index d3ade3ae9014..712fede3c4b7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -106,6 +106,71 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
.config = loongson_gmac_config,
};
+static void loongson_gnet_fix_speed(void *priv, unsigned int speed)
+{
+ struct net_device *ndev = dev_get_drvdata(priv);
+ struct stmmac_priv *ptr = netdev_priv(ndev);
+
+ /* The controller and PHY don't work well together.
+ * We need to use the PS bit to check if the controller's status
+ * is correct and reset PHY if necessary.
+ */
+ if (speed == SPEED_1000)
+ if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */)
+ phy_restart_aneg(ndev->phydev);
+}
+
+static int loongson_gnet_data(struct pci_dev *pdev,
+ struct plat_stmmacenet_data *plat)
+{
+ loongson_default_data(pdev, plat);
+
+ plat->multicast_filter_bins = 256;
+
+ plat->mdio_bus_data->phy_mask = 0xfffffffb;
+
+ plat->phy_addr = 2;
+ plat->phy_interface = PHY_INTERFACE_MODE_INTERNAL;
+
+ plat->bsp_priv = &pdev->dev;
+ plat->fix_mac_speed = loongson_gnet_fix_speed;
+
+ plat->dma_cfg->pbl = 32;
+ plat->dma_cfg->pblx8 = true;
+
+ plat->clk_ref_rate = 125000000;
+ plat->clk_ptp_rate = 125000000;
+
+ return 0;
+}
+
+static int loongson_gnet_config(struct pci_dev *pdev,
+ struct plat_stmmacenet_data *plat,
+ struct stmmac_resources *res)
+{
+ plat->dma_reset_times = 5;
+
+ switch (pdev->revision) {
+ case 0x00:
+ plat->disable_half_duplex = true;
+ plat->disable_force_1000 = true;
+ break;
+ case 0x01:
+ plat->disable_half_duplex = true;
+ plat->use_single_queue = true;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static struct stmmac_pci_info loongson_gnet_pci_info = {
+ .setup = loongson_gnet_data,
+ .config = loongson_gnet_config,
+};
+
static u32 get_irq_type(struct device_node *np)
{
struct of_phandle_args oirq;
@@ -325,9 +390,11 @@ static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
loongson_dwmac_resume);
#define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03
+#define PCI_DEVICE_ID_LOONGSON_GNET 0x7a13
static const struct pci_device_id loongson_dwmac_id_table[] = {
{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
+ { PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
{}
};
MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 2ae73ab842d4..066f42ecf832 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -404,6 +404,12 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
return 0;
}
+ if (priv->plat->disable_force_1000) {
+ if (cmd->base.speed == SPEED_1000 &&
+ cmd->base.autoneg != AUTONEG_ENABLE)
+ return -EOPNOTSUPP;
+ }
+
return phylink_ethtool_ksettings_set(priv->phylink, cmd);
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 692f41a7a175..6797b1742391 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1240,7 +1240,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
}
/* Half-Duplex can only work with single queue */
- if (priv->plat->tx_queues_to_use > 1)
+ if (priv->plat->tx_queues_to_use > 1 || priv->plat->disable_half_duplex)
priv->phylink_config.mac_capabilities &=
~(MAC_10HD | MAC_100HD | MAC_1000HD);
priv->phylink_config.mac_managed_pm = true;
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 9afee011839a..18b4ef614d25 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -362,5 +362,7 @@ struct plat_stmmacenet_data {
u32 irq_flags;
bool disable_flow_control;
bool use_single_queue;
+ bool disable_half_duplex;
+ bool disable_force_1000;
};
#endif
--
2.39.3
Powered by blists - more mailing lists