hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/drivers/net/phy/smsc.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * drivers/net/phy/smsc.c
34 *
....@@ -7,15 +8,11 @@
78 *
89 * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
910 *
10
- * This program is free software; you can redistribute it and/or modify it
11
- * under the terms of the GNU General Public License as published by the
12
- * Free Software Foundation; either version 2 of the License, or (at your
13
- * option) any later version.
14
- *
1511 * Support added for SMSC LAN8187 and LAN8700 by steve.glendinning@shawell.net
1612 *
1713 */
1814
15
+#include <linux/clk.h>
1916 #include <linux/kernel.h>
2017 #include <linux/module.h>
2118 #include <linux/mii.h>
....@@ -24,6 +21,17 @@
2421 #include <linux/phy.h>
2522 #include <linux/netdevice.h>
2623 #include <linux/smscphy.h>
24
+
25
+/* Vendor-specific PHY Definitions */
26
+/* EDPD NLP / crossover time configuration */
27
+#define PHY_EDPD_CONFIG 16
28
+#define PHY_EDPD_CONFIG_EXT_CROSSOVER_ 0x0001
29
+
30
+/* Control/Status Indication Register */
31
+#define SPECIAL_CTRL_STS 27
32
+#define SPECIAL_CTRL_STS_OVRRD_AMDIX_ 0x8000
33
+#define SPECIAL_CTRL_STS_AMDIX_ENABLE_ 0x4000
34
+#define SPECIAL_CTRL_STS_AMDIX_STATE_ 0x2000
2735
2836 struct smsc_hw_stat {
2937 const char *string;
....@@ -37,14 +45,22 @@
3745
3846 struct smsc_phy_priv {
3947 bool energy_enable;
48
+ struct clk *refclk;
4049 };
4150
4251 static int smsc_phy_config_intr(struct phy_device *phydev)
4352 {
44
- int rc = phy_write (phydev, MII_LAN83C185_IM,
45
- ((PHY_INTERRUPT_ENABLED == phydev->interrupts)
46
- ? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS
47
- : 0));
53
+ struct smsc_phy_priv *priv = phydev->priv;
54
+ u16 intmask = 0;
55
+ int rc;
56
+
57
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
58
+ intmask = MII_LAN83C185_ISF_INT4 | MII_LAN83C185_ISF_INT6;
59
+ if (priv->energy_enable)
60
+ intmask |= MII_LAN83C185_ISF_INT7;
61
+ }
62
+
63
+ rc = phy_write(phydev, MII_LAN83C185_IM, intmask);
4864
4965 return rc < 0 ? rc : 0;
5066 }
....@@ -59,19 +75,21 @@
5975 static int smsc_phy_config_init(struct phy_device *phydev)
6076 {
6177 struct smsc_phy_priv *priv = phydev->priv;
78
+ int rc;
6279
63
- int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
80
+ if (!priv->energy_enable)
81
+ return 0;
82
+
83
+ rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
6484
6585 if (rc < 0)
6686 return rc;
6787
68
- if (priv->energy_enable) {
69
- /* Enable energy detect mode for this SMSC Transceivers */
70
- rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
71
- rc | MII_LAN83C185_EDPWRDOWN);
72
- if (rc < 0)
73
- return rc;
74
- }
88
+ /* Enable energy detect mode for this SMSC Transceivers */
89
+ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
90
+ rc | MII_LAN83C185_EDPWRDOWN);
91
+ if (rc < 0)
92
+ return rc;
7593
7694 return smsc_phy_ack_interrupt(phydev);
7795 }
....@@ -100,6 +118,57 @@
100118 return smsc_phy_ack_interrupt(phydev);
101119 }
102120
121
+static int lan87xx_config_aneg(struct phy_device *phydev)
122
+{
123
+ int rc;
124
+ int val;
125
+
126
+ switch (phydev->mdix_ctrl) {
127
+ case ETH_TP_MDI:
128
+ val = SPECIAL_CTRL_STS_OVRRD_AMDIX_;
129
+ break;
130
+ case ETH_TP_MDI_X:
131
+ val = SPECIAL_CTRL_STS_OVRRD_AMDIX_ |
132
+ SPECIAL_CTRL_STS_AMDIX_STATE_;
133
+ break;
134
+ case ETH_TP_MDI_AUTO:
135
+ val = SPECIAL_CTRL_STS_AMDIX_ENABLE_;
136
+ break;
137
+ default:
138
+ return genphy_config_aneg(phydev);
139
+ }
140
+
141
+ rc = phy_read(phydev, SPECIAL_CTRL_STS);
142
+ if (rc < 0)
143
+ return rc;
144
+
145
+ rc &= ~(SPECIAL_CTRL_STS_OVRRD_AMDIX_ |
146
+ SPECIAL_CTRL_STS_AMDIX_ENABLE_ |
147
+ SPECIAL_CTRL_STS_AMDIX_STATE_);
148
+ rc |= val;
149
+ phy_write(phydev, SPECIAL_CTRL_STS, rc);
150
+
151
+ phydev->mdix = phydev->mdix_ctrl;
152
+ return genphy_config_aneg(phydev);
153
+}
154
+
155
+static int lan95xx_config_aneg_ext(struct phy_device *phydev)
156
+{
157
+ int rc;
158
+
159
+ if (phydev->phy_id != 0x0007c0f0) /* not (LAN9500A or LAN9505A) */
160
+ return lan87xx_config_aneg(phydev);
161
+
162
+ /* Extend Manual AutoMDIX timer */
163
+ rc = phy_read(phydev, PHY_EDPD_CONFIG);
164
+ if (rc < 0)
165
+ return rc;
166
+
167
+ rc |= PHY_EDPD_CONFIG_EXT_CROSSOVER_;
168
+ phy_write(phydev, PHY_EDPD_CONFIG, rc);
169
+ return lan87xx_config_aneg(phydev);
170
+}
171
+
103172 /*
104173 * The LAN87xx suffers from rare absence of the ENERGYON-bit when Ethernet cable
105174 * plugs in while LAN87xx is in Energy Detect Power-Down mode. This leads to
....@@ -112,12 +181,13 @@
112181 static int lan87xx_read_status(struct phy_device *phydev)
113182 {
114183 struct smsc_phy_priv *priv = phydev->priv;
184
+ int err;
115185
116
- int err = genphy_read_status(phydev);
186
+ err = genphy_read_status(phydev);
187
+ if (err)
188
+ return err;
117189
118190 if (!phydev->link && priv->energy_enable) {
119
- int i;
120
-
121191 /* Disable EDPD to wake up PHY */
122192 int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
123193 if (rc < 0)
....@@ -128,16 +198,15 @@
128198 if (rc < 0)
129199 return rc;
130200
131
- /* Wait max 640 ms to detect energy */
132
- for (i = 0; i < 64; i++) {
133
- /* Sleep to allow link test pulses to be sent */
134
- msleep(10);
135
- rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
136
- if (rc < 0)
137
- return rc;
138
- if (rc & MII_LAN83C185_ENERGYON)
139
- break;
140
- }
201
+ /* Wait max 640 ms to detect energy and the timeout is not
202
+ * an actual error.
203
+ */
204
+ read_poll_timeout(phy_read, rc,
205
+ rc & MII_LAN83C185_ENERGYON || rc < 0,
206
+ 10000, 640000, true, phydev,
207
+ MII_LAN83C185_CTRL_STATUS);
208
+ if (rc < 0)
209
+ return rc;
141210
142211 /* Re-enable EDPD */
143212 rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
....@@ -192,11 +261,20 @@
192261 data[i] = smsc_get_stat(phydev, i);
193262 }
194263
264
+static void smsc_phy_remove(struct phy_device *phydev)
265
+{
266
+ struct smsc_phy_priv *priv = phydev->priv;
267
+
268
+ clk_disable_unprepare(priv->refclk);
269
+ clk_put(priv->refclk);
270
+}
271
+
195272 static int smsc_phy_probe(struct phy_device *phydev)
196273 {
197274 struct device *dev = &phydev->mdio.dev;
198275 struct device_node *of_node = dev->of_node;
199276 struct smsc_phy_priv *priv;
277
+ int ret;
200278
201279 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
202280 if (!priv)
....@@ -209,6 +287,22 @@
209287
210288 phydev->priv = priv;
211289
290
+ /* Make clk optional to keep DTB backward compatibility. */
291
+ priv->refclk = clk_get_optional(dev, NULL);
292
+ if (IS_ERR(priv->refclk))
293
+ return dev_err_probe(dev, PTR_ERR(priv->refclk),
294
+ "Failed to request clock\n");
295
+
296
+ ret = clk_prepare_enable(priv->refclk);
297
+ if (ret)
298
+ return ret;
299
+
300
+ ret = clk_set_rate(priv->refclk, 50 * 1000 * 1000);
301
+ if (ret) {
302
+ clk_disable_unprepare(priv->refclk);
303
+ return ret;
304
+ }
305
+
212306 return 0;
213307 }
214308
....@@ -218,8 +312,7 @@
218312 .phy_id_mask = 0xfffffff0,
219313 .name = "SMSC LAN83C185",
220314
221
- .features = PHY_BASIC_FEATURES,
222
- .flags = PHY_HAS_INTERRUPT,
315
+ /* PHY_BASIC_FEATURES */
223316
224317 .probe = smsc_phy_probe,
225318
....@@ -238,8 +331,7 @@
238331 .phy_id_mask = 0xfffffff0,
239332 .name = "SMSC LAN8187",
240333
241
- .features = PHY_BASIC_FEATURES,
242
- .flags = PHY_HAS_INTERRUPT,
334
+ /* PHY_BASIC_FEATURES */
243335
244336 .probe = smsc_phy_probe,
245337
....@@ -259,12 +351,14 @@
259351 .suspend = genphy_suspend,
260352 .resume = genphy_resume,
261353 }, {
354
+ /* This covers internal PHY (phy_id: 0x0007C0C3) for
355
+ * LAN9500 (PID: 0x9500), LAN9514 (PID: 0xec00), LAN9505 (PID: 0x9505)
356
+ */
262357 .phy_id = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */
263358 .phy_id_mask = 0xfffffff0,
264359 .name = "SMSC LAN8700",
265360
266
- .features = PHY_BASIC_FEATURES,
267
- .flags = PHY_HAS_INTERRUPT,
361
+ /* PHY_BASIC_FEATURES */
268362
269363 .probe = smsc_phy_probe,
270364
....@@ -272,6 +366,7 @@
272366 .read_status = lan87xx_read_status,
273367 .config_init = smsc_phy_config_init,
274368 .soft_reset = smsc_phy_reset,
369
+ .config_aneg = lan87xx_config_aneg,
275370
276371 /* IRQ related */
277372 .ack_interrupt = smsc_phy_ack_interrupt,
....@@ -289,8 +384,7 @@
289384 .phy_id_mask = 0xfffffff0,
290385 .name = "SMSC LAN911x Internal PHY",
291386
292
- .features = PHY_BASIC_FEATURES,
293
- .flags = PHY_HAS_INTERRUPT,
387
+ /* PHY_BASIC_FEATURES */
294388
295389 .probe = smsc_phy_probe,
296390
....@@ -304,19 +398,23 @@
304398 .suspend = genphy_suspend,
305399 .resume = genphy_resume,
306400 }, {
401
+ /* This covers internal PHY (phy_id: 0x0007C0F0) for
402
+ * LAN9500A (PID: 0x9E00), LAN9505A (PID: 0x9E01)
403
+ */
307404 .phy_id = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */
308405 .phy_id_mask = 0xfffffff0,
309406 .name = "SMSC LAN8710/LAN8720",
310407
311
- .features = PHY_BASIC_FEATURES,
312
- .flags = PHY_HAS_INTERRUPT | PHY_RST_AFTER_CLK_EN,
408
+ /* PHY_BASIC_FEATURES */
313409
314410 .probe = smsc_phy_probe,
411
+ .remove = smsc_phy_remove,
315412
316413 /* basic functions */
317414 .read_status = lan87xx_read_status,
318415 .config_init = smsc_phy_config_init,
319416 .soft_reset = smsc_phy_reset,
417
+ .config_aneg = lan95xx_config_aneg_ext,
320418
321419 /* IRQ related */
322420 .ack_interrupt = smsc_phy_ack_interrupt,
....@@ -334,8 +432,8 @@
334432 .phy_id_mask = 0xfffffff0,
335433 .name = "SMSC LAN8740",
336434
337
- .features = PHY_BASIC_FEATURES,
338
- .flags = PHY_HAS_INTERRUPT,
435
+ /* PHY_BASIC_FEATURES */
436
+ .flags = PHY_RST_AFTER_CLK_EN,
339437
340438 .probe = smsc_phy_probe,
341439