diff options
-rw-r--r-- | Documentation/networking/phy.txt | 13 | ||||
-rw-r--r-- | drivers/net/au1000_eth.c | 3 | ||||
-rw-r--r-- | drivers/net/fs_enet/fs_enet-main.c | 3 | ||||
-rw-r--r-- | drivers/net/gianfar.c | 39 | ||||
-rw-r--r-- | drivers/net/gianfar.h | 3 | ||||
-rw-r--r-- | drivers/net/phy/phy_device.c | 29 | ||||
-rw-r--r-- | include/linux/phy.h | 26 |
7 files changed, 93 insertions, 23 deletions
diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt index 29ccae409031..0bc95eab1512 100644 --- a/Documentation/networking/phy.txt +++ b/Documentation/networking/phy.txt | |||
@@ -1,7 +1,7 @@ | |||
1 | 1 | ||
2 | ------- | 2 | ------- |
3 | PHY Abstraction Layer | 3 | PHY Abstraction Layer |
4 | (Updated 2005-07-21) | 4 | (Updated 2006-11-30) |
5 | 5 | ||
6 | Purpose | 6 | Purpose |
7 | 7 | ||
@@ -97,11 +97,12 @@ Letting the PHY Abstraction Layer do Everything | |||
97 | 97 | ||
98 | Next, you need to know the device name of the PHY connected to this device. | 98 | Next, you need to know the device name of the PHY connected to this device. |
99 | The name will look something like, "phy0:0", where the first number is the | 99 | The name will look something like, "phy0:0", where the first number is the |
100 | bus id, and the second is the PHY's address on that bus. | 100 | bus id, and the second is the PHY's address on that bus. Typically, |
101 | the bus is responsible for making its ID unique. | ||
101 | 102 | ||
102 | Now, to connect, just call this function: | 103 | Now, to connect, just call this function: |
103 | 104 | ||
104 | phydev = phy_connect(dev, phy_name, &adjust_link, flags); | 105 | phydev = phy_connect(dev, phy_name, &adjust_link, flags, interface); |
105 | 106 | ||
106 | phydev is a pointer to the phy_device structure which represents the PHY. If | 107 | phydev is a pointer to the phy_device structure which represents the PHY. If |
107 | phy_connect is successful, it will return the pointer. dev, here, is the | 108 | phy_connect is successful, it will return the pointer. dev, here, is the |
@@ -115,6 +116,10 @@ Letting the PHY Abstraction Layer do Everything | |||
115 | This is useful if the system has put hardware restrictions on | 116 | This is useful if the system has put hardware restrictions on |
116 | the PHY/controller, of which the PHY needs to be aware. | 117 | the PHY/controller, of which the PHY needs to be aware. |
117 | 118 | ||
119 | interface is a u32 which specifies the connection type used | ||
120 | between the controller and the PHY. Examples are GMII, MII, | ||
121 | RGMII, and SGMII. For a full list, see include/linux/phy.h | ||
122 | |||
118 | Now just make sure that phydev->supported and phydev->advertising have any | 123 | Now just make sure that phydev->supported and phydev->advertising have any |
119 | values pruned from them which don't make sense for your controller (a 10/100 | 124 | values pruned from them which don't make sense for your controller (a 10/100 |
120 | controller may be connected to a gigabit capable PHY, so you would need to | 125 | controller may be connected to a gigabit capable PHY, so you would need to |
@@ -191,7 +196,7 @@ Doing it all yourself | |||
191 | start, or disables then frees them for stop. | 196 | start, or disables then frees them for stop. |
192 | 197 | ||
193 | struct phy_device * phy_attach(struct net_device *dev, const char *phy_id, | 198 | struct phy_device * phy_attach(struct net_device *dev, const char *phy_id, |
194 | u32 flags); | 199 | u32 flags, phy_interface_t interface); |
195 | 200 | ||
196 | Attaches a network device to a particular PHY, binding the PHY to a generic | 201 | Attaches a network device to a particular PHY, binding the PHY to a generic |
197 | driver if none was found during bus initialization. Passes in | 202 | driver if none was found during bus initialization. Passes in |
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 7db3c8af0894..f0b6879a1c7d 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c | |||
@@ -360,7 +360,8 @@ static int mii_probe (struct net_device *dev) | |||
360 | BUG_ON(!phydev); | 360 | BUG_ON(!phydev); |
361 | BUG_ON(phydev->attached_dev); | 361 | BUG_ON(phydev->attached_dev); |
362 | 362 | ||
363 | phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0); | 363 | phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0, |
364 | PHY_INTERFACE_MODE_MII); | ||
364 | 365 | ||
365 | if (IS_ERR(phydev)) { | 366 | if (IS_ERR(phydev)) { |
366 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); | 367 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); |
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index cb3958704a87..889d3a13e95e 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c | |||
@@ -779,7 +779,8 @@ static int fs_init_phy(struct net_device *dev) | |||
779 | fep->oldspeed = 0; | 779 | fep->oldspeed = 0; |
780 | fep->oldduplex = -1; | 780 | fep->oldduplex = -1; |
781 | if(fep->fpi->bus_id) | 781 | if(fep->fpi->bus_id) |
782 | phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0); | 782 | phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0, |
783 | PHY_INTERFACE_MODE_MII); | ||
783 | else { | 784 | else { |
784 | printk("No phy bus ID specified in BSP code\n"); | 785 | printk("No phy bus ID specified in BSP code\n"); |
785 | return -EINVAL; | 786 | return -EINVAL; |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 6bf18c82083d..baa35144134c 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * Author: Andy Fleming | 9 | * Author: Andy Fleming |
10 | * Maintainer: Kumar Gala | 10 | * Maintainer: Kumar Gala |
11 | * | 11 | * |
12 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 12 | * Copyright (c) 2002-2006 Freescale Semiconductor, Inc. |
13 | * | 13 | * |
14 | * This program is free software; you can redistribute it and/or modify it | 14 | * This program is free software; you can redistribute it and/or modify it |
15 | * under the terms of the GNU General Public License as published by the | 15 | * under the terms of the GNU General Public License as published by the |
@@ -398,6 +398,38 @@ static int gfar_remove(struct platform_device *pdev) | |||
398 | } | 398 | } |
399 | 399 | ||
400 | 400 | ||
401 | /* Reads the controller's registers to determine what interface | ||
402 | * connects it to the PHY. | ||
403 | */ | ||
404 | static phy_interface_t gfar_get_interface(struct net_device *dev) | ||
405 | { | ||
406 | struct gfar_private *priv = netdev_priv(dev); | ||
407 | u32 ecntrl = gfar_read(&priv->regs->ecntrl); | ||
408 | |||
409 | if (ecntrl & ECNTRL_SGMII_MODE) | ||
410 | return PHY_INTERFACE_MODE_SGMII; | ||
411 | |||
412 | if (ecntrl & ECNTRL_TBI_MODE) { | ||
413 | if (ecntrl & ECNTRL_REDUCED_MODE) | ||
414 | return PHY_INTERFACE_MODE_RTBI; | ||
415 | else | ||
416 | return PHY_INTERFACE_MODE_TBI; | ||
417 | } | ||
418 | |||
419 | if (ecntrl & ECNTRL_REDUCED_MODE) { | ||
420 | if (ecntrl & ECNTRL_REDUCED_MII_MODE) | ||
421 | return PHY_INTERFACE_MODE_RMII; | ||
422 | else | ||
423 | return PHY_INTERFACE_MODE_RGMII; | ||
424 | } | ||
425 | |||
426 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT) | ||
427 | return PHY_INTERFACE_MODE_GMII; | ||
428 | |||
429 | return PHY_INTERFACE_MODE_MII; | ||
430 | } | ||
431 | |||
432 | |||
401 | /* Initializes driver's PHY state, and attaches to the PHY. | 433 | /* Initializes driver's PHY state, and attaches to the PHY. |
402 | * Returns 0 on success. | 434 | * Returns 0 on success. |
403 | */ | 435 | */ |
@@ -409,6 +441,7 @@ static int init_phy(struct net_device *dev) | |||
409 | SUPPORTED_1000baseT_Full : 0; | 441 | SUPPORTED_1000baseT_Full : 0; |
410 | struct phy_device *phydev; | 442 | struct phy_device *phydev; |
411 | char phy_id[BUS_ID_SIZE]; | 443 | char phy_id[BUS_ID_SIZE]; |
444 | phy_interface_t interface; | ||
412 | 445 | ||
413 | priv->oldlink = 0; | 446 | priv->oldlink = 0; |
414 | priv->oldspeed = 0; | 447 | priv->oldspeed = 0; |
@@ -416,7 +449,9 @@ static int init_phy(struct net_device *dev) | |||
416 | 449 | ||
417 | snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id); | 450 | snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id); |
418 | 451 | ||
419 | phydev = phy_connect(dev, phy_id, &adjust_link, 0); | 452 | interface = gfar_get_interface(dev); |
453 | |||
454 | phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface); | ||
420 | 455 | ||
421 | if (IS_ERR(phydev)) { | 456 | if (IS_ERR(phydev)) { |
422 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); | 457 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); |
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 9e81a50cf2be..39e9e321fcbc 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -160,7 +160,10 @@ extern const char gfar_driver_version[]; | |||
160 | 160 | ||
161 | #define ECNTRL_INIT_SETTINGS 0x00001000 | 161 | #define ECNTRL_INIT_SETTINGS 0x00001000 |
162 | #define ECNTRL_TBI_MODE 0x00000020 | 162 | #define ECNTRL_TBI_MODE 0x00000020 |
163 | #define ECNTRL_REDUCED_MODE 0x00000010 | ||
163 | #define ECNTRL_R100 0x00000008 | 164 | #define ECNTRL_R100 0x00000008 |
165 | #define ECNTRL_REDUCED_MII_MODE 0x00000004 | ||
166 | #define ECNTRL_SGMII_MODE 0x00000002 | ||
164 | 167 | ||
165 | #define MRBLR_INIT_SETTINGS DEFAULT_RX_BUFFER_SIZE | 168 | #define MRBLR_INIT_SETTINGS DEFAULT_RX_BUFFER_SIZE |
166 | 169 | ||
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 2a08b2b62c4c..b01fc70a57db 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -59,6 +59,7 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) | |||
59 | dev->duplex = -1; | 59 | dev->duplex = -1; |
60 | dev->pause = dev->asym_pause = 0; | 60 | dev->pause = dev->asym_pause = 0; |
61 | dev->link = 1; | 61 | dev->link = 1; |
62 | dev->interface = PHY_INTERFACE_MODE_GMII; | ||
62 | 63 | ||
63 | dev->autoneg = AUTONEG_ENABLE; | 64 | dev->autoneg = AUTONEG_ENABLE; |
64 | 65 | ||
@@ -137,11 +138,12 @@ void phy_prepare_link(struct phy_device *phydev, | |||
137 | * the desired functionality. | 138 | * the desired functionality. |
138 | */ | 139 | */ |
139 | struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, | 140 | struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, |
140 | void (*handler)(struct net_device *), u32 flags) | 141 | void (*handler)(struct net_device *), u32 flags, |
142 | u32 interface) | ||
141 | { | 143 | { |
142 | struct phy_device *phydev; | 144 | struct phy_device *phydev; |
143 | 145 | ||
144 | phydev = phy_attach(dev, phy_id, flags); | 146 | phydev = phy_attach(dev, phy_id, flags, interface); |
145 | 147 | ||
146 | if (IS_ERR(phydev)) | 148 | if (IS_ERR(phydev)) |
147 | return phydev; | 149 | return phydev; |
@@ -186,7 +188,7 @@ static int phy_compare_id(struct device *dev, void *data) | |||
186 | } | 188 | } |
187 | 189 | ||
188 | struct phy_device *phy_attach(struct net_device *dev, | 190 | struct phy_device *phy_attach(struct net_device *dev, |
189 | const char *phy_id, u32 flags) | 191 | const char *phy_id, u32 flags, u32 interface) |
190 | { | 192 | { |
191 | struct bus_type *bus = &mdio_bus_type; | 193 | struct bus_type *bus = &mdio_bus_type; |
192 | struct phy_device *phydev; | 194 | struct phy_device *phydev; |
@@ -231,6 +233,20 @@ struct phy_device *phy_attach(struct net_device *dev, | |||
231 | 233 | ||
232 | phydev->dev_flags = flags; | 234 | phydev->dev_flags = flags; |
233 | 235 | ||
236 | phydev->interface = interface; | ||
237 | |||
238 | /* Do initial configuration here, now that | ||
239 | * we have certain key parameters | ||
240 | * (dev_flags and interface) */ | ||
241 | if (phydev->drv->config_init) { | ||
242 | int err; | ||
243 | |||
244 | err = phydev->drv->config_init(phydev); | ||
245 | |||
246 | if (err < 0) | ||
247 | return ERR_PTR(err); | ||
248 | } | ||
249 | |||
234 | return phydev; | 250 | return phydev; |
235 | } | 251 | } |
236 | EXPORT_SYMBOL(phy_attach); | 252 | EXPORT_SYMBOL(phy_attach); |
@@ -612,13 +628,8 @@ static int phy_probe(struct device *dev) | |||
612 | 628 | ||
613 | spin_unlock(&phydev->lock); | 629 | spin_unlock(&phydev->lock); |
614 | 630 | ||
615 | if (err < 0) | ||
616 | return err; | ||
617 | |||
618 | if (phydev->drv->config_init) | ||
619 | err = phydev->drv->config_init(phydev); | ||
620 | |||
621 | return err; | 631 | return err; |
632 | |||
622 | } | 633 | } |
623 | 634 | ||
624 | static int phy_remove(struct device *dev) | 635 | static int phy_remove(struct device *dev) |
diff --git a/include/linux/phy.h b/include/linux/phy.h index ce8bc80b3c86..edd4c88ca7d8 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h | |||
@@ -47,15 +47,26 @@ | |||
47 | #define PHY_HAS_INTERRUPT 0x00000001 | 47 | #define PHY_HAS_INTERRUPT 0x00000001 |
48 | #define PHY_HAS_MAGICANEG 0x00000002 | 48 | #define PHY_HAS_MAGICANEG 0x00000002 |
49 | 49 | ||
50 | /* Interface Mode definitions */ | ||
51 | typedef enum { | ||
52 | PHY_INTERFACE_MODE_MII, | ||
53 | PHY_INTERFACE_MODE_GMII, | ||
54 | PHY_INTERFACE_MODE_SGMII, | ||
55 | PHY_INTERFACE_MODE_TBI, | ||
56 | PHY_INTERFACE_MODE_RMII, | ||
57 | PHY_INTERFACE_MODE_RGMII, | ||
58 | PHY_INTERFACE_MODE_RTBI | ||
59 | } phy_interface_t; | ||
60 | |||
50 | #define MII_BUS_MAX 4 | 61 | #define MII_BUS_MAX 4 |
51 | 62 | ||
52 | 63 | ||
53 | #define PHY_INIT_TIMEOUT 100000 | 64 | #define PHY_INIT_TIMEOUT 100000 |
54 | #define PHY_STATE_TIME 1 | 65 | #define PHY_STATE_TIME 1 |
55 | #define PHY_FORCE_TIMEOUT 10 | 66 | #define PHY_FORCE_TIMEOUT 10 |
56 | #define PHY_AN_TIMEOUT 10 | 67 | #define PHY_AN_TIMEOUT 10 |
57 | 68 | ||
58 | #define PHY_MAX_ADDR 32 | 69 | #define PHY_MAX_ADDR 32 |
59 | 70 | ||
60 | /* Used when trying to connect to a specific phy (mii bus id:phy device id) */ | 71 | /* Used when trying to connect to a specific phy (mii bus id:phy device id) */ |
61 | #define PHY_ID_FMT "%x:%02x" | 72 | #define PHY_ID_FMT "%x:%02x" |
@@ -87,8 +98,8 @@ struct mii_bus { | |||
87 | int *irq; | 98 | int *irq; |
88 | }; | 99 | }; |
89 | 100 | ||
90 | #define PHY_INTERRUPT_DISABLED 0x0 | 101 | #define PHY_INTERRUPT_DISABLED 0x0 |
91 | #define PHY_INTERRUPT_ENABLED 0x80000000 | 102 | #define PHY_INTERRUPT_ENABLED 0x80000000 |
92 | 103 | ||
93 | /* PHY state machine states: | 104 | /* PHY state machine states: |
94 | * | 105 | * |
@@ -230,6 +241,8 @@ struct phy_device { | |||
230 | 241 | ||
231 | u32 dev_flags; | 242 | u32 dev_flags; |
232 | 243 | ||
244 | phy_interface_t interface; | ||
245 | |||
233 | /* Bus address of the PHY (0-32) */ | 246 | /* Bus address of the PHY (0-32) */ |
234 | int addr; | 247 | int addr; |
235 | 248 | ||
@@ -345,9 +358,10 @@ struct phy_device* get_phy_device(struct mii_bus *bus, int addr); | |||
345 | int phy_clear_interrupt(struct phy_device *phydev); | 358 | int phy_clear_interrupt(struct phy_device *phydev); |
346 | int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); | 359 | int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); |
347 | struct phy_device * phy_attach(struct net_device *dev, | 360 | struct phy_device * phy_attach(struct net_device *dev, |
348 | const char *phy_id, u32 flags); | 361 | const char *phy_id, u32 flags, phy_interface_t interface); |
349 | struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, | 362 | struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, |
350 | void (*handler)(struct net_device *), u32 flags); | 363 | void (*handler)(struct net_device *), u32 flags, |
364 | phy_interface_t interface); | ||
351 | void phy_disconnect(struct phy_device *phydev); | 365 | void phy_disconnect(struct phy_device *phydev); |
352 | void phy_detach(struct phy_device *phydev); | 366 | void phy_detach(struct phy_device *phydev); |
353 | void phy_start(struct phy_device *phydev); | 367 | void phy_start(struct phy_device *phydev); |