From 6b79484268879d0a68530147964a793fafac6716 Mon Sep 17 00:00:00 2001
From: Birger Koblitz <git@birger-koblitz.de>
Date: Mon, 10 Jan 2022 18:55:24 +0100
Subject: [PATCH] realtek: Add SerDes access functions for RTL931X

Adds RTL931X SerDes access functions as needed by the Ethernet driver.

Signed-off-by: Birger Koblitz <git@birger-koblitz.de>
---
 .../files-5.10/drivers/net/phy/rtl83xx-phy.c  | 46 +++++++++++++++++++
 .../files-5.10/drivers/net/phy/rtl83xx-phy.h  |  6 +++
 2 files changed, 52 insertions(+)

diff --git a/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c b/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c
index 636cda287b..dbeea98101 100644
--- a/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c
+++ b/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c
@@ -312,6 +312,52 @@ int rtl930x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v)
 	return 0;
 }
 
+int rtl931x_read_sds_phy(int phy_addr, int page, int phy_reg)
+{
+	int i;
+	u32 cmd = phy_addr << 2 | page << 7 | phy_reg << 13 | 1;
+
+	pr_debug("%s: phy_addr(SDS-ID) %d, phy_reg: %d\n", __func__, phy_addr, phy_reg);
+	sw_w32(cmd, RTL931X_SERDES_INDRT_ACCESS_CTRL);
+
+	for (i = 0; i < 100; i++) {
+		if (!(sw_r32(RTL931X_SERDES_INDRT_ACCESS_CTRL) & 0x1))
+			break;
+		mdelay(1);
+	}
+
+	if (i >= 100)
+		return -EIO;
+
+	pr_debug("%s: returning %04x\n", __func__, sw_r32(RTL931X_SERDES_INDRT_DATA_CTRL) & 0xffff);
+	return sw_r32(RTL931X_SERDES_INDRT_DATA_CTRL) & 0xffff;
+}
+
+int rtl931x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v)
+{
+	int i;
+	u32 cmd;
+
+	cmd = phy_addr << 2 | page << 7 | phy_reg << 13;
+	sw_w32(cmd, RTL931X_SERDES_INDRT_ACCESS_CTRL);
+
+	sw_w32(v, RTL931X_SERDES_INDRT_DATA_CTRL);
+		
+	cmd =  sw_r32(RTL931X_SERDES_INDRT_ACCESS_CTRL) | 0x3;
+	sw_w32(cmd, RTL931X_SERDES_INDRT_ACCESS_CTRL);
+
+	for (i = 0; i < 100; i++) {
+		if (!(sw_r32(RTL931X_SERDES_INDRT_ACCESS_CTRL) & 0x1))
+			break;
+		mdelay(1);
+	}
+
+	if (i >= 100)
+		return -EIO;
+
+	return 0;
+}
+
 /*
  * On the RTL838x SoCs, the internal SerDes is accessed through direct access to
  * standard PHY registers, where a 32 bit register holds a 16 bit word as found
diff --git a/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.h b/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.h
index 031ec8a0e9..088f903baf 100644
--- a/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.h
+++ b/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.h
@@ -58,3 +58,9 @@ struct __attribute__ ((__packed__)) fw_header {
 /* Registers of the internal Serdes of the 9300 */
 #define RTL930X_SDS_INDACS_CMD			(0x03B0)
 #define RTL930X_SDS_INDACS_DATA			(0x03B4)
+
+/*Registers of the internal SerDes of the 9310 */
+#define RTL931X_SERDES_INDRT_ACCESS_CTRL	(0x5638)
+#define RTL931X_SERDES_INDRT_DATA_CTRL		(0x563C)
+#define RTL931X_SERDES_MODE_CTRL		(0x13cc)
+#define RTL931X_PS_SERDES_OFF_MODE_CTRL		(0x13f4)
-- 
2.30.2