aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2016-06-05 17:41:11 -0400
committerDavid S. Miller <davem@davemloft.net>2016-06-11 01:13:48 -0400
commit112b558d025712c0bbcefa3d07a4433dd3e32d27 (patch)
tree3fe53bc0486c859380d5b51e674cd43e42a097a0
parent0e119b41b7f23e08799fa8b1c9c1360d7da75815 (diff)
NET: PHY: adds driver for Intel XWAY PHY
This adds support for the Intel (former Lantiq) XWAY 11G and 22E PHYs. These PHYs are also named PEF 7061, PEF 7071, PEF 7072. Signed-off-by: John Crispin <john@phrozen.org> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/Kconfig8
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/intel-xway.c376
3 files changed, 385 insertions, 0 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 6dad9a9c356c..37d40c14ee13 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -271,6 +271,14 @@ config MDIO_BCM_IPROC
271 This module provides a driver for the MDIO busses found in the 271 This module provides a driver for the MDIO busses found in the
272 Broadcom iProc SoC's. 272 Broadcom iProc SoC's.
273 273
274config INTEL_XWAY_PHY
275 tristate "Driver for Intel XWAY PHYs"
276 ---help---
277 Supports the Intel XWAY (former Lantiq) 11G and 22E PHYs.
278 These PHYs are marked as standalone chips under the names
279 PEF 7061, PEF 7071 and PEF 7072 or integrated into the Intel
280 SoCs xRX200, xRX300, xRX330, xRX350 and xRX550.
281
274endif # PHYLIB 282endif # PHYLIB
275 283
276config MICREL_KS8995MA 284config MICREL_KS8995MA
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index fcdbb9299fab..c26b651d0971 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -44,3 +44,4 @@ obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o
44obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o 44obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o
45obj-$(CONFIG_MICROCHIP_PHY) += microchip.o 45obj-$(CONFIG_MICROCHIP_PHY) += microchip.o
46obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o 46obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o
47obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o
diff --git a/drivers/net/phy/intel-xway.c b/drivers/net/phy/intel-xway.c
new file mode 100644
index 000000000000..c300ab5587b8
--- /dev/null
+++ b/drivers/net/phy/intel-xway.c
@@ -0,0 +1,376 @@
1/*
2 * Copyright (C) 2012 Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
3 * Copyright (C) 2016 Hauke Mehrtens <hauke@hauke-m.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <linux/mdio.h>
17#include <linux/module.h>
18#include <linux/phy.h>
19#include <linux/of.h>
20
21#define XWAY_MDIO_IMASK 0x19 /* interrupt mask */
22#define XWAY_MDIO_ISTAT 0x1A /* interrupt status */
23
24#define XWAY_MDIO_INIT_WOL BIT(15) /* Wake-On-LAN */
25#define XWAY_MDIO_INIT_MSRE BIT(14)
26#define XWAY_MDIO_INIT_NPRX BIT(13)
27#define XWAY_MDIO_INIT_NPTX BIT(12)
28#define XWAY_MDIO_INIT_ANE BIT(11) /* Auto-Neg error */
29#define XWAY_MDIO_INIT_ANC BIT(10) /* Auto-Neg complete */
30#define XWAY_MDIO_INIT_ADSC BIT(5) /* Link auto-downspeed detect */
31#define XWAY_MDIO_INIT_MPIPC BIT(4)
32#define XWAY_MDIO_INIT_MDIXC BIT(3)
33#define XWAY_MDIO_INIT_DXMC BIT(2) /* Duplex mode change */
34#define XWAY_MDIO_INIT_LSPC BIT(1) /* Link speed change */
35#define XWAY_MDIO_INIT_LSTC BIT(0) /* Link state change */
36#define XWAY_MDIO_INIT_MASK (XWAY_MDIO_INIT_LSTC | \
37 XWAY_MDIO_INIT_ADSC)
38
39#define ADVERTISED_MPD BIT(10) /* Multi-port device */
40
41/* LED Configuration */
42#define XWAY_MMD_LEDCH 0x01E0
43/* Inverse of SCAN Function */
44#define XWAY_MMD_LEDCH_NACS_NONE 0x0000
45#define XWAY_MMD_LEDCH_NACS_LINK 0x0001
46#define XWAY_MMD_LEDCH_NACS_PDOWN 0x0002
47#define XWAY_MMD_LEDCH_NACS_EEE 0x0003
48#define XWAY_MMD_LEDCH_NACS_ANEG 0x0004
49#define XWAY_MMD_LEDCH_NACS_ABIST 0x0005
50#define XWAY_MMD_LEDCH_NACS_CDIAG 0x0006
51#define XWAY_MMD_LEDCH_NACS_TEST 0x0007
52/* Slow Blink Frequency */
53#define XWAY_MMD_LEDCH_SBF_F02HZ 0x0000
54#define XWAY_MMD_LEDCH_SBF_F04HZ 0x0010
55#define XWAY_MMD_LEDCH_SBF_F08HZ 0x0020
56#define XWAY_MMD_LEDCH_SBF_F16HZ 0x0030
57/* Fast Blink Frequency */
58#define XWAY_MMD_LEDCH_FBF_F02HZ 0x0000
59#define XWAY_MMD_LEDCH_FBF_F04HZ 0x0040
60#define XWAY_MMD_LEDCH_FBF_F08HZ 0x0080
61#define XWAY_MMD_LEDCH_FBF_F16HZ 0x00C0
62/* LED Configuration */
63#define XWAY_MMD_LEDCL 0x01E1
64/* Complex Blinking Configuration */
65#define XWAY_MMD_LEDCH_CBLINK_NONE 0x0000
66#define XWAY_MMD_LEDCH_CBLINK_LINK 0x0001
67#define XWAY_MMD_LEDCH_CBLINK_PDOWN 0x0002
68#define XWAY_MMD_LEDCH_CBLINK_EEE 0x0003
69#define XWAY_MMD_LEDCH_CBLINK_ANEG 0x0004
70#define XWAY_MMD_LEDCH_CBLINK_ABIST 0x0005
71#define XWAY_MMD_LEDCH_CBLINK_CDIAG 0x0006
72#define XWAY_MMD_LEDCH_CBLINK_TEST 0x0007
73/* Complex SCAN Configuration */
74#define XWAY_MMD_LEDCH_SCAN_NONE 0x0000
75#define XWAY_MMD_LEDCH_SCAN_LINK 0x0010
76#define XWAY_MMD_LEDCH_SCAN_PDOWN 0x0020
77#define XWAY_MMD_LEDCH_SCAN_EEE 0x0030
78#define XWAY_MMD_LEDCH_SCAN_ANEG 0x0040
79#define XWAY_MMD_LEDCH_SCAN_ABIST 0x0050
80#define XWAY_MMD_LEDCH_SCAN_CDIAG 0x0060
81#define XWAY_MMD_LEDCH_SCAN_TEST 0x0070
82/* Configuration for LED Pin x */
83#define XWAY_MMD_LED0H 0x01E2
84/* Fast Blinking Configuration */
85#define XWAY_MMD_LEDxH_BLINKF_MASK 0x000F
86#define XWAY_MMD_LEDxH_BLINKF_NONE 0x0000
87#define XWAY_MMD_LEDxH_BLINKF_LINK10 0x0001
88#define XWAY_MMD_LEDxH_BLINKF_LINK100 0x0002
89#define XWAY_MMD_LEDxH_BLINKF_LINK10X 0x0003
90#define XWAY_MMD_LEDxH_BLINKF_LINK1000 0x0004
91#define XWAY_MMD_LEDxH_BLINKF_LINK10_0 0x0005
92#define XWAY_MMD_LEDxH_BLINKF_LINK100X 0x0006
93#define XWAY_MMD_LEDxH_BLINKF_LINK10XX 0x0007
94#define XWAY_MMD_LEDxH_BLINKF_PDOWN 0x0008
95#define XWAY_MMD_LEDxH_BLINKF_EEE 0x0009
96#define XWAY_MMD_LEDxH_BLINKF_ANEG 0x000A
97#define XWAY_MMD_LEDxH_BLINKF_ABIST 0x000B
98#define XWAY_MMD_LEDxH_BLINKF_CDIAG 0x000C
99/* Constant On Configuration */
100#define XWAY_MMD_LEDxH_CON_MASK 0x00F0
101#define XWAY_MMD_LEDxH_CON_NONE 0x0000
102#define XWAY_MMD_LEDxH_CON_LINK10 0x0010
103#define XWAY_MMD_LEDxH_CON_LINK100 0x0020
104#define XWAY_MMD_LEDxH_CON_LINK10X 0x0030
105#define XWAY_MMD_LEDxH_CON_LINK1000 0x0040
106#define XWAY_MMD_LEDxH_CON_LINK10_0 0x0050
107#define XWAY_MMD_LEDxH_CON_LINK100X 0x0060
108#define XWAY_MMD_LEDxH_CON_LINK10XX 0x0070
109#define XWAY_MMD_LEDxH_CON_PDOWN 0x0080
110#define XWAY_MMD_LEDxH_CON_EEE 0x0090
111#define XWAY_MMD_LEDxH_CON_ANEG 0x00A0
112#define XWAY_MMD_LEDxH_CON_ABIST 0x00B0
113#define XWAY_MMD_LEDxH_CON_CDIAG 0x00C0
114#define XWAY_MMD_LEDxH_CON_COPPER 0x00D0
115#define XWAY_MMD_LEDxH_CON_FIBER 0x00E0
116/* Configuration for LED Pin x */
117#define XWAY_MMD_LED0L 0x01E3
118/* Pulsing Configuration */
119#define XWAY_MMD_LEDxL_PULSE_MASK 0x000F
120#define XWAY_MMD_LEDxL_PULSE_NONE 0x0000
121#define XWAY_MMD_LEDxL_PULSE_TXACT 0x0001
122#define XWAY_MMD_LEDxL_PULSE_RXACT 0x0002
123#define XWAY_MMD_LEDxL_PULSE_COL 0x0004
124/* Slow Blinking Configuration */
125#define XWAY_MMD_LEDxL_BLINKS_MASK 0x00F0
126#define XWAY_MMD_LEDxL_BLINKS_NONE 0x0000
127#define XWAY_MMD_LEDxL_BLINKS_LINK10 0x0010
128#define XWAY_MMD_LEDxL_BLINKS_LINK100 0x0020
129#define XWAY_MMD_LEDxL_BLINKS_LINK10X 0x0030
130#define XWAY_MMD_LEDxL_BLINKS_LINK1000 0x0040
131#define XWAY_MMD_LEDxL_BLINKS_LINK10_0 0x0050
132#define XWAY_MMD_LEDxL_BLINKS_LINK100X 0x0060
133#define XWAY_MMD_LEDxL_BLINKS_LINK10XX 0x0070
134#define XWAY_MMD_LEDxL_BLINKS_PDOWN 0x0080
135#define XWAY_MMD_LEDxL_BLINKS_EEE 0x0090
136#define XWAY_MMD_LEDxL_BLINKS_ANEG 0x00A0
137#define XWAY_MMD_LEDxL_BLINKS_ABIST 0x00B0
138#define XWAY_MMD_LEDxL_BLINKS_CDIAG 0x00C0
139#define XWAY_MMD_LED1H 0x01E4
140#define XWAY_MMD_LED1L 0x01E5
141#define XWAY_MMD_LED2H 0x01E6
142#define XWAY_MMD_LED2L 0x01E7
143#define XWAY_MMD_LED3H 0x01E8
144#define XWAY_MMD_LED3L 0x01E9
145
146#define PHY_ID_PHY11G_1_3 0x030260D1
147#define PHY_ID_PHY22F_1_3 0x030260E1
148#define PHY_ID_PHY11G_1_4 0xD565A400
149#define PHY_ID_PHY22F_1_4 0xD565A410
150#define PHY_ID_PHY11G_1_5 0xD565A401
151#define PHY_ID_PHY22F_1_5 0xD565A411
152#define PHY_ID_PHY11G_VR9 0xD565A409
153#define PHY_ID_PHY22F_VR9 0xD565A419
154
155static int xway_gphy_config_init(struct phy_device *phydev)
156{
157 int err;
158 u32 ledxh;
159 u32 ledxl;
160
161 /* Mask all interrupts */
162 err = phy_write(phydev, XWAY_MDIO_IMASK, 0);
163 if (err)
164 return err;
165
166 /* Clear all pending interrupts */
167 phy_read(phydev, XWAY_MDIO_ISTAT);
168
169 phy_write_mmd_indirect(phydev, XWAY_MMD_LEDCH, MDIO_MMD_VEND2,
170 XWAY_MMD_LEDCH_NACS_NONE |
171 XWAY_MMD_LEDCH_SBF_F02HZ |
172 XWAY_MMD_LEDCH_FBF_F16HZ);
173 phy_write_mmd_indirect(phydev, XWAY_MMD_LEDCL, MDIO_MMD_VEND2,
174 XWAY_MMD_LEDCH_CBLINK_NONE |
175 XWAY_MMD_LEDCH_SCAN_NONE);
176
177 /**
178 * In most cases only one LED is connected to this phy, so
179 * configure them all to constant on and pulse mode. LED3 is
180 * only available in some packages, leave it in its reset
181 * configuration.
182 */
183 ledxh = XWAY_MMD_LEDxH_BLINKF_NONE | XWAY_MMD_LEDxH_CON_LINK10XX;
184 ledxl = XWAY_MMD_LEDxL_PULSE_TXACT | XWAY_MMD_LEDxL_PULSE_RXACT |
185 XWAY_MMD_LEDxL_BLINKS_NONE;
186 phy_write_mmd_indirect(phydev, XWAY_MMD_LED0H, MDIO_MMD_VEND2, ledxh);
187 phy_write_mmd_indirect(phydev, XWAY_MMD_LED0L, MDIO_MMD_VEND2, ledxl);
188 phy_write_mmd_indirect(phydev, XWAY_MMD_LED1H, MDIO_MMD_VEND2, ledxh);
189 phy_write_mmd_indirect(phydev, XWAY_MMD_LED1L, MDIO_MMD_VEND2, ledxl);
190 phy_write_mmd_indirect(phydev, XWAY_MMD_LED2H, MDIO_MMD_VEND2, ledxh);
191 phy_write_mmd_indirect(phydev, XWAY_MMD_LED2L, MDIO_MMD_VEND2, ledxl);
192
193 return 0;
194}
195
196static int xway_gphy14_config_aneg(struct phy_device *phydev)
197{
198 int reg, err;
199
200 /* Advertise as multi-port device, see IEEE802.3-2002 40.5.1.1 */
201 /* This is a workaround for an errata in rev < 1.5 devices */
202 reg = phy_read(phydev, MII_CTRL1000);
203 reg |= ADVERTISED_MPD;
204 err = phy_write(phydev, MII_CTRL1000, reg);
205 if (err)
206 return err;
207
208 return genphy_config_aneg(phydev);
209}
210
211static int xway_gphy_ack_interrupt(struct phy_device *phydev)
212{
213 int reg;
214
215 reg = phy_read(phydev, XWAY_MDIO_ISTAT);
216 return (reg < 0) ? reg : 0;
217}
218
219static int xway_gphy_did_interrupt(struct phy_device *phydev)
220{
221 int reg;
222
223 reg = phy_read(phydev, XWAY_MDIO_ISTAT);
224 return reg & XWAY_MDIO_INIT_MASK;
225}
226
227static int xway_gphy_config_intr(struct phy_device *phydev)
228{
229 u16 mask = 0;
230
231 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
232 mask = XWAY_MDIO_INIT_MASK;
233
234 return phy_write(phydev, XWAY_MDIO_IMASK, mask);
235}
236
237static struct phy_driver xway_gphy[] = {
238 {
239 .phy_id = PHY_ID_PHY11G_1_3,
240 .phy_id_mask = 0xffffffff,
241 .name = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.3",
242 .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause |
243 SUPPORTED_Asym_Pause),
244 .flags = PHY_HAS_INTERRUPT,
245 .config_init = xway_gphy_config_init,
246 .config_aneg = xway_gphy14_config_aneg,
247 .read_status = genphy_read_status,
248 .ack_interrupt = xway_gphy_ack_interrupt,
249 .did_interrupt = xway_gphy_did_interrupt,
250 .config_intr = xway_gphy_config_intr,
251 .suspend = genphy_suspend,
252 .resume = genphy_resume,
253 }, {
254 .phy_id = PHY_ID_PHY22F_1_3,
255 .phy_id_mask = 0xffffffff,
256 .name = "Intel XWAY PHY22F (PEF 7061) v1.3",
257 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
258 SUPPORTED_Asym_Pause),
259 .flags = PHY_HAS_INTERRUPT,
260 .config_init = xway_gphy_config_init,
261 .config_aneg = xway_gphy14_config_aneg,
262 .read_status = genphy_read_status,
263 .ack_interrupt = xway_gphy_ack_interrupt,
264 .did_interrupt = xway_gphy_did_interrupt,
265 .config_intr = xway_gphy_config_intr,
266 .suspend = genphy_suspend,
267 .resume = genphy_resume,
268 }, {
269 .phy_id = PHY_ID_PHY11G_1_4,
270 .phy_id_mask = 0xffffffff,
271 .name = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.4",
272 .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause |
273 SUPPORTED_Asym_Pause),
274 .flags = PHY_HAS_INTERRUPT,
275 .config_init = xway_gphy_config_init,
276 .config_aneg = xway_gphy14_config_aneg,
277 .read_status = genphy_read_status,
278 .ack_interrupt = xway_gphy_ack_interrupt,
279 .did_interrupt = xway_gphy_did_interrupt,
280 .config_intr = xway_gphy_config_intr,
281 .suspend = genphy_suspend,
282 .resume = genphy_resume,
283 }, {
284 .phy_id = PHY_ID_PHY22F_1_4,
285 .phy_id_mask = 0xffffffff,
286 .name = "Intel XWAY PHY22F (PEF 7061) v1.4",
287 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
288 SUPPORTED_Asym_Pause),
289 .flags = PHY_HAS_INTERRUPT,
290 .config_init = xway_gphy_config_init,
291 .config_aneg = xway_gphy14_config_aneg,
292 .read_status = genphy_read_status,
293 .ack_interrupt = xway_gphy_ack_interrupt,
294 .did_interrupt = xway_gphy_did_interrupt,
295 .config_intr = xway_gphy_config_intr,
296 .suspend = genphy_suspend,
297 .resume = genphy_resume,
298 }, {
299 .phy_id = PHY_ID_PHY11G_1_5,
300 .phy_id_mask = 0xffffffff,
301 .name = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.5 / v1.6",
302 .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause |
303 SUPPORTED_Asym_Pause),
304 .flags = PHY_HAS_INTERRUPT,
305 .config_init = xway_gphy_config_init,
306 .config_aneg = genphy_config_aneg,
307 .read_status = genphy_read_status,
308 .ack_interrupt = xway_gphy_ack_interrupt,
309 .did_interrupt = xway_gphy_did_interrupt,
310 .config_intr = xway_gphy_config_intr,
311 .suspend = genphy_suspend,
312 .resume = genphy_resume,
313 }, {
314 .phy_id = PHY_ID_PHY22F_1_5,
315 .phy_id_mask = 0xffffffff,
316 .name = "Intel XWAY PHY22F (PEF 7061) v1.5 / v1.6",
317 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
318 SUPPORTED_Asym_Pause),
319 .flags = PHY_HAS_INTERRUPT,
320 .config_init = xway_gphy_config_init,
321 .config_aneg = genphy_config_aneg,
322 .read_status = genphy_read_status,
323 .ack_interrupt = xway_gphy_ack_interrupt,
324 .did_interrupt = xway_gphy_did_interrupt,
325 .config_intr = xway_gphy_config_intr,
326 .suspend = genphy_suspend,
327 .resume = genphy_resume,
328 }, {
329 .phy_id = PHY_ID_PHY11G_VR9,
330 .phy_id_mask = 0xffffffff,
331 .name = "Intel XWAY PHY11G (xRX integrated)",
332 .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause |
333 SUPPORTED_Asym_Pause),
334 .flags = PHY_HAS_INTERRUPT,
335 .config_init = xway_gphy_config_init,
336 .config_aneg = genphy_config_aneg,
337 .read_status = genphy_read_status,
338 .ack_interrupt = xway_gphy_ack_interrupt,
339 .did_interrupt = xway_gphy_did_interrupt,
340 .config_intr = xway_gphy_config_intr,
341 .suspend = genphy_suspend,
342 .resume = genphy_resume,
343 }, {
344 .phy_id = PHY_ID_PHY22F_VR9,
345 .phy_id_mask = 0xffffffff,
346 .name = "Intel XWAY PHY22F (xRX integrated)",
347 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
348 SUPPORTED_Asym_Pause),
349 .flags = PHY_HAS_INTERRUPT,
350 .config_init = xway_gphy_config_init,
351 .config_aneg = genphy_config_aneg,
352 .read_status = genphy_read_status,
353 .ack_interrupt = xway_gphy_ack_interrupt,
354 .did_interrupt = xway_gphy_did_interrupt,
355 .config_intr = xway_gphy_config_intr,
356 .suspend = genphy_suspend,
357 .resume = genphy_resume,
358 },
359};
360module_phy_driver(xway_gphy);
361
362static struct mdio_device_id __maybe_unused xway_gphy_tbl[] = {
363 { PHY_ID_PHY11G_1_3, 0xffffffff },
364 { PHY_ID_PHY22F_1_3, 0xffffffff },
365 { PHY_ID_PHY11G_1_4, 0xffffffff },
366 { PHY_ID_PHY22F_1_4, 0xffffffff },
367 { PHY_ID_PHY11G_1_5, 0xffffffff },
368 { PHY_ID_PHY22F_1_5, 0xffffffff },
369 { PHY_ID_PHY11G_VR9, 0xffffffff },
370 { PHY_ID_PHY22F_VR9, 0xffffffff },
371 { }
372};
373MODULE_DEVICE_TABLE(mdio, xway_gphy_tbl);
374
375MODULE_DESCRIPTION("Intel XWAY PHY driver");
376MODULE_LICENSE("GPL");