aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/vitesse.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/vitesse.c')
-rw-r--r--drivers/net/phy/vitesse.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 596222b260d6..6a5385647911 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -21,6 +21,10 @@
21/* Vitesse Extended Control Register 1 */ 21/* Vitesse Extended Control Register 1 */
22#define MII_VSC8244_EXT_CON1 0x17 22#define MII_VSC8244_EXT_CON1 0x17
23#define MII_VSC8244_EXTCON1_INIT 0x0000 23#define MII_VSC8244_EXTCON1_INIT 0x0000
24#define MII_VSC8244_EXTCON1_TX_SKEW_MASK 0x0c00
25#define MII_VSC8244_EXTCON1_RX_SKEW_MASK 0x0300
26#define MII_VSC8244_EXTCON1_TX_SKEW 0x0800
27#define MII_VSC8244_EXTCON1_RX_SKEW 0x0200
24 28
25/* Vitesse Interrupt Mask Register */ 29/* Vitesse Interrupt Mask Register */
26#define MII_VSC8244_IMASK 0x19 30#define MII_VSC8244_IMASK 0x19
@@ -39,7 +43,7 @@
39 43
40/* Vitesse Auxiliary Control/Status Register */ 44/* Vitesse Auxiliary Control/Status Register */
41#define MII_VSC8244_AUX_CONSTAT 0x1c 45#define MII_VSC8244_AUX_CONSTAT 0x1c
42#define MII_VSC8244_AUXCONSTAT_INIT 0x0004 46#define MII_VSC8244_AUXCONSTAT_INIT 0x0000
43#define MII_VSC8244_AUXCONSTAT_DUPLEX 0x0020 47#define MII_VSC8244_AUXCONSTAT_DUPLEX 0x0020
44#define MII_VSC8244_AUXCONSTAT_SPEED 0x0018 48#define MII_VSC8244_AUXCONSTAT_SPEED 0x0018
45#define MII_VSC8244_AUXCONSTAT_GBIT 0x0010 49#define MII_VSC8244_AUXCONSTAT_GBIT 0x0010
@@ -51,6 +55,7 @@ MODULE_LICENSE("GPL");
51 55
52static int vsc824x_config_init(struct phy_device *phydev) 56static int vsc824x_config_init(struct phy_device *phydev)
53{ 57{
58 int extcon;
54 int err; 59 int err;
55 60
56 err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT, 61 err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT,
@@ -58,14 +63,34 @@ static int vsc824x_config_init(struct phy_device *phydev)
58 if (err < 0) 63 if (err < 0)
59 return err; 64 return err;
60 65
61 err = phy_write(phydev, MII_VSC8244_EXT_CON1, 66 extcon = phy_read(phydev, MII_VSC8244_EXT_CON1);
62 MII_VSC8244_EXTCON1_INIT); 67
68 if (extcon < 0)
69 return err;
70
71 extcon &= ~(MII_VSC8244_EXTCON1_TX_SKEW_MASK |
72 MII_VSC8244_EXTCON1_RX_SKEW_MASK);
73
74 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
75 extcon |= (MII_VSC8244_EXTCON1_TX_SKEW |
76 MII_VSC8244_EXTCON1_RX_SKEW);
77
78 err = phy_write(phydev, MII_VSC8244_EXT_CON1, extcon);
79
63 return err; 80 return err;
64} 81}
65 82
66static int vsc824x_ack_interrupt(struct phy_device *phydev) 83static int vsc824x_ack_interrupt(struct phy_device *phydev)
67{ 84{
68 int err = phy_read(phydev, MII_VSC8244_ISTAT); 85 int err = 0;
86
87 /*
88 * Don't bother to ACK the interrupts if interrupts
89 * are disabled. The 824x cannot clear the interrupts
90 * if they are disabled.
91 */
92 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
93 err = phy_read(phydev, MII_VSC8244_ISTAT);
69 94
70 return (err < 0) ? err : 0; 95 return (err < 0) ? err : 0;
71} 96}
@@ -77,8 +102,19 @@ static int vsc824x_config_intr(struct phy_device *phydev)
77 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 102 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
78 err = phy_write(phydev, MII_VSC8244_IMASK, 103 err = phy_write(phydev, MII_VSC8244_IMASK,
79 MII_VSC8244_IMASK_MASK); 104 MII_VSC8244_IMASK_MASK);
80 else 105 else {
106 /*
107 * The Vitesse PHY cannot clear the interrupt
108 * once it has disabled them, so we clear them first
109 */
110 err = phy_read(phydev, MII_VSC8244_ISTAT);
111
112 if (err)
113 return err;
114
81 err = phy_write(phydev, MII_VSC8244_IMASK, 0); 115 err = phy_write(phydev, MII_VSC8244_IMASK, 0);
116 }
117
82 return err; 118 return err;
83} 119}
84 120