aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy')
-rw-r--r--drivers/net/phy/Kconfig16
-rw-r--r--drivers/net/phy/Makefile2
-rw-r--r--drivers/net/phy/broadcom.c214
-rw-r--r--drivers/net/phy/cicada.c1
-rw-r--r--drivers/net/phy/davicom.c1
-rw-r--r--drivers/net/phy/et1011c.c1
-rw-r--r--drivers/net/phy/fixed.c1
-rw-r--r--drivers/net/phy/icplus.c1
-rw-r--r--drivers/net/phy/lxt.c1
-rw-r--r--drivers/net/phy/marvell.c39
-rw-r--r--drivers/net/phy/mdio-bitbang.c1
-rw-r--r--drivers/net/phy/mdio-octeon.c191
-rw-r--r--drivers/net/phy/mdio_bus.c72
-rw-r--r--drivers/net/phy/micrel.c105
-rw-r--r--drivers/net/phy/phy.c23
-rw-r--r--drivers/net/phy/phy_device.c47
-rw-r--r--drivers/net/phy/qsemi.c1
-rw-r--r--drivers/net/phy/smsc.c21
18 files changed, 624 insertions, 114 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index d5d8e1c5bc91..a527e37728cd 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -88,6 +88,11 @@ config LSI_ET1011C_PHY
88 ---help--- 88 ---help---
89 Supports the LSI ET1011C PHY. 89 Supports the LSI ET1011C PHY.
90 90
91config MICREL_PHY
92 tristate "Driver for Micrel PHYs"
93 ---help---
94 Supports the KSZ9021, VSC8201, KS8001 PHYs.
95
91config FIXED_PHY 96config FIXED_PHY
92 bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" 97 bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
93 depends on PHYLIB=y 98 depends on PHYLIB=y
@@ -115,4 +120,15 @@ config MDIO_GPIO
115 To compile this driver as a module, choose M here: the module 120 To compile this driver as a module, choose M here: the module
116 will be called mdio-gpio. 121 will be called mdio-gpio.
117 122
123config MDIO_OCTEON
124 tristate "Support for MDIO buses on Octeon SOCs"
125 depends on CPU_CAVIUM_OCTEON
126 default y
127 help
128
129 This module provides a driver for the Octeon MDIO busses.
130 It is required by the Octeon Ethernet device drivers.
131
132 If in doubt, say Y.
133
118endif # PHYLIB 134endif # PHYLIB
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index edfaac48cbd5..13bebab65d02 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -20,3 +20,5 @@ obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
20obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o 20obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
21obj-$(CONFIG_NATIONAL_PHY) += national.o 21obj-$(CONFIG_NATIONAL_PHY) += national.o
22obj-$(CONFIG_STE10XP) += ste10Xp.o 22obj-$(CONFIG_STE10XP) += ste10Xp.o
23obj-$(CONFIG_MICREL_PHY) += micrel.o
24obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index f81e53222230..f482fc4f8cf1 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -16,14 +16,15 @@
16 16
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/phy.h> 18#include <linux/phy.h>
19#include <linux/brcmphy.h>
19 20
20#define PHY_ID_BCM50610 0x0143bd60
21#define PHY_ID_BCM50610M 0x0143bd70
22#define PHY_ID_BCM57780 0x03625d90
23 21
24#define BRCM_PHY_MODEL(phydev) \ 22#define BRCM_PHY_MODEL(phydev) \
25 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask) 23 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
26 24
25#define BRCM_PHY_REV(phydev) \
26 ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
27
27 28
28#define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */ 29#define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */
29#define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */ 30#define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */
@@ -94,22 +95,35 @@
94#define BCM_LED_SRC_OFF 0xe /* Tied high */ 95#define BCM_LED_SRC_OFF 0xe /* Tied high */
95#define BCM_LED_SRC_ON 0xf /* Tied low */ 96#define BCM_LED_SRC_ON 0xf /* Tied low */
96 97
98
97/* 99/*
98 * BCM5482: Shadow registers 100 * BCM5482: Shadow registers
99 * Shadow values go into bits [14:10] of register 0x1c to select a shadow 101 * Shadow values go into bits [14:10] of register 0x1c to select a shadow
100 * register to access. 102 * register to access.
101 */ 103 */
104/* 00101: Spare Control Register 3 */
105#define BCM54XX_SHD_SCR3 0x05
106#define BCM54XX_SHD_SCR3_DEF_CLK125 0x0001
107#define BCM54XX_SHD_SCR3_DLLAPD_DIS 0x0002
108#define BCM54XX_SHD_SCR3_TRDDAPD 0x0004
109
110/* 01010: Auto Power-Down */
111#define BCM54XX_SHD_APD 0x0a
112#define BCM54XX_SHD_APD_EN 0x0020
113
102#define BCM5482_SHD_LEDS1 0x0d /* 01101: LED Selector 1 */ 114#define BCM5482_SHD_LEDS1 0x0d /* 01101: LED Selector 1 */
103 /* LED3 / ~LINKSPD[2] selector */ 115 /* LED3 / ~LINKSPD[2] selector */
104#define BCM5482_SHD_LEDS1_LED3(src) ((src & 0xf) << 4) 116#define BCM5482_SHD_LEDS1_LED3(src) ((src & 0xf) << 4)
105 /* LED1 / ~LINKSPD[1] selector */ 117 /* LED1 / ~LINKSPD[1] selector */
106#define BCM5482_SHD_LEDS1_LED1(src) ((src & 0xf) << 0) 118#define BCM5482_SHD_LEDS1_LED1(src) ((src & 0xf) << 0)
119#define BCM54XX_SHD_RGMII_MODE 0x0b /* 01011: RGMII Mode Selector */
107#define BCM5482_SHD_SSD 0x14 /* 10100: Secondary SerDes control */ 120#define BCM5482_SHD_SSD 0x14 /* 10100: Secondary SerDes control */
108#define BCM5482_SHD_SSD_LEDM 0x0008 /* SSD LED Mode enable */ 121#define BCM5482_SHD_SSD_LEDM 0x0008 /* SSD LED Mode enable */
109#define BCM5482_SHD_SSD_EN 0x0001 /* SSD enable */ 122#define BCM5482_SHD_SSD_EN 0x0001 /* SSD enable */
110#define BCM5482_SHD_MODE 0x1f /* 11111: Mode Control Register */ 123#define BCM5482_SHD_MODE 0x1f /* 11111: Mode Control Register */
111#define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */ 124#define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */
112 125
126
113/* 127/*
114 * EXPANSION SHADOW ACCESS REGISTERS. (PHY REG 0x15, 0x16, and 0x17) 128 * EXPANSION SHADOW ACCESS REGISTERS. (PHY REG 0x15, 0x16, and 0x17)
115 */ 129 */
@@ -138,16 +152,6 @@
138#define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */ 152#define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */
139#define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */ 153#define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */
140 154
141/*
142 * Device flags for PHYs that can be configured for different operating
143 * modes.
144 */
145#define PHY_BCM_FLAGS_VALID 0x80000000
146#define PHY_BCM_FLAGS_INTF_XAUI 0x00000020
147#define PHY_BCM_FLAGS_INTF_SGMII 0x00000010
148#define PHY_BCM_FLAGS_MODE_1000BX 0x00000002
149#define PHY_BCM_FLAGS_MODE_COPPER 0x00000001
150
151 155
152/*****************************************************************************/ 156/*****************************************************************************/
153/* Fast Ethernet Transceiver definitions. */ 157/* Fast Ethernet Transceiver definitions. */
@@ -237,53 +241,146 @@ static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
237 return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val); 241 return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
238} 242}
239 243
244/* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
240static int bcm50610_a0_workaround(struct phy_device *phydev) 245static int bcm50610_a0_workaround(struct phy_device *phydev)
241{ 246{
242 int err; 247 int err;
243 248
244 err = bcm54xx_auxctl_write(phydev,
245 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
246 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
247 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
248 if (err < 0)
249 return err;
250
251 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
252 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ |
253 MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE);
254 if (err < 0)
255 goto error;
256
257 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0, 249 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
258 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN | 250 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
259 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF); 251 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
260 if (err < 0) 252 if (err < 0)
261 goto error; 253 return err;
262 254
263 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3, 255 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
264 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ); 256 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
265 if (err < 0) 257 if (err < 0)
266 goto error; 258 return err;
267 259
268 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, 260 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
269 MII_BCM54XX_EXP_EXP75_VDACCTRL); 261 MII_BCM54XX_EXP_EXP75_VDACCTRL);
270 if (err < 0) 262 if (err < 0)
271 goto error; 263 return err;
272 264
273 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96, 265 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
274 MII_BCM54XX_EXP_EXP96_MYST); 266 MII_BCM54XX_EXP_EXP96_MYST);
275 if (err < 0) 267 if (err < 0)
276 goto error; 268 return err;
277 269
278 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97, 270 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
279 MII_BCM54XX_EXP_EXP97_MYST); 271 MII_BCM54XX_EXP_EXP97_MYST);
280 272
273 return err;
274}
275
276static int bcm54xx_phydsp_config(struct phy_device *phydev)
277{
278 int err, err2;
279
280 /* Enable the SMDSP clock */
281 err = bcm54xx_auxctl_write(phydev,
282 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
283 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
284 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
285 if (err < 0)
286 return err;
287
288 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
289 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
290 /* Clear bit 9 to fix a phy interop issue. */
291 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
292 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
293 if (err < 0)
294 goto error;
295
296 if (phydev->drv->phy_id == PHY_ID_BCM50610) {
297 err = bcm50610_a0_workaround(phydev);
298 if (err < 0)
299 goto error;
300 }
301 }
302
303 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
304 int val;
305
306 val = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75);
307 if (val < 0)
308 goto error;
309
310 val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
311 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, val);
312 }
313
281error: 314error:
282 bcm54xx_auxctl_write(phydev, 315 /* Disable the SMDSP clock */
283 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, 316 err2 = bcm54xx_auxctl_write(phydev,
284 MII_BCM54XX_AUXCTL_ACTL_TX_6DB); 317 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
318 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
285 319
286 return err; 320 /* Return the first error reported. */
321 return err ? err : err2;
322}
323
324static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
325{
326 u32 orig;
327 int val;
328 bool clk125en = true;
329
330 /* Abort if we are using an untested phy. */
331 if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&
332 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&
333 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
334 return;
335
336 val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
337 if (val < 0)
338 return;
339
340 orig = val;
341
342 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
343 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
344 BRCM_PHY_REV(phydev) >= 0x3) {
345 /*
346 * Here, bit 0 _disables_ CLK125 when set.
347 * This bit is set by default.
348 */
349 clk125en = false;
350 } else {
351 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
352 /* Here, bit 0 _enables_ CLK125 when set */
353 val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
354 clk125en = false;
355 }
356 }
357
358 if (clk125en == false ||
359 (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
360 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
361 else
362 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
363
364 if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY)
365 val |= BCM54XX_SHD_SCR3_TRDDAPD;
366
367 if (orig != val)
368 bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
369
370 val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
371 if (val < 0)
372 return;
373
374 orig = val;
375
376 if (clk125en == false ||
377 (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
378 val |= BCM54XX_SHD_APD_EN;
379 else
380 val &= ~BCM54XX_SHD_APD_EN;
381
382 if (orig != val)
383 bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
287} 384}
288 385
289static int bcm54xx_config_init(struct phy_device *phydev) 386static int bcm54xx_config_init(struct phy_device *phydev)
@@ -308,38 +405,17 @@ static int bcm54xx_config_init(struct phy_device *phydev)
308 if (err < 0) 405 if (err < 0)
309 return err; 406 return err;
310 407
311 if (phydev->drv->phy_id == PHY_ID_BCM50610) { 408 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
312 err = bcm50610_a0_workaround(phydev); 409 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
313 if (err < 0) 410 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
314 return err; 411 bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0);
315 }
316
317 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
318 int err2;
319
320 err = bcm54xx_auxctl_write(phydev,
321 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
322 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
323 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
324 if (err < 0)
325 return err;
326
327 reg = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75);
328 if (reg < 0)
329 goto error;
330 412
331 reg |= MII_BCM54XX_EXP_EXP75_CM_OSC; 413 if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
332 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, reg); 414 (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
415 (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
416 bcm54xx_adjust_rxrefclk(phydev);
333 417
334error: 418 bcm54xx_phydsp_config(phydev);
335 err2 = bcm54xx_auxctl_write(phydev,
336 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
337 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
338 if (err)
339 return err;
340 if (err2)
341 return err2;
342 }
343 419
344 return 0; 420 return 0;
345} 421}
@@ -564,9 +640,11 @@ static int brcm_fet_config_init(struct phy_device *phydev)
564 if (err < 0) 640 if (err < 0)
565 goto done; 641 goto done;
566 642
567 /* Enable auto power down */ 643 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
568 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, 644 /* Enable auto power down */
569 MII_BRCM_FET_SHDW_AS2_APDE); 645 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
646 MII_BRCM_FET_SHDW_AS2_APDE);
647 }
570 648
571done: 649done:
572 /* Disable shadow register access */ 650 /* Disable shadow register access */
@@ -742,7 +820,7 @@ static struct phy_driver bcm57780_driver = {
742}; 820};
743 821
744static struct phy_driver bcmac131_driver = { 822static struct phy_driver bcmac131_driver = {
745 .phy_id = 0x0143bc70, 823 .phy_id = PHY_ID_BCMAC131,
746 .phy_id_mask = 0xfffffff0, 824 .phy_id_mask = 0xfffffff0,
747 .name = "Broadcom BCMAC131", 825 .name = "Broadcom BCMAC131",
748 .features = PHY_BASIC_FEATURES | 826 .features = PHY_BASIC_FEATURES |
diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c
index a1bd599c8a5b..92282b31d94b 100644
--- a/drivers/net/phy/cicada.c
+++ b/drivers/net/phy/cicada.c
@@ -17,7 +17,6 @@
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/unistd.h> 19#include <linux/unistd.h>
20#include <linux/slab.h>
21#include <linux/interrupt.h> 20#include <linux/interrupt.h>
22#include <linux/init.h> 21#include <linux/init.h>
23#include <linux/delay.h> 22#include <linux/delay.h>
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index d926168bc780..c722e95853ff 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -17,7 +17,6 @@
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/unistd.h> 19#include <linux/unistd.h>
20#include <linux/slab.h>
21#include <linux/interrupt.h> 20#include <linux/interrupt.h>
22#include <linux/init.h> 21#include <linux/init.h>
23#include <linux/delay.h> 22#include <linux/delay.h>
diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c
index b031fa21f1aa..7712ebeba9bf 100644
--- a/drivers/net/phy/et1011c.c
+++ b/drivers/net/phy/et1011c.c
@@ -17,7 +17,6 @@
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/unistd.h> 19#include <linux/unistd.h>
20#include <linux/slab.h>
21#include <linux/interrupt.h> 20#include <linux/interrupt.h>
22#include <linux/init.h> 21#include <linux/init.h>
23#include <linux/delay.h> 22#include <linux/delay.h>
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index e7070515d2e3..1fa4d73c3cca 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -20,6 +20,7 @@
20#include <linux/phy.h> 20#include <linux/phy.h>
21#include <linux/phy_fixed.h> 21#include <linux/phy_fixed.h>
22#include <linux/err.h> 22#include <linux/err.h>
23#include <linux/slab.h>
23 24
24#define MII_REGS_NUM 29 25#define MII_REGS_NUM 29
25 26
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index af3f1f2a9f87..904208b95d4b 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -13,7 +13,6 @@
13#include <linux/string.h> 13#include <linux/string.h>
14#include <linux/errno.h> 14#include <linux/errno.h>
15#include <linux/unistd.h> 15#include <linux/unistd.h>
16#include <linux/slab.h>
17#include <linux/interrupt.h> 16#include <linux/interrupt.h>
18#include <linux/init.h> 17#include <linux/init.h>
19#include <linux/delay.h> 18#include <linux/delay.h>
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index 4cf3324ba166..057ecaacde6b 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -17,7 +17,6 @@
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/unistd.h> 19#include <linux/unistd.h>
20#include <linux/slab.h>
21#include <linux/interrupt.h> 20#include <linux/interrupt.h>
22#include <linux/init.h> 21#include <linux/init.h>
23#include <linux/delay.h> 22#include <linux/delay.h>
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 6f69b9ba0df8..64c7fbe0a8e7 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -17,7 +17,6 @@
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/unistd.h> 19#include <linux/unistd.h>
20#include <linux/slab.h>
21#include <linux/interrupt.h> 20#include <linux/interrupt.h>
22#include <linux/init.h> 21#include <linux/init.h>
23#include <linux/delay.h> 22#include <linux/delay.h>
@@ -63,6 +62,7 @@
63#define MII_M1111_HWCFG_MODE_COPPER_RGMII 0xb 62#define MII_M1111_HWCFG_MODE_COPPER_RGMII 0xb
64#define MII_M1111_HWCFG_MODE_FIBER_RGMII 0x3 63#define MII_M1111_HWCFG_MODE_FIBER_RGMII 0x3
65#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4 64#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4
65#define MII_M1111_HWCFG_MODE_COPPER_RTBI 0x9
66#define MII_M1111_HWCFG_FIBER_COPPER_AUTO 0x8000 66#define MII_M1111_HWCFG_FIBER_COPPER_AUTO 0x8000
67#define MII_M1111_HWCFG_FIBER_COPPER_RES 0x2000 67#define MII_M1111_HWCFG_FIBER_COPPER_RES 0x2000
68 68
@@ -269,6 +269,43 @@ static int m88e1111_config_init(struct phy_device *phydev)
269 return err; 269 return err;
270 } 270 }
271 271
272 if (phydev->interface == PHY_INTERFACE_MODE_RTBI) {
273 temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
274 if (temp < 0)
275 return temp;
276 temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
277 err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
278 if (err < 0)
279 return err;
280
281 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
282 if (temp < 0)
283 return temp;
284 temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES);
285 temp |= 0x7 | MII_M1111_HWCFG_FIBER_COPPER_AUTO;
286 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
287 if (err < 0)
288 return err;
289
290 /* soft reset */
291 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
292 if (err < 0)
293 return err;
294 do
295 temp = phy_read(phydev, MII_BMCR);
296 while (temp & BMCR_RESET);
297
298 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
299 if (temp < 0)
300 return temp;
301 temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES);
302 temp |= MII_M1111_HWCFG_MODE_COPPER_RTBI | MII_M1111_HWCFG_FIBER_COPPER_AUTO;
303 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
304 if (err < 0)
305 return err;
306 }
307
308
272 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 309 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
273 if (err < 0) 310 if (err < 0)
274 return err; 311 return err;
diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c
index 2576055b350b..19e70d7e27ab 100644
--- a/drivers/net/phy/mdio-bitbang.c
+++ b/drivers/net/phy/mdio-bitbang.c
@@ -19,7 +19,6 @@
19 19
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/mdio-bitbang.h> 21#include <linux/mdio-bitbang.h>
22#include <linux/slab.h>
23#include <linux/types.h> 22#include <linux/types.h>
24#include <linux/delay.h> 23#include <linux/delay.h>
25 24
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
new file mode 100644
index 000000000000..f443d43edd80
--- /dev/null
+++ b/drivers/net/phy/mdio-octeon.c
@@ -0,0 +1,191 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2009 Cavium Networks
7 */
8
9#include <linux/gfp.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/platform_device.h>
13#include <linux/phy.h>
14
15#include <asm/octeon/octeon.h>
16#include <asm/octeon/cvmx-smix-defs.h>
17
18#define DRV_VERSION "1.0"
19#define DRV_DESCRIPTION "Cavium Networks Octeon SMI/MDIO driver"
20
21struct octeon_mdiobus {
22 struct mii_bus *mii_bus;
23 int unit;
24 int phy_irq[PHY_MAX_ADDR];
25};
26
27static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum)
28{
29 struct octeon_mdiobus *p = bus->priv;
30 union cvmx_smix_cmd smi_cmd;
31 union cvmx_smix_rd_dat smi_rd;
32 int timeout = 1000;
33
34 smi_cmd.u64 = 0;
35 smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */
36 smi_cmd.s.phy_adr = phy_id;
37 smi_cmd.s.reg_adr = regnum;
38 cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64);
39
40 do {
41 /*
42 * Wait 1000 clocks so we don't saturate the RSL bus
43 * doing reads.
44 */
45 cvmx_wait(1000);
46 smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(p->unit));
47 } while (smi_rd.s.pending && --timeout);
48
49 if (smi_rd.s.val)
50 return smi_rd.s.dat;
51 else
52 return -EIO;
53}
54
55static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
56 int regnum, u16 val)
57{
58 struct octeon_mdiobus *p = bus->priv;
59 union cvmx_smix_cmd smi_cmd;
60 union cvmx_smix_wr_dat smi_wr;
61 int timeout = 1000;
62
63 smi_wr.u64 = 0;
64 smi_wr.s.dat = val;
65 cvmx_write_csr(CVMX_SMIX_WR_DAT(p->unit), smi_wr.u64);
66
67 smi_cmd.u64 = 0;
68 smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */
69 smi_cmd.s.phy_adr = phy_id;
70 smi_cmd.s.reg_adr = regnum;
71 cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64);
72
73 do {
74 /*
75 * Wait 1000 clocks so we don't saturate the RSL bus
76 * doing reads.
77 */
78 cvmx_wait(1000);
79 smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(p->unit));
80 } while (smi_wr.s.pending && --timeout);
81
82 if (timeout <= 0)
83 return -EIO;
84
85 return 0;
86}
87
88static int __init octeon_mdiobus_probe(struct platform_device *pdev)
89{
90 struct octeon_mdiobus *bus;
91 union cvmx_smix_en smi_en;
92 int i;
93 int err = -ENOENT;
94
95 bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
96 if (!bus)
97 return -ENOMEM;
98
99 /* The platform_device id is our unit number. */
100 bus->unit = pdev->id;
101
102 bus->mii_bus = mdiobus_alloc();
103
104 if (!bus->mii_bus)
105 goto err;
106
107 smi_en.u64 = 0;
108 smi_en.s.en = 1;
109 cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
110
111 /*
112 * Standard Octeon evaluation boards don't support phy
113 * interrupts, we need to poll.
114 */
115 for (i = 0; i < PHY_MAX_ADDR; i++)
116 bus->phy_irq[i] = PHY_POLL;
117
118 bus->mii_bus->priv = bus;
119 bus->mii_bus->irq = bus->phy_irq;
120 bus->mii_bus->name = "mdio-octeon";
121 snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%x", bus->unit);
122 bus->mii_bus->parent = &pdev->dev;
123
124 bus->mii_bus->read = octeon_mdiobus_read;
125 bus->mii_bus->write = octeon_mdiobus_write;
126
127 dev_set_drvdata(&pdev->dev, bus);
128
129 err = mdiobus_register(bus->mii_bus);
130 if (err)
131 goto err_register;
132
133 dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
134
135 return 0;
136err_register:
137 mdiobus_free(bus->mii_bus);
138
139err:
140 devm_kfree(&pdev->dev, bus);
141 smi_en.u64 = 0;
142 cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
143 return err;
144}
145
146static int __exit octeon_mdiobus_remove(struct platform_device *pdev)
147{
148 struct octeon_mdiobus *bus;
149 union cvmx_smix_en smi_en;
150
151 bus = dev_get_drvdata(&pdev->dev);
152
153 mdiobus_unregister(bus->mii_bus);
154 mdiobus_free(bus->mii_bus);
155 smi_en.u64 = 0;
156 cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
157 return 0;
158}
159
160static struct platform_driver octeon_mdiobus_driver = {
161 .driver = {
162 .name = "mdio-octeon",
163 .owner = THIS_MODULE,
164 },
165 .probe = octeon_mdiobus_probe,
166 .remove = __exit_p(octeon_mdiobus_remove),
167};
168
169void octeon_mdiobus_force_mod_depencency(void)
170{
171 /* Let ethernet drivers force us to be loaded. */
172}
173EXPORT_SYMBOL(octeon_mdiobus_force_mod_depencency);
174
175static int __init octeon_mdiobus_mod_init(void)
176{
177 return platform_driver_register(&octeon_mdiobus_driver);
178}
179
180static void __exit octeon_mdiobus_mod_exit(void)
181{
182 platform_driver_unregister(&octeon_mdiobus_driver);
183}
184
185module_init(octeon_mdiobus_mod_init);
186module_exit(octeon_mdiobus_mod_exit);
187
188MODULE_DESCRIPTION(DRV_DESCRIPTION);
189MODULE_VERSION(DRV_VERSION);
190MODULE_AUTHOR("David Daney");
191MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index bd4e8d72dc08..e17b70291bbc 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -264,6 +264,8 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv)
264 (phydev->phy_id & phydrv->phy_id_mask)); 264 (phydev->phy_id & phydrv->phy_id_mask));
265} 265}
266 266
267#ifdef CONFIG_PM
268
267static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) 269static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
268{ 270{
269 struct device_driver *drv = phydev->dev.driver; 271 struct device_driver *drv = phydev->dev.driver;
@@ -295,34 +297,88 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
295 return true; 297 return true;
296} 298}
297 299
298/* Suspend and resume. Copied from platform_suspend and 300static int mdio_bus_suspend(struct device *dev)
299 * platform_resume
300 */
301static int mdio_bus_suspend(struct device * dev, pm_message_t state)
302{ 301{
303 struct phy_driver *phydrv = to_phy_driver(dev->driver); 302 struct phy_driver *phydrv = to_phy_driver(dev->driver);
304 struct phy_device *phydev = to_phy_device(dev); 303 struct phy_device *phydev = to_phy_device(dev);
305 304
305 /*
306 * We must stop the state machine manually, otherwise it stops out of
307 * control, possibly with the phydev->lock held. Upon resume, netdev
308 * may call phy routines that try to grab the same lock, and that may
309 * lead to a deadlock.
310 */
311 if (phydev->attached_dev)
312 phy_stop_machine(phydev);
313
306 if (!mdio_bus_phy_may_suspend(phydev)) 314 if (!mdio_bus_phy_may_suspend(phydev))
307 return 0; 315 return 0;
316
308 return phydrv->suspend(phydev); 317 return phydrv->suspend(phydev);
309} 318}
310 319
311static int mdio_bus_resume(struct device * dev) 320static int mdio_bus_resume(struct device *dev)
312{ 321{
313 struct phy_driver *phydrv = to_phy_driver(dev->driver); 322 struct phy_driver *phydrv = to_phy_driver(dev->driver);
314 struct phy_device *phydev = to_phy_device(dev); 323 struct phy_device *phydev = to_phy_device(dev);
324 int ret;
315 325
316 if (!mdio_bus_phy_may_suspend(phydev)) 326 if (!mdio_bus_phy_may_suspend(phydev))
327 goto no_resume;
328
329 ret = phydrv->resume(phydev);
330 if (ret < 0)
331 return ret;
332
333no_resume:
334 if (phydev->attached_dev)
335 phy_start_machine(phydev, NULL);
336
337 return 0;
338}
339
340static int mdio_bus_restore(struct device *dev)
341{
342 struct phy_device *phydev = to_phy_device(dev);
343 struct net_device *netdev = phydev->attached_dev;
344 int ret;
345
346 if (!netdev)
317 return 0; 347 return 0;
318 return phydrv->resume(phydev); 348
349 ret = phy_init_hw(phydev);
350 if (ret < 0)
351 return ret;
352
353 /* The PHY needs to renegotiate. */
354 phydev->link = 0;
355 phydev->state = PHY_UP;
356
357 phy_start_machine(phydev, NULL);
358
359 return 0;
319} 360}
320 361
362static struct dev_pm_ops mdio_bus_pm_ops = {
363 .suspend = mdio_bus_suspend,
364 .resume = mdio_bus_resume,
365 .freeze = mdio_bus_suspend,
366 .thaw = mdio_bus_resume,
367 .restore = mdio_bus_restore,
368};
369
370#define MDIO_BUS_PM_OPS (&mdio_bus_pm_ops)
371
372#else
373
374#define MDIO_BUS_PM_OPS NULL
375
376#endif /* CONFIG_PM */
377
321struct bus_type mdio_bus_type = { 378struct bus_type mdio_bus_type = {
322 .name = "mdio_bus", 379 .name = "mdio_bus",
323 .match = mdio_bus_match, 380 .match = mdio_bus_match,
324 .suspend = mdio_bus_suspend, 381 .pm = MDIO_BUS_PM_OPS,
325 .resume = mdio_bus_resume,
326}; 382};
327EXPORT_SYMBOL(mdio_bus_type); 383EXPORT_SYMBOL(mdio_bus_type);
328 384
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
new file mode 100644
index 000000000000..e67691dca4ab
--- /dev/null
+++ b/drivers/net/phy/micrel.c
@@ -0,0 +1,105 @@
1/*
2 * drivers/net/phy/micrel.c
3 *
4 * Driver for Micrel PHYs
5 *
6 * Author: David J. Choi
7 *
8 * Copyright (c) 2010 Micrel, Inc.
9 *
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 *
15 * Support : ksz9021 , vsc8201, ks8001
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/phy.h>
21
22#define PHY_ID_KSZ9021 0x00221611
23#define PHY_ID_VSC8201 0x000FC413
24#define PHY_ID_KS8001 0x0022161A
25
26
27static int kszphy_config_init(struct phy_device *phydev)
28{
29 return 0;
30}
31
32
33static struct phy_driver ks8001_driver = {
34 .phy_id = PHY_ID_KS8001,
35 .name = "Micrel KS8001",
36 .phy_id_mask = 0x00fffff0,
37 .features = PHY_BASIC_FEATURES,
38 .flags = PHY_POLL,
39 .config_init = kszphy_config_init,
40 .config_aneg = genphy_config_aneg,
41 .read_status = genphy_read_status,
42 .driver = { .owner = THIS_MODULE,},
43};
44
45static struct phy_driver vsc8201_driver = {
46 .phy_id = PHY_ID_VSC8201,
47 .name = "Micrel VSC8201",
48 .phy_id_mask = 0x00fffff0,
49 .features = PHY_BASIC_FEATURES,
50 .flags = PHY_POLL,
51 .config_init = kszphy_config_init,
52 .config_aneg = genphy_config_aneg,
53 .read_status = genphy_read_status,
54 .driver = { .owner = THIS_MODULE,},
55};
56
57static struct phy_driver ksz9021_driver = {
58 .phy_id = PHY_ID_KSZ9021,
59 .phy_id_mask = 0x000fff10,
60 .name = "Micrel KSZ9021 Gigabit PHY",
61 .features = PHY_GBIT_FEATURES | SUPPORTED_Pause,
62 .flags = PHY_POLL,
63 .config_init = kszphy_config_init,
64 .config_aneg = genphy_config_aneg,
65 .read_status = genphy_read_status,
66 .driver = { .owner = THIS_MODULE, },
67};
68
69static int __init ksphy_init(void)
70{
71 int ret;
72
73 ret = phy_driver_register(&ks8001_driver);
74 if (ret)
75 goto err1;
76 ret = phy_driver_register(&vsc8201_driver);
77 if (ret)
78 goto err2;
79
80 ret = phy_driver_register(&ksz9021_driver);
81 if (ret)
82 goto err3;
83 return 0;
84
85err3:
86 phy_driver_unregister(&vsc8201_driver);
87err2:
88 phy_driver_unregister(&ks8001_driver);
89err1:
90 return ret;
91}
92
93static void __exit ksphy_exit(void)
94{
95 phy_driver_unregister(&ks8001_driver);
96 phy_driver_unregister(&vsc8201_driver);
97 phy_driver_unregister(&ksz9021_driver);
98}
99
100module_init(ksphy_init);
101module_exit(ksphy_exit);
102
103MODULE_DESCRIPTION("Micrel PHY driver");
104MODULE_AUTHOR("David J. Choi");
105MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 6b71b0034060..64be4664ccab 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -19,7 +19,6 @@
19#include <linux/string.h> 19#include <linux/string.h>
20#include <linux/errno.h> 20#include <linux/errno.h>
21#include <linux/unistd.h> 21#include <linux/unistd.h>
22#include <linux/slab.h>
23#include <linux/interrupt.h> 22#include <linux/interrupt.h>
24#include <linux/init.h> 23#include <linux/init.h>
25#include <linux/delay.h> 24#include <linux/delay.h>
@@ -254,12 +253,12 @@ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
254 if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0) 253 if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
255 return -EINVAL; 254 return -EINVAL;
256 255
257 if (cmd->autoneg == AUTONEG_DISABLE 256 if (cmd->autoneg == AUTONEG_DISABLE &&
258 && ((cmd->speed != SPEED_1000 257 ((cmd->speed != SPEED_1000 &&
259 && cmd->speed != SPEED_100 258 cmd->speed != SPEED_100 &&
260 && cmd->speed != SPEED_10) 259 cmd->speed != SPEED_10) ||
261 || (cmd->duplex != DUPLEX_HALF 260 (cmd->duplex != DUPLEX_HALF &&
262 && cmd->duplex != DUPLEX_FULL))) 261 cmd->duplex != DUPLEX_FULL)))
263 return -EINVAL; 262 return -EINVAL;
264 263
265 phydev->autoneg = cmd->autoneg; 264 phydev->autoneg = cmd->autoneg;
@@ -353,9 +352,9 @@ int phy_mii_ioctl(struct phy_device *phydev,
353 352
354 phy_write(phydev, mii_data->reg_num, val); 353 phy_write(phydev, mii_data->reg_num, val);
355 354
356 if (mii_data->reg_num == MII_BMCR 355 if (mii_data->reg_num == MII_BMCR &&
357 && val & BMCR_RESET 356 val & BMCR_RESET &&
358 && phydev->drv->config_init) { 357 phydev->drv->config_init) {
359 phy_scan_fixups(phydev); 358 phy_scan_fixups(phydev);
360 phydev->drv->config_init(phydev); 359 phydev->drv->config_init(phydev);
361 } 360 }
@@ -410,7 +409,6 @@ EXPORT_SYMBOL(phy_start_aneg);
410 409
411 410
412static void phy_change(struct work_struct *work); 411static void phy_change(struct work_struct *work);
413static void phy_state_machine(struct work_struct *work);
414 412
415/** 413/**
416 * phy_start_machine - start PHY state machine tracking 414 * phy_start_machine - start PHY state machine tracking
@@ -430,7 +428,6 @@ void phy_start_machine(struct phy_device *phydev,
430{ 428{
431 phydev->adjust_state = handler; 429 phydev->adjust_state = handler;
432 430
433 INIT_DELAYED_WORK(&phydev->state_queue, phy_state_machine);
434 schedule_delayed_work(&phydev->state_queue, HZ); 431 schedule_delayed_work(&phydev->state_queue, HZ);
435} 432}
436 433
@@ -761,7 +758,7 @@ EXPORT_SYMBOL(phy_start);
761 * phy_state_machine - Handle the state machine 758 * phy_state_machine - Handle the state machine
762 * @work: work_struct that describes the work to be done 759 * @work: work_struct that describes the work to be done
763 */ 760 */
764static void phy_state_machine(struct work_struct *work) 761void phy_state_machine(struct work_struct *work)
765{ 762{
766 struct delayed_work *dwork = to_delayed_work(work); 763 struct delayed_work *dwork = to_delayed_work(work);
767 struct phy_device *phydev = 764 struct phy_device *phydev =
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index b10fedd82143..db1794546c56 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -177,6 +177,7 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
177 dev->state = PHY_DOWN; 177 dev->state = PHY_DOWN;
178 178
179 mutex_init(&dev->lock); 179 mutex_init(&dev->lock);
180 INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
180 181
181 return dev; 182 return dev;
182} 183}
@@ -276,6 +277,22 @@ int phy_device_register(struct phy_device *phydev)
276EXPORT_SYMBOL(phy_device_register); 277EXPORT_SYMBOL(phy_device_register);
277 278
278/** 279/**
280 * phy_find_first - finds the first PHY device on the bus
281 * @bus: the target MII bus
282 */
283struct phy_device *phy_find_first(struct mii_bus *bus)
284{
285 int addr;
286
287 for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
288 if (bus->phy_map[addr])
289 return bus->phy_map[addr];
290 }
291 return NULL;
292}
293EXPORT_SYMBOL(phy_find_first);
294
295/**
279 * phy_prepare_link - prepares the PHY layer to monitor link status 296 * phy_prepare_link - prepares the PHY layer to monitor link status
280 * @phydev: target phy_device struct 297 * @phydev: target phy_device struct
281 * @handler: callback function for link status change notifications 298 * @handler: callback function for link status change notifications
@@ -378,6 +395,20 @@ void phy_disconnect(struct phy_device *phydev)
378} 395}
379EXPORT_SYMBOL(phy_disconnect); 396EXPORT_SYMBOL(phy_disconnect);
380 397
398int phy_init_hw(struct phy_device *phydev)
399{
400 int ret;
401
402 if (!phydev->drv || !phydev->drv->config_init)
403 return 0;
404
405 ret = phy_scan_fixups(phydev);
406 if (ret < 0)
407 return ret;
408
409 return phydev->drv->config_init(phydev);
410}
411
381/** 412/**
382 * phy_attach_direct - attach a network device to a given PHY device pointer 413 * phy_attach_direct - attach a network device to a given PHY device pointer
383 * @dev: network device to attach 414 * @dev: network device to attach
@@ -425,21 +456,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
425 /* Do initial configuration here, now that 456 /* Do initial configuration here, now that
426 * we have certain key parameters 457 * we have certain key parameters
427 * (dev_flags and interface) */ 458 * (dev_flags and interface) */
428 if (phydev->drv->config_init) { 459 return phy_init_hw(phydev);
429 int err;
430
431 err = phy_scan_fixups(phydev);
432
433 if (err < 0)
434 return err;
435
436 err = phydev->drv->config_init(phydev);
437
438 if (err < 0)
439 return err;
440 }
441
442 return 0;
443} 460}
444EXPORT_SYMBOL(phy_attach_direct); 461EXPORT_SYMBOL(phy_attach_direct);
445 462
diff --git a/drivers/net/phy/qsemi.c b/drivers/net/phy/qsemi.c
index 23062d067231..f6e190f73c32 100644
--- a/drivers/net/phy/qsemi.c
+++ b/drivers/net/phy/qsemi.c
@@ -17,7 +17,6 @@
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/unistd.h> 19#include <linux/unistd.h>
20#include <linux/slab.h>
21#include <linux/interrupt.h> 20#include <linux/interrupt.h>
22#include <linux/init.h> 21#include <linux/init.h>
23#include <linux/delay.h> 22#include <linux/delay.h>
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 5123bb954dd7..ed2644a57500 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -25,6 +25,7 @@
25 25
26#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */ 26#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
27#define MII_LAN83C185_IM 30 /* Interrupt Mask */ 27#define MII_LAN83C185_IM 30 /* Interrupt Mask */
28#define MII_LAN83C185_CTRL_STATUS 17 /* Mode/Status Register */
28 29
29#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */ 30#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
30#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */ 31#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
@@ -37,8 +38,10 @@
37#define MII_LAN83C185_ISF_INT_ALL (0x0e) 38#define MII_LAN83C185_ISF_INT_ALL (0x0e)
38 39
39#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \ 40#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \
40 (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4) 41 (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4 | \
42 MII_LAN83C185_ISF_INT7)
41 43
44#define MII_LAN83C185_EDPWRDOWN (1 << 13) /* EDPWRDOWN */
42 45
43static int smsc_phy_config_intr(struct phy_device *phydev) 46static int smsc_phy_config_intr(struct phy_device *phydev)
44{ 47{
@@ -59,9 +62,23 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev)
59 62
60static int smsc_phy_config_init(struct phy_device *phydev) 63static int smsc_phy_config_init(struct phy_device *phydev)
61{ 64{
65 int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
66 if (rc < 0)
67 return rc;
68
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
62 return smsc_phy_ack_interrupt (phydev); 75 return smsc_phy_ack_interrupt (phydev);
63} 76}
64 77
78static int lan911x_config_init(struct phy_device *phydev)
79{
80 return smsc_phy_ack_interrupt(phydev);
81}
65 82
66static struct phy_driver lan83c185_driver = { 83static struct phy_driver lan83c185_driver = {
67 .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */ 84 .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
@@ -147,7 +164,7 @@ static struct phy_driver lan911x_int_driver = {
147 /* basic functions */ 164 /* basic functions */
148 .config_aneg = genphy_config_aneg, 165 .config_aneg = genphy_config_aneg,
149 .read_status = genphy_read_status, 166 .read_status = genphy_read_status,
150 .config_init = smsc_phy_config_init, 167 .config_init = lan911x_config_init,
151 168
152 /* IRQ related */ 169 /* IRQ related */
153 .ack_interrupt = smsc_phy_ack_interrupt, 170 .ack_interrupt = smsc_phy_ack_interrupt,