From bedbef8ad3e75a304af6361af235302bcc61d06b Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 14 May 2024 06:39:01 +0000
Subject: [PATCH] 修改内核路径

---
 kernel/drivers/net/phy/rk630phy.c |  120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 109 insertions(+), 11 deletions(-)

diff --git a/kernel/drivers/net/phy/rk630phy.c b/kernel/drivers/net/phy/rk630phy.c
index f0128a5..de76196 100644
--- a/kernel/drivers/net/phy/rk630phy.c
+++ b/kernel/drivers/net/phy/rk630phy.c
@@ -16,6 +16,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mii.h>
 #include <linux/netdevice.h>
+#include <linux/nvmem-consumer.h>
 #include <linux/of_irq.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
@@ -24,6 +25,8 @@
 #define RK630_PHY_ID				0x00441400
 
 /* PAGE 0 */
+#define REG_MMD_ACCESS_CONTROL			0x0d
+#define REG_MMD_ACCESS_DATA_ADDRESS		0x0e
 #define REG_INTERRUPT_STATUS			0X10
 #define REG_INTERRUPT_MASK			0X11
 #define REG_GLOBAL_CONFIGURATION		0X13
@@ -50,6 +53,7 @@
 #define REG_PAGE6_CP_CURRENT			0x17
 #define REG_PAGE6_ADC_OP_BIAS			0x18
 #define REG_PAGE6_RX_DECTOR			0x19
+#define REG_PAGE6_TX_MOS_DRV			0x1B
 #define REG_PAGE6_AFE_PDCW			0x1c
 
 /* PAGE 8 */
@@ -61,15 +65,51 @@
  * Addr: 1 --- RK630@S40
  *       2 --- RV1106@T22
  */
-#define PHY_ADDR_S40 1
-#define PHY_ADDR_T22 2
+#define PHY_ADDR_S40				1
+#define PHY_ADDR_T22				2
+
+#define T22_TX_LEVEL_100M			0x2d
+#define T22_TX_LEVEL_10M			0x32
 
 struct rk630_phy_priv {
 	struct phy_device *phydev;
 	bool ieee;
 	int wol_irq;
 	struct wake_lock wol_wake_lock;
+	int tx_level_100M;
+	int tx_level_10M;
 };
+
+static void rk630_phy_t22_get_tx_level_from_efuse(struct phy_device *phydev)
+{
+	struct rk630_phy_priv *priv = phydev->priv;
+	unsigned int tx_level_100M = T22_TX_LEVEL_100M;
+	unsigned int tx_level_10M = T22_TX_LEVEL_10M;
+	unsigned char *efuse_buf;
+	struct nvmem_cell *cell;
+	size_t len;
+
+	cell = nvmem_cell_get(&phydev->mdio.dev, "txlevel");
+	if (IS_ERR(cell)) {
+		phydev_err(phydev, "failed to get txlevel cell: %ld, use default\n",
+			   PTR_ERR(cell));
+	} else {
+		efuse_buf = nvmem_cell_read(cell, &len);
+		nvmem_cell_put(cell);
+		if (!IS_ERR(efuse_buf)) {
+			if (len == 2 && efuse_buf[0] > 0 && efuse_buf[1] > 0) {
+				tx_level_100M = efuse_buf[1];
+				tx_level_10M = efuse_buf[0];
+			}
+			kfree(efuse_buf);
+		} else {
+			phydev_err(phydev, "failed to get efuse buf, use default\n");
+		}
+	}
+
+	priv->tx_level_100M = tx_level_100M;
+	priv->tx_level_10M = tx_level_10M;
+}
 
 static void rk630_phy_wol_enable(struct phy_device *phydev)
 {
@@ -120,14 +160,33 @@
 	phy_write(phydev, REG_PAGE_SEL, 0x0000);
 }
 
-static void rk630_phy_set_uaps(struct phy_device *phydev)
+static void rk630_phy_set_aps(struct phy_device *phydev, bool enable)
+{
+	u32 value;
+
+	/* Switch to page 1 */
+	phy_write(phydev, REG_PAGE_SEL, 0x0100);
+	value = phy_read(phydev, REG_PAGE1_APS_CTRL);
+	if (enable)
+		value |= BIT(15);
+	else
+		value &= ~BIT(15);
+	phy_write(phydev, REG_PAGE1_APS_CTRL, value);
+	/* Switch to page 0 */
+	phy_write(phydev, REG_PAGE_SEL, 0x0000);
+}
+
+static void rk630_phy_set_uaps(struct phy_device *phydev, bool enable)
 {
 	u32 value;
 
 	/* Switch to page 1 */
 	phy_write(phydev, REG_PAGE_SEL, 0x0100);
 	value = phy_read(phydev, REG_PAGE1_UAPS_CONFIGURE);
-	value |= BIT(15);
+	if (enable)
+		value |= BIT(15);
+	else
+		value &= ~BIT(15);
 	phy_write(phydev, REG_PAGE1_UAPS_CONFIGURE, value);
 	/* Switch to page 0 */
 	phy_write(phydev, REG_PAGE_SEL, 0x0000);
@@ -164,8 +223,12 @@
 
 static void rk630_phy_t22_config_init(struct phy_device *phydev)
 {
+	struct rk630_phy_priv *priv = phydev->priv;
+
 	/* Switch to page 1 */
 	phy_write(phydev, REG_PAGE_SEL, 0x0100);
+	/* Enable offset clock */
+	phy_write(phydev, 0x10, 0xfbfe);
 	/* Disable APS */
 	phy_write(phydev, REG_PAGE1_APS_CTRL, 0x4824);
 	/* Switch to page 2 */
@@ -180,8 +243,13 @@
 	phy_write(phydev, REG_PAGE6_GAIN_ANONTROL, 0x0400);
 	/* PHYAFE EQ optimization */
 	phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, 0x1088);
+
+	if (priv->tx_level_100M <= 0 || priv->tx_level_10M <= 0)
+		rk630_phy_t22_get_tx_level_from_efuse(phydev);
+
 	/* PHYAFE TX optimization */
-	phy_write(phydev, REG_PAGE6_AFE_DRIVER2, 0x3030);
+	phy_write(phydev, REG_PAGE6_AFE_DRIVER2,
+		  (priv->tx_level_100M << 8) | priv->tx_level_10M);
 	/* PHYAFE CP current optimization */
 	phy_write(phydev, REG_PAGE6_CP_CURRENT, 0x0575);
 	/* ADC OP BIAS optimization */
@@ -190,14 +258,24 @@
 	phy_write(phydev, REG_PAGE6_RX_DECTOR, 0x0408);
 	/* PHYAFE PDCW optimization */
 	phy_write(phydev, REG_PAGE6_AFE_PDCW, 0x8880);
+	/* Add PHY Tx mos drive, reduce power noise/jitter */
+	phy_write(phydev, REG_PAGE6_TX_MOS_DRV, 0x888e);
 
 	/* Switch to page 8 */
 	phy_write(phydev, REG_PAGE_SEL, 0x0800);
 	/* Disable auto-cal */
 	phy_write(phydev, REG_PAGE8_AUTO_CAL, 0x0844);
+	/* Reatart offset calibration */
+	phy_write(phydev, 0x13, 0xc096);
 
 	/* Switch to page 0 */
 	phy_write(phydev, REG_PAGE_SEL, 0x0000);
+
+	/* Disable eee mode advertised */
+	phy_write(phydev, REG_MMD_ACCESS_CONTROL, 0x0007);
+	phy_write(phydev, REG_MMD_ACCESS_DATA_ADDRESS, 0x003c);
+	phy_write(phydev, REG_MMD_ACCESS_CONTROL, 0x4007);
+	phy_write(phydev, REG_MMD_ACCESS_DATA_ADDRESS, 0x0000);
 }
 
 static int rk630_phy_config_init(struct phy_device *phydev)
@@ -205,9 +283,16 @@
 	switch (phydev->mdio.addr) {
 	case PHY_ADDR_S40:
 		rk630_phy_s40_config_init(phydev);
+		/*
+		 * Ultra Auto-Power Saving Mode (UAPS) is designed to
+		 * save power when cable is not plugged into PHY.
+		 */
+		rk630_phy_set_uaps(phydev, true);
 		break;
 	case PHY_ADDR_T22:
 		rk630_phy_t22_config_init(phydev);
+		rk630_phy_set_aps(phydev, false);
+		rk630_phy_set_uaps(phydev, false);
 		break;
 	default:
 		phydev_err(phydev, "Unsupported address for current phy: %d\n",
@@ -216,13 +301,25 @@
 	}
 
 	rk630_phy_ieee_set(phydev, true);
-	/*
-	 * Ultra Auto-Power Saving Mode (UAPS) is designed to
-	 * save power when cable is not plugged into PHY.
-	 */
-	rk630_phy_set_uaps(phydev);
 
 	return 0;
+}
+
+static void rk630_link_change_notify(struct phy_device *phydev)
+{
+	unsigned int val;
+
+	if (phydev->state == PHY_RUNNING || phydev->state == PHY_NOLINK) {
+		/* Switch to page 6 */
+		phy_write(phydev, REG_PAGE_SEL, 0x0600);
+		val = phy_read(phydev, REG_PAGE6_AFE_TX_CTRL);
+		val &= ~GENMASK(14, 13);
+		if (phydev->speed == SPEED_10 && phydev->link)
+			val |= BIT(13);
+		phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, val);
+		/* Switch to page 0 */
+		phy_write(phydev, REG_PAGE_SEL, 0x0000);
+	}
 }
 
 static irqreturn_t rk630_wol_irq_thread(int irq, void *dev_id)
@@ -310,6 +407,7 @@
 	.name			= "RK630 PHY",
 	.features		= PHY_BASIC_FEATURES,
 	.flags			= 0,
+	.link_change_notify	= rk630_link_change_notify,
 	.probe			= rk630_phy_probe,
 	.remove			= rk630_phy_remove,
 	.soft_reset		= genphy_soft_reset,
@@ -326,7 +424,7 @@
 	{ }
 };
 
-MODULE_DEVICE_TABLE(mdio, rockchip_phy_tbl);
+MODULE_DEVICE_TABLE(mdio, rk630_phy_tbl);
 
 module_phy_driver(rk630_phy_driver);
 

--
Gitblit v1.6.2