forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 072de836f53be56a70cecf70b43ae43b7ce17376
kernel/drivers/net/phy/icplus.c
....@@ -1,13 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * Driver for ICPlus PHYs
34 *
45 * Copyright (c) 2007 Freescale Semiconductor, Inc.
5
- *
6
- * This program is free software; you can redistribute it and/or modify it
7
- * under the terms of the GNU General Public License as published by the
8
- * Free Software Foundation; either version 2 of the License, or (at your
9
- * option) any later version.
10
- *
116 */
127 #include <linux/kernel.h>
138 #include <linux/string.h>
....@@ -25,6 +20,7 @@
2520 #include <linux/mii.h>
2621 #include <linux/ethtool.h>
2722 #include <linux/phy.h>
23
+#include <linux/property.h>
2824
2925 #include <asm/io.h>
3026 #include <asm/irq.h>
....@@ -36,14 +32,34 @@
3632
3733 /* IP101A/G - IP1001 */
3834 #define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */
39
-#define IP1001_RXPHASE_SEL (1<<0) /* Add delay on RX_CLK */
40
-#define IP1001_TXPHASE_SEL (1<<1) /* Add delay on TX_CLK */
35
+#define IP1001_RXPHASE_SEL BIT(0) /* Add delay on RX_CLK */
36
+#define IP1001_TXPHASE_SEL BIT(1) /* Add delay on TX_CLK */
4137 #define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */
4238 #define IP1001_APS_ON 11 /* IP1001 APS Mode bit */
43
-#define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */
39
+#define IP101A_G_APS_ON BIT(1) /* IP101A/G APS Mode bit */
4440 #define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */
45
-#define IP101A_G_IRQ_PIN_USED (1<<15) /* INTR pin used */
46
-#define IP101A_G_IRQ_DEFAULT IP101A_G_IRQ_PIN_USED
41
+#define IP101A_G_IRQ_PIN_USED BIT(15) /* INTR pin used */
42
+#define IP101A_G_IRQ_ALL_MASK BIT(11) /* IRQ's inactive */
43
+#define IP101A_G_IRQ_SPEED_CHANGE BIT(2)
44
+#define IP101A_G_IRQ_DUPLEX_CHANGE BIT(1)
45
+#define IP101A_G_IRQ_LINK_CHANGE BIT(0)
46
+
47
+#define IP101G_DIGITAL_IO_SPEC_CTRL 0x1d
48
+#define IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32 BIT(2)
49
+
50
+/* The 32-pin IP101GR package can re-configure the mode of the RXER/INTR_32 pin
51
+ * (pin number 21). The hardware default is RXER (receive error) mode. But it
52
+ * can be configured to interrupt mode manually.
53
+ */
54
+enum ip101gr_sel_intr32 {
55
+ IP101GR_SEL_INTR32_KEEP,
56
+ IP101GR_SEL_INTR32_INTR,
57
+ IP101GR_SEL_INTR32_RXER,
58
+};
59
+
60
+struct ip101a_g_phy_priv {
61
+ enum ip101gr_sel_intr32 sel_intr32;
62
+};
4763
4864 static int ip175c_config_init(struct phy_device *phydev)
4965 {
....@@ -162,26 +178,6 @@
162178 return 0;
163179 }
164180
165
-static int ip101a_g_config_init(struct phy_device *phydev)
166
-{
167
- int c;
168
-
169
- c = ip1xx_reset(phydev);
170
- if (c < 0)
171
- return c;
172
-
173
- /* INTR pin used: speed/link/duplex will cause an interrupt */
174
- c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT);
175
- if (c < 0)
176
- return c;
177
-
178
- /* Enable Auto Power Saving mode */
179
- c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
180
- c |= IP101A_G_APS_ON;
181
-
182
- return phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
183
-}
184
-
185181 static int ip175c_read_status(struct phy_device *phydev)
186182 {
187183 if (phydev->mdio.addr == 4) /* WAN port */
....@@ -201,6 +197,106 @@
201197 return 0;
202198 }
203199
200
+static int ip101a_g_probe(struct phy_device *phydev)
201
+{
202
+ struct device *dev = &phydev->mdio.dev;
203
+ struct ip101a_g_phy_priv *priv;
204
+
205
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
206
+ if (!priv)
207
+ return -ENOMEM;
208
+
209
+ /* Both functions (RX error and interrupt status) are sharing the same
210
+ * pin on the 32-pin IP101GR, so this is an exclusive choice.
211
+ */
212
+ if (device_property_read_bool(dev, "icplus,select-rx-error") &&
213
+ device_property_read_bool(dev, "icplus,select-interrupt")) {
214
+ dev_err(dev,
215
+ "RXER and INTR mode cannot be selected together\n");
216
+ return -EINVAL;
217
+ }
218
+
219
+ if (device_property_read_bool(dev, "icplus,select-rx-error"))
220
+ priv->sel_intr32 = IP101GR_SEL_INTR32_RXER;
221
+ else if (device_property_read_bool(dev, "icplus,select-interrupt"))
222
+ priv->sel_intr32 = IP101GR_SEL_INTR32_INTR;
223
+ else
224
+ priv->sel_intr32 = IP101GR_SEL_INTR32_KEEP;
225
+
226
+ phydev->priv = priv;
227
+
228
+ return 0;
229
+}
230
+
231
+static int ip101a_g_config_init(struct phy_device *phydev)
232
+{
233
+ struct ip101a_g_phy_priv *priv = phydev->priv;
234
+ int err, c;
235
+
236
+ c = ip1xx_reset(phydev);
237
+ if (c < 0)
238
+ return c;
239
+
240
+ /* configure the RXER/INTR_32 pin of the 32-pin IP101GR if needed: */
241
+ switch (priv->sel_intr32) {
242
+ case IP101GR_SEL_INTR32_RXER:
243
+ err = phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
244
+ IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 0);
245
+ if (err < 0)
246
+ return err;
247
+ break;
248
+
249
+ case IP101GR_SEL_INTR32_INTR:
250
+ err = phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
251
+ IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32,
252
+ IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32);
253
+ if (err < 0)
254
+ return err;
255
+ break;
256
+
257
+ default:
258
+ /* Don't touch IP101G_DIGITAL_IO_SPEC_CTRL because it's not
259
+ * documented on IP101A and it's not clear whether this would
260
+ * cause problems.
261
+ * For the 32-pin IP101GR we simply keep the SEL_INTR32
262
+ * configuration as set by the bootloader when not configured
263
+ * to one of the special functions.
264
+ */
265
+ break;
266
+ }
267
+
268
+ /* Enable Auto Power Saving mode */
269
+ c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
270
+ c |= IP101A_G_APS_ON;
271
+
272
+ return phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
273
+}
274
+
275
+static int ip101a_g_config_intr(struct phy_device *phydev)
276
+{
277
+ u16 val;
278
+
279
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
280
+ /* INTR pin used: Speed/link/duplex will cause an interrupt */
281
+ val = IP101A_G_IRQ_PIN_USED;
282
+ else
283
+ val = IP101A_G_IRQ_ALL_MASK;
284
+
285
+ return phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, val);
286
+}
287
+
288
+static int ip101a_g_did_interrupt(struct phy_device *phydev)
289
+{
290
+ int val = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS);
291
+
292
+ if (val < 0)
293
+ return 0;
294
+
295
+ return val & (IP101A_G_IRQ_SPEED_CHANGE |
296
+ IP101A_G_IRQ_DUPLEX_CHANGE |
297
+ IP101A_G_IRQ_LINK_CHANGE);
298
+}
299
+
204300 static int ip101a_g_ack_interrupt(struct phy_device *phydev)
205301 {
206302 int err = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS);
....@@ -215,7 +311,7 @@
215311 .phy_id = 0x02430d80,
216312 .name = "ICPlus IP175C",
217313 .phy_id_mask = 0x0ffffff0,
218
- .features = PHY_BASIC_FEATURES,
314
+ /* PHY_BASIC_FEATURES */
219315 .config_init = &ip175c_config_init,
220316 .config_aneg = &ip175c_config_aneg,
221317 .read_status = &ip175c_read_status,
....@@ -225,7 +321,7 @@
225321 .phy_id = 0x02430d90,
226322 .name = "ICPlus IP1001",
227323 .phy_id_mask = 0x0ffffff0,
228
- .features = PHY_GBIT_FEATURES,
324
+ /* PHY_GBIT_FEATURES */
229325 .config_init = &ip1001_config_init,
230326 .suspend = genphy_suspend,
231327 .resume = genphy_resume,
....@@ -233,8 +329,10 @@
233329 .phy_id = 0x02430c54,
234330 .name = "ICPlus IP101A/G",
235331 .phy_id_mask = 0x0ffffff0,
236
- .features = PHY_BASIC_FEATURES,
237
- .flags = PHY_HAS_INTERRUPT,
332
+ /* PHY_BASIC_FEATURES */
333
+ .probe = ip101a_g_probe,
334
+ .config_intr = ip101a_g_config_intr,
335
+ .did_interrupt = ip101a_g_did_interrupt,
238336 .ack_interrupt = ip101a_g_ack_interrupt,
239337 .config_init = &ip101a_g_config_init,
240338 .suspend = genphy_suspend,