From e3e12f52b214121840b44c91de5b3e5af5d3eb84 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 06 Nov 2023 03:04:41 +0000
Subject: [PATCH] rk3568 rt init

---
 kernel/drivers/net/phy/rk630phy.c |   71 +++++++++++++++++++++++++++++++----
 1 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/kernel/drivers/net/phy/rk630phy.c b/kernel/drivers/net/phy/rk630phy.c
index f0128a5..327301d 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)
 {
@@ -164,6 +204,8 @@
 
 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);
 	/* Disable APS */
@@ -180,8 +222,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,6 +237,8 @@
 	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);
@@ -198,6 +247,12 @@
 
 	/* 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,6 +260,11 @@
 	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);
 		break;
 	case PHY_ADDR_T22:
 		rk630_phy_t22_config_init(phydev);
@@ -216,11 +276,6 @@
 	}
 
 	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;
 }

--
Gitblit v1.6.2