hc
2024-09-20 a36159eec6ca17402b0e146b86efaf76568dc353
kernel/drivers/net/phy/motorcomm.c
....@@ -8,9 +8,12 @@
88 #include <linux/kernel.h>
99 #include <linux/module.h>
1010 #include <linux/netdevice.h>
11
+#include <linux/of_device.h>
1112 #include <linux/phy.h>
1213
1314 #define PHY_ID_YT8511 0x0000010a
15
+#define PHY_ID_YT8512 0x00000118
16
+#define PHY_ID_YT8512B 0x00000128
1417 #define PHY_ID_YT8531S 0x4f51e91a
1518 #define PHY_ID_YT8531 0x4f51e91b
1619
....@@ -40,6 +43,33 @@
4043 #define YT8511_DELAY_GE_TX_DIS (0x2 << 4)
4144 #define YT8511_DELAY_FE_TX_EN (0xf << 12)
4245 #define YT8511_DELAY_FE_TX_DIS (0x2 << 12)
46
+
47
+#define YT8512_EXTREG_AFE_PLL 0x50
48
+#define YT8512_EXTREG_EXTEND_COMBO 0x4000
49
+#define YT8512_EXTREG_LED0 0x40c0
50
+#define YT8512_EXTREG_LED1 0x40c3
51
+
52
+#define YT8512_EXTREG_SLEEP_CONTROL1 0x2027
53
+
54
+#define YT_SOFTWARE_RESET 0x8000
55
+
56
+#define YT8512_CONFIG_PLL_REFCLK_SEL_EN 0x0040
57
+#define YT8512_CONTROL1_RMII_EN 0x0001
58
+#define YT8512_LED0_ACT_BLK_IND 0x1000
59
+#define YT8512_LED0_DIS_LED_AN_TRY 0x0001
60
+#define YT8512_LED0_BT_BLK_EN 0x0002
61
+#define YT8512_LED0_HT_BLK_EN 0x0004
62
+#define YT8512_LED0_COL_BLK_EN 0x0008
63
+#define YT8512_LED0_BT_ON_EN 0x0010
64
+#define YT8512_LED1_BT_ON_EN 0x0010
65
+#define YT8512_LED1_TXACT_BLK_EN 0x0100
66
+#define YT8512_LED1_RXACT_BLK_EN 0x0200
67
+#define YT8512_SPEED_MODE 0xc000
68
+#define YT8512_DUPLEX 0x2000
69
+
70
+#define YT8512_SPEED_MODE_BIT 14
71
+#define YT8512_DUPLEX_BIT 13
72
+#define YT8512_EN_SLEEP_SW_BIT 15
4373
4474 /* if system depends on ethernet packet to restore from sleep,
4575 * please define this macro to 1 otherwise, define it to 0.
....@@ -153,16 +183,6 @@
153183 return phy_restore_page(phydev, oldpage, ret);
154184 }
155185
156
-static inline void phy_lock_mdio_bus(struct phy_device *phydev)
157
-{
158
- mutex_lock(&phydev->mdio.bus->mdio_lock);
159
-}
160
-
161
-static inline void phy_unlock_mdio_bus(struct phy_device *phydev)
162
-{
163
- mutex_unlock(&phydev->mdio.bus->mdio_lock);
164
-}
165
-
166186 static u32 ytphy_read_ext(struct phy_device *phydev, u32 regnum)
167187 {
168188 int ret;
....@@ -212,6 +232,150 @@
212232 return ret;
213233
214234 return ret;
235
+}
236
+
237
+static int yt8512_clk_init(struct phy_device *phydev)
238
+{
239
+ struct device_node *node = phydev->mdio.dev.of_node;
240
+ const char *strings = NULL;
241
+ int ret;
242
+ int val;
243
+
244
+ if (node && node->parent && node->parent->parent) {
245
+ ret = of_property_read_string(node->parent->parent,
246
+ "clock_in_out", &strings);
247
+ if (!ret) {
248
+ if (!strcmp(strings, "input"))
249
+ return 0;
250
+ }
251
+ }
252
+
253
+ val = ytphy_read_ext(phydev, YT8512_EXTREG_AFE_PLL);
254
+ if (val < 0)
255
+ return val;
256
+
257
+ val |= YT8512_CONFIG_PLL_REFCLK_SEL_EN;
258
+
259
+ ret = ytphy_write_ext(phydev, YT8512_EXTREG_AFE_PLL, val);
260
+ if (ret < 0)
261
+ return ret;
262
+
263
+ val = ytphy_read_ext(phydev, YT8512_EXTREG_EXTEND_COMBO);
264
+ if (val < 0)
265
+ return val;
266
+
267
+ val |= YT8512_CONTROL1_RMII_EN;
268
+
269
+ ret = ytphy_write_ext(phydev, YT8512_EXTREG_EXTEND_COMBO, val);
270
+ if (ret < 0)
271
+ return ret;
272
+
273
+ val = phy_read(phydev, MII_BMCR);
274
+ if (val < 0)
275
+ return val;
276
+
277
+ val |= YT_SOFTWARE_RESET;
278
+ ret = phy_write(phydev, MII_BMCR, val);
279
+
280
+ return ret;
281
+}
282
+
283
+static int yt8512_led_init(struct phy_device *phydev)
284
+{
285
+ int ret;
286
+ int val;
287
+ int mask;
288
+
289
+ val = ytphy_read_ext(phydev, YT8512_EXTREG_LED0);
290
+ if (val < 0)
291
+ return val;
292
+
293
+ val |= YT8512_LED0_ACT_BLK_IND;
294
+
295
+ mask = YT8512_LED0_DIS_LED_AN_TRY | YT8512_LED0_BT_BLK_EN |
296
+ YT8512_LED0_HT_BLK_EN | YT8512_LED0_COL_BLK_EN |
297
+ YT8512_LED0_BT_ON_EN;
298
+ val &= ~mask;
299
+
300
+ ret = ytphy_write_ext(phydev, YT8512_EXTREG_LED0, val);
301
+ if (ret < 0)
302
+ return ret;
303
+
304
+ val = ytphy_read_ext(phydev, YT8512_EXTREG_LED1);
305
+ if (val < 0)
306
+ return val;
307
+
308
+ val |= YT8512_LED1_BT_ON_EN;
309
+
310
+ mask = YT8512_LED1_TXACT_BLK_EN | YT8512_LED1_RXACT_BLK_EN;
311
+ val &= ~mask;
312
+
313
+ ret = ytphy_write_ext(phydev, YT8512_LED1_BT_ON_EN, val);
314
+
315
+ return ret;
316
+}
317
+
318
+static int yt8512_config_init(struct phy_device *phydev)
319
+{
320
+ int ret;
321
+ int val;
322
+
323
+ ret = yt8512_clk_init(phydev);
324
+ if (ret < 0)
325
+ return ret;
326
+
327
+ ret = yt8512_led_init(phydev);
328
+ if (ret < 0)
329
+ return ret;
330
+
331
+ /* disable auto sleep */
332
+ val = ytphy_read_ext(phydev, YT8512_EXTREG_SLEEP_CONTROL1);
333
+ if (val < 0)
334
+ return val;
335
+
336
+ val &= (~BIT(YT8512_EN_SLEEP_SW_BIT));
337
+
338
+ ret = ytphy_write_ext(phydev, YT8512_EXTREG_SLEEP_CONTROL1, val);
339
+ if (ret < 0)
340
+ return ret;
341
+
342
+ return ret;
343
+}
344
+
345
+static int yt8512_read_status(struct phy_device *phydev)
346
+{
347
+ int ret;
348
+ int val;
349
+ int speed, speed_mode, duplex;
350
+
351
+ ret = genphy_update_link(phydev);
352
+ if (ret)
353
+ return ret;
354
+
355
+ val = phy_read(phydev, REG_PHY_SPEC_STATUS);
356
+ if (val < 0)
357
+ return val;
358
+
359
+ duplex = (val & YT8512_DUPLEX) >> YT8512_DUPLEX_BIT;
360
+ speed_mode = (val & YT8512_SPEED_MODE) >> YT8512_SPEED_MODE_BIT;
361
+ switch (speed_mode) {
362
+ case 0:
363
+ speed = SPEED_10;
364
+ break;
365
+ case 1:
366
+ speed = SPEED_100;
367
+ break;
368
+ case 2:
369
+ case 3:
370
+ default:
371
+ speed = SPEED_UNKNOWN;
372
+ break;
373
+ }
374
+
375
+ phydev->speed = speed;
376
+ phydev->duplex = duplex;
377
+
378
+ return 0;
215379 }
216380
217381 static int yt8521_soft_reset(struct phy_device *phydev)
....@@ -573,7 +737,7 @@
573737
574738 static int yt8531_config_init(struct phy_device *phydev)
575739 {
576
- int ret = 0;
740
+ int ret = 0, val;
577741
578742 #if (YTPHY8531A_XTAL_INIT)
579743 ret = yt8531a_xtal_init(phydev);
....@@ -591,10 +755,17 @@
591755 return ret;
592756
593757 /* RXC, PHY_CLK_OUT and RXData Drive strength:
594
- * Drive strength of RXC = 4, PHY_CLK_OUT = 3, RXD0 = 4 (default)
595
- * If the io voltage is 3.3v, PHY_CLK_OUT = 2, set 0xa010 = 0x9acf
758
+ * Drive strength of RXC = 6, PHY_CLK_OUT = 3, RXD0 = 4 (default 1.8v)
759
+ * If the io voltage is 3.3v, PHY_CLK_OUT = 2, set 0xa010 = 0xdacf
596760 */
597
- ret = ytphy_write_ext(phydev, 0xa010, 0x9bcf);
761
+ ret = ytphy_write_ext(phydev, 0xa010, 0xdbcf);
762
+ if (ret < 0)
763
+ return ret;
764
+
765
+ /* Change 100M default BGS voltage from 0x294c to 0x274c */
766
+ val = ytphy_read_ext(phydev, 0x57);
767
+ val = (val & ~(0xf << 8)) | (7 << 8);
768
+ ret = ytphy_write_ext(phydev, 0x57, val);
598769 if (ret < 0)
599770 return ret;
600771
....@@ -610,6 +781,20 @@
610781 .resume = genphy_resume,
611782 .read_page = yt8511_read_page,
612783 .write_page = yt8511_write_page,
784
+ }, {
785
+ PHY_ID_MATCH_EXACT(PHY_ID_YT8512),
786
+ .name = "YT8512 Ethernet",
787
+ .config_init = yt8512_config_init,
788
+ .read_status = yt8512_read_status,
789
+ .suspend = genphy_suspend,
790
+ .resume = genphy_resume,
791
+ }, {
792
+ PHY_ID_MATCH_EXACT(PHY_ID_YT8512B),
793
+ .name = "YT8512B Ethernet",
794
+ .config_init = yt8512_config_init,
795
+ .read_status = yt8512_read_status,
796
+ .suspend = genphy_suspend,
797
+ .resume = genphy_resume,
613798 }, {
614799 /* same as 8521 */
615800 PHY_ID_MATCH_EXACT(PHY_ID_YT8531S),
....@@ -648,6 +833,8 @@
648833
649834 static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = {
650835 { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) },
836
+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8512) },
837
+ { PHY_ID_MATCH_EXACT(PHY_ID_YT8512B) },
651838 { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) },
652839 { PHY_ID_MATCH_EXACT(PHY_ID_YT8531) },
653840 { /* sentinal */ }