From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB
---
kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-rk-tool.c | 233 ++++++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 171 insertions(+), 62 deletions(-)
diff --git a/kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-rk-tool.c b/kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-rk-tool.c
index aea25b6..702dfc7 100644
--- a/kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-rk-tool.c
+++ b/kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-rk-tool.c
@@ -9,6 +9,7 @@
#include <linux/if_ether.h>
#include <linux/if.h>
#include <linux/dma-mapping.h>
+#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/prefetch.h>
#include <linux/regmap.h>
@@ -100,6 +101,7 @@
#define STMMAC_ALIGN(x) __ALIGN_KERNEL(x, SMP_CACHE_BYTES)
#define MAX_DELAYLINE 0x7f
+#define RK3588_MAX_DELAYLINE 0xc7
#define SCAN_STEP 0x5
#define SCAN_VALID_RANGE 0xA
@@ -120,7 +122,8 @@
.size = 1024,
};
-static int dwmac_rk_enable_mac_loopback(struct stmmac_priv *priv, int speed)
+static int dwmac_rk_enable_mac_loopback(struct stmmac_priv *priv, int speed,
+ int addr, bool phy)
{
u32 ctrl;
int phy_val;
@@ -129,25 +132,30 @@
ctrl &= ~priv->hw->link.speed_mask;
ctrl |= GMAC_CONTROL_LM;
- phy_val = mdiobus_read(priv->mii, priv->plat->phy_addr, MII_BMCR);
+ if (phy)
+ phy_val = mdiobus_read(priv->mii, addr, MII_BMCR);
switch (speed) {
case LOOPBACK_SPEED1000:
ctrl |= priv->hw->link.speed1000;
- phy_val |= BMCR_ANENABLE;
- phy_val |= BMCR_SPEED1000;
+ if (phy) {
+ phy_val &= ~BMCR_SPEED100;
+ phy_val |= BMCR_SPEED1000;
+ }
break;
case LOOPBACK_SPEED100:
ctrl |= priv->hw->link.speed100;
- phy_val &= ~BMCR_ANENABLE;
- phy_val &= ~BMCR_SPEED1000;
- phy_val |= BMCR_SPEED100;
+ if (phy) {
+ phy_val &= ~BMCR_SPEED1000;
+ phy_val |= BMCR_SPEED100;
+ }
break;
case LOOPBACK_SPEED10:
ctrl |= priv->hw->link.speed10;
- phy_val &= ~BMCR_ANENABLE;
- phy_val &= ~BMCR_SPEED1000;
- phy_val &= ~BMCR_SPEED100;
+ if (phy) {
+ phy_val &= ~BMCR_SPEED1000;
+ phy_val &= ~BMCR_SPEED100;
+ }
break;
default:
return -EPERM;
@@ -156,9 +164,14 @@
ctrl |= priv->hw->link.duplex;
writel(ctrl, priv->ioaddr + GMAC_CONTROL);
- phy_val |= BMCR_FULLDPLX;
- mdiobus_write(priv->mii, priv->plat->phy_addr, MII_BMCR, phy_val);
- phy_val = mdiobus_read(priv->mii, priv->plat->phy_addr, MII_BMCR);
+ if (phy) {
+ phy_val &= ~BMCR_PDOWN;
+ phy_val &= ~BMCR_ANENABLE;
+ phy_val &= ~BMCR_PDOWN;
+ phy_val |= BMCR_FULLDPLX;
+ mdiobus_write(priv->mii, addr, MII_BMCR, phy_val);
+ phy_val = mdiobus_read(priv->mii, addr, MII_BMCR);
+ }
if (likely(priv->plat->fix_mac_speed))
priv->plat->fix_mac_speed(priv->plat->bsp_priv, speed);
@@ -166,7 +179,7 @@
return 0;
}
-static int dwmac_rk_disable_mac_loopback(struct stmmac_priv *priv)
+static int dwmac_rk_disable_mac_loopback(struct stmmac_priv *priv, int addr)
{
u32 ctrl;
int phy_val;
@@ -175,25 +188,27 @@
ctrl &= ~GMAC_CONTROL_LM;
writel(ctrl, priv->ioaddr + GMAC_CONTROL);
- phy_val = mdiobus_read(priv->mii, priv->plat->phy_addr, MII_BMCR);
+ phy_val = mdiobus_read(priv->mii, addr, MII_BMCR);
phy_val |= BMCR_ANENABLE;
- mdiobus_write(priv->mii, priv->plat->phy_addr, MII_BMCR, phy_val);
- phy_val = mdiobus_read(priv->mii, priv->plat->phy_addr, MII_BMCR);
+ mdiobus_write(priv->mii, addr, MII_BMCR, phy_val);
+ phy_val = mdiobus_read(priv->mii, addr, MII_BMCR);
return 0;
}
static int dwmac_rk_set_mac_loopback(struct stmmac_priv *priv,
- int speed, bool enable)
+ int speed, bool enable,
+ int addr, bool phy)
{
if (enable)
- return dwmac_rk_enable_mac_loopback(priv, speed);
+ return dwmac_rk_enable_mac_loopback(priv, speed, addr, phy);
else
- return dwmac_rk_disable_mac_loopback(priv);
+ return dwmac_rk_disable_mac_loopback(priv, addr);
}
-static int dwmac_rk_enable_phy_loopback(struct stmmac_priv *priv, int speed)
+static int dwmac_rk_enable_phy_loopback(struct stmmac_priv *priv, int speed,
+ int addr, bool phy)
{
u32 ctrl;
int val;
@@ -201,25 +216,30 @@
ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
ctrl &= ~priv->hw->link.speed_mask;
- val = mdiobus_read(priv->mii, 0, MII_BMCR);
-
- val &= ~BMCR_ANENABLE;
- val |= BMCR_LOOPBACK;
+ if (phy)
+ val = mdiobus_read(priv->mii, addr, MII_BMCR);
switch (speed) {
case LOOPBACK_SPEED1000:
ctrl |= priv->hw->link.speed1000;
- val |= BMCR_SPEED1000;
+ if (phy) {
+ val &= ~BMCR_SPEED100;
+ val |= BMCR_SPEED1000;
+ }
break;
case LOOPBACK_SPEED100:
ctrl |= priv->hw->link.speed100;
- val &= ~BMCR_SPEED1000;
- val |= BMCR_SPEED100;
+ if (phy) {
+ val &= ~BMCR_SPEED1000;
+ val |= BMCR_SPEED100;
+ }
break;
case LOOPBACK_SPEED10:
ctrl |= priv->hw->link.speed10;
- val &= ~BMCR_SPEED1000;
- val &= ~BMCR_SPEED100;
+ if (phy) {
+ val &= ~BMCR_SPEED1000;
+ val &= ~BMCR_SPEED100;
+ }
break;
default:
return -EPERM;
@@ -228,9 +248,14 @@
ctrl |= priv->hw->link.duplex;
writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
- val |= BMCR_FULLDPLX;
- mdiobus_write(priv->mii, 0, MII_BMCR, val);
- val = mdiobus_read(priv->mii, 0, MII_BMCR);
+ if (phy) {
+ val |= BMCR_FULLDPLX;
+ val &= ~BMCR_PDOWN;
+ val &= ~BMCR_ANENABLE;
+ val |= BMCR_LOOPBACK;
+ mdiobus_write(priv->mii, addr, MII_BMCR, val);
+ val = mdiobus_read(priv->mii, addr, MII_BMCR);
+ }
if (likely(priv->plat->fix_mac_speed))
priv->plat->fix_mac_speed(priv->plat->bsp_priv, speed);
@@ -238,40 +263,43 @@
return 0;
}
-static int dwmac_rk_disable_phy_loopback(struct stmmac_priv *priv)
+static int dwmac_rk_disable_phy_loopback(struct stmmac_priv *priv, int addr)
{
int val;
- val = mdiobus_read(priv->mii, 0, MII_BMCR);
+ val = mdiobus_read(priv->mii, addr, MII_BMCR);
val |= BMCR_ANENABLE;
val &= ~BMCR_LOOPBACK;
- mdiobus_write(priv->mii, 0, MII_BMCR, val);
- val = mdiobus_read(priv->mii, priv->plat->phy_addr, MII_BMCR);
+ mdiobus_write(priv->mii, addr, MII_BMCR, val);
+ val = mdiobus_read(priv->mii, addr, MII_BMCR);
return 0;
}
static int dwmac_rk_set_phy_loopback(struct stmmac_priv *priv,
- int speed, bool enable)
+ int speed, bool enable,
+ int addr, bool phy)
{
if (enable)
- return dwmac_rk_enable_phy_loopback(priv, speed);
+ return dwmac_rk_enable_phy_loopback(priv, speed,
+ addr, phy);
else
- return dwmac_rk_disable_phy_loopback(priv);
+ return dwmac_rk_disable_phy_loopback(priv, addr);
}
static int dwmac_rk_set_loopback(struct stmmac_priv *priv,
- int type, int speed, bool enable)
+ int type, int speed, bool enable,
+ int addr, bool phy)
{
int ret;
switch (type) {
case LOOPBACK_TYPE_PHY:
- ret = dwmac_rk_set_phy_loopback(priv, speed, enable);
+ ret = dwmac_rk_set_phy_loopback(priv, speed, enable, addr, phy);
break;
case LOOPBACK_TYPE_GMAC:
- ret = dwmac_rk_set_mac_loopback(priv, speed, enable);
+ ret = dwmac_rk_set_mac_loopback(priv, speed, enable, addr, phy);
break;
default:
ret = -EOPNOTSUPP;
@@ -1005,17 +1033,17 @@
int ret = -ENOMEM;
/* desc dma map */
- lb_priv->dma_rx = dma_zalloc_coherent(priv->device,
- sizeof(struct dma_desc),
- &lb_priv->dma_rx_phy,
- GFP_KERNEL);
+ lb_priv->dma_rx = dma_alloc_coherent(priv->device,
+ sizeof(struct dma_desc),
+ &lb_priv->dma_rx_phy,
+ GFP_KERNEL);
if (!lb_priv->dma_rx)
return ret;
- lb_priv->dma_tx = dma_zalloc_coherent(priv->device,
- sizeof(struct dma_desc),
- &lb_priv->dma_tx_phy,
- GFP_KERNEL);
+ lb_priv->dma_tx = dma_alloc_coherent(priv->device,
+ sizeof(struct dma_desc),
+ &lb_priv->dma_tx_phy,
+ GFP_KERNEL);
if (!lb_priv->dma_tx) {
dma_free_coherent(priv->device,
sizeof(struct dma_desc),
@@ -1126,6 +1154,54 @@
}
}
+static void dwmac_rk_rx_queue_dma_chan_map(struct stmmac_priv *priv)
+{
+ u32 rx_queues_count = min_t(u32, priv->plat->rx_queues_to_use, 1);
+ u32 queue;
+ u32 chan;
+
+ for (queue = 0; queue < rx_queues_count; queue++) {
+ chan = priv->plat->rx_queues_cfg[queue].chan;
+ stmmac_map_mtl_to_dma(priv, priv->hw, queue, chan);
+ }
+}
+
+static void dwmac_rk_mac_enable_rx_queues(struct stmmac_priv *priv)
+{
+ u32 rx_queues_count = min_t(u32, priv->plat->rx_queues_to_use, 1);
+ int queue;
+ u8 mode;
+
+ for (queue = 0; queue < rx_queues_count; queue++) {
+ mode = priv->plat->rx_queues_cfg[queue].mode_to_use;
+ stmmac_rx_queue_enable(priv, priv->hw, mode, queue);
+ }
+}
+
+static void dwmac_rk_mtl_configuration(struct stmmac_priv *priv)
+{
+ /* Map RX MTL to DMA channels */
+ dwmac_rk_rx_queue_dma_chan_map(priv);
+
+ /* Enable MAC RX Queues */
+ dwmac_rk_mac_enable_rx_queues(priv);
+}
+
+static void dwmac_rk_mmc_setup(struct stmmac_priv *priv)
+{
+ unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
+ MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
+
+ stmmac_mmc_intr_all_mask(priv, priv->mmcaddr);
+
+ if (priv->dma_cap.rmon) {
+ stmmac_mmc_ctrl(priv, priv->mmcaddr, mode);
+ memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
+ } else {
+ netdev_info(priv->dev, "No MAC Management Counters available\n");
+ }
+}
+
static int dwmac_rk_init(struct net_device *dev,
struct dwmac_rk_lb_priv *lb_priv)
{
@@ -1165,6 +1241,10 @@
/* Initialize the MAC Core */
stmmac_core_init(priv, priv->hw, dev);
+ dwmac_rk_mtl_configuration(priv);
+
+ dwmac_rk_mmc_setup(priv);
+
ret = priv->hw->mac->rx_ipc(priv->hw);
if (!ret) {
pr_warn(" RX IPC Checksum Offload disabled\n");
@@ -1186,7 +1266,7 @@
writel((mode & ~DMA_CONTROL_OSF), priv->ioaddr + DMA_CONTROL);
}
- stmmac_enable_dma_irq(priv, priv->ioaddr, 0);
+ stmmac_enable_dma_irq(priv, priv->ioaddr, 0, 1, 1);
if (priv->hw->pcs)
stmmac_pcs_ctrl_ane(priv, priv->hw, 1, priv->hw->ps, 0);
@@ -1203,7 +1283,7 @@
{
struct stmmac_priv *priv = netdev_priv(dev);
- stmmac_disable_dma_irq(priv, priv->ioaddr, 0);
+ stmmac_disable_dma_irq(priv, priv->ioaddr, 0, 0, 0);
/* Release and free the Rx/Tx resources */
dwmac_rk_free_dma_desc_resources(priv, lb_priv);
@@ -1211,7 +1291,33 @@
static int dwmac_rk_get_max_delayline(struct stmmac_priv *priv)
{
- return MAX_DELAYLINE;
+ if (of_device_is_compatible(priv->device->of_node,
+ "rockchip,rk3588-gmac"))
+ return RK3588_MAX_DELAYLINE;
+ else
+ return MAX_DELAYLINE;
+}
+
+static int dwmac_rk_phy_poll_reset(struct stmmac_priv *priv, int addr)
+{
+ /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */
+ unsigned int val, retries = 12;
+ int ret;
+
+ val = mdiobus_read(priv->mii, addr, MII_BMCR);
+ mdiobus_write(priv->mii, addr, MII_BMCR, val | BMCR_RESET);
+
+ do {
+ msleep(50);
+ ret = mdiobus_read(priv->mii, addr, MII_BMCR);
+ if (ret < 0)
+ return ret;
+ } while (ret & BMCR_RESET && --retries);
+ if (ret & BMCR_RESET)
+ return -ETIMEDOUT;
+
+ msleep(1);
+ return 0;
}
static int dwmac_rk_loopback_run(struct stmmac_priv *priv,
@@ -1219,12 +1325,13 @@
{
struct net_device *ndev = priv->dev;
int phy_iface = dwmac_rk_get_phy_interface(priv);
- int ndev_up;
+ int ndev_up, phy_addr;
int ret = -EINVAL;
if (!ndev || !priv->mii)
return -EINVAL;
+ phy_addr = priv->dev->phydev->mdio.addr;
lb_priv->max_delay = dwmac_rk_get_max_delayline(priv);
rtnl_lock();
@@ -1249,20 +1356,22 @@
if (priv->plat->stmmac_rst)
reset_control_assert(priv->plat->stmmac_rst);
-
- if (priv->mii)
- priv->mii->reset(priv->mii);
-
+ dwmac_rk_phy_poll_reset(priv, phy_addr);
if (priv->plat->stmmac_rst)
reset_control_deassert(priv->plat->stmmac_rst);
}
/* wait for phy and controller ready */
usleep_range(100000, 200000);
+ dwmac_rk_set_loopback(priv, lb_priv->type, lb_priv->speed,
+ true, phy_addr, true);
+
ret = dwmac_rk_init(ndev, lb_priv);
if (ret)
goto exit_init;
- dwmac_rk_set_loopback(priv, lb_priv->type, lb_priv->speed, true);
+
+ dwmac_rk_set_loopback(priv, lb_priv->type, lb_priv->speed,
+ true, phy_addr, false);
if (lb_priv->scan) {
/* scan only support for rgmii mode */
@@ -1285,8 +1394,8 @@
out:
dwmac_rk_release(ndev, lb_priv);
- dwmac_rk_set_loopback(priv, lb_priv->type, lb_priv->speed, false);
-
+ dwmac_rk_set_loopback(priv, lb_priv->type, lb_priv->speed,
+ false, phy_addr, false);
exit_init:
if (ndev_up)
ndev->netdev_ops->ndo_open(ndev);
--
Gitblit v1.6.2