aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-04 14:47:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-04 14:47:58 -0400
commit6ba74014c1ab0e37af7de6f64b4eccbbae3cb9e7 (patch)
tree8f3892fc44f1e403675a6d7e88fda5c70e56ee4c /drivers/net/phy
parent5abd9ccced7a726c817dd6b5b96bc933859138d1 (diff)
parent3ff1c25927e3af61c6bf0e4ed959504058ae4565 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1443 commits) phy/marvell: add 88ec048 support igb: Program MDICNFG register prior to PHY init e1000e: correct MAC-PHY interconnect register offset for 82579 hso: Add new product ID can: Add driver for esd CAN-USB/2 device l2tp: fix export of header file for userspace can-raw: Fix skb_orphan_try handling Revert "net: remove zap_completion_queue" net: cleanup inclusion phy/marvell: add 88e1121 interface mode support u32: negative offset fix net: Fix a typo from "dev" to "ndev" igb: Use irq_synchronize per vector when using MSI-X ixgbevf: fix null pointer dereference due to filter being set for VLAN 0 e1000e: Fix irq_synchronize in MSI-X case e1000e: register pm_qos request on hardware activation ip_fragment: fix subtracting PPPOE_SES_HLEN from mtu twice net: Add getsockopt support for TCP thin-streams cxgb4: update driver version cxgb4: add new PCI IDs ... Manually fix up conflicts in: - drivers/net/e1000e/netdev.c: due to pm_qos registration infrastructure changes - drivers/net/phy/marvell.c: conflict between adding 88ec048 support and cleaning up the IDs - drivers/net/wireless/ipw2x00/ipw2100.c: trivial ipw2100_pm_qos_req conflict (registration change vs marking it static)
Diffstat (limited to 'drivers/net/phy')
-rw-r--r--drivers/net/phy/broadcom.c46
-rw-r--r--drivers/net/phy/icplus.c2
-rw-r--r--drivers/net/phy/marvell.c77
-rw-r--r--drivers/net/phy/mdio-octeon.c6
-rw-r--r--drivers/net/phy/micrel.c167
-rw-r--r--drivers/net/phy/phy.c8
-rw-r--r--drivers/net/phy/phy_device.c2
7 files changed, 270 insertions, 38 deletions
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index cecdbbd549ec..4accd83d3dfe 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -685,7 +685,7 @@ static int brcm_fet_config_intr(struct phy_device *phydev)
685} 685}
686 686
687static struct phy_driver bcm5411_driver = { 687static struct phy_driver bcm5411_driver = {
688 .phy_id = 0x00206070, 688 .phy_id = PHY_ID_BCM5411,
689 .phy_id_mask = 0xfffffff0, 689 .phy_id_mask = 0xfffffff0,
690 .name = "Broadcom BCM5411", 690 .name = "Broadcom BCM5411",
691 .features = PHY_GBIT_FEATURES | 691 .features = PHY_GBIT_FEATURES |
@@ -700,7 +700,7 @@ static struct phy_driver bcm5411_driver = {
700}; 700};
701 701
702static struct phy_driver bcm5421_driver = { 702static struct phy_driver bcm5421_driver = {
703 .phy_id = 0x002060e0, 703 .phy_id = PHY_ID_BCM5421,
704 .phy_id_mask = 0xfffffff0, 704 .phy_id_mask = 0xfffffff0,
705 .name = "Broadcom BCM5421", 705 .name = "Broadcom BCM5421",
706 .features = PHY_GBIT_FEATURES | 706 .features = PHY_GBIT_FEATURES |
@@ -715,7 +715,7 @@ static struct phy_driver bcm5421_driver = {
715}; 715};
716 716
717static struct phy_driver bcm5461_driver = { 717static struct phy_driver bcm5461_driver = {
718 .phy_id = 0x002060c0, 718 .phy_id = PHY_ID_BCM5461,
719 .phy_id_mask = 0xfffffff0, 719 .phy_id_mask = 0xfffffff0,
720 .name = "Broadcom BCM5461", 720 .name = "Broadcom BCM5461",
721 .features = PHY_GBIT_FEATURES | 721 .features = PHY_GBIT_FEATURES |
@@ -730,7 +730,7 @@ static struct phy_driver bcm5461_driver = {
730}; 730};
731 731
732static struct phy_driver bcm5464_driver = { 732static struct phy_driver bcm5464_driver = {
733 .phy_id = 0x002060b0, 733 .phy_id = PHY_ID_BCM5464,
734 .phy_id_mask = 0xfffffff0, 734 .phy_id_mask = 0xfffffff0,
735 .name = "Broadcom BCM5464", 735 .name = "Broadcom BCM5464",
736 .features = PHY_GBIT_FEATURES | 736 .features = PHY_GBIT_FEATURES |
@@ -745,7 +745,7 @@ static struct phy_driver bcm5464_driver = {
745}; 745};
746 746
747static struct phy_driver bcm5481_driver = { 747static struct phy_driver bcm5481_driver = {
748 .phy_id = 0x0143bca0, 748 .phy_id = PHY_ID_BCM5481,
749 .phy_id_mask = 0xfffffff0, 749 .phy_id_mask = 0xfffffff0,
750 .name = "Broadcom BCM5481", 750 .name = "Broadcom BCM5481",
751 .features = PHY_GBIT_FEATURES | 751 .features = PHY_GBIT_FEATURES |
@@ -760,7 +760,7 @@ static struct phy_driver bcm5481_driver = {
760}; 760};
761 761
762static struct phy_driver bcm5482_driver = { 762static struct phy_driver bcm5482_driver = {
763 .phy_id = 0x0143bcb0, 763 .phy_id = PHY_ID_BCM5482,
764 .phy_id_mask = 0xfffffff0, 764 .phy_id_mask = 0xfffffff0,
765 .name = "Broadcom BCM5482", 765 .name = "Broadcom BCM5482",
766 .features = PHY_GBIT_FEATURES | 766 .features = PHY_GBIT_FEATURES |
@@ -834,6 +834,21 @@ static struct phy_driver bcmac131_driver = {
834 .driver = { .owner = THIS_MODULE }, 834 .driver = { .owner = THIS_MODULE },
835}; 835};
836 836
837static struct phy_driver bcm5241_driver = {
838 .phy_id = PHY_ID_BCM5241,
839 .phy_id_mask = 0xfffffff0,
840 .name = "Broadcom BCM5241",
841 .features = PHY_BASIC_FEATURES |
842 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
843 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
844 .config_init = brcm_fet_config_init,
845 .config_aneg = genphy_config_aneg,
846 .read_status = genphy_read_status,
847 .ack_interrupt = brcm_fet_ack_interrupt,
848 .config_intr = brcm_fet_config_intr,
849 .driver = { .owner = THIS_MODULE },
850};
851
837static int __init broadcom_init(void) 852static int __init broadcom_init(void)
838{ 853{
839 int ret; 854 int ret;
@@ -868,8 +883,13 @@ static int __init broadcom_init(void)
868 ret = phy_driver_register(&bcmac131_driver); 883 ret = phy_driver_register(&bcmac131_driver);
869 if (ret) 884 if (ret)
870 goto out_ac131; 885 goto out_ac131;
886 ret = phy_driver_register(&bcm5241_driver);
887 if (ret)
888 goto out_5241;
871 return ret; 889 return ret;
872 890
891out_5241:
892 phy_driver_unregister(&bcmac131_driver);
873out_ac131: 893out_ac131:
874 phy_driver_unregister(&bcm57780_driver); 894 phy_driver_unregister(&bcm57780_driver);
875out_57780: 895out_57780:
@@ -894,6 +914,7 @@ out_5411:
894 914
895static void __exit broadcom_exit(void) 915static void __exit broadcom_exit(void)
896{ 916{
917 phy_driver_unregister(&bcm5241_driver);
897 phy_driver_unregister(&bcmac131_driver); 918 phy_driver_unregister(&bcmac131_driver);
898 phy_driver_unregister(&bcm57780_driver); 919 phy_driver_unregister(&bcm57780_driver);
899 phy_driver_unregister(&bcm50610m_driver); 920 phy_driver_unregister(&bcm50610m_driver);
@@ -910,16 +931,17 @@ module_init(broadcom_init);
910module_exit(broadcom_exit); 931module_exit(broadcom_exit);
911 932
912static struct mdio_device_id broadcom_tbl[] = { 933static struct mdio_device_id broadcom_tbl[] = {
913 { 0x00206070, 0xfffffff0 }, 934 { PHY_ID_BCM5411, 0xfffffff0 },
914 { 0x002060e0, 0xfffffff0 }, 935 { PHY_ID_BCM5421, 0xfffffff0 },
915 { 0x002060c0, 0xfffffff0 }, 936 { PHY_ID_BCM5461, 0xfffffff0 },
916 { 0x002060b0, 0xfffffff0 }, 937 { PHY_ID_BCM5464, 0xfffffff0 },
917 { 0x0143bca0, 0xfffffff0 }, 938 { PHY_ID_BCM5482, 0xfffffff0 },
918 { 0x0143bcb0, 0xfffffff0 }, 939 { PHY_ID_BCM5482, 0xfffffff0 },
919 { PHY_ID_BCM50610, 0xfffffff0 }, 940 { PHY_ID_BCM50610, 0xfffffff0 },
920 { PHY_ID_BCM50610M, 0xfffffff0 }, 941 { PHY_ID_BCM50610M, 0xfffffff0 },
921 { PHY_ID_BCM57780, 0xfffffff0 }, 942 { PHY_ID_BCM57780, 0xfffffff0 },
922 { PHY_ID_BCMAC131, 0xfffffff0 }, 943 { PHY_ID_BCMAC131, 0xfffffff0 },
944 { PHY_ID_BCM5241, 0xfffffff0 },
923 { } 945 { }
924}; 946};
925 947
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index 439adafeacb1..3f2583f18a39 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -116,6 +116,8 @@ static struct phy_driver ip175c_driver = {
116 .config_init = &ip175c_config_init, 116 .config_init = &ip175c_config_init,
117 .config_aneg = &ip175c_config_aneg, 117 .config_aneg = &ip175c_config_aneg,
118 .read_status = &ip175c_read_status, 118 .read_status = &ip175c_read_status,
119 .suspend = genphy_suspend,
120 .resume = genphy_resume,
119 .driver = { .owner = THIS_MODULE,}, 121 .driver = { .owner = THIS_MODULE,},
120}; 122};
121 123
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 5a1bd5db2a93..0101f2bdf400 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -68,6 +68,15 @@
68#define MII_M1111_COPPER 0 68#define MII_M1111_COPPER 0
69#define MII_M1111_FIBER 1 69#define MII_M1111_FIBER 1
70 70
71#define MII_88E1121_PHY_MSCR_PAGE 2
72#define MII_88E1121_PHY_MSCR_REG 21
73#define MII_88E1121_PHY_MSCR_RX_DELAY BIT(5)
74#define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4)
75#define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4))
76
77#define MII_88EC048_PHY_MSCR1_REG 16
78#define MII_88EC048_PHY_MSCR1_PAD_ODD BIT(6)
79
71#define MII_88E1121_PHY_LED_CTRL 16 80#define MII_88E1121_PHY_LED_CTRL 16
72#define MII_88E1121_PHY_LED_PAGE 3 81#define MII_88E1121_PHY_LED_PAGE 3
73#define MII_88E1121_PHY_LED_DEF 0x0030 82#define MII_88E1121_PHY_LED_DEF 0x0030
@@ -179,7 +188,30 @@ static int marvell_config_aneg(struct phy_device *phydev)
179 188
180static int m88e1121_config_aneg(struct phy_device *phydev) 189static int m88e1121_config_aneg(struct phy_device *phydev)
181{ 190{
182 int err, temp; 191 int err, oldpage, mscr;
192
193 oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE);
194
195 err = phy_write(phydev, MII_88E1121_PHY_PAGE,
196 MII_88E1121_PHY_MSCR_PAGE);
197 if (err < 0)
198 return err;
199 mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) &
200 MII_88E1121_PHY_MSCR_DELAY_MASK;
201
202 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
203 mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
204 MII_88E1121_PHY_MSCR_TX_DELAY);
205 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
206 mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
207 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
208 mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
209
210 err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
211 if (err < 0)
212 return err;
213
214 phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
183 215
184 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 216 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
185 if (err < 0) 217 if (err < 0)
@@ -190,17 +222,42 @@ static int m88e1121_config_aneg(struct phy_device *phydev)
190 if (err < 0) 222 if (err < 0)
191 return err; 223 return err;
192 224
193 temp = phy_read(phydev, MII_88E1121_PHY_PAGE); 225 oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE);
194 226
195 phy_write(phydev, MII_88E1121_PHY_PAGE, MII_88E1121_PHY_LED_PAGE); 227 phy_write(phydev, MII_88E1121_PHY_PAGE, MII_88E1121_PHY_LED_PAGE);
196 phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF); 228 phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF);
197 phy_write(phydev, MII_88E1121_PHY_PAGE, temp); 229 phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
198 230
199 err = genphy_config_aneg(phydev); 231 err = genphy_config_aneg(phydev);
200 232
201 return err; 233 return err;
202} 234}
203 235
236static int m88ec048_config_aneg(struct phy_device *phydev)
237{
238 int err, oldpage, mscr;
239
240 oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE);
241
242 err = phy_write(phydev, MII_88E1121_PHY_PAGE,
243 MII_88E1121_PHY_MSCR_PAGE);
244 if (err < 0)
245 return err;
246
247 mscr = phy_read(phydev, MII_88EC048_PHY_MSCR1_REG);
248 mscr |= MII_88EC048_PHY_MSCR1_PAD_ODD;
249
250 err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
251 if (err < 0)
252 return err;
253
254 err = phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
255 if (err < 0)
256 return err;
257
258 return m88e1121_config_aneg(phydev);
259}
260
204static int m88e1111_config_init(struct phy_device *phydev) 261static int m88e1111_config_init(struct phy_device *phydev)
205{ 262{
206 int err; 263 int err;
@@ -595,6 +652,19 @@ static struct phy_driver marvell_drivers[] = {
595 .driver = { .owner = THIS_MODULE }, 652 .driver = { .owner = THIS_MODULE },
596 }, 653 },
597 { 654 {
655 .phy_id = MARVELL_PHY_ID_88EC048,
656 .phy_id_mask = MARVELL_PHY_ID_MASK,
657 .name = "Marvell 88EC048",
658 .features = PHY_GBIT_FEATURES,
659 .flags = PHY_HAS_INTERRUPT,
660 .config_aneg = &m88ec048_config_aneg,
661 .read_status = &marvell_read_status,
662 .ack_interrupt = &marvell_ack_interrupt,
663 .config_intr = &marvell_config_intr,
664 .did_interrupt = &m88e1121_did_interrupt,
665 .driver = { .owner = THIS_MODULE },
666 },
667 {
598 .phy_id = MARVELL_PHY_ID_88E1145, 668 .phy_id = MARVELL_PHY_ID_88E1145,
599 .phy_id_mask = MARVELL_PHY_ID_MASK, 669 .phy_id_mask = MARVELL_PHY_ID_MASK,
600 .name = "Marvell 88E1145", 670 .name = "Marvell 88E1145",
@@ -659,6 +729,7 @@ static struct mdio_device_id marvell_tbl[] = {
659 { 0x01410cb0, 0xfffffff0 }, 729 { 0x01410cb0, 0xfffffff0 },
660 { 0x01410cd0, 0xfffffff0 }, 730 { 0x01410cd0, 0xfffffff0 },
661 { 0x01410e30, 0xfffffff0 }, 731 { 0x01410e30, 0xfffffff0 },
732 { 0x01410e90, 0xfffffff0 },
662 { } 733 { }
663}; 734};
664 735
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
index f443d43edd80..bd12ba941be5 100644
--- a/drivers/net/phy/mdio-octeon.c
+++ b/drivers/net/phy/mdio-octeon.c
@@ -85,7 +85,7 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
85 return 0; 85 return 0;
86} 86}
87 87
88static int __init octeon_mdiobus_probe(struct platform_device *pdev) 88static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
89{ 89{
90 struct octeon_mdiobus *bus; 90 struct octeon_mdiobus *bus;
91 union cvmx_smix_en smi_en; 91 union cvmx_smix_en smi_en;
@@ -143,7 +143,7 @@ err:
143 return err; 143 return err;
144} 144}
145 145
146static int __exit octeon_mdiobus_remove(struct platform_device *pdev) 146static int __devexit octeon_mdiobus_remove(struct platform_device *pdev)
147{ 147{
148 struct octeon_mdiobus *bus; 148 struct octeon_mdiobus *bus;
149 union cvmx_smix_en smi_en; 149 union cvmx_smix_en smi_en;
@@ -163,7 +163,7 @@ static struct platform_driver octeon_mdiobus_driver = {
163 .owner = THIS_MODULE, 163 .owner = THIS_MODULE,
164 }, 164 },
165 .probe = octeon_mdiobus_probe, 165 .probe = octeon_mdiobus_probe,
166 .remove = __exit_p(octeon_mdiobus_remove), 166 .remove = __devexit_p(octeon_mdiobus_remove),
167}; 167};
168 168
169void octeon_mdiobus_force_mod_depencency(void) 169void octeon_mdiobus_force_mod_depencency(void)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 0692f750c404..8bb7db676a5c 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -12,7 +12,8 @@
12 * Free Software Foundation; either version 2 of the License, or (at your 12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version. 13 * option) any later version.
14 * 14 *
15 * Support : ksz9021 , vsc8201, ks8001 15 * Support : ksz9021 1000/100/10 phy from Micrel
16 * ks8001, ks8737, ks8721, ks8041, ks8051 100/10 phy
16 */ 17 */
17 18
18#include <linux/kernel.h> 19#include <linux/kernel.h>
@@ -20,37 +21,146 @@
20#include <linux/phy.h> 21#include <linux/phy.h>
21 22
22#define PHY_ID_KSZ9021 0x00221611 23#define PHY_ID_KSZ9021 0x00221611
23#define PHY_ID_VSC8201 0x000FC413 24#define PHY_ID_KS8737 0x00221720
25#define PHY_ID_KS8041 0x00221510
26#define PHY_ID_KS8051 0x00221550
27/* both for ks8001 Rev. A/B, and for ks8721 Rev 3. */
24#define PHY_ID_KS8001 0x0022161A 28#define PHY_ID_KS8001 0x0022161A
25 29
30/* general Interrupt control/status reg in vendor specific block. */
31#define MII_KSZPHY_INTCS 0x1B
32#define KSZPHY_INTCS_JABBER (1 << 15)
33#define KSZPHY_INTCS_RECEIVE_ERR (1 << 14)
34#define KSZPHY_INTCS_PAGE_RECEIVE (1 << 13)
35#define KSZPHY_INTCS_PARELLEL (1 << 12)
36#define KSZPHY_INTCS_LINK_PARTNER_ACK (1 << 11)
37#define KSZPHY_INTCS_LINK_DOWN (1 << 10)
38#define KSZPHY_INTCS_REMOTE_FAULT (1 << 9)
39#define KSZPHY_INTCS_LINK_UP (1 << 8)
40#define KSZPHY_INTCS_ALL (KSZPHY_INTCS_LINK_UP |\
41 KSZPHY_INTCS_LINK_DOWN)
42
43/* general PHY control reg in vendor specific block. */
44#define MII_KSZPHY_CTRL 0x1F
45/* bitmap of PHY register to set interrupt mode */
46#define KSZPHY_CTRL_INT_ACTIVE_HIGH (1 << 9)
47#define KSZ9021_CTRL_INT_ACTIVE_HIGH (1 << 14)
48#define KS8737_CTRL_INT_ACTIVE_HIGH (1 << 14)
49
50static int kszphy_ack_interrupt(struct phy_device *phydev)
51{
52 /* bit[7..0] int status, which is a read and clear register. */
53 int rc;
54
55 rc = phy_read(phydev, MII_KSZPHY_INTCS);
56
57 return (rc < 0) ? rc : 0;
58}
59
60static int kszphy_set_interrupt(struct phy_device *phydev)
61{
62 int temp;
63 temp = (PHY_INTERRUPT_ENABLED == phydev->interrupts) ?
64 KSZPHY_INTCS_ALL : 0;
65 return phy_write(phydev, MII_KSZPHY_INTCS, temp);
66}
67
68static int kszphy_config_intr(struct phy_device *phydev)
69{
70 int temp, rc;
71
72 /* set the interrupt pin active low */
73 temp = phy_read(phydev, MII_KSZPHY_CTRL);
74 temp &= ~KSZPHY_CTRL_INT_ACTIVE_HIGH;
75 phy_write(phydev, MII_KSZPHY_CTRL, temp);
76 rc = kszphy_set_interrupt(phydev);
77 return rc < 0 ? rc : 0;
78}
79
80static int ksz9021_config_intr(struct phy_device *phydev)
81{
82 int temp, rc;
83
84 /* set the interrupt pin active low */
85 temp = phy_read(phydev, MII_KSZPHY_CTRL);
86 temp &= ~KSZ9021_CTRL_INT_ACTIVE_HIGH;
87 phy_write(phydev, MII_KSZPHY_CTRL, temp);
88 rc = kszphy_set_interrupt(phydev);
89 return rc < 0 ? rc : 0;
90}
91
92static int ks8737_config_intr(struct phy_device *phydev)
93{
94 int temp, rc;
95
96 /* set the interrupt pin active low */
97 temp = phy_read(phydev, MII_KSZPHY_CTRL);
98 temp &= ~KS8737_CTRL_INT_ACTIVE_HIGH;
99 phy_write(phydev, MII_KSZPHY_CTRL, temp);
100 rc = kszphy_set_interrupt(phydev);
101 return rc < 0 ? rc : 0;
102}
26 103
27static int kszphy_config_init(struct phy_device *phydev) 104static int kszphy_config_init(struct phy_device *phydev)
28{ 105{
29 return 0; 106 return 0;
30} 107}
31 108
109static struct phy_driver ks8737_driver = {
110 .phy_id = PHY_ID_KS8737,
111 .phy_id_mask = 0x00fffff0,
112 .name = "Micrel KS8737",
113 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
114 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
115 .config_init = kszphy_config_init,
116 .config_aneg = genphy_config_aneg,
117 .read_status = genphy_read_status,
118 .ack_interrupt = kszphy_ack_interrupt,
119 .config_intr = ks8737_config_intr,
120 .driver = { .owner = THIS_MODULE,},
121};
122
123static struct phy_driver ks8041_driver = {
124 .phy_id = PHY_ID_KS8041,
125 .phy_id_mask = 0x00fffff0,
126 .name = "Micrel KS8041",
127 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
128 | SUPPORTED_Asym_Pause),
129 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
130 .config_init = kszphy_config_init,
131 .config_aneg = genphy_config_aneg,
132 .read_status = genphy_read_status,
133 .ack_interrupt = kszphy_ack_interrupt,
134 .config_intr = kszphy_config_intr,
135 .driver = { .owner = THIS_MODULE,},
136};
32 137
33static struct phy_driver ks8001_driver = { 138static struct phy_driver ks8051_driver = {
34 .phy_id = PHY_ID_KS8001, 139 .phy_id = PHY_ID_KS8051,
35 .name = "Micrel KS8001",
36 .phy_id_mask = 0x00fffff0, 140 .phy_id_mask = 0x00fffff0,
37 .features = PHY_BASIC_FEATURES, 141 .name = "Micrel KS8051",
38 .flags = PHY_POLL, 142 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
143 | SUPPORTED_Asym_Pause),
144 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
39 .config_init = kszphy_config_init, 145 .config_init = kszphy_config_init,
40 .config_aneg = genphy_config_aneg, 146 .config_aneg = genphy_config_aneg,
41 .read_status = genphy_read_status, 147 .read_status = genphy_read_status,
148 .ack_interrupt = kszphy_ack_interrupt,
149 .config_intr = kszphy_config_intr,
42 .driver = { .owner = THIS_MODULE,}, 150 .driver = { .owner = THIS_MODULE,},
43}; 151};
44 152
45static struct phy_driver vsc8201_driver = { 153static struct phy_driver ks8001_driver = {
46 .phy_id = PHY_ID_VSC8201, 154 .phy_id = PHY_ID_KS8001,
47 .name = "Micrel VSC8201", 155 .name = "Micrel KS8001 or KS8721",
48 .phy_id_mask = 0x00fffff0, 156 .phy_id_mask = 0x00fffff0,
49 .features = PHY_BASIC_FEATURES, 157 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
50 .flags = PHY_POLL, 158 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
51 .config_init = kszphy_config_init, 159 .config_init = kszphy_config_init,
52 .config_aneg = genphy_config_aneg, 160 .config_aneg = genphy_config_aneg,
53 .read_status = genphy_read_status, 161 .read_status = genphy_read_status,
162 .ack_interrupt = kszphy_ack_interrupt,
163 .config_intr = kszphy_config_intr,
54 .driver = { .owner = THIS_MODULE,}, 164 .driver = { .owner = THIS_MODULE,},
55}; 165};
56 166
@@ -58,11 +168,14 @@ static struct phy_driver ksz9021_driver = {
58 .phy_id = PHY_ID_KSZ9021, 168 .phy_id = PHY_ID_KSZ9021,
59 .phy_id_mask = 0x000fff10, 169 .phy_id_mask = 0x000fff10,
60 .name = "Micrel KSZ9021 Gigabit PHY", 170 .name = "Micrel KSZ9021 Gigabit PHY",
61 .features = PHY_GBIT_FEATURES | SUPPORTED_Pause, 171 .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause
62 .flags = PHY_POLL, 172 | SUPPORTED_Asym_Pause),
173 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
63 .config_init = kszphy_config_init, 174 .config_init = kszphy_config_init,
64 .config_aneg = genphy_config_aneg, 175 .config_aneg = genphy_config_aneg,
65 .read_status = genphy_read_status, 176 .read_status = genphy_read_status,
177 .ack_interrupt = kszphy_ack_interrupt,
178 .config_intr = ksz9021_config_intr,
66 .driver = { .owner = THIS_MODULE, }, 179 .driver = { .owner = THIS_MODULE, },
67}; 180};
68 181
@@ -73,17 +186,29 @@ static int __init ksphy_init(void)
73 ret = phy_driver_register(&ks8001_driver); 186 ret = phy_driver_register(&ks8001_driver);
74 if (ret) 187 if (ret)
75 goto err1; 188 goto err1;
76 ret = phy_driver_register(&vsc8201_driver); 189
190 ret = phy_driver_register(&ksz9021_driver);
77 if (ret) 191 if (ret)
78 goto err2; 192 goto err2;
79 193
80 ret = phy_driver_register(&ksz9021_driver); 194 ret = phy_driver_register(&ks8737_driver);
81 if (ret) 195 if (ret)
82 goto err3; 196 goto err3;
197 ret = phy_driver_register(&ks8041_driver);
198 if (ret)
199 goto err4;
200 ret = phy_driver_register(&ks8051_driver);
201 if (ret)
202 goto err5;
203
83 return 0; 204 return 0;
84 205
206err5:
207 phy_driver_unregister(&ks8041_driver);
208err4:
209 phy_driver_unregister(&ks8737_driver);
85err3: 210err3:
86 phy_driver_unregister(&vsc8201_driver); 211 phy_driver_unregister(&ksz9021_driver);
87err2: 212err2:
88 phy_driver_unregister(&ks8001_driver); 213 phy_driver_unregister(&ks8001_driver);
89err1: 214err1:
@@ -93,8 +218,10 @@ err1:
93static void __exit ksphy_exit(void) 218static void __exit ksphy_exit(void)
94{ 219{
95 phy_driver_unregister(&ks8001_driver); 220 phy_driver_unregister(&ks8001_driver);
96 phy_driver_unregister(&vsc8201_driver); 221 phy_driver_unregister(&ks8737_driver);
97 phy_driver_unregister(&ksz9021_driver); 222 phy_driver_unregister(&ksz9021_driver);
223 phy_driver_unregister(&ks8041_driver);
224 phy_driver_unregister(&ks8051_driver);
98} 225}
99 226
100module_init(ksphy_init); 227module_init(ksphy_init);
@@ -106,8 +233,10 @@ MODULE_LICENSE("GPL");
106 233
107static struct mdio_device_id micrel_tbl[] = { 234static struct mdio_device_id micrel_tbl[] = {
108 { PHY_ID_KSZ9021, 0x000fff10 }, 235 { PHY_ID_KSZ9021, 0x000fff10 },
109 { PHY_ID_VSC8201, 0x00fffff0 },
110 { PHY_ID_KS8001, 0x00fffff0 }, 236 { PHY_ID_KS8001, 0x00fffff0 },
237 { PHY_ID_KS8737, 0x00fffff0 },
238 { PHY_ID_KS8041, 0x00fffff0 },
239 { PHY_ID_KS8051, 0x00fffff0 },
111 { } 240 { }
112}; 241};
113 242
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 64be4664ccab..5130db8f5c4e 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -309,8 +309,9 @@ EXPORT_SYMBOL(phy_ethtool_gset);
309 * current state. Use at own risk. 309 * current state. Use at own risk.
310 */ 310 */
311int phy_mii_ioctl(struct phy_device *phydev, 311int phy_mii_ioctl(struct phy_device *phydev,
312 struct mii_ioctl_data *mii_data, int cmd) 312 struct ifreq *ifr, int cmd)
313{ 313{
314 struct mii_ioctl_data *mii_data = if_mii(ifr);
314 u16 val = mii_data->val_in; 315 u16 val = mii_data->val_in;
315 316
316 switch (cmd) { 317 switch (cmd) {
@@ -360,6 +361,11 @@ int phy_mii_ioctl(struct phy_device *phydev,
360 } 361 }
361 break; 362 break;
362 363
364 case SIOCSHWTSTAMP:
365 if (phydev->drv->hwtstamp)
366 return phydev->drv->hwtstamp(phydev, ifr);
367 /* fall through */
368
363 default: 369 default:
364 return -EOPNOTSUPP; 370 return -EOPNOTSUPP;
365 } 371 }
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 1a99bb244106..c0761197c07e 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -460,6 +460,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
460 } 460 }
461 461
462 phydev->attached_dev = dev; 462 phydev->attached_dev = dev;
463 dev->phydev = phydev;
463 464
464 phydev->dev_flags = flags; 465 phydev->dev_flags = flags;
465 466
@@ -513,6 +514,7 @@ EXPORT_SYMBOL(phy_attach);
513 */ 514 */
514void phy_detach(struct phy_device *phydev) 515void phy_detach(struct phy_device *phydev)
515{ 516{
517 phydev->attached_dev->phydev = NULL;
516 phydev->attached_dev = NULL; 518 phydev->attached_dev = NULL;
517 519
518 /* If the device had no specific driver before (i.e. - it 520 /* If the device had no specific driver before (i.e. - it