diff options
Diffstat (limited to 'drivers/net/phy')
-rw-r--r-- | drivers/net/phy/Kconfig | 16 | ||||
-rw-r--r-- | drivers/net/phy/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/phy/broadcom.c | 214 | ||||
-rw-r--r-- | drivers/net/phy/cicada.c | 1 | ||||
-rw-r--r-- | drivers/net/phy/davicom.c | 1 | ||||
-rw-r--r-- | drivers/net/phy/et1011c.c | 1 | ||||
-rw-r--r-- | drivers/net/phy/fixed.c | 1 | ||||
-rw-r--r-- | drivers/net/phy/icplus.c | 1 | ||||
-rw-r--r-- | drivers/net/phy/lxt.c | 1 | ||||
-rw-r--r-- | drivers/net/phy/marvell.c | 39 | ||||
-rw-r--r-- | drivers/net/phy/mdio-bitbang.c | 1 | ||||
-rw-r--r-- | drivers/net/phy/mdio-octeon.c | 191 | ||||
-rw-r--r-- | drivers/net/phy/mdio_bus.c | 72 | ||||
-rw-r--r-- | drivers/net/phy/micrel.c | 105 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 23 | ||||
-rw-r--r-- | drivers/net/phy/phy_device.c | 47 | ||||
-rw-r--r-- | drivers/net/phy/qsemi.c | 1 | ||||
-rw-r--r-- | drivers/net/phy/smsc.c | 21 |
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 | ||
91 | config MICREL_PHY | ||
92 | tristate "Driver for Micrel PHYs" | ||
93 | ---help--- | ||
94 | Supports the KSZ9021, VSC8201, KS8001 PHYs. | ||
95 | |||
91 | config FIXED_PHY | 96 | config 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 | ||
123 | config 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 | |||
118 | endif # PHYLIB | 134 | endif # 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 | |||
20 | obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o | 20 | obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o |
21 | obj-$(CONFIG_NATIONAL_PHY) += national.o | 21 | obj-$(CONFIG_NATIONAL_PHY) += national.o |
22 | obj-$(CONFIG_STE10XP) += ste10Xp.o | 22 | obj-$(CONFIG_STE10XP) += ste10Xp.o |
23 | obj-$(CONFIG_MICREL_PHY) += micrel.o | ||
24 | obj-$(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() */ | ||
240 | static int bcm50610_a0_workaround(struct phy_device *phydev) | 245 | static 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 | |||
276 | static 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 | |||
281 | error: | 314 | error: |
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 | |||
324 | static 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 | ||
289 | static int bcm54xx_config_init(struct phy_device *phydev) | 386 | static 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 | ||
334 | error: | 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 | ||
571 | done: | 649 | done: |
572 | /* Disable shadow register access */ | 650 | /* Disable shadow register access */ |
@@ -742,7 +820,7 @@ static struct phy_driver bcm57780_driver = { | |||
742 | }; | 820 | }; |
743 | 821 | ||
744 | static struct phy_driver bcmac131_driver = { | 822 | static 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 | |||
21 | struct octeon_mdiobus { | ||
22 | struct mii_bus *mii_bus; | ||
23 | int unit; | ||
24 | int phy_irq[PHY_MAX_ADDR]; | ||
25 | }; | ||
26 | |||
27 | static 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 | |||
55 | static 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 | |||
88 | static 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; | ||
136 | err_register: | ||
137 | mdiobus_free(bus->mii_bus); | ||
138 | |||
139 | err: | ||
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 | |||
146 | static 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 | |||
160 | static 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 | |||
169 | void octeon_mdiobus_force_mod_depencency(void) | ||
170 | { | ||
171 | /* Let ethernet drivers force us to be loaded. */ | ||
172 | } | ||
173 | EXPORT_SYMBOL(octeon_mdiobus_force_mod_depencency); | ||
174 | |||
175 | static int __init octeon_mdiobus_mod_init(void) | ||
176 | { | ||
177 | return platform_driver_register(&octeon_mdiobus_driver); | ||
178 | } | ||
179 | |||
180 | static void __exit octeon_mdiobus_mod_exit(void) | ||
181 | { | ||
182 | platform_driver_unregister(&octeon_mdiobus_driver); | ||
183 | } | ||
184 | |||
185 | module_init(octeon_mdiobus_mod_init); | ||
186 | module_exit(octeon_mdiobus_mod_exit); | ||
187 | |||
188 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | ||
189 | MODULE_VERSION(DRV_VERSION); | ||
190 | MODULE_AUTHOR("David Daney"); | ||
191 | MODULE_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 | |||
267 | static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) | 269 | static 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 | 300 | static int mdio_bus_suspend(struct device *dev) |
299 | * platform_resume | ||
300 | */ | ||
301 | static 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 | ||
311 | static int mdio_bus_resume(struct device * dev) | 320 | static 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 | |||
333 | no_resume: | ||
334 | if (phydev->attached_dev) | ||
335 | phy_start_machine(phydev, NULL); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static 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 | ||
362 | static 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 | |||
321 | struct bus_type mdio_bus_type = { | 378 | struct 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 | }; |
327 | EXPORT_SYMBOL(mdio_bus_type); | 383 | EXPORT_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 | |||
27 | static int kszphy_config_init(struct phy_device *phydev) | ||
28 | { | ||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | |||
33 | static 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 | |||
45 | static 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 | |||
57 | static 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 | |||
69 | static 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 | |||
85 | err3: | ||
86 | phy_driver_unregister(&vsc8201_driver); | ||
87 | err2: | ||
88 | phy_driver_unregister(&ks8001_driver); | ||
89 | err1: | ||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | static 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 | |||
100 | module_init(ksphy_init); | ||
101 | module_exit(ksphy_exit); | ||
102 | |||
103 | MODULE_DESCRIPTION("Micrel PHY driver"); | ||
104 | MODULE_AUTHOR("David J. Choi"); | ||
105 | MODULE_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 | ||
412 | static void phy_change(struct work_struct *work); | 411 | static void phy_change(struct work_struct *work); |
413 | static 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 | */ |
764 | static void phy_state_machine(struct work_struct *work) | 761 | void 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) | |||
276 | EXPORT_SYMBOL(phy_device_register); | 277 | EXPORT_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 | */ | ||
283 | struct 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 | } | ||
293 | EXPORT_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 | } |
379 | EXPORT_SYMBOL(phy_disconnect); | 396 | EXPORT_SYMBOL(phy_disconnect); |
380 | 397 | ||
398 | int 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 | } |
444 | EXPORT_SYMBOL(phy_attach_direct); | 461 | EXPORT_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 | ||
43 | static int smsc_phy_config_intr(struct phy_device *phydev) | 46 | static 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 | ||
60 | static int smsc_phy_config_init(struct phy_device *phydev) | 63 | static 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 | ||
78 | static int lan911x_config_init(struct phy_device *phydev) | ||
79 | { | ||
80 | return smsc_phy_ack_interrupt(phydev); | ||
81 | } | ||
65 | 82 | ||
66 | static struct phy_driver lan83c185_driver = { | 83 | static 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, |