blob: dd199bdb9efffc73b0e2ff08f04d4aee883697a0 [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;
118 MII_MGMT_ADDR_t miiAddr;
119 MII_MGMT_CMD_t miiCmd;
120 MII_MGMT_INDICATOR_t miiIndicator;
121
122 /* Save a local copy of the registers we are dealing with so we can
123 * set them back
124 */
125 miiAddr.value = readl(&mac->mii_mgmt_addr.value);
126 miiCmd.value = readl(&mac->mii_mgmt_cmd.value);
127
128 /* Stop the current operation */
129 writel(0, &mac->mii_mgmt_cmd.value);
130
131 /* Set up the register we need to read from on the correct PHY */
132 {
133 MII_MGMT_ADDR_t mii_mgmt_addr = { 0 };
134
135 mii_mgmt_addr.bits.phy_addr = xcvrAddr;
136 mii_mgmt_addr.bits.reg_addr = xcvrReg;
137 writel(mii_mgmt_addr.value, &mac->mii_mgmt_addr.value);
138 }
139
140 /* Kick the read cycle off */
141 delay = 0;
142
143 writel(0x1, &mac->mii_mgmt_cmd.value);
144
145 do {
146 udelay(50);
147 delay++;
148 miiIndicator.value = readl(&mac->mii_mgmt_indicator.value);
149 } while ((miiIndicator.bits.not_valid || miiIndicator.bits.busy) &&
150 delay < 50);
151
152 /* If we hit the max delay, we could not read the register */
153 if (delay >= 50) {
Alan Cox15700032009-08-27 11:03:09 +0100154 dev_warn(&adapter->pdev->dev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700155 "xcvrReg 0x%08x could not be read\n", xcvrReg);
Alan Cox15700032009-08-27 11:03:09 +0100156 dev_warn(&adapter->pdev->dev, "status is 0x%08x\n",
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700157 miiIndicator.value);
158
159 status = -EIO;
160 }
161
162 /* If we hit here we were able to read the register and we need to
163 * return the value to the caller
164 */
165 /* TODO: make this stuff a simple readw()?! */
166 {
167 MII_MGMT_STAT_t mii_mgmt_stat;
168
169 mii_mgmt_stat.value = readl(&mac->mii_mgmt_stat.value);
170 *value = (uint16_t) mii_mgmt_stat.bits.phy_stat;
171 }
172
173 /* Stop the read operation */
174 writel(0, &mac->mii_mgmt_cmd.value);
175
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700176 /* set the registers we touched back to the state at which we entered
177 * this function
178 */
179 writel(miiAddr.value, &mac->mii_mgmt_addr.value);
180 writel(miiCmd.value, &mac->mii_mgmt_cmd.value);
181
182 return status;
183}
184
185/**
186 * MiWrite - Write to a PHY register through the MII interface of the MAC
187 * @adapter: pointer to our private adapter structure
188 * @xcvrReg: the register to read
189 * @value: 16-bit value to write
190 *
191 * Return 0 on success, errno on failure (as defined in errno.h)
192 */
193int MiWrite(struct et131x_adapter *adapter, uint8_t xcvrReg, uint16_t value)
194{
Alan Coxf3f415a2009-08-27 10:59:30 +0100195 struct _MAC_t __iomem *mac = &adapter->regs->mac;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700196 int status = 0;
197 uint8_t xcvrAddr = adapter->Stats.xcvr_addr;
198 uint32_t delay;
199 MII_MGMT_ADDR_t miiAddr;
200 MII_MGMT_CMD_t miiCmd;
201 MII_MGMT_INDICATOR_t miiIndicator;
202
203 /* Save a local copy of the registers we are dealing with so we can
204 * set them back
205 */
206 miiAddr.value = readl(&mac->mii_mgmt_addr.value);
207 miiCmd.value = readl(&mac->mii_mgmt_cmd.value);
208
209 /* Stop the current operation */
210 writel(0, &mac->mii_mgmt_cmd.value);
211
212 /* Set up the register we need to write to on the correct PHY */
213 {
214 MII_MGMT_ADDR_t mii_mgmt_addr;
215
216 mii_mgmt_addr.bits.phy_addr = xcvrAddr;
217 mii_mgmt_addr.bits.reg_addr = xcvrReg;
218 writel(mii_mgmt_addr.value, &mac->mii_mgmt_addr.value);
219 }
220
221 /* Add the value to write to the registers to the mac */
222 writel(value, &mac->mii_mgmt_ctrl.value);
223 delay = 0;
224
225 do {
226 udelay(50);
227 delay++;
228 miiIndicator.value = readl(&mac->mii_mgmt_indicator.value);
229 } while (miiIndicator.bits.busy && delay < 100);
230
231 /* If we hit the max delay, we could not write the register */
232 if (delay == 100) {
233 uint16_t TempValue;
234
Alan Cox15700032009-08-27 11:03:09 +0100235 dev_warn(&adapter->pdev->dev,
236 "xcvrReg 0x%08x could not be written", xcvrReg);
237 dev_warn(&adapter->pdev->dev, "status is 0x%08x\n",
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700238 miiIndicator.value);
Alan Cox15700032009-08-27 11:03:09 +0100239 dev_warn(&adapter->pdev->dev, "command is 0x%08x\n",
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700240 readl(&mac->mii_mgmt_cmd.value));
241
242 MiRead(adapter, xcvrReg, &TempValue);
243
244 status = -EIO;
245 }
246
247 /* Stop the write operation */
248 writel(0, &mac->mii_mgmt_cmd.value);
249
250 /* set the registers we touched back to the state at which we entered
Alan Cox64f93032009-06-10 17:30:41 +0100251 * this function
252 */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700253 writel(miiAddr.value, &mac->mii_mgmt_addr.value);
254 writel(miiCmd.value, &mac->mii_mgmt_cmd.value);
255
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700256 return status;
257}
258
259/**
260 * et131x_xcvr_find - Find the PHY ID
261 * @adapter: pointer to our private adapter structure
262 *
263 * Returns 0 on success, errno on failure (as defined in errno.h)
264 */
265int et131x_xcvr_find(struct et131x_adapter *adapter)
266{
267 int status = -ENODEV;
268 uint8_t xcvr_addr;
269 MI_IDR1_t idr1;
270 MI_IDR2_t idr2;
271 uint32_t xcvr_id;
272
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700273 /* We need to get xcvr id and address we just get the first one */
274 for (xcvr_addr = 0; xcvr_addr < 32; xcvr_addr++) {
275 /* Read the ID from the PHY */
276 PhyMiRead(adapter, xcvr_addr,
277 (uint8_t) offsetof(MI_REGS_t, idr1),
278 &idr1.value);
279 PhyMiRead(adapter, xcvr_addr,
280 (uint8_t) offsetof(MI_REGS_t, idr2),
281 &idr2.value);
282
283 xcvr_id = (uint32_t) ((idr1.value << 16) | idr2.value);
284
285 if ((idr1.value != 0) && (idr1.value != 0xffff)) {
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700286 adapter->Stats.xcvr_id = xcvr_id;
287 adapter->Stats.xcvr_addr = xcvr_addr;
288
289 status = 0;
290 break;
291 }
292 }
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700293 return status;
294}
295
296/**
297 * et131x_setphy_normal - Set PHY for normal operation.
298 * @adapter: pointer to our private adapter structure
299 *
300 * Used by Power Management to force the PHY into 10 Base T half-duplex mode,
301 * when going to D3 in WOL mode. Also used during initialization to set the
302 * PHY for normal operation.
303 */
304int et131x_setphy_normal(struct et131x_adapter *adapter)
305{
306 int status;
307
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700308 /* Make sure the PHY is powered up */
309 ET1310_PhyPowerDown(adapter, 0);
310 status = et131x_xcvr_init(adapter);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700311 return status;
312}
313
314/**
315 * et131x_xcvr_init - Init the phy if we are setting it into force mode
316 * @adapter: pointer to our private adapter structure
317 *
318 * Returns 0 on success, errno on failure (as defined in errno.h)
319 */
320static int et131x_xcvr_init(struct et131x_adapter *adapter)
321{
322 int status = 0;
323 MI_IMR_t imr;
324 MI_ISR_t isr;
325 MI_LCR2_t lcr2;
326
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700327 /* Zero out the adapter structure variable representing BMSR */
328 adapter->Bmsr.value = 0;
329
330 MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, isr), &isr.value);
331
332 MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, imr), &imr.value);
333
334 /* Set the link status interrupt only. Bad behavior when link status
335 * and auto neg are set, we run into a nested interrupt problem
336 */
337 imr.bits.int_en = 0x1;
338 imr.bits.link_status = 0x1;
339 imr.bits.autoneg_status = 0x1;
340
341 MiWrite(adapter, (uint8_t) offsetof(MI_REGS_t, imr), imr.value);
342
343 /* Set the LED behavior such that LED 1 indicates speed (off =
344 * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates
345 * link and activity (on for link, blink off for activity).
346 *
347 * NOTE: Some customizations have been added here for specific
348 * vendors; The LED behavior is now determined by vendor data in the
349 * EEPROM. However, the above description is the default.
350 */
351 if ((adapter->eepromData[1] & 0x4) == 0) {
352 MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, lcr2),
353 &lcr2.value);
354 if ((adapter->eepromData[1] & 0x8) == 0)
355 lcr2.bits.led_tx_rx = 0x3;
356 else
357 lcr2.bits.led_tx_rx = 0x4;
358 lcr2.bits.led_link = 0xa;
359 MiWrite(adapter, (uint8_t) offsetof(MI_REGS_t, lcr2),
360 lcr2.value);
361 }
362
363 /* Determine if we need to go into a force mode and set it */
364 if (adapter->AiForceSpeed == 0 && adapter->AiForceDpx == 0) {
365 if ((adapter->RegistryFlowControl == TxOnly) ||
366 (adapter->RegistryFlowControl == Both)) {
367 ET1310_PhyAccessMiBit(adapter,
368 TRUEPHY_BIT_SET, 4, 11, NULL);
369 } else {
370 ET1310_PhyAccessMiBit(adapter,
371 TRUEPHY_BIT_CLEAR, 4, 11, NULL);
372 }
373
374 if (adapter->RegistryFlowControl == Both) {
375 ET1310_PhyAccessMiBit(adapter,
376 TRUEPHY_BIT_SET, 4, 10, NULL);
377 } else {
378 ET1310_PhyAccessMiBit(adapter,
379 TRUEPHY_BIT_CLEAR, 4, 10, NULL);
380 }
381
382 /* Set the phy to autonegotiation */
383 ET1310_PhyAutoNeg(adapter, true);
384
385 /* NOTE - Do we need this? */
386 ET1310_PhyAccessMiBit(adapter, TRUEPHY_BIT_SET, 0, 9, NULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700387 return status;
388 } else {
389 ET1310_PhyAutoNeg(adapter, false);
390
391 /* Set to the correct force mode. */
392 if (adapter->AiForceDpx != 1) {
393 if ((adapter->RegistryFlowControl == TxOnly) ||
394 (adapter->RegistryFlowControl == Both)) {
395 ET1310_PhyAccessMiBit(adapter,
396 TRUEPHY_BIT_SET, 4, 11,
397 NULL);
398 } else {
399 ET1310_PhyAccessMiBit(adapter,
400 TRUEPHY_BIT_CLEAR, 4, 11,
401 NULL);
402 }
403
404 if (adapter->RegistryFlowControl == Both) {
405 ET1310_PhyAccessMiBit(adapter,
406 TRUEPHY_BIT_SET, 4, 10,
407 NULL);
408 } else {
409 ET1310_PhyAccessMiBit(adapter,
410 TRUEPHY_BIT_CLEAR, 4, 10,
411 NULL);
412 }
413 } else {
414 ET1310_PhyAccessMiBit(adapter,
415 TRUEPHY_BIT_CLEAR, 4, 10, NULL);
416 ET1310_PhyAccessMiBit(adapter,
417 TRUEPHY_BIT_CLEAR, 4, 11, NULL);
418 }
419
420 switch (adapter->AiForceSpeed) {
421 case 10:
Alan Cox64f93032009-06-10 17:30:41 +0100422 if (adapter->AiForceDpx == 1)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700423 TPAL_SetPhy10HalfDuplex(adapter);
Alan Cox64f93032009-06-10 17:30:41 +0100424 else if (adapter->AiForceDpx == 2)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700425 TPAL_SetPhy10FullDuplex(adapter);
Alan Cox64f93032009-06-10 17:30:41 +0100426 else
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700427 TPAL_SetPhy10Force(adapter);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700428 break;
429 case 100:
Alan Cox64f93032009-06-10 17:30:41 +0100430 if (adapter->AiForceDpx == 1)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700431 TPAL_SetPhy100HalfDuplex(adapter);
Alan Cox64f93032009-06-10 17:30:41 +0100432 else if (adapter->AiForceDpx == 2)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700433 TPAL_SetPhy100FullDuplex(adapter);
Alan Cox64f93032009-06-10 17:30:41 +0100434 else
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700435 TPAL_SetPhy100Force(adapter);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700436 break;
437 case 1000:
438 TPAL_SetPhy1000FullDuplex(adapter);
439 break;
440 }
441
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700442 return status;
443 }
444}
445
Alan Cox25ad00b2009-08-19 18:21:44 +0100446void et131x_Mii_check(struct et131x_adapter *etdev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700447 MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints)
448{
Alan Cox9fa81092009-08-27 11:00:36 +0100449 uint8_t link_status;
450 uint32_t autoneg_status;
451 uint32_t speed;
452 uint32_t duplex;
453 uint32_t mdi_mdix;
454 uint32_t masterslave;
455 uint32_t polarity;
Alan Cox37628602009-08-19 18:21:50 +0100456 unsigned long flags;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700457
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700458 if (bmsr_ints.bits.link_status) {
459 if (bmsr.bits.link_status) {
Alan Cox25ad00b2009-08-19 18:21:44 +0100460 etdev->PoMgmt.TransPhyComaModeOnBoot = 20;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700461
462 /* Update our state variables and indicate the
463 * connected state
464 */
Alan Cox37628602009-08-19 18:21:50 +0100465 spin_lock_irqsave(&etdev->Lock, flags);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700466
Alan Cox25ad00b2009-08-19 18:21:44 +0100467 etdev->MediaState = NETIF_STATUS_MEDIA_CONNECT;
Alan Coxf6b35d62009-08-27 11:02:05 +0100468 etdev->Flags &= ~fMP_ADAPTER_LINK_DETECTION;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700469
Alan Cox37628602009-08-19 18:21:50 +0100470 spin_unlock_irqrestore(&etdev->Lock, flags);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700471
472 /* Don't indicate state if we're in loopback mode */
Alan Cox25ad00b2009-08-19 18:21:44 +0100473 if (etdev->RegistryPhyLoopbk == false)
474 netif_carrier_on(etdev->netdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700475 } else {
Alan Cox15700032009-08-27 11:03:09 +0100476 dev_warn(&etdev->pdev->dev,
477 "Link down - cable problem ?\n");
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700478
Alan Cox9fa81092009-08-27 11:00:36 +0100479 if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) {
Alan Cox64f93032009-06-10 17:30:41 +0100480 /* NOTE - Is there a way to query this without
481 * TruePHY?
Alan Cox25ad00b2009-08-19 18:21:44 +0100482 * && TRU_QueryCoreType(etdev->hTruePhy, 0) == EMI_TRUEPHY_A13O) {
Alan Cox64f93032009-06-10 17:30:41 +0100483 */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700484 uint16_t Register18;
485
Alan Cox25ad00b2009-08-19 18:21:44 +0100486 MiRead(etdev, 0x12, &Register18);
487 MiWrite(etdev, 0x12, Register18 | 0x4);
488 MiWrite(etdev, 0x10, Register18 | 0x8402);
489 MiWrite(etdev, 0x11, Register18 | 511);
490 MiWrite(etdev, 0x12, Register18);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700491 }
492
493 /* For the first N seconds of life, we are in "link
494 * detection" When we are in this state, we should
495 * only report "connected". When the LinkDetection
496 * Timer expires, we can report disconnected (handled
497 * in the LinkDetectionDPC).
498 */
Alan Coxf6b35d62009-08-27 11:02:05 +0100499 if (!(etdev->Flags & fMP_ADAPTER_LINK_DETECTION) ||
500 (etdev->MediaState == NETIF_STATUS_MEDIA_DISCONNECT)) {
Alan Cox37628602009-08-19 18:21:50 +0100501 spin_lock_irqsave(&etdev->Lock, flags);
Alan Cox25ad00b2009-08-19 18:21:44 +0100502 etdev->MediaState =
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700503 NETIF_STATUS_MEDIA_DISCONNECT;
Alan Cox25ad00b2009-08-19 18:21:44 +0100504 spin_unlock_irqrestore(&etdev->Lock,
Alan Cox37628602009-08-19 18:21:50 +0100505 flags);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700506
507 /* Only indicate state if we're in loopback
508 * mode
509 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100510 if (etdev->RegistryPhyLoopbk == false)
511 netif_carrier_off(etdev->netdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700512 }
513
Alan Cox9fa81092009-08-27 11:00:36 +0100514 etdev->linkspeed = 0;
Alan Cox576b38e2009-08-27 11:00:47 +0100515 etdev->duplex_mode = 0;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700516
517 /* Free the packets being actively sent & stopped */
Alan Cox25ad00b2009-08-19 18:21:44 +0100518 et131x_free_busy_send_packets(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700519
520 /* Re-initialize the send structures */
Alan Cox25ad00b2009-08-19 18:21:44 +0100521 et131x_init_send(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700522
523 /* Reset the RFD list and re-start RU */
Alan Cox25ad00b2009-08-19 18:21:44 +0100524 et131x_reset_recv(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700525
526 /*
527 * Bring the device back to the state it was during
528 * init prior to autonegotiation being complete. This
529 * way, when we get the auto-neg complete interrupt,
530 * we can complete init by calling ConfigMacREGS2.
531 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100532 et131x_soft_reset(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700533
534 /* Setup ET1310 as per the documentation */
Alan Cox25ad00b2009-08-19 18:21:44 +0100535 et131x_adapter_setup(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700536
537 /* Setup the PHY into coma mode until the cable is
538 * plugged back in
539 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100540 if (etdev->RegistryPhyComa == 1)
541 EnablePhyComa(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700542 }
543 }
544
545 if (bmsr_ints.bits.auto_neg_complete ||
Alan Cox25ad00b2009-08-19 18:21:44 +0100546 (etdev->AiForceDpx == 3 && bmsr_ints.bits.link_status)) {
547 if (bmsr.bits.auto_neg_complete || etdev->AiForceDpx == 3) {
548 ET1310_PhyLinkStatus(etdev,
Alan Cox9fa81092009-08-27 11:00:36 +0100549 &link_status, &autoneg_status,
550 &speed, &duplex, &mdi_mdix,
551 &masterslave, &polarity);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700552
Alan Cox9fa81092009-08-27 11:00:36 +0100553 etdev->linkspeed = speed;
554 etdev->duplex_mode = duplex;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700555
Alan Cox25ad00b2009-08-19 18:21:44 +0100556 etdev->PoMgmt.TransPhyComaModeOnBoot = 20;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700557
Alan Cox9fa81092009-08-27 11:00:36 +0100558 if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) {
Alan Cox64f93032009-06-10 17:30:41 +0100559 /*
560 * NOTE - Is there a way to query this without
561 * TruePHY?
Alan Cox25ad00b2009-08-19 18:21:44 +0100562 * && TRU_QueryCoreType(etdev->hTruePhy, 0)== EMI_TRUEPHY_A13O) {
Alan Cox64f93032009-06-10 17:30:41 +0100563 */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700564 uint16_t Register18;
565
Alan Cox25ad00b2009-08-19 18:21:44 +0100566 MiRead(etdev, 0x12, &Register18);
567 MiWrite(etdev, 0x12, Register18 | 0x4);
568 MiWrite(etdev, 0x10, Register18 | 0x8402);
569 MiWrite(etdev, 0x11, Register18 | 511);
570 MiWrite(etdev, 0x12, Register18);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700571 }
572
Alan Cox25ad00b2009-08-19 18:21:44 +0100573 ConfigFlowControl(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700574
Alan Cox9fa81092009-08-27 11:00:36 +0100575 if (etdev->linkspeed == TRUEPHY_SPEED_1000MBPS &&
Alan Cox25ad00b2009-08-19 18:21:44 +0100576 etdev->RegistryJumboPacket > 2048)
577 ET1310_PhyAndOrReg(etdev, 0x16, 0xcfff,
Alan Cox64f93032009-06-10 17:30:41 +0100578 0x2000);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700579
Alan Cox25ad00b2009-08-19 18:21:44 +0100580 SetRxDmaTimer(etdev);
581 ConfigMACRegs2(etdev);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700582 }
583 }
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700584}
585
586/**
587 * TPAL_SetPhy10HalfDuplex - Force the phy into 10 Base T Half Duplex mode.
Alan Cox25ad00b2009-08-19 18:21:44 +0100588 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700589 *
590 * Also sets the MAC so it is syncd up properly
591 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100592void TPAL_SetPhy10HalfDuplex(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700593{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700594 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100595 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700596
597 /* First we need to turn off all other advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100598 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700599
Alan Cox25ad00b2009-08-19 18:21:44 +0100600 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700601
602 /* Set our advertise values accordingly */
Alan Cox25ad00b2009-08-19 18:21:44 +0100603 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_HALF);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700604
605 /* Power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100606 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700607}
608
609/**
610 * TPAL_SetPhy10FullDuplex - Force the phy into 10 Base T Full Duplex mode.
Alan Cox25ad00b2009-08-19 18:21:44 +0100611 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700612 *
613 * Also sets the MAC so it is syncd up properly
614 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100615void TPAL_SetPhy10FullDuplex(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700616{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700617 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100618 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700619
620 /* First we need to turn off all other advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100621 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700622
Alan Cox25ad00b2009-08-19 18:21:44 +0100623 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700624
625 /* Set our advertise values accordingly */
Alan Cox25ad00b2009-08-19 18:21:44 +0100626 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_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_SetPhy10Force - Force Base-T FD mode WITHOUT using autonegotiation
Alan Cox25ad00b2009-08-19 18:21:44 +0100634 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700635 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100636void TPAL_SetPhy10Force(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700637{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700638 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100639 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700640
641 /* Disable autoneg */
Alan Cox25ad00b2009-08-19 18:21:44 +0100642 ET1310_PhyAutoNeg(etdev, false);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700643
644 /* Disable all advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100645 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
646 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
647 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700648
649 /* Force 10 Mbps */
Alan Cox25ad00b2009-08-19 18:21:44 +0100650 ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_10MBPS);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700651
652 /* Force Full duplex */
Alan Cox25ad00b2009-08-19 18:21:44 +0100653 ET1310_PhyDuplexMode(etdev, TRUEPHY_DUPLEX_FULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700654
655 /* Power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100656 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700657}
658
659/**
660 * TPAL_SetPhy100HalfDuplex - Force 100 Base T Half Duplex mode.
Alan Cox25ad00b2009-08-19 18:21:44 +0100661 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700662 *
663 * Also sets the MAC so it is syncd up properly.
664 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100665void TPAL_SetPhy100HalfDuplex(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700666{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700667 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100668 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700669
670 /* first we need to turn off all other advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100671 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700672
Alan Cox25ad00b2009-08-19 18:21:44 +0100673 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700674
675 /* Set our advertise values accordingly */
Alan Cox25ad00b2009-08-19 18:21:44 +0100676 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_HALF);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700677
678 /* Set speed */
Alan Cox25ad00b2009-08-19 18:21:44 +0100679 ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_100MBPS);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700680
681 /* Power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100682 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700683}
684
685/**
686 * TPAL_SetPhy100FullDuplex - Force 100 Base T Full Duplex mode.
Alan Cox25ad00b2009-08-19 18:21:44 +0100687 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700688 *
689 * Also sets the MAC so it is syncd up properly
690 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100691void TPAL_SetPhy100FullDuplex(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700692{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700693 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100694 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700695
696 /* First we need to turn off all other advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100697 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700698
Alan Cox25ad00b2009-08-19 18:21:44 +0100699 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700700
701 /* Set our advertise values accordingly */
Alan Cox25ad00b2009-08-19 18:21:44 +0100702 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_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_SetPhy100Force - Force 100 BaseT FD mode WITHOUT using autonegotiation
Alan Cox25ad00b2009-08-19 18:21:44 +0100710 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700711 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100712void TPAL_SetPhy100Force(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700713{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700714 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100715 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700716
717 /* Disable autoneg */
Alan Cox25ad00b2009-08-19 18:21:44 +0100718 ET1310_PhyAutoNeg(etdev, false);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700719
720 /* Disable all advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100721 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
722 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
723 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700724
725 /* Force 100 Mbps */
Alan Cox25ad00b2009-08-19 18:21:44 +0100726 ET1310_PhySpeedSelect(etdev, TRUEPHY_SPEED_100MBPS);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700727
728 /* Force Full duplex */
Alan Cox25ad00b2009-08-19 18:21:44 +0100729 ET1310_PhyDuplexMode(etdev, TRUEPHY_DUPLEX_FULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700730
731 /* Power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100732 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700733}
734
735/**
736 * TPAL_SetPhy1000FullDuplex - Force 1000 Base T Full Duplex mode
Alan Cox25ad00b2009-08-19 18:21:44 +0100737 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700738 *
739 * Also sets the MAC so it is syncd up properly.
740 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100741void TPAL_SetPhy1000FullDuplex(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700742{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700743 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100744 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700745
746 /* first we need to turn off all other advertisement */
Alan Cox25ad00b2009-08-19 18:21:44 +0100747 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700748
Alan Cox25ad00b2009-08-19 18:21:44 +0100749 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700750
751 /* set our advertise values accordingly */
Alan Cox25ad00b2009-08-19 18:21:44 +0100752 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700753
754 /* power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100755 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700756}
757
758/**
759 * TPAL_SetPhyAutoNeg - Set phy to autonegotiation mode.
Alan Cox25ad00b2009-08-19 18:21:44 +0100760 * @etdev: pointer to the adapter structure
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700761 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100762void TPAL_SetPhyAutoNeg(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700763{
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700764 /* Power down PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100765 ET1310_PhyPowerDown(etdev, 1);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700766
767 /* Turn on advertisement of all capabilities */
Alan Cox25ad00b2009-08-19 18:21:44 +0100768 ET1310_PhyAdvertise10BaseT(etdev, TRUEPHY_ADV_DUPLEX_BOTH);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700769
Alan Cox25ad00b2009-08-19 18:21:44 +0100770 ET1310_PhyAdvertise100BaseT(etdev, TRUEPHY_ADV_DUPLEX_BOTH);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700771
Alan Cox5ec34872009-08-27 10:59:13 +0100772 if (etdev->pdev->device != ET131X_PCI_DEVICE_ID_FAST)
Alan Cox25ad00b2009-08-19 18:21:44 +0100773 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_FULL);
Alan Cox64f93032009-06-10 17:30:41 +0100774 else
Alan Cox25ad00b2009-08-19 18:21:44 +0100775 ET1310_PhyAdvertise1000BaseT(etdev, TRUEPHY_ADV_DUPLEX_NONE);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700776
777 /* Make sure auto-neg is ON (it is disabled in FORCE modes) */
Alan Cox25ad00b2009-08-19 18:21:44 +0100778 ET1310_PhyAutoNeg(etdev, true);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700779
780 /* Power up PHY */
Alan Cox25ad00b2009-08-19 18:21:44 +0100781 ET1310_PhyPowerDown(etdev, 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700782}
783
784
785/*
786 * The routines which follow provide low-level access to the PHY, and are used
787 * primarily by the routines above (although there are a few places elsewhere
788 * in the driver where this level of access is required).
789 */
790
791static const uint16_t ConfigPhy[25][2] = {
792 /* Reg Value Register */
793 /* Addr */
794 {0x880B, 0x0926}, /* AfeIfCreg4B1000Msbs */
795 {0x880C, 0x0926}, /* AfeIfCreg4B100Msbs */
796 {0x880D, 0x0926}, /* AfeIfCreg4B10Msbs */
797
798 {0x880E, 0xB4D3}, /* AfeIfCreg4B1000Lsbs */
799 {0x880F, 0xB4D3}, /* AfeIfCreg4B100Lsbs */
800 {0x8810, 0xB4D3}, /* AfeIfCreg4B10Lsbs */
801
802 {0x8805, 0xB03E}, /* AfeIfCreg3B1000Msbs */
803 {0x8806, 0xB03E}, /* AfeIfCreg3B100Msbs */
804 {0x8807, 0xFF00}, /* AfeIfCreg3B10Msbs */
805
806 {0x8808, 0xE090}, /* AfeIfCreg3B1000Lsbs */
807 {0x8809, 0xE110}, /* AfeIfCreg3B100Lsbs */
808 {0x880A, 0x0000}, /* AfeIfCreg3B10Lsbs */
809
810 {0x300D, 1}, /* DisableNorm */
811
812 {0x280C, 0x0180}, /* LinkHoldEnd */
813
814 {0x1C21, 0x0002}, /* AlphaM */
815
816 {0x3821, 6}, /* FfeLkgTx0 */
817 {0x381D, 1}, /* FfeLkg1g4 */
818 {0x381E, 1}, /* FfeLkg1g5 */
819 {0x381F, 1}, /* FfeLkg1g6 */
820 {0x3820, 1}, /* FfeLkg1g7 */
821
822 {0x8402, 0x01F0}, /* Btinact */
823 {0x800E, 20}, /* LftrainTime */
824 {0x800F, 24}, /* DvguardTime */
825 {0x8010, 46}, /* IdlguardTime */
826
827 {0, 0}
828
829};
830
831/* condensed version of the phy initialization routine */
Alan Cox25ad00b2009-08-19 18:21:44 +0100832void ET1310_PhyInit(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700833{
Alan Cox9fa81092009-08-27 11:00:36 +0100834 uint16_t data, index;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700835
Alan Cox25ad00b2009-08-19 18:21:44 +0100836 if (etdev == NULL)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700837 return;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700838
Alan Cox64f93032009-06-10 17:30:41 +0100839 /* get the identity (again ?) */
Alan Cox9fa81092009-08-27 11:00:36 +0100840 MiRead(etdev, PHY_ID_1, &data);
841 MiRead(etdev, PHY_ID_2, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700842
Alan Cox64f93032009-06-10 17:30:41 +0100843 /* what does this do/achieve ? */
Alan Cox9fa81092009-08-27 11:00:36 +0100844 MiRead(etdev, PHY_MPHY_CONTROL_REG, &data); /* should read 0002 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100845 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0006);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700846
Alan Cox64f93032009-06-10 17:30:41 +0100847 /* read modem register 0402, should I do something with the return
848 data ? */
Alan Cox25ad00b2009-08-19 18:21:44 +0100849 MiWrite(etdev, PHY_INDEX_REG, 0x0402);
Alan Cox9fa81092009-08-27 11:00:36 +0100850 MiRead(etdev, PHY_DATA_REG, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700851
Alan Cox64f93032009-06-10 17:30:41 +0100852 /* what does this do/achieve ? */
Alan Cox25ad00b2009-08-19 18:21:44 +0100853 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700854
Alan Cox64f93032009-06-10 17:30:41 +0100855 /* get the identity (again ?) */
Alan Cox9fa81092009-08-27 11:00:36 +0100856 MiRead(etdev, PHY_ID_1, &data);
857 MiRead(etdev, PHY_ID_2, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700858
Alan Cox64f93032009-06-10 17:30:41 +0100859 /* what does this achieve ? */
Alan Cox9fa81092009-08-27 11:00:36 +0100860 MiRead(etdev, PHY_MPHY_CONTROL_REG, &data); /* should read 0002 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100861 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0006);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700862
Alan Cox64f93032009-06-10 17:30:41 +0100863 /* read modem register 0402, should I do something with
864 the return data? */
Alan Cox25ad00b2009-08-19 18:21:44 +0100865 MiWrite(etdev, PHY_INDEX_REG, 0x0402);
Alan Cox9fa81092009-08-27 11:00:36 +0100866 MiRead(etdev, PHY_DATA_REG, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700867
Alan Cox25ad00b2009-08-19 18:21:44 +0100868 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700869
Alan Cox64f93032009-06-10 17:30:41 +0100870 /* what does this achieve (should return 0x1040) */
Alan Cox9fa81092009-08-27 11:00:36 +0100871 MiRead(etdev, PHY_CONTROL, &data);
872 MiRead(etdev, PHY_MPHY_CONTROL_REG, &data); /* should read 0002 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100873 MiWrite(etdev, PHY_CONTROL, 0x1840);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700874
Alan Cox25ad00b2009-08-19 18:21:44 +0100875 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0007);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700876
Alan Cox64f93032009-06-10 17:30:41 +0100877 /* here the writing of the array starts.... */
Alan Cox9fa81092009-08-27 11:00:36 +0100878 index = 0;
879 while (ConfigPhy[index][0] != 0x0000) {
Alan Cox64f93032009-06-10 17:30:41 +0100880 /* write value */
Alan Cox9fa81092009-08-27 11:00:36 +0100881 MiWrite(etdev, PHY_INDEX_REG, ConfigPhy[index][0]);
882 MiWrite(etdev, PHY_DATA_REG, ConfigPhy[index][1]);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700883
Alan Cox64f93032009-06-10 17:30:41 +0100884 /* read it back */
Alan Cox9fa81092009-08-27 11:00:36 +0100885 MiWrite(etdev, PHY_INDEX_REG, ConfigPhy[index][0]);
886 MiRead(etdev, PHY_DATA_REG, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700887
Alan Cox64f93032009-06-10 17:30:41 +0100888 /* do a check on the value read back ? */
Alan Cox9fa81092009-08-27 11:00:36 +0100889 index++;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700890 }
Alan Cox64f93032009-06-10 17:30:41 +0100891 /* here the writing of the array ends... */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700892
Alan Cox9fa81092009-08-27 11:00:36 +0100893 MiRead(etdev, PHY_CONTROL, &data); /* 0x1840 */
894 MiRead(etdev, PHY_MPHY_CONTROL_REG, &data);/* should read 0007 */
Alan Cox25ad00b2009-08-19 18:21:44 +0100895 MiWrite(etdev, PHY_CONTROL, 0x1040);
896 MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700897}
898
Alan Cox25ad00b2009-08-19 18:21:44 +0100899void ET1310_PhyReset(struct et131x_adapter *etdev)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700900{
Alan Cox25ad00b2009-08-19 18:21:44 +0100901 MiWrite(etdev, PHY_CONTROL, 0x8000);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700902}
903
Alan Cox25ad00b2009-08-19 18:21:44 +0100904void ET1310_PhyPowerDown(struct et131x_adapter *etdev, bool down)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700905{
Alan Cox9fa81092009-08-27 11:00:36 +0100906 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700907
Alan Cox9fa81092009-08-27 11:00:36 +0100908 MiRead(etdev, PHY_CONTROL, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700909
910 if (down == false) {
Alan Cox64f93032009-06-10 17:30:41 +0100911 /* Power UP */
Alan Cox9fa81092009-08-27 11:00:36 +0100912 data &= ~0x0800;
913 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700914 } else {
Alan Cox64f93032009-06-10 17:30:41 +0100915 /* Power DOWN */
Alan Cox9fa81092009-08-27 11:00:36 +0100916 data |= 0x0800;
917 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700918 }
919}
920
Alan Cox25ad00b2009-08-19 18:21:44 +0100921void ET1310_PhyAutoNeg(struct et131x_adapter *etdev, bool enable)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700922{
Alan Cox9fa81092009-08-27 11:00:36 +0100923 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700924
Alan Cox9fa81092009-08-27 11:00:36 +0100925 MiRead(etdev, PHY_CONTROL, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700926
927 if (enable == true) {
Alan Cox64f93032009-06-10 17:30:41 +0100928 /* Autonegotiation ON */
Alan Cox9fa81092009-08-27 11:00:36 +0100929 data |= 0x1000;
930 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700931 } else {
Alan Cox64f93032009-06-10 17:30:41 +0100932 /* Autonegotiation OFF */
Alan Cox9fa81092009-08-27 11:00:36 +0100933 data &= ~0x1000;
934 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700935 }
936}
937
Alan Cox25ad00b2009-08-19 18:21:44 +0100938void ET1310_PhyDuplexMode(struct et131x_adapter *etdev, uint16_t duplex)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700939{
Alan Cox9fa81092009-08-27 11:00:36 +0100940 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700941
Alan Cox9fa81092009-08-27 11:00:36 +0100942 MiRead(etdev, PHY_CONTROL, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700943
944 if (duplex == TRUEPHY_DUPLEX_FULL) {
Alan Cox64f93032009-06-10 17:30:41 +0100945 /* Set Full Duplex */
Alan Cox9fa81092009-08-27 11:00:36 +0100946 data |= 0x100;
947 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700948 } else {
Alan Cox64f93032009-06-10 17:30:41 +0100949 /* Set Half Duplex */
Alan Cox9fa81092009-08-27 11:00:36 +0100950 data &= ~0x100;
951 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700952 }
953}
954
Alan Cox25ad00b2009-08-19 18:21:44 +0100955void ET1310_PhySpeedSelect(struct et131x_adapter *etdev, uint16_t speed)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700956{
Alan Cox9fa81092009-08-27 11:00:36 +0100957 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700958
Alan Cox64f93032009-06-10 17:30:41 +0100959 /* Read the PHY control register */
Alan Cox9fa81092009-08-27 11:00:36 +0100960 MiRead(etdev, PHY_CONTROL, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700961
Alan Cox64f93032009-06-10 17:30:41 +0100962 /* Clear all Speed settings (Bits 6, 13) */
Alan Cox9fa81092009-08-27 11:00:36 +0100963 data &= ~0x2040;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700964
Alan Cox64f93032009-06-10 17:30:41 +0100965 /* Reset the speed bits based on user selection */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700966 switch (speed) {
967 case TRUEPHY_SPEED_10MBPS:
Alan Cox64f93032009-06-10 17:30:41 +0100968 /* Bits already cleared above, do nothing */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700969 break;
970
971 case TRUEPHY_SPEED_100MBPS:
Alan Cox64f93032009-06-10 17:30:41 +0100972 /* 100M == Set bit 13 */
Alan Cox9fa81092009-08-27 11:00:36 +0100973 data |= 0x2000;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700974 break;
975
976 case TRUEPHY_SPEED_1000MBPS:
977 default:
Alan Cox9fa81092009-08-27 11:00:36 +0100978 data |= 0x0040;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700979 break;
980 }
981
Alan Cox64f93032009-06-10 17:30:41 +0100982 /* Write back the new speed */
Alan Cox9fa81092009-08-27 11:00:36 +0100983 MiWrite(etdev, PHY_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700984}
985
Alan Cox25ad00b2009-08-19 18:21:44 +0100986void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *etdev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700987 uint16_t duplex)
988{
Alan Cox9fa81092009-08-27 11:00:36 +0100989 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700990
Alan Cox64f93032009-06-10 17:30:41 +0100991 /* Read the PHY 1000 Base-T Control Register */
Alan Cox9fa81092009-08-27 11:00:36 +0100992 MiRead(etdev, PHY_1000_CONTROL, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700993
Alan Cox64f93032009-06-10 17:30:41 +0100994 /* Clear Bits 8,9 */
Alan Cox9fa81092009-08-27 11:00:36 +0100995 data &= ~0x0300;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -0700996
997 switch (duplex) {
998 case TRUEPHY_ADV_DUPLEX_NONE:
Alan Cox64f93032009-06-10 17:30:41 +0100999 /* Duplex already cleared, do nothing */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001000 break;
1001
1002 case TRUEPHY_ADV_DUPLEX_FULL:
Alan Cox64f93032009-06-10 17:30:41 +01001003 /* Set Bit 9 */
Alan Cox9fa81092009-08-27 11:00:36 +01001004 data |= 0x0200;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001005 break;
1006
1007 case TRUEPHY_ADV_DUPLEX_HALF:
Alan Cox64f93032009-06-10 17:30:41 +01001008 /* Set Bit 8 */
Alan Cox9fa81092009-08-27 11:00:36 +01001009 data |= 0x0100;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001010 break;
1011
1012 case TRUEPHY_ADV_DUPLEX_BOTH:
1013 default:
Alan Cox9fa81092009-08-27 11:00:36 +01001014 data |= 0x0300;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001015 break;
1016 }
1017
Alan Cox64f93032009-06-10 17:30:41 +01001018 /* Write back advertisement */
Alan Cox9fa81092009-08-27 11:00:36 +01001019 MiWrite(etdev, PHY_1000_CONTROL, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001020}
1021
Alan Cox25ad00b2009-08-19 18:21:44 +01001022void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *etdev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001023 uint16_t duplex)
1024{
Alan Cox9fa81092009-08-27 11:00:36 +01001025 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001026
Alan Cox64f93032009-06-10 17:30:41 +01001027 /* Read the Autonegotiation Register (10/100) */
Alan Cox9fa81092009-08-27 11:00:36 +01001028 MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001029
Alan Cox64f93032009-06-10 17:30:41 +01001030 /* Clear bits 7,8 */
Alan Cox9fa81092009-08-27 11:00:36 +01001031 data &= ~0x0180;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001032
1033 switch (duplex) {
1034 case TRUEPHY_ADV_DUPLEX_NONE:
Alan Cox64f93032009-06-10 17:30:41 +01001035 /* Duplex already cleared, do nothing */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001036 break;
1037
1038 case TRUEPHY_ADV_DUPLEX_FULL:
Alan Cox64f93032009-06-10 17:30:41 +01001039 /* Set Bit 8 */
Alan Cox9fa81092009-08-27 11:00:36 +01001040 data |= 0x0100;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001041 break;
1042
1043 case TRUEPHY_ADV_DUPLEX_HALF:
Alan Cox64f93032009-06-10 17:30:41 +01001044 /* Set Bit 7 */
Alan Cox9fa81092009-08-27 11:00:36 +01001045 data |= 0x0080;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001046 break;
1047
1048 case TRUEPHY_ADV_DUPLEX_BOTH:
1049 default:
Alan Cox64f93032009-06-10 17:30:41 +01001050 /* Set Bits 7,8 */
Alan Cox9fa81092009-08-27 11:00:36 +01001051 data |= 0x0180;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001052 break;
1053 }
1054
Alan Cox64f93032009-06-10 17:30:41 +01001055 /* Write back advertisement */
Alan Cox9fa81092009-08-27 11:00:36 +01001056 MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001057}
1058
Alan Cox25ad00b2009-08-19 18:21:44 +01001059void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *etdev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001060 uint16_t duplex)
1061{
Alan Cox9fa81092009-08-27 11:00:36 +01001062 uint16_t data;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001063
Alan Cox64f93032009-06-10 17:30:41 +01001064 /* Read the Autonegotiation Register (10/100) */
Alan Cox9fa81092009-08-27 11:00:36 +01001065 MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001066
Alan Cox64f93032009-06-10 17:30:41 +01001067 /* Clear bits 5,6 */
Alan Cox9fa81092009-08-27 11:00:36 +01001068 data &= ~0x0060;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001069
1070 switch (duplex) {
1071 case TRUEPHY_ADV_DUPLEX_NONE:
Alan Cox64f93032009-06-10 17:30:41 +01001072 /* Duplex already cleared, do nothing */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001073 break;
1074
1075 case TRUEPHY_ADV_DUPLEX_FULL:
Alan Cox64f93032009-06-10 17:30:41 +01001076 /* Set Bit 6 */
Alan Cox9fa81092009-08-27 11:00:36 +01001077 data |= 0x0040;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001078 break;
1079
1080 case TRUEPHY_ADV_DUPLEX_HALF:
Alan Cox64f93032009-06-10 17:30:41 +01001081 /* Set Bit 5 */
Alan Cox9fa81092009-08-27 11:00:36 +01001082 data |= 0x0020;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001083 break;
1084
1085 case TRUEPHY_ADV_DUPLEX_BOTH:
1086 default:
Alan Cox64f93032009-06-10 17:30:41 +01001087 /* Set Bits 5,6 */
Alan Cox9fa81092009-08-27 11:00:36 +01001088 data |= 0x0060;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001089 break;
1090 }
1091
Alan Cox64f93032009-06-10 17:30:41 +01001092 /* Write back advertisement */
Alan Cox9fa81092009-08-27 11:00:36 +01001093 MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001094}
1095
Alan Cox25ad00b2009-08-19 18:21:44 +01001096void ET1310_PhyLinkStatus(struct et131x_adapter *etdev,
Alan Cox9fa81092009-08-27 11:00:36 +01001097 uint8_t *link_status,
1098 uint32_t *autoneg,
1099 uint32_t *linkspeed,
1100 uint32_t *duplex_mode,
1101 uint32_t *mdi_mdix,
1102 uint32_t *masterslave, uint32_t *polarity)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001103{
Alan Cox9fa81092009-08-27 11:00:36 +01001104 uint16_t mistatus = 0;
1105 uint16_t is1000BaseT = 0;
1106 uint16_t vmi_phystatus = 0;
1107 uint16_t control = 0;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001108
Alan Cox9fa81092009-08-27 11:00:36 +01001109 MiRead(etdev, PHY_STATUS, &mistatus);
1110 MiRead(etdev, PHY_1000_STATUS, &is1000BaseT);
1111 MiRead(etdev, PHY_PHY_STATUS, &vmi_phystatus);
1112 MiRead(etdev, PHY_CONTROL, &control);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001113
Alan Cox9fa81092009-08-27 11:00:36 +01001114 if (link_status) {
1115 *link_status =
1116 (unsigned char)((vmi_phystatus & 0x0040) ? 1 : 0);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001117 }
1118
Alan Cox9fa81092009-08-27 11:00:36 +01001119 if (autoneg) {
1120 *autoneg =
1121 (control & 0x1000) ? ((vmi_phystatus & 0x0020) ?
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001122 TRUEPHY_ANEG_COMPLETE :
1123 TRUEPHY_ANEG_NOT_COMPLETE) :
1124 TRUEPHY_ANEG_DISABLED;
1125 }
1126
Alan Cox9fa81092009-08-27 11:00:36 +01001127 if (linkspeed)
1128 *linkspeed = (vmi_phystatus & 0x0300) >> 8;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001129
Alan Cox9fa81092009-08-27 11:00:36 +01001130 if (duplex_mode)
1131 *duplex_mode = (vmi_phystatus & 0x0080) >> 7;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001132
Alan Cox9fa81092009-08-27 11:00:36 +01001133 if (mdi_mdix)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001134 /* NOTE: Need to complete this */
Alan Cox9fa81092009-08-27 11:00:36 +01001135 *mdi_mdix = 0;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001136
Alan Cox9fa81092009-08-27 11:00:36 +01001137 if (masterslave) {
1138 *masterslave =
1139 (is1000BaseT & 0x4000) ? TRUEPHY_CFG_MASTER :
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001140 TRUEPHY_CFG_SLAVE;
1141 }
1142
Alan Cox9fa81092009-08-27 11:00:36 +01001143 if (polarity) {
1144 *polarity =
1145 (vmi_phystatus & 0x0400) ? TRUEPHY_POLARITY_INVERTED :
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001146 TRUEPHY_POLARITY_NORMAL;
1147 }
1148}
1149
Alan Cox25ad00b2009-08-19 18:21:44 +01001150void ET1310_PhyAndOrReg(struct et131x_adapter *etdev,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001151 uint16_t regnum, uint16_t andMask, uint16_t orMask)
1152{
1153 uint16_t reg;
1154
Alan Cox64f93032009-06-10 17:30:41 +01001155 /* Read the requested register */
Alan Cox25ad00b2009-08-19 18:21:44 +01001156 MiRead(etdev, regnum, &reg);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001157
Alan Cox64f93032009-06-10 17:30:41 +01001158 /* Apply the AND mask */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001159 reg &= andMask;
1160
Alan Cox64f93032009-06-10 17:30:41 +01001161 /* Apply the OR mask */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001162 reg |= orMask;
1163
Alan Cox64f93032009-06-10 17:30:41 +01001164 /* Write the value back to the register */
Alan Cox25ad00b2009-08-19 18:21:44 +01001165 MiWrite(etdev, regnum, reg);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001166}
1167
Alan Cox25ad00b2009-08-19 18:21:44 +01001168void ET1310_PhyAccessMiBit(struct et131x_adapter *etdev, uint16_t action,
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001169 uint16_t regnum, uint16_t bitnum, uint8_t *value)
1170{
1171 uint16_t reg;
1172 uint16_t mask = 0;
1173
Alan Cox64f93032009-06-10 17:30:41 +01001174 /* Create a mask to isolate the requested bit */
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001175 mask = 0x0001 << bitnum;
1176
Alan Cox64f93032009-06-10 17:30:41 +01001177 /* Read the requested register */
Alan Cox25ad00b2009-08-19 18:21:44 +01001178 MiRead(etdev, regnum, &reg);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001179
1180 switch (action) {
1181 case TRUEPHY_BIT_READ:
Alan Cox64f93032009-06-10 17:30:41 +01001182 if (value != NULL)
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001183 *value = (reg & mask) >> bitnum;
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001184 break;
1185
1186 case TRUEPHY_BIT_SET:
1187 reg |= mask;
Alan Cox25ad00b2009-08-19 18:21:44 +01001188 MiWrite(etdev, regnum, reg);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001189 break;
1190
1191 case TRUEPHY_BIT_CLEAR:
1192 reg &= ~mask;
Alan Cox25ad00b2009-08-19 18:21:44 +01001193 MiWrite(etdev, regnum, reg);
Greg Kroah-Hartmancfb739b2008-04-03 17:30:53 -07001194 break;
1195
1196 default:
1197 break;
1198 }
1199}