brintos

brintos / linux-shallow public Read only

0
0
Text · 22.8 KiB · f19370c Raw
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 *) &eth_addr[2] = htonl(addr[0]);61	*(u16 *) &eth_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