877 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright(c) 2007 Atheros Corporation. All rights reserved.4 *5 * Derived from Intel e1000 driver6 * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.7 */8#include <linux/pci.h>9#include <linux/delay.h>10#include <linux/mii.h>11#include <linux/crc32.h>12 13#include "atl1c.h"14 15/*16 * check_eeprom_exist17 * return 1 if eeprom exist18 */19int atl1c_check_eeprom_exist(struct atl1c_hw *hw)20{21 u32 data;22 23 AT_READ_REG(hw, REG_TWSI_DEBUG, &data);24 if (data & TWSI_DEBUG_DEV_EXIST)25 return 1;26 27 AT_READ_REG(hw, REG_MASTER_CTRL, &data);28 if (data & MASTER_CTRL_OTP_SEL)29 return 1;30 return 0;31}32 33void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr)34{35 u32 value;36 /*37 * 00-0B-6A-F6-00-DC38 * 0: 6AF600DC 1: 000B39 * low dword40 */41 value = mac_addr[2] << 24 |42 mac_addr[3] << 16 |43 mac_addr[4] << 8 |44 mac_addr[5];45 AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);46 /* hight dword */47 value = mac_addr[0] << 8 |48 mac_addr[1];49 AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);50}51 52/* read mac address from hardware register */53static bool atl1c_read_current_addr(struct atl1c_hw *hw, u8 *eth_addr)54{55 u32 addr[2];56 57 AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);58 AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);59 60 *(u32 *) ð_addr[2] = htonl(addr[0]);61 *(u16 *) ð_addr[0] = htons((u16)addr[1]);62 63 return is_valid_ether_addr(eth_addr);64}65 66/*67 * atl1c_get_permanent_address68 * return 0 if get valid mac address,69 */70static int atl1c_get_permanent_address(struct atl1c_hw *hw)71{72 u32 i;73 u32 otp_ctrl_data;74 u32 twsi_ctrl_data;75 u16 phy_data;76 bool raise_vol = false;77 78 /* MAC-address from BIOS is the 1st priority */79 if (atl1c_read_current_addr(hw, hw->perm_mac_addr))80 return 0;81 82 /* init */83 AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);84 if (atl1c_check_eeprom_exist(hw)) {85 if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) {86 /* Enable OTP CLK */87 if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) {88 otp_ctrl_data |= OTP_CTRL_CLK_EN;89 AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);90 AT_WRITE_FLUSH(hw);91 msleep(1);92 }93 }94 /* raise voltage temporally for l2cb */95 if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {96 atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data);97 phy_data &= ~ANACTRL_HB_EN;98 atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data);99 atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);100 phy_data |= VOLT_CTRL_SWLOWEST;101 atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);102 udelay(20);103 raise_vol = true;104 }105 106 AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);107 twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;108 AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);109 for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {110 msleep(10);111 AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);112 if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)113 break;114 }115 if (i >= AT_TWSI_EEPROM_TIMEOUT)116 return -1;117 }118 /* Disable OTP_CLK */119 if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) {120 otp_ctrl_data &= ~OTP_CTRL_CLK_EN;121 AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);122 msleep(1);123 }124 if (raise_vol) {125 atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data);126 phy_data |= ANACTRL_HB_EN;127 atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data);128 atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);129 phy_data &= ~VOLT_CTRL_SWLOWEST;130 atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);131 udelay(20);132 }133 134 if (atl1c_read_current_addr(hw, hw->perm_mac_addr))135 return 0;136 137 return -1;138}139 140bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value)141{142 int i;143 bool ret = false;144 u32 otp_ctrl_data;145 u32 control;146 u32 data;147 148 if (offset & 3)149 return ret; /* address do not align */150 151 AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);152 if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))153 AT_WRITE_REG(hw, REG_OTP_CTRL,154 (otp_ctrl_data | OTP_CTRL_CLK_EN));155 156 AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0);157 control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT;158 AT_WRITE_REG(hw, REG_EEPROM_CTRL, control);159 160 for (i = 0; i < 10; i++) {161 udelay(100);162 AT_READ_REG(hw, REG_EEPROM_CTRL, &control);163 if (control & EEPROM_CTRL_RW)164 break;165 }166 if (control & EEPROM_CTRL_RW) {167 AT_READ_REG(hw, REG_EEPROM_CTRL, &data);168 AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value);169 data = data & 0xFFFF;170 *p_value = swab32((data << 16) | (*p_value >> 16));171 ret = true;172 }173 if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))174 AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);175 176 return ret;177}178/*179 * Reads the adapter's MAC address from the EEPROM180 *181 * hw - Struct containing variables accessed by shared code182 */183int atl1c_read_mac_addr(struct atl1c_hw *hw)184{185 int err = 0;186 187 err = atl1c_get_permanent_address(hw);188 if (err)189 eth_random_addr(hw->perm_mac_addr);190 191 memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));192 return err;193}194 195/*196 * atl1c_hash_mc_addr197 * purpose198 * set hash value for a multicast address199 * hash calcu processing :200 * 1. calcu 32bit CRC for multicast address201 * 2. reverse crc with MSB to LSB202 */203u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr)204{205 u32 crc32;206 u32 value = 0;207 int i;208 209 crc32 = ether_crc_le(6, mc_addr);210 for (i = 0; i < 32; i++)211 value |= (((crc32 >> i) & 1) << (31 - i));212 213 return value;214}215 216/*217 * Sets the bit in the multicast table corresponding to the hash value.218 * hw - Struct containing variables accessed by shared code219 * hash_value - Multicast address hash value220 */221void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value)222{223 u32 hash_bit, hash_reg;224 u32 mta;225 226 /*227 * The HASH Table is a register array of 2 32-bit registers.228 * It is treated like an array of 64 bits. We want to set229 * bit BitArray[hash_value]. So we figure out what register230 * the bit is in, read it, OR in the new bit, then write231 * back the new value. The register is determined by the232 * upper bit of the hash value and the bit within that233 * register are determined by the lower 5 bits of the value.234 */235 hash_reg = (hash_value >> 31) & 0x1;236 hash_bit = (hash_value >> 26) & 0x1F;237 238 mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);239 240 mta |= (1 << hash_bit);241 242 AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);243}244 245/*246 * wait mdio module be idle247 * return true: idle248 * false: still busy249 */250bool atl1c_wait_mdio_idle(struct atl1c_hw *hw)251{252 u32 val;253 int i;254 255 for (i = 0; i < MDIO_MAX_AC_TO; i++) {256 AT_READ_REG(hw, REG_MDIO_CTRL, &val);257 if (!(val & (MDIO_CTRL_BUSY | MDIO_CTRL_START)))258 break;259 udelay(10);260 }261 262 return i != MDIO_MAX_AC_TO;263}264 265void atl1c_stop_phy_polling(struct atl1c_hw *hw)266{267 if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))268 return;269 270 AT_WRITE_REG(hw, REG_MDIO_CTRL, 0);271 atl1c_wait_mdio_idle(hw);272}273 274void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel)275{276 u32 val;277 278 if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))279 return;280 281 val = MDIO_CTRL_SPRES_PRMBL |282 FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |283 FIELDX(MDIO_CTRL_REG, 1) |284 MDIO_CTRL_START |285 MDIO_CTRL_OP_READ;286 AT_WRITE_REG(hw, REG_MDIO_CTRL, val);287 atl1c_wait_mdio_idle(hw);288 val |= MDIO_CTRL_AP_EN;289 val &= ~MDIO_CTRL_START;290 AT_WRITE_REG(hw, REG_MDIO_CTRL, val);291 udelay(30);292}293 294 295/*296 * atl1c_read_phy_core297 * core function to read register in PHY via MDIO control register.298 * ext: extension register (see IEEE 802.3)299 * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)300 * reg: reg to read301 */302int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,303 u16 reg, u16 *phy_data)304{305 u32 val;306 u16 clk_sel = MDIO_CTRL_CLK_25_4;307 308 atl1c_stop_phy_polling(hw);309 310 *phy_data = 0;311 312 /* only l2c_b2 & l1d_2 could use slow clock */313 if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) &&314 hw->hibernate)315 clk_sel = MDIO_CTRL_CLK_25_128;316 if (ext) {317 val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg);318 AT_WRITE_REG(hw, REG_MDIO_EXTN, val);319 val = MDIO_CTRL_SPRES_PRMBL |320 FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |321 MDIO_CTRL_START |322 MDIO_CTRL_MODE_EXT |323 MDIO_CTRL_OP_READ;324 } else {325 val = MDIO_CTRL_SPRES_PRMBL |326 FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |327 FIELDX(MDIO_CTRL_REG, reg) |328 MDIO_CTRL_START |329 MDIO_CTRL_OP_READ;330 }331 AT_WRITE_REG(hw, REG_MDIO_CTRL, val);332 333 if (!atl1c_wait_mdio_idle(hw))334 return -1;335 336 AT_READ_REG(hw, REG_MDIO_CTRL, &val);337 *phy_data = (u16)FIELD_GETX(val, MDIO_CTRL_DATA);338 339 atl1c_start_phy_polling(hw, clk_sel);340 341 return 0;342}343 344/*345 * atl1c_write_phy_core346 * core function to write to register in PHY via MDIO control register.347 * ext: extension register (see IEEE 802.3)348 * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)349 * reg: reg to write350 */351int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,352 u16 reg, u16 phy_data)353{354 u32 val;355 u16 clk_sel = MDIO_CTRL_CLK_25_4;356 357 atl1c_stop_phy_polling(hw);358 359 360 /* only l2c_b2 & l1d_2 could use slow clock */361 if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) &&362 hw->hibernate)363 clk_sel = MDIO_CTRL_CLK_25_128;364 365 if (ext) {366 val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg);367 AT_WRITE_REG(hw, REG_MDIO_EXTN, val);368 val = MDIO_CTRL_SPRES_PRMBL |369 FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |370 FIELDX(MDIO_CTRL_DATA, phy_data) |371 MDIO_CTRL_START |372 MDIO_CTRL_MODE_EXT;373 } else {374 val = MDIO_CTRL_SPRES_PRMBL |375 FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |376 FIELDX(MDIO_CTRL_DATA, phy_data) |377 FIELDX(MDIO_CTRL_REG, reg) |378 MDIO_CTRL_START;379 }380 AT_WRITE_REG(hw, REG_MDIO_CTRL, val);381 382 if (!atl1c_wait_mdio_idle(hw))383 return -1;384 385 atl1c_start_phy_polling(hw, clk_sel);386 387 return 0;388}389 390/*391 * Reads the value from a PHY register392 * hw - Struct containing variables accessed by shared code393 * reg_addr - address of the PHY register to read394 */395int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)396{397 return atl1c_read_phy_core(hw, false, 0, reg_addr, phy_data);398}399 400/*401 * Writes a value to a PHY register402 * hw - Struct containing variables accessed by shared code403 * reg_addr - address of the PHY register to write404 * data - data to write to the PHY405 */406int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)407{408 return atl1c_write_phy_core(hw, false, 0, reg_addr, phy_data);409}410 411/* read from PHY extension register */412int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr,413 u16 reg_addr, u16 *phy_data)414{415 return atl1c_read_phy_core(hw, true, dev_addr, reg_addr, phy_data);416}417 418/* write to PHY extension register */419int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,420 u16 reg_addr, u16 phy_data)421{422 return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data);423}424 425int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)426{427 int err;428 429 err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr);430 if (unlikely(err))431 return err;432 else433 err = atl1c_read_phy_reg(hw, MII_DBG_DATA, phy_data);434 435 return err;436}437 438int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data)439{440 int err;441 442 err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr);443 if (unlikely(err))444 return err;445 else446 err = atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);447 448 return err;449}450 451/*452 * Configures PHY autoneg and flow control advertisement settings453 *454 * hw - Struct containing variables accessed by shared code455 */456static int atl1c_phy_setup_adv(struct atl1c_hw *hw)457{458 u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_ALL;459 u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP &460 ~GIGA_CR_1000T_SPEED_MASK;461 462 if (hw->autoneg_advertised & ADVERTISED_10baseT_Half)463 mii_adv_data |= ADVERTISE_10HALF;464 if (hw->autoneg_advertised & ADVERTISED_10baseT_Full)465 mii_adv_data |= ADVERTISE_10FULL;466 if (hw->autoneg_advertised & ADVERTISED_100baseT_Half)467 mii_adv_data |= ADVERTISE_100HALF;468 if (hw->autoneg_advertised & ADVERTISED_100baseT_Full)469 mii_adv_data |= ADVERTISE_100FULL;470 471 if (hw->autoneg_advertised & ADVERTISED_Autoneg)472 mii_adv_data |= ADVERTISE_10HALF | ADVERTISE_10FULL |473 ADVERTISE_100HALF | ADVERTISE_100FULL;474 475 if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) {476 if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half)477 mii_giga_ctrl_data |= ADVERTISE_1000HALF;478 if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full)479 mii_giga_ctrl_data |= ADVERTISE_1000FULL;480 if (hw->autoneg_advertised & ADVERTISED_Autoneg)481 mii_giga_ctrl_data |= ADVERTISE_1000HALF |482 ADVERTISE_1000FULL;483 }484 485 if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 ||486 atl1c_write_phy_reg(hw, MII_CTRL1000, mii_giga_ctrl_data) != 0)487 return -1;488 return 0;489}490 491void atl1c_phy_disable(struct atl1c_hw *hw)492{493 atl1c_power_saving(hw, 0);494}495 496 497int atl1c_phy_reset(struct atl1c_hw *hw)498{499 struct atl1c_adapter *adapter = hw->adapter;500 struct pci_dev *pdev = adapter->pdev;501 u16 phy_data;502 u32 phy_ctrl_data, lpi_ctrl;503 int err;504 505 /* reset PHY core */506 AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data);507 phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_PHY_IDDQ |508 GPHY_CTRL_GATE_25M_EN | GPHY_CTRL_PWDOWN_HW | GPHY_CTRL_CLS);509 phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST;510 if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE))511 phy_ctrl_data |= (GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE);512 else513 phy_ctrl_data &= ~(GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE);514 AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);515 AT_WRITE_FLUSH(hw);516 udelay(10);517 AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data | GPHY_CTRL_EXT_RESET);518 AT_WRITE_FLUSH(hw);519 udelay(10 * GPHY_CTRL_EXT_RST_TO); /* delay 800us */520 521 /* switch clock */522 if (hw->nic_type == athr_l2c_b) {523 atl1c_read_phy_dbg(hw, MIIDBG_CFGLPSPD, &phy_data);524 atl1c_write_phy_dbg(hw, MIIDBG_CFGLPSPD,525 phy_data & ~CFGLPSPD_RSTCNT_CLK125SW);526 }527 528 /* tx-half amplitude issue fix */529 if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {530 atl1c_read_phy_dbg(hw, MIIDBG_CABLE1TH_DET, &phy_data);531 phy_data |= CABLE1TH_DET_EN;532 atl1c_write_phy_dbg(hw, MIIDBG_CABLE1TH_DET, phy_data);533 }534 535 /* clear bit3 of dbgport 3B to lower voltage */536 if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) {537 if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {538 atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);539 phy_data &= ~VOLT_CTRL_SWLOWEST;540 atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);541 }542 /* power saving config */543 phy_data =544 hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ?545 L1D_LEGCYPS_DEF : L1C_LEGCYPS_DEF;546 atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, phy_data);547 /* hib */548 atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL,549 SYSMODCTRL_IECHOADJ_DEF);550 } else {551 /* disable pws */552 atl1c_read_phy_dbg(hw, MIIDBG_LEGCYPS, &phy_data);553 atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS,554 phy_data & ~LEGCYPS_EN);555 /* disable hibernate */556 atl1c_read_phy_dbg(hw, MIIDBG_HIBNEG, &phy_data);557 atl1c_write_phy_dbg(hw, MIIDBG_HIBNEG,558 phy_data & HIBNEG_PSHIB_EN);559 }560 /* disable AZ(EEE) by default */561 if (hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ||562 hw->nic_type == athr_l2c_b2) {563 AT_READ_REG(hw, REG_LPI_CTRL, &lpi_ctrl);564 AT_WRITE_REG(hw, REG_LPI_CTRL, lpi_ctrl & ~LPI_CTRL_EN);565 atl1c_write_phy_ext(hw, MIIEXT_ANEG, MIIEXT_LOCAL_EEEADV, 0);566 atl1c_write_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL3,567 L2CB_CLDCTRL3);568 }569 570 /* other debug port to set */571 atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, ANACTRL_DEF);572 atl1c_write_phy_dbg(hw, MIIDBG_SRDSYSMOD, SRDSYSMOD_DEF);573 atl1c_write_phy_dbg(hw, MIIDBG_TST10BTCFG, TST10BTCFG_DEF);574 /* UNH-IOL test issue, set bit7 */575 atl1c_write_phy_dbg(hw, MIIDBG_TST100BTCFG,576 TST100BTCFG_DEF | TST100BTCFG_LITCH_EN);577 578 /* set phy interrupt mask */579 phy_data = IER_LINK_UP | IER_LINK_DOWN;580 err = atl1c_write_phy_reg(hw, MII_IER, phy_data);581 if (err) {582 if (netif_msg_hw(adapter))583 dev_err(&pdev->dev,584 "Error enable PHY linkChange Interrupt\n");585 return err;586 }587 return 0;588}589 590int atl1c_phy_init(struct atl1c_hw *hw)591{592 struct atl1c_adapter *adapter = hw->adapter;593 struct pci_dev *pdev = adapter->pdev;594 int ret_val;595 u16 mii_bmcr_data = BMCR_RESET;596 597 if (hw->nic_type == athr_mt) {598 hw->phy_configured = true;599 return 0;600 }601 602 if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &hw->phy_id1) != 0) ||603 (atl1c_read_phy_reg(hw, MII_PHYSID2, &hw->phy_id2) != 0)) {604 dev_err(&pdev->dev, "Error get phy ID\n");605 return -1;606 }607 switch (hw->media_type) {608 case MEDIA_TYPE_AUTO_SENSOR:609 ret_val = atl1c_phy_setup_adv(hw);610 if (ret_val) {611 if (netif_msg_link(adapter))612 dev_err(&pdev->dev,613 "Error Setting up Auto-Negotiation\n");614 return ret_val;615 }616 mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART;617 break;618 case MEDIA_TYPE_100M_FULL:619 mii_bmcr_data |= BMCR_SPEED100 | BMCR_FULLDPLX;620 break;621 case MEDIA_TYPE_100M_HALF:622 mii_bmcr_data |= BMCR_SPEED100;623 break;624 case MEDIA_TYPE_10M_FULL:625 mii_bmcr_data |= BMCR_FULLDPLX;626 break;627 case MEDIA_TYPE_10M_HALF:628 break;629 default:630 if (netif_msg_link(adapter))631 dev_err(&pdev->dev, "Wrong Media type %d\n",632 hw->media_type);633 return -1;634 }635 636 ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);637 if (ret_val)638 return ret_val;639 hw->phy_configured = true;640 641 return 0;642}643 644bool atl1c_get_link_status(struct atl1c_hw *hw)645{646 u16 phy_data;647 648 if (hw->nic_type == athr_mt) {649 u32 spd;650 651 AT_READ_REG(hw, REG_MT_SPEED, &spd);652 return !!spd;653 }654 655 /* MII_BMSR must be read twice */656 atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);657 atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);658 return !!(phy_data & BMSR_LSTATUS);659}660 661/*662 * Detects the current speed and duplex settings of the hardware.663 *664 * hw - Struct containing variables accessed by shared code665 * speed - Speed of the connection666 * duplex - Duplex setting of the connection667 */668int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)669{670 int err;671 u16 phy_data;672 673 if (hw->nic_type == athr_mt) {674 u32 spd;675 676 AT_READ_REG(hw, REG_MT_SPEED, &spd);677 *speed = spd;678 *duplex = FULL_DUPLEX;679 return 0;680 }681 682 /* Read PHY Specific Status Register (17) */683 err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data);684 if (err)685 return err;686 687 if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED))688 return -1;689 690 switch (phy_data & GIGA_PSSR_SPEED) {691 case GIGA_PSSR_1000MBS:692 *speed = SPEED_1000;693 break;694 case GIGA_PSSR_100MBS:695 *speed = SPEED_100;696 break;697 case GIGA_PSSR_10MBS:698 *speed = SPEED_10;699 break;700 default:701 return -1;702 }703 704 if (phy_data & GIGA_PSSR_DPLX)705 *duplex = FULL_DUPLEX;706 else707 *duplex = HALF_DUPLEX;708 709 return 0;710}711 712/* select one link mode to get lower power consumption */713int atl1c_phy_to_ps_link(struct atl1c_hw *hw)714{715 struct atl1c_adapter *adapter = hw->adapter;716 struct pci_dev *pdev = adapter->pdev;717 int ret = 0;718 u16 autoneg_advertised = ADVERTISED_10baseT_Half;719 u16 save_autoneg_advertised;720 u16 mii_lpa_data;721 u16 speed = SPEED_0;722 u16 duplex = FULL_DUPLEX;723 int i;724 725 if (atl1c_get_link_status(hw)) {726 atl1c_read_phy_reg(hw, MII_LPA, &mii_lpa_data);727 if (mii_lpa_data & LPA_10FULL)728 autoneg_advertised = ADVERTISED_10baseT_Full;729 else if (mii_lpa_data & LPA_10HALF)730 autoneg_advertised = ADVERTISED_10baseT_Half;731 else if (mii_lpa_data & LPA_100HALF)732 autoneg_advertised = ADVERTISED_100baseT_Half;733 else if (mii_lpa_data & LPA_100FULL)734 autoneg_advertised = ADVERTISED_100baseT_Full;735 736 save_autoneg_advertised = hw->autoneg_advertised;737 hw->phy_configured = false;738 hw->autoneg_advertised = autoneg_advertised;739 if (atl1c_restart_autoneg(hw) != 0) {740 dev_dbg(&pdev->dev, "phy autoneg failed\n");741 ret = -1;742 }743 hw->autoneg_advertised = save_autoneg_advertised;744 745 if (mii_lpa_data) {746 for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {747 mdelay(100);748 if (atl1c_get_link_status(hw)) {749 if (atl1c_get_speed_and_duplex(hw, &speed,750 &duplex) != 0)751 dev_dbg(&pdev->dev,752 "get speed and duplex failed\n");753 break;754 }755 }756 }757 } else {758 speed = SPEED_10;759 duplex = HALF_DUPLEX;760 }761 adapter->link_speed = speed;762 adapter->link_duplex = duplex;763 764 return ret;765}766 767int atl1c_restart_autoneg(struct atl1c_hw *hw)768{769 int err = 0;770 u16 mii_bmcr_data = BMCR_RESET;771 772 err = atl1c_phy_setup_adv(hw);773 if (err)774 return err;775 mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART;776 777 return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);778}779 780int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc)781{782 struct atl1c_adapter *adapter = hw->adapter;783 struct pci_dev *pdev = adapter->pdev;784 u32 master_ctrl, mac_ctrl, phy_ctrl;785 u32 wol_ctrl, speed;786 u16 phy_data;787 788 wol_ctrl = 0;789 speed = adapter->link_speed == SPEED_1000 ?790 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100;791 792 AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl);793 AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl);794 AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl);795 796 master_ctrl &= ~MASTER_CTRL_CLK_SEL_DIS;797 mac_ctrl = FIELD_SETX(mac_ctrl, MAC_CTRL_SPEED, speed);798 mac_ctrl &= ~(MAC_CTRL_DUPLX | MAC_CTRL_RX_EN | MAC_CTRL_TX_EN);799 if (adapter->link_duplex == FULL_DUPLEX)800 mac_ctrl |= MAC_CTRL_DUPLX;801 phy_ctrl &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS);802 phy_ctrl |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE |803 GPHY_CTRL_HIB_EN;804 if (!wufc) { /* without WoL */805 master_ctrl |= MASTER_CTRL_CLK_SEL_DIS;806 phy_ctrl |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW;807 AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl);808 AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl);809 AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl);810 AT_WRITE_REG(hw, REG_WOL_CTRL, 0);811 hw->phy_configured = false; /* re-init PHY when resume */812 return 0;813 }814 phy_ctrl |= GPHY_CTRL_EXT_RESET;815 if (wufc & AT_WUFC_MAG) {816 mac_ctrl |= MAC_CTRL_RX_EN | MAC_CTRL_BC_EN;817 wol_ctrl |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;818 if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V11)819 wol_ctrl |= WOL_PATTERN_EN | WOL_PATTERN_PME_EN;820 }821 if (wufc & AT_WUFC_LNKC) {822 wol_ctrl |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;823 if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {824 dev_dbg(&pdev->dev, "%s: write phy MII_IER failed.\n",825 atl1c_driver_name);826 }827 }828 /* clear PHY interrupt */829 atl1c_read_phy_reg(hw, MII_ISR, &phy_data);830 831 dev_dbg(&pdev->dev, "%s: suspend MAC=%x,MASTER=%x,PHY=0x%x,WOL=%x\n",832 atl1c_driver_name, mac_ctrl, master_ctrl, phy_ctrl, wol_ctrl);833 AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl);834 AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl);835 AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl);836 AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl);837 838 return 0;839}840 841 842/* configure phy after Link change Event */843void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed)844{845 u16 phy_val;846 bool adj_thresh = false;847 848 if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 ||849 hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2)850 adj_thresh = true;851 852 if (link_speed != SPEED_0) { /* link up */853 /* az with brcm, half-amp */854 if (hw->nic_type == athr_l1d_2) {855 atl1c_read_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL6,856 &phy_val);857 phy_val = FIELD_GETX(phy_val, CLDCTRL6_CAB_LEN);858 phy_val = phy_val > CLDCTRL6_CAB_LEN_SHORT ?859 AZ_ANADECT_LONG : AZ_ANADECT_DEF;860 atl1c_write_phy_dbg(hw, MIIDBG_AZ_ANADECT, phy_val);861 }862 /* threshold adjust */863 if (adj_thresh && link_speed == SPEED_100 && hw->msi_lnkpatch) {864 atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, L1D_MSE16DB_UP);865 atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL,866 L1D_SYSMODCTRL_IECHOADJ_DEF);867 }868 } else { /* link down */869 if (adj_thresh && hw->msi_lnkpatch) {870 atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL,871 SYSMODCTRL_IECHOADJ_DEF);872 atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB,873 L1D_MSE16DB_DOWN);874 }875 }876}877