hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
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 {
....@@ -120,14 +160,33 @@
120160 phy_write(phydev, REG_PAGE_SEL, 0x0000);
121161 }
122162
123
-static void rk630_phy_set_uaps(struct phy_device *phydev)
163
+static void rk630_phy_set_aps(struct phy_device *phydev, bool enable)
164
+{
165
+ u32 value;
166
+
167
+ /* Switch to page 1 */
168
+ phy_write(phydev, REG_PAGE_SEL, 0x0100);
169
+ value = phy_read(phydev, REG_PAGE1_APS_CTRL);
170
+ if (enable)
171
+ value |= BIT(15);
172
+ else
173
+ value &= ~BIT(15);
174
+ phy_write(phydev, REG_PAGE1_APS_CTRL, value);
175
+ /* Switch to page 0 */
176
+ phy_write(phydev, REG_PAGE_SEL, 0x0000);
177
+}
178
+
179
+static void rk630_phy_set_uaps(struct phy_device *phydev, bool enable)
124180 {
125181 u32 value;
126182
127183 /* Switch to page 1 */
128184 phy_write(phydev, REG_PAGE_SEL, 0x0100);
129185 value = phy_read(phydev, REG_PAGE1_UAPS_CONFIGURE);
130
- value |= BIT(15);
186
+ if (enable)
187
+ value |= BIT(15);
188
+ else
189
+ value &= ~BIT(15);
131190 phy_write(phydev, REG_PAGE1_UAPS_CONFIGURE, value);
132191 /* Switch to page 0 */
133192 phy_write(phydev, REG_PAGE_SEL, 0x0000);
....@@ -164,8 +223,12 @@
164223
165224 static void rk630_phy_t22_config_init(struct phy_device *phydev)
166225 {
226
+ struct rk630_phy_priv *priv = phydev->priv;
227
+
167228 /* Switch to page 1 */
168229 phy_write(phydev, REG_PAGE_SEL, 0x0100);
230
+ /* Enable offset clock */
231
+ phy_write(phydev, 0x10, 0xfbfe);
169232 /* Disable APS */
170233 phy_write(phydev, REG_PAGE1_APS_CTRL, 0x4824);
171234 /* Switch to page 2 */
....@@ -180,8 +243,13 @@
180243 phy_write(phydev, REG_PAGE6_GAIN_ANONTROL, 0x0400);
181244 /* PHYAFE EQ optimization */
182245 phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, 0x1088);
246
+
247
+ if (priv->tx_level_100M <= 0 || priv->tx_level_10M <= 0)
248
+ rk630_phy_t22_get_tx_level_from_efuse(phydev);
249
+
183250 /* PHYAFE TX optimization */
184
- phy_write(phydev, REG_PAGE6_AFE_DRIVER2, 0x3030);
251
+ phy_write(phydev, REG_PAGE6_AFE_DRIVER2,
252
+ (priv->tx_level_100M << 8) | priv->tx_level_10M);
185253 /* PHYAFE CP current optimization */
186254 phy_write(phydev, REG_PAGE6_CP_CURRENT, 0x0575);
187255 /* ADC OP BIAS optimization */
....@@ -190,14 +258,24 @@
190258 phy_write(phydev, REG_PAGE6_RX_DECTOR, 0x0408);
191259 /* PHYAFE PDCW optimization */
192260 phy_write(phydev, REG_PAGE6_AFE_PDCW, 0x8880);
261
+ /* Add PHY Tx mos drive, reduce power noise/jitter */
262
+ phy_write(phydev, REG_PAGE6_TX_MOS_DRV, 0x888e);
193263
194264 /* Switch to page 8 */
195265 phy_write(phydev, REG_PAGE_SEL, 0x0800);
196266 /* Disable auto-cal */
197267 phy_write(phydev, REG_PAGE8_AUTO_CAL, 0x0844);
268
+ /* Reatart offset calibration */
269
+ phy_write(phydev, 0x13, 0xc096);
198270
199271 /* Switch to page 0 */
200272 phy_write(phydev, REG_PAGE_SEL, 0x0000);
273
+
274
+ /* Disable eee mode advertised */
275
+ phy_write(phydev, REG_MMD_ACCESS_CONTROL, 0x0007);
276
+ phy_write(phydev, REG_MMD_ACCESS_DATA_ADDRESS, 0x003c);
277
+ phy_write(phydev, REG_MMD_ACCESS_CONTROL, 0x4007);
278
+ phy_write(phydev, REG_MMD_ACCESS_DATA_ADDRESS, 0x0000);
201279 }
202280
203281 static int rk630_phy_config_init(struct phy_device *phydev)
....@@ -205,9 +283,16 @@
205283 switch (phydev->mdio.addr) {
206284 case PHY_ADDR_S40:
207285 rk630_phy_s40_config_init(phydev);
286
+ /*
287
+ * Ultra Auto-Power Saving Mode (UAPS) is designed to
288
+ * save power when cable is not plugged into PHY.
289
+ */
290
+ rk630_phy_set_uaps(phydev, true);
208291 break;
209292 case PHY_ADDR_T22:
210293 rk630_phy_t22_config_init(phydev);
294
+ rk630_phy_set_aps(phydev, false);
295
+ rk630_phy_set_uaps(phydev, false);
211296 break;
212297 default:
213298 phydev_err(phydev, "Unsupported address for current phy: %d\n",
....@@ -216,13 +301,25 @@
216301 }
217302
218303 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);
224304
225305 return 0;
306
+}
307
+
308
+static void rk630_link_change_notify(struct phy_device *phydev)
309
+{
310
+ unsigned int val;
311
+
312
+ if (phydev->state == PHY_RUNNING || phydev->state == PHY_NOLINK) {
313
+ /* Switch to page 6 */
314
+ phy_write(phydev, REG_PAGE_SEL, 0x0600);
315
+ val = phy_read(phydev, REG_PAGE6_AFE_TX_CTRL);
316
+ val &= ~GENMASK(14, 13);
317
+ if (phydev->speed == SPEED_10 && phydev->link)
318
+ val |= BIT(13);
319
+ phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, val);
320
+ /* Switch to page 0 */
321
+ phy_write(phydev, REG_PAGE_SEL, 0x0000);
322
+ }
226323 }
227324
228325 static irqreturn_t rk630_wol_irq_thread(int irq, void *dev_id)
....@@ -310,6 +407,7 @@
310407 .name = "RK630 PHY",
311408 .features = PHY_BASIC_FEATURES,
312409 .flags = 0,
410
+ .link_change_notify = rk630_link_change_notify,
313411 .probe = rk630_phy_probe,
314412 .remove = rk630_phy_remove,
315413 .soft_reset = genphy_soft_reset,
....@@ -326,7 +424,7 @@
326424 { }
327425 };
328426
329
-MODULE_DEVICE_TABLE(mdio, rockchip_phy_tbl);
427
+MODULE_DEVICE_TABLE(mdio, rk630_phy_tbl);
330428
331429 module_phy_driver(rk630_phy_driver);
332430