compat-wireless-2010-03-10
[pandora-wifi.git] / drivers / net / atl1c / atl1c_hw.c
1 /*
2  * Copyright(c) 2007 Atheros Corporation. All rights reserved.
3  *
4  * Derived from Intel e1000 driver
5  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along with
18  * this program; if not, write to the Free Software Foundation, Inc., 59
19  * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  */
21 #include <linux/pci.h>
22 #include <linux/delay.h>
23 #include <linux/mii.h>
24 #include <linux/crc32.h>
25
26 #include "atl1c.h"
27
28 /*
29  * check_eeprom_exist
30  * return 1 if eeprom exist
31  */
32 int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
33 {
34         u32 data;
35
36         AT_READ_REG(hw, REG_TWSI_DEBUG, &data);
37         if (data & TWSI_DEBUG_DEV_EXIST)
38                 return 1;
39
40         return 0;
41 }
42
43 void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
44 {
45         u32 value;
46         /*
47          * 00-0B-6A-F6-00-DC
48          * 0:  6AF600DC 1: 000B
49          * low dword
50          */
51         value = (((u32)hw->mac_addr[2]) << 24) |
52                 (((u32)hw->mac_addr[3]) << 16) |
53                 (((u32)hw->mac_addr[4]) << 8)  |
54                 (((u32)hw->mac_addr[5])) ;
55         AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
56         /* hight dword */
57         value = (((u32)hw->mac_addr[0]) << 8) |
58                 (((u32)hw->mac_addr[1])) ;
59         AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
60 }
61
62 /*
63  * atl1c_get_permanent_address
64  * return 0 if get valid mac address,
65  */
66 static int atl1c_get_permanent_address(struct atl1c_hw *hw)
67 {
68         u32 addr[2];
69         u32 i;
70         u32 otp_ctrl_data;
71         u32 twsi_ctrl_data;
72         u8  eth_addr[ETH_ALEN];
73         u16 phy_data;
74         bool raise_vol = false;
75
76         /* init */
77         addr[0] = addr[1] = 0;
78         AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
79         if (atl1c_check_eeprom_exist(hw)) {
80                 if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b) {
81                         /* Enable OTP CLK */
82                         if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) {
83                                 otp_ctrl_data |= OTP_CTRL_CLK_EN;
84                                 AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
85                                 AT_WRITE_FLUSH(hw);
86                                 msleep(1);
87                         }
88                 }
89
90                 if (hw->nic_type == athr_l2c_b ||
91                     hw->nic_type == athr_l2c_b2 ||
92                     hw->nic_type == athr_l1d) {
93                         atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
94                         if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
95                                 goto out;
96                         phy_data &= 0xFF7F;
97                         atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
98
99                         atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
100                         if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
101                                 goto out;
102                         phy_data |= 0x8;
103                         atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
104                         udelay(20);
105                         raise_vol = true;
106                 }
107
108                 AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
109                 twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
110                 AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
111                 for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
112                         msleep(10);
113                         AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
114                         if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
115                                 break;
116                 }
117                 if (i >= AT_TWSI_EEPROM_TIMEOUT)
118                         return -1;
119         }
120         /* Disable OTP_CLK */
121         if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) {
122                 if (otp_ctrl_data & OTP_CTRL_CLK_EN) {
123                         otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
124                         AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
125                         AT_WRITE_FLUSH(hw);
126                         msleep(1);
127                 }
128         }
129         if (raise_vol) {
130                 if (hw->nic_type == athr_l2c_b ||
131                     hw->nic_type == athr_l2c_b2 ||
132                     hw->nic_type == athr_l1d) {
133                         atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
134                         if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
135                                 goto out;
136                         phy_data |= 0x80;
137                         atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
138
139                         atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
140                         if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
141                                 goto out;
142                         phy_data &= 0xFFF7;
143                         atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
144                         udelay(20);
145                 }
146         }
147
148         /* maybe MAC-address is from BIOS */
149         AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
150         AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
151         *(u32 *) &eth_addr[2] = swab32(addr[0]);
152         *(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
153
154         if (is_valid_ether_addr(eth_addr)) {
155                 memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
156                 return 0;
157         }
158
159 out:
160         return -1;
161 }
162
163 bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value)
164 {
165         int i;
166         int ret = false;
167         u32 otp_ctrl_data;
168         u32 control;
169         u32 data;
170
171         if (offset & 3)
172                 return ret; /* address do not align */
173
174         AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
175         if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
176                 AT_WRITE_REG(hw, REG_OTP_CTRL,
177                                 (otp_ctrl_data | OTP_CTRL_CLK_EN));
178
179         AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0);
180         control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT;
181         AT_WRITE_REG(hw, REG_EEPROM_CTRL, control);
182
183         for (i = 0; i < 10; i++) {
184                 udelay(100);
185                 AT_READ_REG(hw, REG_EEPROM_CTRL, &control);
186                 if (control & EEPROM_CTRL_RW)
187                         break;
188         }
189         if (control & EEPROM_CTRL_RW) {
190                 AT_READ_REG(hw, REG_EEPROM_CTRL, &data);
191                 AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value);
192                 data = data & 0xFFFF;
193                 *p_value = swab32((data << 16) | (*p_value >> 16));
194                 ret = true;
195         }
196         if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
197                 AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
198
199         return ret;
200 }
201 /*
202  * Reads the adapter's MAC address from the EEPROM
203  *
204  * hw - Struct containing variables accessed by shared code
205  */
206 int atl1c_read_mac_addr(struct atl1c_hw *hw)
207 {
208         int err = 0;
209
210         err = atl1c_get_permanent_address(hw);
211         if (err)
212                 random_ether_addr(hw->perm_mac_addr);
213
214         memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
215         return 0;
216 }
217
218 /*
219  * atl1c_hash_mc_addr
220  *  purpose
221  *      set hash value for a multicast address
222  *      hash calcu processing :
223  *          1. calcu 32bit CRC for multicast address
224  *          2. reverse crc with MSB to LSB
225  */
226 u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr)
227 {
228         u32 crc32;
229         u32 value = 0;
230         int i;
231
232         crc32 = ether_crc_le(6, mc_addr);
233         for (i = 0; i < 32; i++)
234                 value |= (((crc32 >> i) & 1) << (31 - i));
235
236         return value;
237 }
238
239 /*
240  * Sets the bit in the multicast table corresponding to the hash value.
241  * hw - Struct containing variables accessed by shared code
242  * hash_value - Multicast address hash value
243  */
244 void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value)
245 {
246         u32 hash_bit, hash_reg;
247         u32 mta;
248
249         /*
250          * The HASH Table  is a register array of 2 32-bit registers.
251          * It is treated like an array of 64 bits.  We want to set
252          * bit BitArray[hash_value]. So we figure out what register
253          * the bit is in, read it, OR in the new bit, then write
254          * back the new value.  The register is determined by the
255          * upper bit of the hash value and the bit within that
256          * register are determined by the lower 5 bits of the value.
257          */
258         hash_reg = (hash_value >> 31) & 0x1;
259         hash_bit = (hash_value >> 26) & 0x1F;
260
261         mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
262
263         mta |= (1 << hash_bit);
264
265         AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
266 }
267
268 /*
269  * Reads the value from a PHY register
270  * hw - Struct containing variables accessed by shared code
271  * reg_addr - address of the PHY register to read
272  */
273 int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
274 {
275         u32 val;
276         int i;
277
278         val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
279                 MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
280                 MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
281
282         AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
283
284         for (i = 0; i < MDIO_WAIT_TIMES; i++) {
285                 udelay(2);
286                 AT_READ_REG(hw, REG_MDIO_CTRL, &val);
287                 if (!(val & (MDIO_START | MDIO_BUSY)))
288                         break;
289         }
290         if (!(val & (MDIO_START | MDIO_BUSY))) {
291                 *phy_data = (u16)val;
292                 return 0;
293         }
294
295         return -1;
296 }
297
298 /*
299  * Writes a value to a PHY register
300  * hw - Struct containing variables accessed by shared code
301  * reg_addr - address of the PHY register to write
302  * data - data to write to the PHY
303  */
304 int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
305 {
306         int i;
307         u32 val;
308
309         val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT   |
310                (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
311                MDIO_SUP_PREAMBLE | MDIO_START |
312                MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
313
314         AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
315
316         for (i = 0; i < MDIO_WAIT_TIMES; i++) {
317                 udelay(2);
318                 AT_READ_REG(hw, REG_MDIO_CTRL, &val);
319                 if (!(val & (MDIO_START | MDIO_BUSY)))
320                         break;
321         }
322
323         if (!(val & (MDIO_START | MDIO_BUSY)))
324                 return 0;
325
326         return -1;
327 }
328
329 /*
330  * Configures PHY autoneg and flow control advertisement settings
331  *
332  * hw - Struct containing variables accessed by shared code
333  */
334 static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
335 {
336         u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_SPEED_MASK;
337         u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP &
338                                 ~GIGA_CR_1000T_SPEED_MASK;
339
340         if (hw->autoneg_advertised & ADVERTISED_10baseT_Half)
341                 mii_adv_data |= ADVERTISE_10HALF;
342         if (hw->autoneg_advertised & ADVERTISED_10baseT_Full)
343                 mii_adv_data |= ADVERTISE_10FULL;
344         if (hw->autoneg_advertised & ADVERTISED_100baseT_Half)
345                 mii_adv_data |= ADVERTISE_100HALF;
346         if (hw->autoneg_advertised & ADVERTISED_100baseT_Full)
347                 mii_adv_data |= ADVERTISE_100FULL;
348
349         if (hw->autoneg_advertised & ADVERTISED_Autoneg)
350                 mii_adv_data |= ADVERTISE_10HALF  | ADVERTISE_10FULL |
351                                 ADVERTISE_100HALF | ADVERTISE_100FULL;
352
353         if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) {
354                 if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half)
355                         mii_giga_ctrl_data |= ADVERTISE_1000HALF;
356                 if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full)
357                         mii_giga_ctrl_data |= ADVERTISE_1000FULL;
358                 if (hw->autoneg_advertised & ADVERTISED_Autoneg)
359                         mii_giga_ctrl_data |= ADVERTISE_1000HALF |
360                                         ADVERTISE_1000FULL;
361         }
362
363         if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 ||
364             atl1c_write_phy_reg(hw, MII_GIGA_CR, mii_giga_ctrl_data) != 0)
365                 return -1;
366         return 0;
367 }
368
369 void atl1c_phy_disable(struct atl1c_hw *hw)
370 {
371         AT_WRITE_REGW(hw, REG_GPHY_CTRL,
372                         GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
373 }
374
375 static void atl1c_phy_magic_data(struct atl1c_hw *hw)
376 {
377         u16 data;
378
379         data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
380                 ((1 & ANA_INTERVAL_SEL_TIMER_MASK) <<
381                 ANA_INTERVAL_SEL_TIMER_SHIFT);
382
383         atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18);
384         atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
385
386         data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG |
387                 ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL |
388                 ANA_SERDES_EN_LCKDT;
389
390         atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5);
391         atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
392
393         data = (44 & ANA_LONG_CABLE_TH_100_MASK) |
394                 ((33 & ANA_SHORT_CABLE_TH_100_MASK) <<
395                 ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM |
396                 ANA_BP_SMALL_BW;
397
398         atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54);
399         atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
400
401         data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) <<
402                 ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
403                 ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
404                 ANA_IECHO_ADJ_0_SHIFT);
405
406         atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4);
407         atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
408
409         data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) <<
410                 ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE |
411                 ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M;
412
413         atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0);
414         atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
415
416         if (hw->ctrl_flags & ATL1C_HIB_DISABLE) {
417                 atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41);
418                 if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
419                         return;
420                 data &= ~ANA_TOP_PS_EN;
421                 atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
422
423                 atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11);
424                 if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
425                         return;
426                 data &= ~ANA_PS_HIB_EN;
427                 atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
428         }
429 }
430
431 int atl1c_phy_reset(struct atl1c_hw *hw)
432 {
433         struct atl1c_adapter *adapter = hw->adapter;
434         struct pci_dev *pdev = adapter->pdev;
435         u16 phy_data;
436         u32 phy_ctrl_data = GPHY_CTRL_DEFAULT;
437         u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN;
438         int err;
439
440         if (hw->ctrl_flags & ATL1C_HIB_DISABLE)
441                 phy_ctrl_data &= ~GPHY_CTRL_HIB_EN;
442
443         AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
444         AT_WRITE_FLUSH(hw);
445         msleep(40);
446         phy_ctrl_data |= GPHY_CTRL_EXT_RESET;
447         AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
448         AT_WRITE_FLUSH(hw);
449         msleep(10);
450
451         if (hw->nic_type == athr_l2c_b) {
452                 atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x0A);
453                 atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
454                 atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xDFFF);
455         }
456
457         if (hw->nic_type == athr_l2c_b ||
458             hw->nic_type == athr_l2c_b2 ||
459             hw->nic_type == athr_l1d) {
460                 atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
461                 atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
462                 atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7);
463                 msleep(20);
464         }
465
466         /*Enable PHY LinkChange Interrupt */
467         err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data);
468         if (err) {
469                 if (netif_msg_hw(adapter))
470                         dev_err(&pdev->dev,
471                                 "Error enable PHY linkChange Interrupt\n");
472                 return err;
473         }
474         if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
475                 atl1c_phy_magic_data(hw);
476         return 0;
477 }
478
479 int atl1c_phy_init(struct atl1c_hw *hw)
480 {
481         struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
482         struct pci_dev *pdev = adapter->pdev;
483         int ret_val;
484         u16 mii_bmcr_data = BMCR_RESET;
485         u16 phy_id1, phy_id2;
486
487         if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &phy_id1) != 0) ||
488                 (atl1c_read_phy_reg(hw, MII_PHYSID2, &phy_id2) != 0)) {
489                         if (netif_msg_link(adapter))
490                                 dev_err(&pdev->dev, "Error get phy ID\n");
491                 return -1;
492         }
493         switch (hw->media_type) {
494         case MEDIA_TYPE_AUTO_SENSOR:
495                 ret_val = atl1c_phy_setup_adv(hw);
496                 if (ret_val) {
497                         if (netif_msg_link(adapter))
498                                 dev_err(&pdev->dev,
499                                         "Error Setting up Auto-Negotiation\n");
500                         return ret_val;
501                 }
502                 mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
503                 break;
504         case MEDIA_TYPE_100M_FULL:
505                 mii_bmcr_data |= BMCR_SPEED_100 | BMCR_FULL_DUPLEX;
506                 break;
507         case MEDIA_TYPE_100M_HALF:
508                 mii_bmcr_data |= BMCR_SPEED_100;
509                 break;
510         case MEDIA_TYPE_10M_FULL:
511                 mii_bmcr_data |= BMCR_SPEED_10 | BMCR_FULL_DUPLEX;
512                 break;
513         case MEDIA_TYPE_10M_HALF:
514                 mii_bmcr_data |= BMCR_SPEED_10;
515                 break;
516         default:
517                 if (netif_msg_link(adapter))
518                         dev_err(&pdev->dev, "Wrong Media type %d\n",
519                                 hw->media_type);
520                 return -1;
521                 break;
522         }
523
524         ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
525         if (ret_val)
526                 return ret_val;
527         hw->phy_configured = true;
528
529         return 0;
530 }
531
532 /*
533  * Detects the current speed and duplex settings of the hardware.
534  *
535  * hw - Struct containing variables accessed by shared code
536  * speed - Speed of the connection
537  * duplex - Duplex setting of the connection
538  */
539 int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
540 {
541         int err;
542         u16 phy_data;
543
544         /* Read   PHY Specific Status Register (17) */
545         err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data);
546         if (err)
547                 return err;
548
549         if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED))
550                 return -1;
551
552         switch (phy_data & GIGA_PSSR_SPEED) {
553         case GIGA_PSSR_1000MBS:
554                 *speed = SPEED_1000;
555                 break;
556         case GIGA_PSSR_100MBS:
557                 *speed = SPEED_100;
558                 break;
559         case  GIGA_PSSR_10MBS:
560                 *speed = SPEED_10;
561                 break;
562         default:
563                 return -1;
564                 break;
565         }
566
567         if (phy_data & GIGA_PSSR_DPLX)
568                 *duplex = FULL_DUPLEX;
569         else
570                 *duplex = HALF_DUPLEX;
571
572         return 0;
573 }
574
575 int atl1c_restart_autoneg(struct atl1c_hw *hw)
576 {
577         int err = 0;
578         u16 mii_bmcr_data = BMCR_RESET;
579
580         err = atl1c_phy_setup_adv(hw);
581         if (err)
582                 return err;
583         mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
584
585         return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
586 }