blob: 6b77c541df2c5f4a4cde2f8b9f586c498b5c8124 [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 */
112int PhyMiRead(struct et131x_adapter *adapter, uint8_t xcvrAddr,
113 uint8_t xcvrReg, uint16_t *value)
114{
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;
117 uint32_t 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 *
177 * Return 0 on success, errno on failure (as defined in errno.h)
178 */
179int MiWrite(struct et131x_adapter *adapter, uint8_t xcvrReg, uint16_t value)
180{
Alan Coxf3f415a2009-08-27 10:59:30 +0100181 struct _MAC_t __iomem *mac = &adapter->regs->mac;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700182 int status = 0;
183 uint8_t xcvrAddr = adapter->Stats.xcvr_addr;
184 uint32_t delay;
Alan Cox57aed3b2009-10-06 15:51:04 +0100185 u32 miiAddr;
186 u32 miiCmd;
187 u32 miiIndicator;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700188
189 /* Save a local copy of the registers we are dealing with so we can
190 * set them back
191 */
Alan Cox57aed3b2009-10-06 15:51:04 +0100192 miiAddr = readl(&mac->mii_mgmt_addr);
193 miiCmd = readl(&mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700194
195 /* Stop the current operation */
Alan Cox57aed3b2009-10-06 15:51:04 +0100196 writel(0, &mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700197
198 /* Set up the register we need to write to on the correct PHY */
Alan Cox57aed3b2009-10-06 15:51:04 +0100199 writel(MII_ADDR(xcvrAddr, xcvrReg), &mac->mii_mgmt_addr);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700200
201 /* Add the value to write to the registers to the mac */
Alan Cox57aed3b2009-10-06 15:51:04 +0100202 writel(value, &mac->mii_mgmt_ctrl);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700203 delay = 0;
204
205 do {
206 udelay(50);
207 delay++;
Alan Cox57aed3b2009-10-06 15:51:04 +0100208 miiIndicator = readl(&mac->mii_mgmt_indicator);
209 } while ((miiIndicator & MGMT_BUSY) && delay < 100);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700210
211 /* If we hit the max delay, we could not write the register */
212 if (delay == 100) {
213 uint16_t TempValue;
214
Alan Cox15700032009-08-27 11:03:09 +0100215 dev_warn(&adapter->pdev->dev,
216 "xcvrReg 0x%08x could not be written", xcvrReg);
217 dev_warn(&adapter->pdev->dev, "status is 0x%08x\n",
Alan Cox57aed3b2009-10-06 15:51:04 +0100218 miiIndicator);
Alan Cox15700032009-08-27 11:03:09 +0100219 dev_warn(&adapter->pdev->dev, "command is 0x%08x\n",
Alan Cox57aed3b2009-10-06 15:51:04 +0100220 readl(&mac->mii_mgmt_cmd));
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700221
222 MiRead(adapter, xcvrReg, &TempValue);
223
224 status = -EIO;
225 }
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700226 /* Stop the write operation */
Alan Cox57aed3b2009-10-06 15:51:04 +0100227 writel(0, &mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700228
229 /* set the registers we touched back to the state at which we entered
Alan Cox64f93032009-06-10 17:30:41 +0100230 * this function
231 */
Alan Cox57aed3b2009-10-06 15:51:04 +0100232 writel(miiAddr, &mac->mii_mgmt_addr);
233 writel(miiCmd, &mac->mii_mgmt_cmd);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700234
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700235 return status;
236}
237
238/**
239 * et131x_xcvr_find - Find the PHY ID
240 * @adapter: pointer to our private adapter structure
241 *
242 * Returns 0 on success, errno on failure (as defined in errno.h)
243 */
244int et131x_xcvr_find(struct et131x_adapter *adapter)
245{
246 int status = -ENODEV;
247 uint8_t xcvr_addr;
248 MI_IDR1_t idr1;
249 MI_IDR2_t idr2;
250 uint32_t xcvr_id;
251
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700252 /* We need to get xcvr id and address we just get the first one */
253 for (xcvr_addr = 0; xcvr_addr < 32; xcvr_addr++) {
254 /* Read the ID from the PHY */
255 PhyMiRead(adapter, xcvr_addr,
256 (uint8_t) offsetof(MI_REGS_t, idr1),
257 &idr1.value);
258 PhyMiRead(adapter, xcvr_addr,
259 (uint8_t) offsetof(MI_REGS_t, idr2),
260 &idr2.value);
261
262 xcvr_id = (uint32_t) ((idr1.value << 16) | idr2.value);
263
264 if ((idr1.value != 0) && (idr1.value != 0xffff)) {
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700265 adapter->Stats.xcvr_id = xcvr_id;
266 adapter->Stats.xcvr_addr = xcvr_addr;
267
268 status = 0;
269 break;
270 }
271 }
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700272 return status;
273}
274
275/**
276 * et131x_setphy_normal - Set PHY for normal operation.
277 * @adapter: pointer to our private adapter structure
278 *
279 * Used by Power Management to force the PHY into 10 Base T half-duplex mode,
280 * when going to D3 in WOL mode. Also used during initialization to set the
281 * PHY for normal operation.
282 */
283int et131x_setphy_normal(struct et131x_adapter *adapter)
284{
285 int status;
286
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700287 /* Make sure the PHY is powered up */
288 ET1310_PhyPowerDown(adapter, 0);
289 status = et131x_xcvr_init(adapter);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700290 return status;
291}
292
293/**
294 * et131x_xcvr_init - Init the phy if we are setting it into force mode
295 * @adapter: pointer to our private adapter structure
296 *
297 * Returns 0 on success, errno on failure (as defined in errno.h)
298 */
299static int et131x_xcvr_init(struct et131x_adapter *adapter)
300{
301 int status = 0;
302 MI_IMR_t imr;
303 MI_ISR_t isr;
304 MI_LCR2_t lcr2;
305
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700306 /* Zero out the adapter structure variable representing BMSR */
307 adapter->Bmsr.value = 0;
308
309 MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, isr), &isr.value);
310
311 MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, imr), &imr.value);
312
313 /* Set the link status interrupt only. Bad behavior when link status
314 * and auto neg are set, we run into a nested interrupt problem
315 */
316 imr.bits.int_en = 0x1;
317 imr.bits.link_status = 0x1;
318 imr.bits.autoneg_status = 0x1;
319
320 MiWrite(adapter, (uint8_t) offsetof(MI_REGS_t, imr), imr.value);
321
322 /* Set the LED behavior such that LED 1 indicates speed (off =
323 * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates
324 * link and activity (on for link, blink off for activity).
325 *
326 * NOTE: Some customizations have been added here for specific
327 * vendors; The LED behavior is now determined by vendor data in the
328 * EEPROM. However, the above description is the default.
329 */
330 if ((adapter->eepromData[1] & 0x4) == 0) {
331 MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, lcr2),
332 &lcr2.value);
333 if ((adapter->eepromData[1] & 0x8) == 0)
334 lcr2.bits.led_tx_rx = 0x3;
335 else
336 lcr2.bits.led_tx_rx = 0x4;
337 lcr2.bits.led_link = 0xa;
338 MiWrite(adapter, (uint8_t) offsetof(MI_REGS_t, lcr2),
339 lcr2.value);
340 }
341
342 /* Determine if we need to go into a force mode and set it */
343 if (adapter->AiForceSpeed == 0 && adapter->AiForceDpx == 0) {
344 if ((adapter->RegistryFlowControl == TxOnly) ||
345 (adapter->RegistryFlowControl == Both)) {
346 ET1310_PhyAccessMiBit(adapter,
347 TRUEPHY_BIT_SET, 4, 11, NULL);
348 } else {
349 ET1310_PhyAccessMiBit(adapter,
350 TRUEPHY_BIT_CLEAR, 4, 11, NULL);
351 }
352
353 if (adapter->RegistryFlowControl == Both) {
354 ET1310_PhyAccessMiBit(adapter,
355 TRUEPHY_BIT_SET, 4, 10, NULL);
356 } else {
357 ET1310_PhyAccessMiBit(adapter,
358 TRUEPHY_BIT_CLEAR, 4, 10, NULL);
359 }
360
361 /* Set the phy to autonegotiation */
362 ET1310_PhyAutoNeg(adapter, true);
363
364 /* NOTE - Do we need this? */
365 ET1310_PhyAccessMiBit(adapter, TRUEPHY_BIT_SET, 0, 9, NULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700366 return status;
367 } else {
368 ET1310_PhyAutoNeg(adapter, false);
369
370 /* Set to the correct force mode. */
371 if (adapter->AiForceDpx != 1) {
372 if ((adapter->RegistryFlowControl == TxOnly) ||
373 (adapter->RegistryFlowControl == Both)) {
374 ET1310_PhyAccessMiBit(adapter,
375 TRUEPHY_BIT_SET, 4, 11,
376 NULL);
377 } else {
378 ET1310_PhyAccessMiBit(adapter,
379 TRUEPHY_BIT_CLEAR, 4, 11,
380 NULL);
381 }
382
383 if (adapter->RegistryFlowControl == Both) {
384 ET1310_PhyAccessMiBit(adapter,
385 TRUEPHY_BIT_SET, 4, 10,
386 NULL);
387 } else {
388 ET1310_PhyAccessMiBit(adapter,
389 TRUEPHY_BIT_CLEAR, 4, 10,
390 NULL);
391 }
392 } else {
393 ET1310_PhyAccessMiBit(adapter,
394 TRUEPHY_BIT_CLEAR, 4, 10, NULL);
395 ET1310_PhyAccessMiBit(adapter,
396 TRUEPHY_BIT_CLEAR, 4, 11, NULL);
397 }
398
399 switch (adapter->AiForceSpeed) {
400 case 10:
Alan Cox64f93032009-06-10 17:30:41 +0100401 if (adapter->AiForceDpx == 1)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700402 TPAL_SetPhy10HalfDuplex(adapter);
Alan Cox64f93032009-06-10 17:30:41 +0100403 else if (adapter->AiForceDpx == 2)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700404 TPAL_SetPhy10FullDuplex(adapter);
Alan Cox64f93032009-06-10 17:30:41 +0100405 else
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700406 TPAL_SetPhy10Force(adapter);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700407 break;
408 case 100:
Alan Cox64f93032009-06-10 17:30:41 +0100409 if (adapter->AiForceDpx == 1)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700410 TPAL_SetPhy100HalfDuplex(adapter);
Alan Cox64f93032009-06-10 17:30:41 +0100411 else if (adapter->AiForceDpx == 2)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700412 TPAL_SetPhy100FullDuplex(adapter);
Alan Cox64f93032009-06-10 17:30:41 +0100413 else
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700414 TPAL_SetPhy100Force(adapter);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700415 break;
416 case 1000:
417 TPAL_SetPhy1000FullDuplex(adapter);
418 break;
419 }
420
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700421 return status;
422 }
423}
424
Alan Cox25ad00b2009-08-19 18:21:44 +0100425void et131x_Mii_check(struct et131x_adapter *etdev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700426 MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints)
427{
Alan Cox9fa81092009-08-27 11:00:36 +0100428 uint8_t link_status;
429 uint32_t autoneg_status;
430 uint32_t speed;
431 uint32_t duplex;
432 uint32_t mdi_mdix;
433 uint32_t masterslave;
434 uint32_t polarity;
Alan Cox37628602009-08-19 18:21:50 +0100435 unsigned long flags;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700436
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700437 if (bmsr_ints.bits.link_status) {
438 if (bmsr.bits.link_status) {
Alan Cox25ad00b2009-08-19 18:21:44 +0100439 etdev->PoMgmt.TransPhyComaModeOnBoot = 20;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700440
441 /* Update our state variables and indicate the
442 * connected state
443 */
Alan Cox37628602009-08-19 18:21:50 +0100444 spin_lock_irqsave(&etdev->Lock, flags);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700445
Alan Cox25ad00b2009-08-19 18:21:44 +0100446 etdev->MediaState = NETIF_STATUS_MEDIA_CONNECT;
Alan Coxf6b35d62009-08-27 11:02:05 +0100447 etdev->Flags &= ~fMP_ADAPTER_LINK_DETECTION;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700448
Alan Cox37628602009-08-19 18:21:50 +0100449 spin_unlock_irqrestore(&etdev->Lock, flags);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700450
Alan Cox5f1377d2009-10-06 15:47:55 +0100451 netif_carrier_on(etdev->netdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700452 } else {
Alan Cox15700032009-08-27 11:03:09 +0100453 dev_warn(&etdev->pdev->dev,
454 "Link down - cable problem ?\n");
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700455
Alan Cox9fa81092009-08-27 11:00:36 +0100456 if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) {
Alan Cox64f93032009-06-10 17:30:41 +0100457 /* NOTE - Is there a way to query this without
458 * TruePHY?
Alan Cox25ad00b2009-08-19 18:21:44 +0100459 * && TRU_QueryCoreType(etdev->hTruePhy, 0) == EMI_TRUEPHY_A13O) {
Alan Cox64f93032009-06-10 17:30:41 +0100460 */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700461 uint16_t Register18;
462
Alan Cox25ad00b2009-08-19 18:21:44 +0100463 MiRead(etdev, 0x12, &Register18);
464 MiWrite(etdev, 0x12, Register18 | 0x4);
465 MiWrite(etdev, 0x10, Register18 | 0x8402);
466 MiWrite(etdev, 0x11, Register18 | 511);
467 MiWrite(etdev, 0x12, Register18);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700468 }
469
470 /* For the first N seconds of life, we are in "link
471 * detection" When we are in this state, we should
472 * only report "connected". When the LinkDetection
473 * Timer expires, we can report disconnected (handled
474 * in the LinkDetectionDPC).
475 */
Alan Coxf6b35d62009-08-27 11:02:05 +0100476 if (!(etdev->Flags & fMP_ADAPTER_LINK_DETECTION) ||
477 (etdev->MediaState == NETIF_STATUS_MEDIA_DISCONNECT)) {
Alan Cox37628602009-08-19 18:21:50 +0100478 spin_lock_irqsave(&etdev->Lock, flags);
Alan Cox25ad00b2009-08-19 18:21:44 +0100479 etdev->MediaState =
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700480 NETIF_STATUS_MEDIA_DISCONNECT;
Alan Cox25ad00b2009-08-19 18:21:44 +0100481 spin_unlock_irqrestore(&etdev->Lock,
Alan Cox37628602009-08-19 18:21:50 +0100482 flags);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700483
Alan Cox5f1377d2009-10-06 15:47:55 +0100484 netif_carrier_off(etdev->netdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700485 }
486
Alan Cox9fa81092009-08-27 11:00:36 +0100487 etdev->linkspeed = 0;
Alan Cox576b38e2009-08-27 11:00:47 +0100488 etdev->duplex_mode = 0;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700489
490 /* Free the packets being actively sent & stopped */
Alan Cox25ad00b2009-08-19 18:21:44 +0100491 et131x_free_busy_send_packets(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700492
493 /* Re-initialize the send structures */
Alan Cox25ad00b2009-08-19 18:21:44 +0100494 et131x_init_send(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700495
496 /* Reset the RFD list and re-start RU */
Alan Cox25ad00b2009-08-19 18:21:44 +0100497 et131x_reset_recv(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700498
499 /*
500 * Bring the device back to the state it was during
501 * init prior to autonegotiation being complete. This
502 * way, when we get the auto-neg complete interrupt,
503 * we can complete init by calling ConfigMacREGS2.
504 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100505 et131x_soft_reset(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700506
507 /* Setup ET1310 as per the documentation */
Alan Cox25ad00b2009-08-19 18:21:44 +0100508 et131x_adapter_setup(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700509
510 /* Setup the PHY into coma mode until the cable is
511 * plugged back in
512 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100513 if (etdev->RegistryPhyComa == 1)
514 EnablePhyComa(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700515 }
516 }
517
518 if (bmsr_ints.bits.auto_neg_complete ||
Alan Cox25ad00b2009-08-19 18:21:44 +0100519 (etdev->AiForceDpx == 3 && bmsr_ints.bits.link_status)) {
520 if (bmsr.bits.auto_neg_complete || etdev->AiForceDpx == 3) {
521 ET1310_PhyLinkStatus(etdev,
Alan Cox9fa81092009-08-27 11:00:36 +0100522 &link_status, &autoneg_status,
523 &speed, &duplex, &mdi_mdix,
524 &masterslave, &polarity);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700525
Alan Cox9fa81092009-08-27 11:00:36 +0100526 etdev->linkspeed = speed;
527 etdev->duplex_mode = duplex;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700528
Alan Cox25ad00b2009-08-19 18:21:44 +0100529 etdev->PoMgmt.TransPhyComaModeOnBoot = 20;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700530
Alan Cox9fa81092009-08-27 11:00:36 +0100531 if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) {
Alan Cox64f93032009-06-10 17:30:41 +0100532 /*
533 * NOTE - Is there a way to query this without
534 * TruePHY?
Alan Cox25ad00b2009-08-19 18:21:44 +0100535 * && TRU_QueryCoreType(etdev->hTruePhy, 0)== EMI_TRUEPHY_A13O) {
Alan Cox64f93032009-06-10 17:30:41 +0100536 */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700537 uint16_t Register18;
538
Alan Cox25ad00b2009-08-19 18:21:44 +0100539 MiRead(etdev, 0x12, &Register18);
540 MiWrite(etdev, 0x12, Register18 | 0x4);
541 MiWrite(etdev, 0x10, Register18 | 0x8402);
542 MiWrite(etdev, 0x11, Register18 | 511);
543 MiWrite(etdev, 0x12, Register18);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700544 }
545
Alan Cox25ad00b2009-08-19 18:21:44 +0100546 ConfigFlowControl(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700547
Alan Cox9fa81092009-08-27 11:00:36 +0100548 if (etdev->linkspeed == TRUEPHY_SPEED_1000MBPS &&
Alan Cox25ad00b2009-08-19 18:21:44 +0100549 etdev->RegistryJumboPacket > 2048)
550 ET1310_PhyAndOrReg(etdev, 0x16, 0xcfff,
Alan Cox64f93032009-06-10 17:30:41 +0100551 0x2000);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700552
Alan Cox25ad00b2009-08-19 18:21:44 +0100553 SetRxDmaTimer(etdev);
554 ConfigMACRegs2(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700555 }
556 }
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700557}
558
559/**
560 * TPAL_SetPhy10HalfDuplex - Force the phy into 10 Base T Half Duplex mode.
Alan Cox25ad00b2009-08-19 18:21:44 +0100561 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700562 *
563 * Also sets the MAC so it is syncd up properly
564 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100565void TPAL_SetPhy10HalfDuplex(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700566{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700567 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100568 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700569
570 /* First we need to turn off all other advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100571 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700572
Alan Cox25ad00b2009-08-19 18:21:44 +0100573 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700574
575 /* Set our advertise values accordingly */
Alan Cox25ad00b2009-08-19 18:21:44 +0100576 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_HALF);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700577
578 /* Power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100579 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700580}
581
582/**
583 * TPAL_SetPhy10FullDuplex - Force the phy into 10 Base T Full Duplex mode.
Alan Cox25ad00b2009-08-19 18:21:44 +0100584 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700585 *
586 * Also sets the MAC so it is syncd up properly
587 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100588void TPAL_SetPhy10FullDuplex(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700589{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700590 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100591 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700592
593 /* First we need to turn off all other advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100594 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700595
Alan Cox25ad00b2009-08-19 18:21:44 +0100596 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700597
598 /* Set our advertise values accordingly */
Alan Cox25ad00b2009-08-19 18:21:44 +0100599 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700600
601 /* Power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100602 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700603}
604
605/**
606 * TPAL_SetPhy10Force - Force Base-T FD mode WITHOUT using autonegotiation
Alan Cox25ad00b2009-08-19 18:21:44 +0100607 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700608 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100609void TPAL_SetPhy10Force(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700610{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700611 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100612 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700613
614 /* Disable autoneg */
Alan Cox25ad00b2009-08-19 18:21:44 +0100615 ET1310_PhyAutoNeg(etdev, false);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700616
617 /* Disable all advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100618 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
619 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
620 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700621
622 /* Force 10 Mbps */
Alan Cox25ad00b2009-08-19 18:21:44 +0100623 ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_10MBPS);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700624
625 /* Force Full duplex */
Alan Cox25ad00b2009-08-19 18:21:44 +0100626 ET1310_PhyDuplexMode(etdev, TRUEPHY_DUPLEX_FULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700627
628 /* Power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100629 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700630}
631
632/**
633 * TPAL_SetPhy100HalfDuplex - Force 100 Base T Half Duplex mode.
Alan Cox25ad00b2009-08-19 18:21:44 +0100634 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700635 *
636 * Also sets the MAC so it is syncd up properly.
637 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100638void TPAL_SetPhy100HalfDuplex(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700639{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700640 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100641 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700642
643 /* first we need to turn off all other advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100644 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700645
Alan Cox25ad00b2009-08-19 18:21:44 +0100646 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700647
648 /* Set our advertise values accordingly */
Alan Cox25ad00b2009-08-19 18:21:44 +0100649 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_HALF);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700650
651 /* Set speed */
Alan Cox25ad00b2009-08-19 18:21:44 +0100652 ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_100MBPS);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700653
654 /* Power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100655 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700656}
657
658/**
659 * TPAL_SetPhy100FullDuplex - Force 100 Base T Full Duplex mode.
Alan Cox25ad00b2009-08-19 18:21:44 +0100660 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700661 *
662 * Also sets the MAC so it is syncd up properly
663 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100664void TPAL_SetPhy100FullDuplex(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700665{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700666 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100667 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700668
669 /* First we need to turn off all other advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100670 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700671
Alan Cox25ad00b2009-08-19 18:21:44 +0100672 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700673
674 /* Set our advertise values accordingly */
Alan Cox25ad00b2009-08-19 18:21:44 +0100675 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700676
677 /* Power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100678 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700679}
680
681/**
682 * TPAL_SetPhy100Force - Force 100 BaseT FD mode WITHOUT using autonegotiation
Alan Cox25ad00b2009-08-19 18:21:44 +0100683 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700684 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100685void TPAL_SetPhy100Force(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700686{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700687 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100688 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700689
690 /* Disable autoneg */
Alan Cox25ad00b2009-08-19 18:21:44 +0100691 ET1310_PhyAutoNeg(etdev, false);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700692
693 /* Disable all advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100694 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
695 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
696 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700697
698 /* Force 100 Mbps */
Alan Cox25ad00b2009-08-19 18:21:44 +0100699 ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_100MBPS);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700700
701 /* Force Full duplex */
Alan Cox25ad00b2009-08-19 18:21:44 +0100702 ET1310_PhyDuplexMode(etdev, TRUEPHY_DUPLEX_FULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700703
704 /* Power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100705 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700706}
707
708/**
709 * TPAL_SetPhy1000FullDuplex - Force 1000 Base T Full Duplex mode
Alan Cox25ad00b2009-08-19 18:21:44 +0100710 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700711 *
712 * Also sets the MAC so it is syncd up properly.
713 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100714void TPAL_SetPhy1000FullDuplex(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700715{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700716 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100717 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700718
719 /* first we need to turn off all other advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100720 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700721
Alan Cox25ad00b2009-08-19 18:21:44 +0100722 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700723
724 /* set our advertise values accordingly */
Alan Cox25ad00b2009-08-19 18:21:44 +0100725 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700726
727 /* power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100728 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700729}
730
731/**
732 * TPAL_SetPhyAutoNeg - Set phy to autonegotiation mode.
Alan Cox25ad00b2009-08-19 18:21:44 +0100733 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700734 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100735void TPAL_SetPhyAutoNeg(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700736{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700737 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100738 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700739
740 /* Turn on advertisement of all capabilities */
Alan Cox25ad00b2009-08-19 18:21:44 +0100741 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_BOTH);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700742
Alan Cox25ad00b2009-08-19 18:21:44 +0100743 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_BOTH);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700744
Alan Cox5ec34872009-08-27 10:59:13 +0100745 if (etdev->pdev->device != ET131X_PCI_DEVICE_ID_FAST)
Alan Cox25ad00b2009-08-19 18:21:44 +0100746 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL);
Alan Cox64f93032009-06-10 17:30:41 +0100747 else
Alan Cox25ad00b2009-08-19 18:21:44 +0100748 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700749
750 /* Make sure auto-neg is ON (it is disabled in FORCE modes) */
Alan Cox25ad00b2009-08-19 18:21:44 +0100751 ET1310_PhyAutoNeg(etdev, true);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700752
753 /* Power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100754 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700755}
756
757
758/*
759 * The routines which follow provide low-level access to the PHY, and are used
760 * primarily by the routines above (although there are a few places elsewhere
761 * in the driver where this level of access is required).
762 */
763
764static const uint16_t ConfigPhy[25][2] = {
765 /* Reg Value Register */
766 /* Addr */
767 {0x880B, 0x0926}, /* AfeIfCreg4B1000Msbs */
768 {0x880C, 0x0926}, /* AfeIfCreg4B100Msbs */
769 {0x880D, 0x0926}, /* AfeIfCreg4B10Msbs */
770
771 {0x880E, 0xB4D3}, /* AfeIfCreg4B1000Lsbs */
772 {0x880F, 0xB4D3}, /* AfeIfCreg4B100Lsbs */
773 {0x8810, 0xB4D3}, /* AfeIfCreg4B10Lsbs */
774
775 {0x8805, 0xB03E}, /* AfeIfCreg3B1000Msbs */
776 {0x8806, 0xB03E}, /* AfeIfCreg3B100Msbs */
777 {0x8807, 0xFF00}, /* AfeIfCreg3B10Msbs */
778
779 {0x8808, 0xE090}, /* AfeIfCreg3B1000Lsbs */
780 {0x8809, 0xE110}, /* AfeIfCreg3B100Lsbs */
781 {0x880A, 0x0000}, /* AfeIfCreg3B10Lsbs */
782
783 {0x300D, 1}, /* DisableNorm */
784
785 {0x280C, 0x0180}, /* LinkHoldEnd */
786
787 {0x1C21, 0x0002}, /* AlphaM */
788
789 {0x3821, 6}, /* FfeLkgTx0 */
790 {0x381D, 1}, /* FfeLkg1g4 */
791 {0x381E, 1}, /* FfeLkg1g5 */
792 {0x381F, 1}, /* FfeLkg1g6 */
793 {0x3820, 1}, /* FfeLkg1g7 */
794
795 {0x8402, 0x01F0}, /* Btinact */
796 {0x800E, 20}, /* LftrainTime */
797 {0x800F, 24}, /* DvguardTime */
798 {0x8010, 46}, /* IdlguardTime */
799
800 {0, 0}
801
802};
803
804/* condensed version of the phy initialization routine */
Alan Cox25ad00b2009-08-19 18:21:44 +0100805void ET1310_PhyInit(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700806{
Alan Cox9fa81092009-08-27 11:00:36 +0100807 uint16_t data, index;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700808
Alan Cox25ad00b2009-08-19 18:21:44 +0100809 if (etdev == NULL)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700810 return;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700811
Alan Cox64f93032009-06-10 17:30:41 +0100812 /* get the identity (again ?) */
Alan Cox9fa81092009-08-27 11:00:36 +0100813 MiRead(etdev, PHY_ID_1, &data);
814 MiRead(etdev, PHY_ID_2, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700815
Alan Cox64f93032009-06-10 17:30:41 +0100816 /* what does this do/achieve ? */
Alan Cox9fa81092009-08-27 11:00:36 +0100817 MiRead(etdev, PHY_MPHY_CONTROL_REG, &data); /* should read 0002 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100818 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0006);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700819
Alan Cox64f93032009-06-10 17:30:41 +0100820 /* read modem register 0402, should I do something with the return
821 data ? */
Alan Cox25ad00b2009-08-19 18:21:44 +0100822 MiWrite(etdev, PHY_INDEX_REG, 0x0402);
Alan Cox9fa81092009-08-27 11:00:36 +0100823 MiRead(etdev, PHY_DATA_REG, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700824
Alan Cox64f93032009-06-10 17:30:41 +0100825 /* what does this do/achieve ? */
Alan Cox25ad00b2009-08-19 18:21:44 +0100826 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700827
Alan Cox64f93032009-06-10 17:30:41 +0100828 /* get the identity (again ?) */
Alan Cox9fa81092009-08-27 11:00:36 +0100829 MiRead(etdev, PHY_ID_1, &data);
830 MiRead(etdev, PHY_ID_2, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700831
Alan Cox64f93032009-06-10 17:30:41 +0100832 /* what does this achieve ? */
Alan Cox9fa81092009-08-27 11:00:36 +0100833 MiRead(etdev, PHY_MPHY_CONTROL_REG, &data); /* should read 0002 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100834 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0006);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700835
Alan Cox64f93032009-06-10 17:30:41 +0100836 /* read modem register 0402, should I do something with
837 the return data? */
Alan Cox25ad00b2009-08-19 18:21:44 +0100838 MiWrite(etdev, PHY_INDEX_REG, 0x0402);
Alan Cox9fa81092009-08-27 11:00:36 +0100839 MiRead(etdev, PHY_DATA_REG, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700840
Alan Cox25ad00b2009-08-19 18:21:44 +0100841 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700842
Alan Cox64f93032009-06-10 17:30:41 +0100843 /* what does this achieve (should return 0x1040) */
Alan Cox9fa81092009-08-27 11:00:36 +0100844 MiRead(etdev, PHY_CONTROL, &data);
845 MiRead(etdev, PHY_MPHY_CONTROL_REG, &data); /* should read 0002 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100846 MiWrite(etdev, PHY_CONTROL, 0x1840);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700847
Alan Cox25ad00b2009-08-19 18:21:44 +0100848 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0007);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700849
Alan Cox64f93032009-06-10 17:30:41 +0100850 /* here the writing of the array starts.... */
Alan Cox9fa81092009-08-27 11:00:36 +0100851 index = 0;
852 while (ConfigPhy[index][0] != 0x0000) {
Alan Cox64f93032009-06-10 17:30:41 +0100853 /* write value */
Alan Cox9fa81092009-08-27 11:00:36 +0100854 MiWrite(etdev, PHY_INDEX_REG, ConfigPhy[index][0]);
855 MiWrite(etdev, PHY_DATA_REG, ConfigPhy[index][1]);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700856
Alan Cox64f93032009-06-10 17:30:41 +0100857 /* read it back */
Alan Cox9fa81092009-08-27 11:00:36 +0100858 MiWrite(etdev, PHY_INDEX_REG, ConfigPhy[index][0]);
859 MiRead(etdev, PHY_DATA_REG, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700860
Alan Cox64f93032009-06-10 17:30:41 +0100861 /* do a check on the value read back ? */
Alan Cox9fa81092009-08-27 11:00:36 +0100862 index++;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700863 }
Alan Cox64f93032009-06-10 17:30:41 +0100864 /* here the writing of the array ends... */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700865
Alan Cox9fa81092009-08-27 11:00:36 +0100866 MiRead(etdev, PHY_CONTROL, &data); /* 0x1840 */
867 MiRead(etdev, PHY_MPHY_CONTROL_REG, &data);/* should read 0007 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100868 MiWrite(etdev, PHY_CONTROL, 0x1040);
869 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700870}
871
Alan Cox25ad00b2009-08-19 18:21:44 +0100872void ET1310_PhyReset(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700873{
Alan Cox25ad00b2009-08-19 18:21:44 +0100874 MiWrite(etdev, PHY_CONTROL, 0x8000);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700875}
876
Alan Cox25ad00b2009-08-19 18:21:44 +0100877void ET1310_PhyPowerDown(struct et131x_adapter *etdev, bool down)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700878{
Alan Cox9fa81092009-08-27 11:00:36 +0100879 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700880
Alan Cox9fa81092009-08-27 11:00:36 +0100881 MiRead(etdev, PHY_CONTROL, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700882
883 if (down == false) {
Alan Cox64f93032009-06-10 17:30:41 +0100884 /* Power UP */
Alan Cox9fa81092009-08-27 11:00:36 +0100885 data &= ~0x0800;
886 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700887 } else {
Alan Cox64f93032009-06-10 17:30:41 +0100888 /* Power DOWN */
Alan Cox9fa81092009-08-27 11:00:36 +0100889 data |= 0x0800;
890 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700891 }
892}
893
Alan Cox25ad00b2009-08-19 18:21:44 +0100894void ET1310_PhyAutoNeg(struct et131x_adapter *etdev, bool enable)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700895{
Alan Cox9fa81092009-08-27 11:00:36 +0100896 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700897
Alan Cox9fa81092009-08-27 11:00:36 +0100898 MiRead(etdev, PHY_CONTROL, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700899
900 if (enable == true) {
Alan Cox64f93032009-06-10 17:30:41 +0100901 /* Autonegotiation ON */
Alan Cox9fa81092009-08-27 11:00:36 +0100902 data |= 0x1000;
903 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700904 } else {
Alan Cox64f93032009-06-10 17:30:41 +0100905 /* Autonegotiation OFF */
Alan Cox9fa81092009-08-27 11:00:36 +0100906 data &= ~0x1000;
907 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700908 }
909}
910
Alan Cox25ad00b2009-08-19 18:21:44 +0100911void ET1310_PhyDuplexMode(struct et131x_adapter *etdev, uint16_t duplex)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700912{
Alan Cox9fa81092009-08-27 11:00:36 +0100913 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700914
Alan Cox9fa81092009-08-27 11:00:36 +0100915 MiRead(etdev, PHY_CONTROL, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700916
917 if (duplex == TRUEPHY_DUPLEX_FULL) {
Alan Cox64f93032009-06-10 17:30:41 +0100918 /* Set Full Duplex */
Alan Cox9fa81092009-08-27 11:00:36 +0100919 data |= 0x100;
920 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700921 } else {
Alan Cox64f93032009-06-10 17:30:41 +0100922 /* Set Half Duplex */
Alan Cox9fa81092009-08-27 11:00:36 +0100923 data &= ~0x100;
924 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700925 }
926}
927
Alan Cox25ad00b2009-08-19 18:21:44 +0100928void ET1310_PhySpeedSelect(struct et131x_adapter *etdev, uint16_t speed)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700929{
Alan Cox9fa81092009-08-27 11:00:36 +0100930 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700931
Alan Cox64f93032009-06-10 17:30:41 +0100932 /* Read the PHY control register */
Alan Cox9fa81092009-08-27 11:00:36 +0100933 MiRead(etdev, PHY_CONTROL, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700934
Alan Cox64f93032009-06-10 17:30:41 +0100935 /* Clear all Speed settings (Bits 6, 13) */
Alan Cox9fa81092009-08-27 11:00:36 +0100936 data &= ~0x2040;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700937
Alan Cox64f93032009-06-10 17:30:41 +0100938 /* Reset the speed bits based on user selection */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700939 switch (speed) {
940 case TRUEPHY_SPEED_10MBPS:
Alan Cox64f93032009-06-10 17:30:41 +0100941 /* Bits already cleared above, do nothing */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700942 break;
943
944 case TRUEPHY_SPEED_100MBPS:
Alan Cox64f93032009-06-10 17:30:41 +0100945 /* 100M == Set bit 13 */
Alan Cox9fa81092009-08-27 11:00:36 +0100946 data |= 0x2000;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700947 break;
948
949 case TRUEPHY_SPEED_1000MBPS:
950 default:
Alan Cox9fa81092009-08-27 11:00:36 +0100951 data |= 0x0040;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700952 break;
953 }
954
Alan Cox64f93032009-06-10 17:30:41 +0100955 /* Write back the new speed */
Alan Cox9fa81092009-08-27 11:00:36 +0100956 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700957}
958
Alan Cox25ad00b2009-08-19 18:21:44 +0100959void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *etdev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700960 uint16_t duplex)
961{
Alan Cox9fa81092009-08-27 11:00:36 +0100962 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700963
Alan Cox64f93032009-06-10 17:30:41 +0100964 /* Read the PHY 1000 Base-T Control Register */
Alan Cox9fa81092009-08-27 11:00:36 +0100965 MiRead(etdev, PHY_1000_CONTROL, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700966
Alan Cox64f93032009-06-10 17:30:41 +0100967 /* Clear Bits 8,9 */
Alan Cox9fa81092009-08-27 11:00:36 +0100968 data &= ~0x0300;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700969
970 switch (duplex) {
971 case TRUEPHY_ADV_DUPLEX_NONE:
Alan Cox64f93032009-06-10 17:30:41 +0100972 /* Duplex already cleared, do nothing */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700973 break;
974
975 case TRUEPHY_ADV_DUPLEX_FULL:
Alan Cox64f93032009-06-10 17:30:41 +0100976 /* Set Bit 9 */
Alan Cox9fa81092009-08-27 11:00:36 +0100977 data |= 0x0200;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700978 break;
979
980 case TRUEPHY_ADV_DUPLEX_HALF:
Alan Cox64f93032009-06-10 17:30:41 +0100981 /* Set Bit 8 */
Alan Cox9fa81092009-08-27 11:00:36 +0100982 data |= 0x0100;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700983 break;
984
985 case TRUEPHY_ADV_DUPLEX_BOTH:
986 default:
Alan Cox9fa81092009-08-27 11:00:36 +0100987 data |= 0x0300;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700988 break;
989 }
990
Alan Cox64f93032009-06-10 17:30:41 +0100991 /* Write back advertisement */
Alan Cox9fa81092009-08-27 11:00:36 +0100992 MiWrite(etdev, PHY_1000_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700993}
994
Alan Cox25ad00b2009-08-19 18:21:44 +0100995void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *etdev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700996 uint16_t duplex)
997{
Alan Cox9fa81092009-08-27 11:00:36 +0100998 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700999
Alan Cox64f93032009-06-10 17:30:41 +01001000 /* Read the Autonegotiation Register (10/100) */
Alan Cox9fa81092009-08-27 11:00:36 +01001001 MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001002
Alan Cox64f93032009-06-10 17:30:41 +01001003 /* Clear bits 7,8 */
Alan Cox9fa81092009-08-27 11:00:36 +01001004 data &= ~0x0180;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001005
1006 switch (duplex) {
1007 case TRUEPHY_ADV_DUPLEX_NONE:
Alan Cox64f93032009-06-10 17:30:41 +01001008 /* Duplex already cleared, do nothing */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001009 break;
1010
1011 case TRUEPHY_ADV_DUPLEX_FULL:
Alan Cox64f93032009-06-10 17:30:41 +01001012 /* Set Bit 8 */
Alan Cox9fa81092009-08-27 11:00:36 +01001013 data |= 0x0100;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001014 break;
1015
1016 case TRUEPHY_ADV_DUPLEX_HALF:
Alan Cox64f93032009-06-10 17:30:41 +01001017 /* Set Bit 7 */
Alan Cox9fa81092009-08-27 11:00:36 +01001018 data |= 0x0080;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001019 break;
1020
1021 case TRUEPHY_ADV_DUPLEX_BOTH:
1022 default:
Alan Cox64f93032009-06-10 17:30:41 +01001023 /* Set Bits 7,8 */
Alan Cox9fa81092009-08-27 11:00:36 +01001024 data |= 0x0180;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001025 break;
1026 }
1027
Alan Cox64f93032009-06-10 17:30:41 +01001028 /* Write back advertisement */
Alan Cox9fa81092009-08-27 11:00:36 +01001029 MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001030}
1031
Alan Cox25ad00b2009-08-19 18:21:44 +01001032void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *etdev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001033 uint16_t duplex)
1034{
Alan Cox9fa81092009-08-27 11:00:36 +01001035 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001036
Alan Cox64f93032009-06-10 17:30:41 +01001037 /* Read the Autonegotiation Register (10/100) */
Alan Cox9fa81092009-08-27 11:00:36 +01001038 MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001039
Alan Cox64f93032009-06-10 17:30:41 +01001040 /* Clear bits 5,6 */
Alan Cox9fa81092009-08-27 11:00:36 +01001041 data &= ~0x0060;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001042
1043 switch (duplex) {
1044 case TRUEPHY_ADV_DUPLEX_NONE:
Alan Cox64f93032009-06-10 17:30:41 +01001045 /* Duplex already cleared, do nothing */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001046 break;
1047
1048 case TRUEPHY_ADV_DUPLEX_FULL:
Alan Cox64f93032009-06-10 17:30:41 +01001049 /* Set Bit 6 */
Alan Cox9fa81092009-08-27 11:00:36 +01001050 data |= 0x0040;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001051 break;
1052
1053 case TRUEPHY_ADV_DUPLEX_HALF:
Alan Cox64f93032009-06-10 17:30:41 +01001054 /* Set Bit 5 */
Alan Cox9fa81092009-08-27 11:00:36 +01001055 data |= 0x0020;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001056 break;
1057
1058 case TRUEPHY_ADV_DUPLEX_BOTH:
1059 default:
Alan Cox64f93032009-06-10 17:30:41 +01001060 /* Set Bits 5,6 */
Alan Cox9fa81092009-08-27 11:00:36 +01001061 data |= 0x0060;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001062 break;
1063 }
1064
Alan Cox64f93032009-06-10 17:30:41 +01001065 /* Write back advertisement */
Alan Cox9fa81092009-08-27 11:00:36 +01001066 MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001067}
1068
Alan Cox25ad00b2009-08-19 18:21:44 +01001069void ET1310_PhyLinkStatus(struct et131x_adapter *etdev,
Alan Cox9fa81092009-08-27 11:00:36 +01001070 uint8_t *link_status,
1071 uint32_t *autoneg,
1072 uint32_t *linkspeed,
1073 uint32_t *duplex_mode,
1074 uint32_t *mdi_mdix,
1075 uint32_t *masterslave, uint32_t *polarity)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001076{
Alan Cox9fa81092009-08-27 11:00:36 +01001077 uint16_t mistatus = 0;
1078 uint16_t is1000BaseT = 0;
1079 uint16_t vmi_phystatus = 0;
1080 uint16_t control = 0;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001081
Alan Cox9fa81092009-08-27 11:00:36 +01001082 MiRead(etdev, PHY_STATUS, &mistatus);
1083 MiRead(etdev, PHY_1000_STATUS, &is1000BaseT);
1084 MiRead(etdev, PHY_PHY_STATUS, &vmi_phystatus);
1085 MiRead(etdev, PHY_CONTROL, &control);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001086
Alan Cox9fa81092009-08-27 11:00:36 +01001087 if (link_status) {
1088 *link_status =
1089 (unsigned char)((vmi_phystatus & 0x0040) ? 1 : 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001090 }
1091
Alan Cox9fa81092009-08-27 11:00:36 +01001092 if (autoneg) {
1093 *autoneg =
1094 (control & 0x1000) ? ((vmi_phystatus & 0x0020) ?
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001095 TRUEPHY_ANEG_COMPLETE :
1096 TRUEPHY_ANEG_NOT_COMPLETE) :
1097 TRUEPHY_ANEG_DISABLED;
1098 }
1099
Alan Cox9fa81092009-08-27 11:00:36 +01001100 if (linkspeed)
1101 *linkspeed = (vmi_phystatus & 0x0300) >> 8;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001102
Alan Cox9fa81092009-08-27 11:00:36 +01001103 if (duplex_mode)
1104 *duplex_mode = (vmi_phystatus & 0x0080) >> 7;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001105
Alan Cox9fa81092009-08-27 11:00:36 +01001106 if (mdi_mdix)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001107 /* NOTE: Need to complete this */
Alan Cox9fa81092009-08-27 11:00:36 +01001108 *mdi_mdix = 0;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001109
Alan Cox9fa81092009-08-27 11:00:36 +01001110 if (masterslave) {
1111 *masterslave =
1112 (is1000BaseT & 0x4000) ? TRUEPHY_CFG_MASTER :
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001113 TRUEPHY_CFG_SLAVE;
1114 }
1115
Alan Cox9fa81092009-08-27 11:00:36 +01001116 if (polarity) {
1117 *polarity =
1118 (vmi_phystatus & 0x0400) ? TRUEPHY_POLARITY_INVERTED :
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001119 TRUEPHY_POLARITY_NORMAL;
1120 }
1121}
1122
Alan Cox25ad00b2009-08-19 18:21:44 +01001123void ET1310_PhyAndOrReg(struct et131x_adapter *etdev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001124 uint16_t regnum, uint16_t andMask, uint16_t orMask)
1125{
1126 uint16_t reg;
1127
Alan Cox64f93032009-06-10 17:30:41 +01001128 /* Read the requested register */
Alan Cox25ad00b2009-08-19 18:21:44 +01001129 MiRead(etdev, regnum, &reg);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001130
Alan Cox64f93032009-06-10 17:30:41 +01001131 /* Apply the AND mask */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001132 reg &= andMask;
1133
Alan Cox64f93032009-06-10 17:30:41 +01001134 /* Apply the OR mask */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001135 reg |= orMask;
1136
Alan Cox64f93032009-06-10 17:30:41 +01001137 /* Write the value back to the register */
Alan Cox25ad00b2009-08-19 18:21:44 +01001138 MiWrite(etdev, regnum, reg);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001139}
1140
Alan Cox25ad00b2009-08-19 18:21:44 +01001141void ET1310_PhyAccessMiBit(struct et131x_adapter *etdev, uint16_t action,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001142 uint16_t regnum, uint16_t bitnum, uint8_t *value)
1143{
1144 uint16_t reg;
1145 uint16_t mask = 0;
1146
Alan Cox64f93032009-06-10 17:30:41 +01001147 /* Create a mask to isolate the requested bit */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001148 mask = 0x0001 << bitnum;
1149
Alan Cox64f93032009-06-10 17:30:41 +01001150 /* Read the requested register */
Alan Cox25ad00b2009-08-19 18:21:44 +01001151 MiRead(etdev, regnum, &reg);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001152
1153 switch (action) {
1154 case TRUEPHY_BIT_READ:
Alan Cox64f93032009-06-10 17:30:41 +01001155 if (value != NULL)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001156 *value = (reg & mask) >> bitnum;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001157 break;
1158
1159 case TRUEPHY_BIT_SET:
1160 reg |= mask;
Alan Cox25ad00b2009-08-19 18:21:44 +01001161 MiWrite(etdev, regnum, reg);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001162 break;
1163
1164 case TRUEPHY_BIT_CLEAR:
1165 reg &= ~mask;
Alan Cox25ad00b2009-08-19 18:21:44 +01001166 MiWrite(etdev, regnum, reg);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001167 break;
1168
1169 default:
1170 break;
1171 }
1172}