blob: c1aedbb2469aaab8820ad32f99087ec853cdf306 [file] [log] [blame]
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001/*
2 * Agere Systems Inc.
3 * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
4 *
Alan Cox64f93032009-06-10 17:30:41 +01005 * Copyright * 2005 Agere Systems Inc.
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07006 * All rights reserved.
7 * http://www.agere.com
8 *
9 *------------------------------------------------------------------------------
10 *
11 * et1310_phy.c - Routines for configuring and accessing the PHY
12 *
13 *------------------------------------------------------------------------------
14 *
15 * SOFTWARE LICENSE
16 *
17 * This software is provided subject to the following terms and conditions,
18 * which you should read carefully before using the software. Using this
19 * software indicates your acceptance of these terms and conditions. If you do
20 * not agree with these terms and conditions, do not use the software.
21 *
Alan Cox64f93032009-06-10 17:30:41 +010022 * Copyright * 2005 Agere Systems Inc.
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -070023 * All rights reserved.
24 *
25 * Redistribution and use in source or binary forms, with or without
26 * modifications, are permitted provided that the following conditions are met:
27 *
28 * . Redistributions of source code must retain the above copyright notice, this
29 * list of conditions and the following Disclaimer as comments in the code as
30 * well as in the documentation and/or other materials provided with the
31 * distribution.
32 *
33 * . Redistributions in binary form must reproduce the above copyright notice,
34 * this list of conditions and the following Disclaimer in the documentation
35 * and/or other materials provided with the distribution.
36 *
37 * . Neither the name of Agere Systems Inc. nor the names of the contributors
38 * may be used to endorse or promote products derived from this software
39 * without specific prior written permission.
40 *
41 * Disclaimer
42 *
Alan Cox64f93032009-06-10 17:30:41 +010043 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -070044 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
45 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
46 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
47 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
48 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
49 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
50 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
51 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
53 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
54 * DAMAGE.
55 *
56 */
57
58#include "et131x_version.h"
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -070059#include "et131x_defs.h"
60
61#include <linux/pci.h>
62#include <linux/init.h>
63#include <linux/module.h>
64#include <linux/types.h>
65#include <linux/kernel.h>
66
67#include <linux/sched.h>
68#include <linux/ptrace.h>
69#include <linux/slab.h>
70#include <linux/ctype.h>
71#include <linux/string.h>
72#include <linux/timer.h>
73#include <linux/interrupt.h>
74#include <linux/in.h>
75#include <linux/delay.h>
Alan Cox64f93032009-06-10 17:30:41 +010076#include <linux/io.h>
77#include <linux/bitops.h>
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -070078#include <asm/system.h>
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -070079
80#include <linux/netdevice.h>
81#include <linux/etherdevice.h>
82#include <linux/skbuff.h>
83#include <linux/if_arp.h>
84#include <linux/ioport.h>
85#include <linux/random.h>
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -070086
87#include "et1310_phy.h"
88#include "et1310_pm.h"
89#include "et1310_jagcore.h"
90
91#include "et131x_adapter.h"
92#include "et131x_netdev.h"
93#include "et131x_initpci.h"
94
95#include "et1310_address_map.h"
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -070096#include "et1310_tx.h"
97#include "et1310_rx.h"
98#include "et1310_mac.h"
99
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700100/* Prototypes for functions with local scope */
101static int et131x_xcvr_init(struct et131x_adapter *adapter);
102
103/**
104 * PhyMiRead - Read from the PHY through the MII Interface on the MAC
105 * @adapter: pointer to our private adapter structure
106 * @xcvrAddr: the address of the transciever
107 * @xcvrReg: the register to read
108 * @value: pointer to a 16-bit value in which the value will be stored
109 *
110 * Returns 0 on success, errno on failure (as defined in errno.h)
111 */
Alan Cox1210db92009-10-06 15:51:10 +0100112int PhyMiRead(struct et131x_adapter *adapter, u8 xcvrAddr,
113 u8 xcvrReg, u16 *value)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700114{
Alan Coxf3f415a2009-08-27 10:59:30 +0100115 struct _MAC_t __iomem *mac = &adapter->regs->mac;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700116 int status = 0;
Alan Cox1210db92009-10-06 15:51:10 +0100117 u32 delay;
Alan Cox57aed3b2009-10-06 15:51:04 +0100118 u32 miiAddr;
119 u32 miiCmd;
120 u32 miiIndicator;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700121
122 /* Save a local copy of the registers we are dealing with so we can
123 * set them back
124 */
Alan Cox57aed3b2009-10-06 15:51:04 +0100125 miiAddr = readl(&mac->mii_mgmt_addr);
126 miiCmd = readl(&mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700127
128 /* Stop the current operation */
Alan Cox57aed3b2009-10-06 15:51:04 +0100129 writel(0, &mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700130
131 /* Set up the register we need to read from on the correct PHY */
Alan Cox57aed3b2009-10-06 15:51:04 +0100132 writel(MII_ADDR(xcvrAddr, xcvrReg), &mac->mii_mgmt_addr);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700133
134 /* Kick the read cycle off */
135 delay = 0;
136
Alan Cox57aed3b2009-10-06 15:51:04 +0100137 writel(0x1, &mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700138
139 do {
140 udelay(50);
141 delay++;
Alan Cox57aed3b2009-10-06 15:51:04 +0100142 miiIndicator = readl(&mac->mii_mgmt_indicator);
143 } while ((miiIndicator & MGMT_WAIT) && delay < 50);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700144
145 /* If we hit the max delay, we could not read the register */
Alan Cox57aed3b2009-10-06 15:51:04 +0100146 if (delay == 50) {
Alan Cox15700032009-08-27 11:03:09 +0100147 dev_warn(&adapter->pdev->dev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700148 "xcvrReg 0x%08x could not be read\n", xcvrReg);
Alan Cox15700032009-08-27 11:03:09 +0100149 dev_warn(&adapter->pdev->dev, "status is 0x%08x\n",
Alan Cox57aed3b2009-10-06 15:51:04 +0100150 miiIndicator);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700151
152 status = -EIO;
153 }
154
155 /* If we hit here we were able to read the register and we need to
Alan Cox57aed3b2009-10-06 15:51:04 +0100156 * return the value to the caller */
157 *value = readl(&mac->mii_mgmt_stat) & 0xFFFF;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700158
159 /* Stop the read operation */
Alan Cox57aed3b2009-10-06 15:51:04 +0100160 writel(0, &mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700161
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700162 /* set the registers we touched back to the state at which we entered
163 * this function
164 */
Alan Cox57aed3b2009-10-06 15:51:04 +0100165 writel(miiAddr, &mac->mii_mgmt_addr);
166 writel(miiCmd, &mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700167
168 return status;
169}
170
171/**
172 * MiWrite - Write to a PHY register through the MII interface of the MAC
173 * @adapter: pointer to our private adapter structure
174 * @xcvrReg: the register to read
175 * @value: 16-bit value to write
176 *
Alan Cox1210db92009-10-06 15:51:10 +0100177 * FIXME: one caller in netdev still
178 *
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700179 * Return 0 on success, errno on failure (as defined in errno.h)
180 */
Alan Cox1210db92009-10-06 15:51:10 +0100181int MiWrite(struct et131x_adapter *adapter, u8 xcvrReg, u16 value)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700182{
Alan Coxf3f415a2009-08-27 10:59:30 +0100183 struct _MAC_t __iomem *mac = &adapter->regs->mac;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700184 int status = 0;
Alan Cox1210db92009-10-06 15:51:10 +0100185 u8 xcvrAddr = adapter->Stats.xcvr_addr;
186 u32 delay;
Alan Cox57aed3b2009-10-06 15:51:04 +0100187 u32 miiAddr;
188 u32 miiCmd;
189 u32 miiIndicator;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700190
191 /* Save a local copy of the registers we are dealing with so we can
192 * set them back
193 */
Alan Cox57aed3b2009-10-06 15:51:04 +0100194 miiAddr = readl(&mac->mii_mgmt_addr);
195 miiCmd = readl(&mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700196
197 /* Stop the current operation */
Alan Cox57aed3b2009-10-06 15:51:04 +0100198 writel(0, &mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700199
200 /* Set up the register we need to write to on the correct PHY */
Alan Cox57aed3b2009-10-06 15:51:04 +0100201 writel(MII_ADDR(xcvrAddr, xcvrReg), &mac->mii_mgmt_addr);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700202
203 /* Add the value to write to the registers to the mac */
Alan Cox57aed3b2009-10-06 15:51:04 +0100204 writel(value, &mac->mii_mgmt_ctrl);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700205 delay = 0;
206
207 do {
208 udelay(50);
209 delay++;
Alan Cox57aed3b2009-10-06 15:51:04 +0100210 miiIndicator = readl(&mac->mii_mgmt_indicator);
211 } while ((miiIndicator & MGMT_BUSY) && delay < 100);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700212
213 /* If we hit the max delay, we could not write the register */
214 if (delay == 100) {
Alan Cox1210db92009-10-06 15:51:10 +0100215 u16 TempValue;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700216
Alan Cox15700032009-08-27 11:03:09 +0100217 dev_warn(&adapter->pdev->dev,
218 "xcvrReg 0x%08x could not be written", xcvrReg);
219 dev_warn(&adapter->pdev->dev, "status is 0x%08x\n",
Alan Cox57aed3b2009-10-06 15:51:04 +0100220 miiIndicator);
Alan Cox15700032009-08-27 11:03:09 +0100221 dev_warn(&adapter->pdev->dev, "command is 0x%08x\n",
Alan Cox57aed3b2009-10-06 15:51:04 +0100222 readl(&mac->mii_mgmt_cmd));
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700223
224 MiRead(adapter, xcvrReg, &TempValue);
225
226 status = -EIO;
227 }
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700228 /* Stop the write operation */
Alan Cox57aed3b2009-10-06 15:51:04 +0100229 writel(0, &mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700230
231 /* set the registers we touched back to the state at which we entered
Alan Cox64f93032009-06-10 17:30:41 +0100232 * this function
233 */
Alan Cox57aed3b2009-10-06 15:51:04 +0100234 writel(miiAddr, &mac->mii_mgmt_addr);
235 writel(miiCmd, &mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700236
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700237 return status;
238}
239
240/**
241 * et131x_xcvr_find - Find the PHY ID
242 * @adapter: pointer to our private adapter structure
243 *
244 * Returns 0 on success, errno on failure (as defined in errno.h)
245 */
246int et131x_xcvr_find(struct et131x_adapter *adapter)
247{
248 int status = -ENODEV;
Alan Cox1210db92009-10-06 15:51:10 +0100249 u8 xcvr_addr;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700250 MI_IDR1_t idr1;
251 MI_IDR2_t idr2;
Alan Cox1210db92009-10-06 15:51:10 +0100252 u32 xcvr_id;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700253
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700254 /* We need to get xcvr id and address we just get the first one */
255 for (xcvr_addr = 0; xcvr_addr < 32; xcvr_addr++) {
256 /* Read the ID from the PHY */
257 PhyMiRead(adapter, xcvr_addr,
Alan Cox1210db92009-10-06 15:51:10 +0100258 (u8) offsetof(MI_REGS_t, idr1),
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700259 &idr1.value);
260 PhyMiRead(adapter, xcvr_addr,
Alan Cox1210db92009-10-06 15:51:10 +0100261 (u8) offsetof(MI_REGS_t, idr2),
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700262 &idr2.value);
263
Alan Cox1210db92009-10-06 15:51:10 +0100264 xcvr_id = (u32) ((idr1.value << 16) | idr2.value);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700265
266 if ((idr1.value != 0) && (idr1.value != 0xffff)) {
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700267 adapter->Stats.xcvr_id = xcvr_id;
268 adapter->Stats.xcvr_addr = xcvr_addr;
269
270 status = 0;
271 break;
272 }
273 }
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700274 return status;
275}
276
277/**
278 * et131x_setphy_normal - Set PHY for normal operation.
279 * @adapter: pointer to our private adapter structure
280 *
281 * Used by Power Management to force the PHY into 10 Base T half-duplex mode,
282 * when going to D3 in WOL mode. Also used during initialization to set the
283 * PHY for normal operation.
284 */
285int et131x_setphy_normal(struct et131x_adapter *adapter)
286{
287 int status;
288
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700289 /* Make sure the PHY is powered up */
290 ET1310_PhyPowerDown(adapter, 0);
291 status = et131x_xcvr_init(adapter);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700292 return status;
293}
294
Alan Cox1210db92009-10-06 15:51:10 +0100295void ET1310_PhyReset(struct et131x_adapter *etdev)
296{
297 MiWrite(etdev, PHY_CONTROL, 0x8000);
298}
299
300void ET1310_PhyPowerDown(struct et131x_adapter *etdev, bool down)
301{
302 u16 data;
303
304 MiRead(etdev, PHY_CONTROL, &data);
305
306 if (down == false) {
307 /* Power UP */
308 data &= ~0x0800;
309 MiWrite(etdev, PHY_CONTROL, data);
310 } else {
311 /* Power DOWN */
312 data |= 0x0800;
313 MiWrite(etdev, PHY_CONTROL, data);
314 }
315}
316
317static void ET1310_PhyAutoNeg(struct et131x_adapter *etdev, bool enable)
318{
319 u16 data;
320
321 MiRead(etdev, PHY_CONTROL, &data);
322
323 if (enable == true) {
324 /* Autonegotiation ON */
325 data |= 0x1000;
326 MiWrite(etdev, PHY_CONTROL, data);
327 } else {
328 /* Autonegotiation OFF */
329 data &= ~0x1000;
330 MiWrite(etdev, PHY_CONTROL, data);
331 }
332}
333
334static void ET1310_PhyDuplexMode(struct et131x_adapter *etdev, u16 duplex)
335{
336 u16 data;
337
338 MiRead(etdev, PHY_CONTROL, &data);
339
340 if (duplex == TRUEPHY_DUPLEX_FULL) {
341 /* Set Full Duplex */
342 data |= 0x100;
343 MiWrite(etdev, PHY_CONTROL, data);
344 } else {
345 /* Set Half Duplex */
346 data &= ~0x100;
347 MiWrite(etdev, PHY_CONTROL, data);
348 }
349}
350
351static void ET1310_PhySpeedSelect(struct et131x_adapter *etdev, u16 speed)
352{
353 u16 data;
354
355 /* Read the PHY control register */
356 MiRead(etdev, PHY_CONTROL, &data);
357
358 /* Clear all Speed settings (Bits 6, 13) */
359 data &= ~0x2040;
360
361 /* Reset the speed bits based on user selection */
362 switch (speed) {
363 case TRUEPHY_SPEED_10MBPS:
364 /* Bits already cleared above, do nothing */
365 break;
366
367 case TRUEPHY_SPEED_100MBPS:
368 /* 100M == Set bit 13 */
369 data |= 0x2000;
370 break;
371
372 case TRUEPHY_SPEED_1000MBPS:
373 default:
374 data |= 0x0040;
375 break;
376 }
377
378 /* Write back the new speed */
379 MiWrite(etdev, PHY_CONTROL, data);
380}
381
382static void ET1310_PhyLinkStatus(struct et131x_adapter *etdev,
383 u8 *link_status,
384 u32 *autoneg,
385 u32 *linkspeed,
386 u32 *duplex_mode,
387 u32 *mdi_mdix,
388 u32 *masterslave, u32 *polarity)
389{
390 u16 mistatus = 0;
391 u16 is1000BaseT = 0;
392 u16 vmi_phystatus = 0;
393 u16 control = 0;
394
395 MiRead(etdev, PHY_STATUS, &mistatus);
396 MiRead(etdev, PHY_1000_STATUS, &is1000BaseT);
397 MiRead(etdev, PHY_PHY_STATUS, &vmi_phystatus);
398 MiRead(etdev, PHY_CONTROL, &control);
399
400 if (link_status) {
401 *link_status =
402 (unsigned char)((vmi_phystatus & 0x0040) ? 1 : 0);
403 }
404
405 if (autoneg) {
406 *autoneg =
407 (control & 0x1000) ? ((vmi_phystatus & 0x0020) ?
408 TRUEPHY_ANEG_COMPLETE :
409 TRUEPHY_ANEG_NOT_COMPLETE) :
410 TRUEPHY_ANEG_DISABLED;
411 }
412
413 if (linkspeed)
414 *linkspeed = (vmi_phystatus & 0x0300) >> 8;
415
416 if (duplex_mode)
417 *duplex_mode = (vmi_phystatus & 0x0080) >> 7;
418
419 if (mdi_mdix)
420 /* NOTE: Need to complete this */
421 *mdi_mdix = 0;
422
423 if (masterslave) {
424 *masterslave =
425 (is1000BaseT & 0x4000) ? TRUEPHY_CFG_MASTER :
426 TRUEPHY_CFG_SLAVE;
427 }
428
429 if (polarity) {
430 *polarity =
431 (vmi_phystatus & 0x0400) ? TRUEPHY_POLARITY_INVERTED :
432 TRUEPHY_POLARITY_NORMAL;
433 }
434}
435
436static void ET1310_PhyAndOrReg(struct et131x_adapter *etdev,
437 u16 regnum, u16 andMask, u16 orMask)
438{
439 u16 reg;
440
441 /* Read the requested register */
442 MiRead(etdev, regnum, &reg);
443
444 /* Apply the AND mask */
445 reg &= andMask;
446
447 /* Apply the OR mask */
448 reg |= orMask;
449
450 /* Write the value back to the register */
451 MiWrite(etdev, regnum, reg);
452}
453
454/* Still used from _mac */
455void ET1310_PhyAccessMiBit(struct et131x_adapter *etdev, u16 action,
456 u16 regnum, u16 bitnum, u8 *value)
457{
458 u16 reg;
459 u16 mask = 0;
460
461 /* Create a mask to isolate the requested bit */
462 mask = 0x0001 << bitnum;
463
464 /* Read the requested register */
465 MiRead(etdev, regnum, &reg);
466
467 switch (action) {
468 case TRUEPHY_BIT_READ:
469 if (value != NULL)
470 *value = (reg & mask) >> bitnum;
471 break;
472
473 case TRUEPHY_BIT_SET:
474 reg |= mask;
475 MiWrite(etdev, regnum, reg);
476 break;
477
478 case TRUEPHY_BIT_CLEAR:
479 reg &= ~mask;
480 MiWrite(etdev, regnum, reg);
481 break;
482
483 default:
484 break;
485 }
486}
487
488void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *etdev,
489 u16 duplex)
490{
491 u16 data;
492
493 /* Read the PHY 1000 Base-T Control Register */
494 MiRead(etdev, PHY_1000_CONTROL, &data);
495
496 /* Clear Bits 8,9 */
497 data &= ~0x0300;
498
499 switch (duplex) {
500 case TRUEPHY_ADV_DUPLEX_NONE:
501 /* Duplex already cleared, do nothing */
502 break;
503
504 case TRUEPHY_ADV_DUPLEX_FULL:
505 /* Set Bit 9 */
506 data |= 0x0200;
507 break;
508
509 case TRUEPHY_ADV_DUPLEX_HALF:
510 /* Set Bit 8 */
511 data |= 0x0100;
512 break;
513
514 case TRUEPHY_ADV_DUPLEX_BOTH:
515 default:
516 data |= 0x0300;
517 break;
518 }
519
520 /* Write back advertisement */
521 MiWrite(etdev, PHY_1000_CONTROL, data);
522}
523
524static void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *etdev,
525 u16 duplex)
526{
527 u16 data;
528
529 /* Read the Autonegotiation Register (10/100) */
530 MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data);
531
532 /* Clear bits 7,8 */
533 data &= ~0x0180;
534
535 switch (duplex) {
536 case TRUEPHY_ADV_DUPLEX_NONE:
537 /* Duplex already cleared, do nothing */
538 break;
539
540 case TRUEPHY_ADV_DUPLEX_FULL:
541 /* Set Bit 8 */
542 data |= 0x0100;
543 break;
544
545 case TRUEPHY_ADV_DUPLEX_HALF:
546 /* Set Bit 7 */
547 data |= 0x0080;
548 break;
549
550 case TRUEPHY_ADV_DUPLEX_BOTH:
551 default:
552 /* Set Bits 7,8 */
553 data |= 0x0180;
554 break;
555 }
556
557 /* Write back advertisement */
558 MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data);
559}
560
561static void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *etdev,
562 u16 duplex)
563{
564 u16 data;
565
566 /* Read the Autonegotiation Register (10/100) */
567 MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data);
568
569 /* Clear bits 5,6 */
570 data &= ~0x0060;
571
572 switch (duplex) {
573 case TRUEPHY_ADV_DUPLEX_NONE:
574 /* Duplex already cleared, do nothing */
575 break;
576
577 case TRUEPHY_ADV_DUPLEX_FULL:
578 /* Set Bit 6 */
579 data |= 0x0040;
580 break;
581
582 case TRUEPHY_ADV_DUPLEX_HALF:
583 /* Set Bit 5 */
584 data |= 0x0020;
585 break;
586
587 case TRUEPHY_ADV_DUPLEX_BOTH:
588 default:
589 /* Set Bits 5,6 */
590 data |= 0x0060;
591 break;
592 }
593
594 /* Write back advertisement */
595 MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data);
596}
597
598
599/**
600 * TPAL_SetPhy10HalfDuplex - Force the phy into 10 Base T Half Duplex mode.
601 * @etdev: pointer to the adapter structure
602 *
603 * Also sets the MAC so it is syncd up properly
604 */
605static void TPAL_SetPhy10HalfDuplex(struct et131x_adapter *etdev)
606{
607 /* Power down PHY */
608 ET1310_PhyPowerDown(etdev, 1);
609
610 /* First we need to turn off all other advertisement */
611 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
612
613 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
614
615 /* Set our advertise values accordingly */
616 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_HALF);
617
618 /* Power up PHY */
619 ET1310_PhyPowerDown(etdev, 0);
620}
621
622/**
623 * TPAL_SetPhy10FullDuplex - Force the phy into 10 Base T Full Duplex mode.
624 * @etdev: pointer to the adapter structure
625 *
626 * Also sets the MAC so it is syncd up properly
627 */
628static void TPAL_SetPhy10FullDuplex(struct et131x_adapter *etdev)
629{
630 /* Power down PHY */
631 ET1310_PhyPowerDown(etdev, 1);
632
633 /* First we need to turn off all other advertisement */
634 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
635
636 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
637
638 /* Set our advertise values accordingly */
639 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL);
640
641 /* Power up PHY */
642 ET1310_PhyPowerDown(etdev, 0);
643}
644
645/**
646 * TPAL_SetPhy10Force - Force Base-T FD mode WITHOUT using autonegotiation
647 * @etdev: pointer to the adapter structure
648 */
649static void TPAL_SetPhy10Force(struct et131x_adapter *etdev)
650{
651 /* Power down PHY */
652 ET1310_PhyPowerDown(etdev, 1);
653
654 /* Disable autoneg */
655 ET1310_PhyAutoNeg(etdev, false);
656
657 /* Disable all advertisement */
658 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
659 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
660 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
661
662 /* Force 10 Mbps */
663 ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_10MBPS);
664
665 /* Force Full duplex */
666 ET1310_PhyDuplexMode(etdev, TRUEPHY_DUPLEX_FULL);
667
668 /* Power up PHY */
669 ET1310_PhyPowerDown(etdev, 0);
670}
671
672/**
673 * TPAL_SetPhy100HalfDuplex - Force 100 Base T Half Duplex mode.
674 * @etdev: pointer to the adapter structure
675 *
676 * Also sets the MAC so it is syncd up properly.
677 */
678static void TPAL_SetPhy100HalfDuplex(struct et131x_adapter *etdev)
679{
680 /* Power down PHY */
681 ET1310_PhyPowerDown(etdev, 1);
682
683 /* first we need to turn off all other advertisement */
684 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
685
686 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
687
688 /* Set our advertise values accordingly */
689 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_HALF);
690
691 /* Set speed */
692 ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_100MBPS);
693
694 /* Power up PHY */
695 ET1310_PhyPowerDown(etdev, 0);
696}
697
698/**
699 * TPAL_SetPhy100FullDuplex - Force 100 Base T Full Duplex mode.
700 * @etdev: pointer to the adapter structure
701 *
702 * Also sets the MAC so it is syncd up properly
703 */
704static void TPAL_SetPhy100FullDuplex(struct et131x_adapter *etdev)
705{
706 /* Power down PHY */
707 ET1310_PhyPowerDown(etdev, 1);
708
709 /* First we need to turn off all other advertisement */
710 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
711
712 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
713
714 /* Set our advertise values accordingly */
715 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL);
716
717 /* Power up PHY */
718 ET1310_PhyPowerDown(etdev, 0);
719}
720
721/**
722 * TPAL_SetPhy100Force - Force 100 BaseT FD mode WITHOUT using autonegotiation
723 * @etdev: pointer to the adapter structure
724 */
725static void TPAL_SetPhy100Force(struct et131x_adapter *etdev)
726{
727 /* Power down PHY */
728 ET1310_PhyPowerDown(etdev, 1);
729
730 /* Disable autoneg */
731 ET1310_PhyAutoNeg(etdev, false);
732
733 /* Disable all advertisement */
734 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
735 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
736 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
737
738 /* Force 100 Mbps */
739 ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_100MBPS);
740
741 /* Force Full duplex */
742 ET1310_PhyDuplexMode(etdev, TRUEPHY_DUPLEX_FULL);
743
744 /* Power up PHY */
745 ET1310_PhyPowerDown(etdev, 0);
746}
747
748/**
749 * TPAL_SetPhy1000FullDuplex - Force 1000 Base T Full Duplex mode
750 * @etdev: pointer to the adapter structure
751 *
752 * Also sets the MAC so it is syncd up properly.
753 */
754static void TPAL_SetPhy1000FullDuplex(struct et131x_adapter *etdev)
755{
756 /* Power down PHY */
757 ET1310_PhyPowerDown(etdev, 1);
758
759 /* first we need to turn off all other advertisement */
760 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
761
762 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
763
764 /* set our advertise values accordingly */
765 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL);
766
767 /* power up PHY */
768 ET1310_PhyPowerDown(etdev, 0);
769}
770
771/**
772 * TPAL_SetPhyAutoNeg - Set phy to autonegotiation mode.
773 * @etdev: pointer to the adapter structure
774 */
775static void TPAL_SetPhyAutoNeg(struct et131x_adapter *etdev)
776{
777 /* Power down PHY */
778 ET1310_PhyPowerDown(etdev, 1);
779
780 /* Turn on advertisement of all capabilities */
781 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_BOTH);
782
783 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_BOTH);
784
785 if (etdev->pdev->device != ET131X_PCI_DEVICE_ID_FAST)
786 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL);
787 else
788 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
789
790 /* Make sure auto-neg is ON (it is disabled in FORCE modes) */
791 ET1310_PhyAutoNeg(etdev, true);
792
793 /* Power up PHY */
794 ET1310_PhyPowerDown(etdev, 0);
795}
796
797
798
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700799/**
800 * et131x_xcvr_init - Init the phy if we are setting it into force mode
801 * @adapter: pointer to our private adapter structure
802 *
803 * Returns 0 on success, errno on failure (as defined in errno.h)
804 */
805static int et131x_xcvr_init(struct et131x_adapter *adapter)
806{
807 int status = 0;
808 MI_IMR_t imr;
809 MI_ISR_t isr;
810 MI_LCR2_t lcr2;
811
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700812 /* Zero out the adapter structure variable representing BMSR */
813 adapter->Bmsr.value = 0;
814
Alan Cox1210db92009-10-06 15:51:10 +0100815 MiRead(adapter, (u8) offsetof(MI_REGS_t, isr), &isr.value);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700816
Alan Cox1210db92009-10-06 15:51:10 +0100817 MiRead(adapter, (u8) offsetof(MI_REGS_t, imr), &imr.value);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700818
819 /* Set the link status interrupt only. Bad behavior when link status
820 * and auto neg are set, we run into a nested interrupt problem
821 */
822 imr.bits.int_en = 0x1;
823 imr.bits.link_status = 0x1;
824 imr.bits.autoneg_status = 0x1;
825
Alan Cox1210db92009-10-06 15:51:10 +0100826 MiWrite(adapter, (u8) offsetof(MI_REGS_t, imr), imr.value);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700827
828 /* Set the LED behavior such that LED 1 indicates speed (off =
829 * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates
830 * link and activity (on for link, blink off for activity).
831 *
832 * NOTE: Some customizations have been added here for specific
833 * vendors; The LED behavior is now determined by vendor data in the
834 * EEPROM. However, the above description is the default.
835 */
836 if ((adapter->eepromData[1] & 0x4) == 0) {
Alan Cox1210db92009-10-06 15:51:10 +0100837 MiRead(adapter, (u8) offsetof(MI_REGS_t, lcr2),
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700838 &lcr2.value);
839 if ((adapter->eepromData[1] & 0x8) == 0)
840 lcr2.bits.led_tx_rx = 0x3;
841 else
842 lcr2.bits.led_tx_rx = 0x4;
843 lcr2.bits.led_link = 0xa;
Alan Cox1210db92009-10-06 15:51:10 +0100844 MiWrite(adapter, (u8) offsetof(MI_REGS_t, lcr2),
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700845 lcr2.value);
846 }
847
848 /* Determine if we need to go into a force mode and set it */
849 if (adapter->AiForceSpeed == 0 && adapter->AiForceDpx == 0) {
Alan Cox1210db92009-10-06 15:51:10 +0100850 if (adapter->RegistryFlowControl == TxOnly ||
851 adapter->RegistryFlowControl == Both)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700852 ET1310_PhyAccessMiBit(adapter,
853 TRUEPHY_BIT_SET, 4, 11, NULL);
Alan Cox1210db92009-10-06 15:51:10 +0100854 else
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700855 ET1310_PhyAccessMiBit(adapter,
856 TRUEPHY_BIT_CLEAR, 4, 11, NULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700857
Alan Cox1210db92009-10-06 15:51:10 +0100858 if (adapter->RegistryFlowControl == Both)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700859 ET1310_PhyAccessMiBit(adapter,
860 TRUEPHY_BIT_SET, 4, 10, NULL);
Alan Cox1210db92009-10-06 15:51:10 +0100861 else
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700862 ET1310_PhyAccessMiBit(adapter,
863 TRUEPHY_BIT_CLEAR, 4, 10, NULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700864
865 /* Set the phy to autonegotiation */
866 ET1310_PhyAutoNeg(adapter, true);
867
868 /* NOTE - Do we need this? */
869 ET1310_PhyAccessMiBit(adapter, TRUEPHY_BIT_SET, 0, 9, NULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700870 return status;
871 } else {
872 ET1310_PhyAutoNeg(adapter, false);
873
874 /* Set to the correct force mode. */
875 if (adapter->AiForceDpx != 1) {
Alan Cox1210db92009-10-06 15:51:10 +0100876 if (adapter->RegistryFlowControl == TxOnly ||
877 adapter->RegistryFlowControl == Both)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700878 ET1310_PhyAccessMiBit(adapter,
879 TRUEPHY_BIT_SET, 4, 11,
880 NULL);
Alan Cox1210db92009-10-06 15:51:10 +0100881 else
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700882 ET1310_PhyAccessMiBit(adapter,
883 TRUEPHY_BIT_CLEAR, 4, 11,
884 NULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700885
Alan Cox1210db92009-10-06 15:51:10 +0100886 if (adapter->RegistryFlowControl == Both)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700887 ET1310_PhyAccessMiBit(adapter,
888 TRUEPHY_BIT_SET, 4, 10,
889 NULL);
Alan Cox1210db92009-10-06 15:51:10 +0100890 else
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700891 ET1310_PhyAccessMiBit(adapter,
892 TRUEPHY_BIT_CLEAR, 4, 10,
893 NULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700894 } else {
895 ET1310_PhyAccessMiBit(adapter,
896 TRUEPHY_BIT_CLEAR, 4, 10, NULL);
897 ET1310_PhyAccessMiBit(adapter,
898 TRUEPHY_BIT_CLEAR, 4, 11, NULL);
899 }
900
901 switch (adapter->AiForceSpeed) {
902 case 10:
Alan Cox64f93032009-06-10 17:30:41 +0100903 if (adapter->AiForceDpx == 1)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700904 TPAL_SetPhy10HalfDuplex(adapter);
Alan Cox64f93032009-06-10 17:30:41 +0100905 else if (adapter->AiForceDpx == 2)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700906 TPAL_SetPhy10FullDuplex(adapter);
Alan Cox64f93032009-06-10 17:30:41 +0100907 else
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700908 TPAL_SetPhy10Force(adapter);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700909 break;
910 case 100:
Alan Cox64f93032009-06-10 17:30:41 +0100911 if (adapter->AiForceDpx == 1)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700912 TPAL_SetPhy100HalfDuplex(adapter);
Alan Cox64f93032009-06-10 17:30:41 +0100913 else if (adapter->AiForceDpx == 2)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700914 TPAL_SetPhy100FullDuplex(adapter);
Alan Cox64f93032009-06-10 17:30:41 +0100915 else
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700916 TPAL_SetPhy100Force(adapter);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700917 break;
918 case 1000:
919 TPAL_SetPhy1000FullDuplex(adapter);
920 break;
921 }
922
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700923 return status;
924 }
925}
926
Alan Cox25ad00b2009-08-19 18:21:44 +0100927void et131x_Mii_check(struct et131x_adapter *etdev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700928 MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints)
929{
Alan Cox1210db92009-10-06 15:51:10 +0100930 u8 link_status;
931 u32 autoneg_status;
932 u32 speed;
933 u32 duplex;
934 u32 mdi_mdix;
935 u32 masterslave;
936 u32 polarity;
Alan Cox37628602009-08-19 18:21:50 +0100937 unsigned long flags;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700938
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700939 if (bmsr_ints.bits.link_status) {
940 if (bmsr.bits.link_status) {
Alan Cox25ad00b2009-08-19 18:21:44 +0100941 etdev->PoMgmt.TransPhyComaModeOnBoot = 20;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700942
943 /* Update our state variables and indicate the
944 * connected state
945 */
Alan Cox37628602009-08-19 18:21:50 +0100946 spin_lock_irqsave(&etdev->Lock, flags);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700947
Alan Cox25ad00b2009-08-19 18:21:44 +0100948 etdev->MediaState = NETIF_STATUS_MEDIA_CONNECT;
Alan Coxf6b35d62009-08-27 11:02:05 +0100949 etdev->Flags &= ~fMP_ADAPTER_LINK_DETECTION;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700950
Alan Cox37628602009-08-19 18:21:50 +0100951 spin_unlock_irqrestore(&etdev->Lock, flags);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700952
Alan Cox5f1377d2009-10-06 15:47:55 +0100953 netif_carrier_on(etdev->netdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700954 } else {
Alan Cox15700032009-08-27 11:03:09 +0100955 dev_warn(&etdev->pdev->dev,
956 "Link down - cable problem ?\n");
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700957
Alan Cox9fa81092009-08-27 11:00:36 +0100958 if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) {
Alan Cox64f93032009-06-10 17:30:41 +0100959 /* NOTE - Is there a way to query this without
960 * TruePHY?
Alan Cox25ad00b2009-08-19 18:21:44 +0100961 * && TRU_QueryCoreType(etdev->hTruePhy, 0) == EMI_TRUEPHY_A13O) {
Alan Cox64f93032009-06-10 17:30:41 +0100962 */
Alan Cox1210db92009-10-06 15:51:10 +0100963 u16 Register18;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700964
Alan Cox25ad00b2009-08-19 18:21:44 +0100965 MiRead(etdev, 0x12, &Register18);
966 MiWrite(etdev, 0x12, Register18 | 0x4);
967 MiWrite(etdev, 0x10, Register18 | 0x8402);
968 MiWrite(etdev, 0x11, Register18 | 511);
969 MiWrite(etdev, 0x12, Register18);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700970 }
971
972 /* For the first N seconds of life, we are in "link
973 * detection" When we are in this state, we should
974 * only report "connected". When the LinkDetection
975 * Timer expires, we can report disconnected (handled
976 * in the LinkDetectionDPC).
977 */
Alan Coxf6b35d62009-08-27 11:02:05 +0100978 if (!(etdev->Flags & fMP_ADAPTER_LINK_DETECTION) ||
979 (etdev->MediaState == NETIF_STATUS_MEDIA_DISCONNECT)) {
Alan Cox37628602009-08-19 18:21:50 +0100980 spin_lock_irqsave(&etdev->Lock, flags);
Alan Cox25ad00b2009-08-19 18:21:44 +0100981 etdev->MediaState =
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700982 NETIF_STATUS_MEDIA_DISCONNECT;
Alan Cox25ad00b2009-08-19 18:21:44 +0100983 spin_unlock_irqrestore(&etdev->Lock,
Alan Cox37628602009-08-19 18:21:50 +0100984 flags);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700985
Alan Cox5f1377d2009-10-06 15:47:55 +0100986 netif_carrier_off(etdev->netdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700987 }
988
Alan Cox9fa81092009-08-27 11:00:36 +0100989 etdev->linkspeed = 0;
Alan Cox576b38e2009-08-27 11:00:47 +0100990 etdev->duplex_mode = 0;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700991
992 /* Free the packets being actively sent & stopped */
Alan Cox25ad00b2009-08-19 18:21:44 +0100993 et131x_free_busy_send_packets(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700994
995 /* Re-initialize the send structures */
Alan Cox25ad00b2009-08-19 18:21:44 +0100996 et131x_init_send(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700997
998 /* Reset the RFD list and re-start RU */
Alan Cox25ad00b2009-08-19 18:21:44 +0100999 et131x_reset_recv(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001000
1001 /*
1002 * Bring the device back to the state it was during
1003 * init prior to autonegotiation being complete. This
1004 * way, when we get the auto-neg complete interrupt,
1005 * we can complete init by calling ConfigMacREGS2.
1006 */
Alan Cox25ad00b2009-08-19 18:21:44 +01001007 et131x_soft_reset(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001008
1009 /* Setup ET1310 as per the documentation */
Alan Cox25ad00b2009-08-19 18:21:44 +01001010 et131x_adapter_setup(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001011
1012 /* Setup the PHY into coma mode until the cable is
1013 * plugged back in
1014 */
Alan Cox25ad00b2009-08-19 18:21:44 +01001015 if (etdev->RegistryPhyComa == 1)
1016 EnablePhyComa(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001017 }
1018 }
1019
1020 if (bmsr_ints.bits.auto_neg_complete ||
Alan Cox25ad00b2009-08-19 18:21:44 +01001021 (etdev->AiForceDpx == 3 && bmsr_ints.bits.link_status)) {
1022 if (bmsr.bits.auto_neg_complete || etdev->AiForceDpx == 3) {
1023 ET1310_PhyLinkStatus(etdev,
Alan Cox9fa81092009-08-27 11:00:36 +01001024 &link_status, &autoneg_status,
1025 &speed, &duplex, &mdi_mdix,
1026 &masterslave, &polarity);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001027
Alan Cox9fa81092009-08-27 11:00:36 +01001028 etdev->linkspeed = speed;
1029 etdev->duplex_mode = duplex;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001030
Alan Cox25ad00b2009-08-19 18:21:44 +01001031 etdev->PoMgmt.TransPhyComaModeOnBoot = 20;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001032
Alan Cox9fa81092009-08-27 11:00:36 +01001033 if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) {
Alan Cox64f93032009-06-10 17:30:41 +01001034 /*
1035 * NOTE - Is there a way to query this without
1036 * TruePHY?
Alan Cox25ad00b2009-08-19 18:21:44 +01001037 * && TRU_QueryCoreType(etdev->hTruePhy, 0)== EMI_TRUEPHY_A13O) {
Alan Cox64f93032009-06-10 17:30:41 +01001038 */
Alan Cox1210db92009-10-06 15:51:10 +01001039 u16 Register18;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001040
Alan Cox25ad00b2009-08-19 18:21:44 +01001041 MiRead(etdev, 0x12, &Register18);
1042 MiWrite(etdev, 0x12, Register18 | 0x4);
1043 MiWrite(etdev, 0x10, Register18 | 0x8402);
1044 MiWrite(etdev, 0x11, Register18 | 511);
1045 MiWrite(etdev, 0x12, Register18);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001046 }
1047
Alan Cox25ad00b2009-08-19 18:21:44 +01001048 ConfigFlowControl(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001049
Alan Cox9fa81092009-08-27 11:00:36 +01001050 if (etdev->linkspeed == TRUEPHY_SPEED_1000MBPS &&
Alan Cox25ad00b2009-08-19 18:21:44 +01001051 etdev->RegistryJumboPacket > 2048)
1052 ET1310_PhyAndOrReg(etdev, 0x16, 0xcfff,
Alan Cox64f93032009-06-10 17:30:41 +01001053 0x2000);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001054
Alan Cox25ad00b2009-08-19 18:21:44 +01001055 SetRxDmaTimer(etdev);
1056 ConfigMACRegs2(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001057 }
1058 }
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001059}
1060
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001061/*
1062 * The routines which follow provide low-level access to the PHY, and are used
1063 * primarily by the routines above (although there are a few places elsewhere
1064 * in the driver where this level of access is required).
1065 */
1066
Alan Cox1210db92009-10-06 15:51:10 +01001067static const u16 ConfigPhy[25][2] = {
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001068 /* Reg Value Register */
1069 /* Addr */
1070 {0x880B, 0x0926}, /* AfeIfCreg4B1000Msbs */
1071 {0x880C, 0x0926}, /* AfeIfCreg4B100Msbs */
1072 {0x880D, 0x0926}, /* AfeIfCreg4B10Msbs */
1073
1074 {0x880E, 0xB4D3}, /* AfeIfCreg4B1000Lsbs */
1075 {0x880F, 0xB4D3}, /* AfeIfCreg4B100Lsbs */
1076 {0x8810, 0xB4D3}, /* AfeIfCreg4B10Lsbs */
1077
1078 {0x8805, 0xB03E}, /* AfeIfCreg3B1000Msbs */
1079 {0x8806, 0xB03E}, /* AfeIfCreg3B100Msbs */
1080 {0x8807, 0xFF00}, /* AfeIfCreg3B10Msbs */
1081
1082 {0x8808, 0xE090}, /* AfeIfCreg3B1000Lsbs */
1083 {0x8809, 0xE110}, /* AfeIfCreg3B100Lsbs */
1084 {0x880A, 0x0000}, /* AfeIfCreg3B10Lsbs */
1085
1086 {0x300D, 1}, /* DisableNorm */
1087
1088 {0x280C, 0x0180}, /* LinkHoldEnd */
1089
1090 {0x1C21, 0x0002}, /* AlphaM */
1091
1092 {0x3821, 6}, /* FfeLkgTx0 */
1093 {0x381D, 1}, /* FfeLkg1g4 */
1094 {0x381E, 1}, /* FfeLkg1g5 */
1095 {0x381F, 1}, /* FfeLkg1g6 */
1096 {0x3820, 1}, /* FfeLkg1g7 */
1097
1098 {0x8402, 0x01F0}, /* Btinact */
1099 {0x800E, 20}, /* LftrainTime */
1100 {0x800F, 24}, /* DvguardTime */
1101 {0x8010, 46}, /* IdlguardTime */
1102
1103 {0, 0}
1104
1105};
1106
1107/* condensed version of the phy initialization routine */
Alan Cox25ad00b2009-08-19 18:21:44 +01001108void ET1310_PhyInit(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001109{
Alan Cox1210db92009-10-06 15:51:10 +01001110 u16 data, index;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001111
Alan Cox25ad00b2009-08-19 18:21:44 +01001112 if (etdev == NULL)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001113 return;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001114
Alan Cox64f93032009-06-10 17:30:41 +01001115 /* get the identity (again ?) */
Alan Cox9fa81092009-08-27 11:00:36 +01001116 MiRead(etdev, PHY_ID_1, &data);
1117 MiRead(etdev, PHY_ID_2, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001118
Alan Cox64f93032009-06-10 17:30:41 +01001119 /* what does this do/achieve ? */
Alan Cox9fa81092009-08-27 11:00:36 +01001120 MiRead(etdev, PHY_MPHY_CONTROL_REG, &data); /* should read 0002 */
Alan Cox25ad00b2009-08-19 18:21:44 +01001121 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0006);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001122
Alan Cox64f93032009-06-10 17:30:41 +01001123 /* read modem register 0402, should I do something with the return
1124 data ? */
Alan Cox25ad00b2009-08-19 18:21:44 +01001125 MiWrite(etdev, PHY_INDEX_REG, 0x0402);
Alan Cox9fa81092009-08-27 11:00:36 +01001126 MiRead(etdev, PHY_DATA_REG, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001127
Alan Cox64f93032009-06-10 17:30:41 +01001128 /* what does this do/achieve ? */
Alan Cox25ad00b2009-08-19 18:21:44 +01001129 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001130
Alan Cox64f93032009-06-10 17:30:41 +01001131 /* get the identity (again ?) */
Alan Cox9fa81092009-08-27 11:00:36 +01001132 MiRead(etdev, PHY_ID_1, &data);
1133 MiRead(etdev, PHY_ID_2, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001134
Alan Cox64f93032009-06-10 17:30:41 +01001135 /* what does this achieve ? */
Alan Cox9fa81092009-08-27 11:00:36 +01001136 MiRead(etdev, PHY_MPHY_CONTROL_REG, &data); /* should read 0002 */
Alan Cox25ad00b2009-08-19 18:21:44 +01001137 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0006);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001138
Alan Cox64f93032009-06-10 17:30:41 +01001139 /* read modem register 0402, should I do something with
1140 the return data? */
Alan Cox25ad00b2009-08-19 18:21:44 +01001141 MiWrite(etdev, PHY_INDEX_REG, 0x0402);
Alan Cox9fa81092009-08-27 11:00:36 +01001142 MiRead(etdev, PHY_DATA_REG, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001143
Alan Cox25ad00b2009-08-19 18:21:44 +01001144 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001145
Alan Cox64f93032009-06-10 17:30:41 +01001146 /* what does this achieve (should return 0x1040) */
Alan Cox9fa81092009-08-27 11:00:36 +01001147 MiRead(etdev, PHY_CONTROL, &data);
1148 MiRead(etdev, PHY_MPHY_CONTROL_REG, &data); /* should read 0002 */
Alan Cox25ad00b2009-08-19 18:21:44 +01001149 MiWrite(etdev, PHY_CONTROL, 0x1840);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001150
Alan Cox25ad00b2009-08-19 18:21:44 +01001151 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0007);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001152
Alan Cox64f93032009-06-10 17:30:41 +01001153 /* here the writing of the array starts.... */
Alan Cox9fa81092009-08-27 11:00:36 +01001154 index = 0;
1155 while (ConfigPhy[index][0] != 0x0000) {
Alan Cox64f93032009-06-10 17:30:41 +01001156 /* write value */
Alan Cox9fa81092009-08-27 11:00:36 +01001157 MiWrite(etdev, PHY_INDEX_REG, ConfigPhy[index][0]);
1158 MiWrite(etdev, PHY_DATA_REG, ConfigPhy[index][1]);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001159
Alan Cox64f93032009-06-10 17:30:41 +01001160 /* read it back */
Alan Cox9fa81092009-08-27 11:00:36 +01001161 MiWrite(etdev, PHY_INDEX_REG, ConfigPhy[index][0]);
1162 MiRead(etdev, PHY_DATA_REG, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001163
Alan Cox64f93032009-06-10 17:30:41 +01001164 /* do a check on the value read back ? */
Alan Cox9fa81092009-08-27 11:00:36 +01001165 index++;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001166 }
Alan Cox64f93032009-06-10 17:30:41 +01001167 /* here the writing of the array ends... */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001168
Alan Cox9fa81092009-08-27 11:00:36 +01001169 MiRead(etdev, PHY_CONTROL, &data); /* 0x1840 */
1170 MiRead(etdev, PHY_MPHY_CONTROL_REG, &data);/* should read 0007 */
Alan Cox25ad00b2009-08-19 18:21:44 +01001171 MiWrite(etdev, PHY_CONTROL, 0x1040);
1172 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001173}
1174