aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy')
-rw-r--r--drivers/net/phy/broadcom.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 5b80358af658..f5310ed3760d 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -99,6 +99,41 @@ static int bcm54xx_config_intr(struct phy_device *phydev)
99 return err; 99 return err;
100} 100}
101 101
102static int bcm5481_config_aneg(struct phy_device *phydev)
103{
104 int ret;
105
106 /* Aneg firsly. */
107 ret = genphy_config_aneg(phydev);
108
109 /* Then we can set up the delay. */
110 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
111 u16 reg;
112
113 /*
114 * There is no BCM5481 specification available, so down
115 * here is everything we know about "register 0x18". This
116 * at least helps BCM5481 to successfuly receive packets
117 * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
118 * says: "This sets delay between the RXD and RXC signals
119 * instead of using trace lengths to achieve timing".
120 */
121
122 /* Set RDX clk delay. */
123 reg = 0x7 | (0x7 << 12);
124 phy_write(phydev, 0x18, reg);
125
126 reg = phy_read(phydev, 0x18);
127 /* Set RDX-RXC skew. */
128 reg |= (1 << 8);
129 /* Write bits 14:0. */
130 reg |= (1 << 15);
131 phy_write(phydev, 0x18, reg);
132 }
133
134 return ret;
135}
136
102static struct phy_driver bcm5411_driver = { 137static struct phy_driver bcm5411_driver = {
103 .phy_id = 0x00206070, 138 .phy_id = 0x00206070,
104 .phy_id_mask = 0xfffffff0, 139 .phy_id_mask = 0xfffffff0,
@@ -141,8 +176,22 @@ static struct phy_driver bcm5461_driver = {
141 .driver = { .owner = THIS_MODULE }, 176 .driver = { .owner = THIS_MODULE },
142}; 177};
143 178
179static struct phy_driver bcm5481_driver = {
180 .phy_id = 0x0143bca0,
181 .phy_id_mask = 0xfffffff0,
182 .name = "Broadcom BCM5481",
183 .features = PHY_GBIT_FEATURES,
184 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
185 .config_init = bcm54xx_config_init,
186 .config_aneg = bcm5481_config_aneg,
187 .read_status = genphy_read_status,
188 .ack_interrupt = bcm54xx_ack_interrupt,
189 .config_intr = bcm54xx_config_intr,
190 .driver = { .owner = THIS_MODULE },
191};
192
144static struct phy_driver bcm5482_driver = { 193static struct phy_driver bcm5482_driver = {
145 .phy_id = 0x0143bcb0, 194 .phy_id = 0x0143bcb0,
146 .phy_id_mask = 0xfffffff0, 195 .phy_id_mask = 0xfffffff0,
147 .name = "Broadcom BCM5482", 196 .name = "Broadcom BCM5482",
148 .features = PHY_GBIT_FEATURES, 197 .features = PHY_GBIT_FEATURES,
@@ -168,12 +217,17 @@ static int __init broadcom_init(void)
168 ret = phy_driver_register(&bcm5461_driver); 217 ret = phy_driver_register(&bcm5461_driver);
169 if (ret) 218 if (ret)
170 goto out_5461; 219 goto out_5461;
220 ret = phy_driver_register(&bcm5481_driver);
221 if (ret)
222 goto out_5481;
171 ret = phy_driver_register(&bcm5482_driver); 223 ret = phy_driver_register(&bcm5482_driver);
172 if (ret) 224 if (ret)
173 goto out_5482; 225 goto out_5482;
174 return ret; 226 return ret;
175 227
176out_5482: 228out_5482:
229 phy_driver_unregister(&bcm5481_driver);
230out_5481:
177 phy_driver_unregister(&bcm5461_driver); 231 phy_driver_unregister(&bcm5461_driver);
178out_5461: 232out_5461:
179 phy_driver_unregister(&bcm5421_driver); 233 phy_driver_unregister(&bcm5421_driver);
@@ -186,6 +240,7 @@ out_5411:
186static void __exit broadcom_exit(void) 240static void __exit broadcom_exit(void)
187{ 241{
188 phy_driver_unregister(&bcm5482_driver); 242 phy_driver_unregister(&bcm5482_driver);
243 phy_driver_unregister(&bcm5481_driver);
189 phy_driver_unregister(&bcm5461_driver); 244 phy_driver_unregister(&bcm5461_driver);
190 phy_driver_unregister(&bcm5421_driver); 245 phy_driver_unregister(&bcm5421_driver);
191 phy_driver_unregister(&bcm5411_driver); 246 phy_driver_unregister(&bcm5411_driver);