hc
2023-11-06 e3e12f52b214121840b44c91de5b3e5af5d3eb84
kernel/drivers/net/phy/rk630phy.c
....@@ -16,6 +16,7 @@
1616 #include <linux/mfd/core.h>
1717 #include <linux/mii.h>
1818 #include <linux/netdevice.h>
19
+#include <linux/nvmem-consumer.h>
1920 #include <linux/of_irq.h>
2021 #include <linux/phy.h>
2122 #include <linux/platform_device.h>
....@@ -24,6 +25,8 @@
2425 #define RK630_PHY_ID 0x00441400
2526
2627 /* PAGE 0 */
28
+#define REG_MMD_ACCESS_CONTROL 0x0d
29
+#define REG_MMD_ACCESS_DATA_ADDRESS 0x0e
2730 #define REG_INTERRUPT_STATUS 0X10
2831 #define REG_INTERRUPT_MASK 0X11
2932 #define REG_GLOBAL_CONFIGURATION 0X13
....@@ -50,6 +53,7 @@
5053 #define REG_PAGE6_CP_CURRENT 0x17
5154 #define REG_PAGE6_ADC_OP_BIAS 0x18
5255 #define REG_PAGE6_RX_DECTOR 0x19
56
+#define REG_PAGE6_TX_MOS_DRV 0x1B
5357 #define REG_PAGE6_AFE_PDCW 0x1c
5458
5559 /* PAGE 8 */
....@@ -61,15 +65,51 @@
6165 * Addr: 1 --- RK630@S40
6266 * 2 --- RV1106@T22
6367 */
64
-#define PHY_ADDR_S40 1
65
-#define PHY_ADDR_T22 2
68
+#define PHY_ADDR_S40 1
69
+#define PHY_ADDR_T22 2
70
+
71
+#define T22_TX_LEVEL_100M 0x2d
72
+#define T22_TX_LEVEL_10M 0x32
6673
6774 struct rk630_phy_priv {
6875 struct phy_device *phydev;
6976 bool ieee;
7077 int wol_irq;
7178 struct wake_lock wol_wake_lock;
79
+ int tx_level_100M;
80
+ int tx_level_10M;
7281 };
82
+
83
+static void rk630_phy_t22_get_tx_level_from_efuse(struct phy_device *phydev)
84
+{
85
+ struct rk630_phy_priv *priv = phydev->priv;
86
+ unsigned int tx_level_100M = T22_TX_LEVEL_100M;
87
+ unsigned int tx_level_10M = T22_TX_LEVEL_10M;
88
+ unsigned char *efuse_buf;
89
+ struct nvmem_cell *cell;
90
+ size_t len;
91
+
92
+ cell = nvmem_cell_get(&phydev->mdio.dev, "txlevel");
93
+ if (IS_ERR(cell)) {
94
+ phydev_err(phydev, "failed to get txlevel cell: %ld, use default\n",
95
+ PTR_ERR(cell));
96
+ } else {
97
+ efuse_buf = nvmem_cell_read(cell, &len);
98
+ nvmem_cell_put(cell);
99
+ if (!IS_ERR(efuse_buf)) {
100
+ if (len == 2 && efuse_buf[0] > 0 && efuse_buf[1] > 0) {
101
+ tx_level_100M = efuse_buf[1];
102
+ tx_level_10M = efuse_buf[0];
103
+ }
104
+ kfree(efuse_buf);
105
+ } else {
106
+ phydev_err(phydev, "failed to get efuse buf, use default\n");
107
+ }
108
+ }
109
+
110
+ priv->tx_level_100M = tx_level_100M;
111
+ priv->tx_level_10M = tx_level_10M;
112
+}
73113
74114 static void rk630_phy_wol_enable(struct phy_device *phydev)
75115 {
....@@ -164,6 +204,8 @@
164204
165205 static void rk630_phy_t22_config_init(struct phy_device *phydev)
166206 {
207
+ struct rk630_phy_priv *priv = phydev->priv;
208
+
167209 /* Switch to page 1 */
168210 phy_write(phydev, REG_PAGE_SEL, 0x0100);
169211 /* Disable APS */
....@@ -180,8 +222,13 @@
180222 phy_write(phydev, REG_PAGE6_GAIN_ANONTROL, 0x0400);
181223 /* PHYAFE EQ optimization */
182224 phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, 0x1088);
225
+
226
+ if (priv->tx_level_100M <= 0 || priv->tx_level_10M <= 0)
227
+ rk630_phy_t22_get_tx_level_from_efuse(phydev);
228
+
183229 /* PHYAFE TX optimization */
184
- phy_write(phydev, REG_PAGE6_AFE_DRIVER2, 0x3030);
230
+ phy_write(phydev, REG_PAGE6_AFE_DRIVER2,
231
+ (priv->tx_level_100M << 8) | priv->tx_level_10M);
185232 /* PHYAFE CP current optimization */
186233 phy_write(phydev, REG_PAGE6_CP_CURRENT, 0x0575);
187234 /* ADC OP BIAS optimization */
....@@ -190,6 +237,8 @@
190237 phy_write(phydev, REG_PAGE6_RX_DECTOR, 0x0408);
191238 /* PHYAFE PDCW optimization */
192239 phy_write(phydev, REG_PAGE6_AFE_PDCW, 0x8880);
240
+ /* Add PHY Tx mos drive, reduce power noise/jitter */
241
+ phy_write(phydev, REG_PAGE6_TX_MOS_DRV, 0x888e);
193242
194243 /* Switch to page 8 */
195244 phy_write(phydev, REG_PAGE_SEL, 0x0800);
....@@ -198,6 +247,12 @@
198247
199248 /* Switch to page 0 */
200249 phy_write(phydev, REG_PAGE_SEL, 0x0000);
250
+
251
+ /* Disable eee mode advertised */
252
+ phy_write(phydev, REG_MMD_ACCESS_CONTROL, 0x0007);
253
+ phy_write(phydev, REG_MMD_ACCESS_DATA_ADDRESS, 0x003c);
254
+ phy_write(phydev, REG_MMD_ACCESS_CONTROL, 0x4007);
255
+ phy_write(phydev, REG_MMD_ACCESS_DATA_ADDRESS, 0x0000);
201256 }
202257
203258 static int rk630_phy_config_init(struct phy_device *phydev)
....@@ -205,6 +260,11 @@
205260 switch (phydev->mdio.addr) {
206261 case PHY_ADDR_S40:
207262 rk630_phy_s40_config_init(phydev);
263
+ /*
264
+ * Ultra Auto-Power Saving Mode (UAPS) is designed to
265
+ * save power when cable is not plugged into PHY.
266
+ */
267
+ rk630_phy_set_uaps(phydev);
208268 break;
209269 case PHY_ADDR_T22:
210270 rk630_phy_t22_config_init(phydev);
....@@ -216,11 +276,6 @@
216276 }
217277
218278 rk630_phy_ieee_set(phydev, true);
219
- /*
220
- * Ultra Auto-Power Saving Mode (UAPS) is designed to
221
- * save power when cable is not plugged into PHY.
222
- */
223
- rk630_phy_set_uaps(phydev);
224279
225280 return 0;
226281 }