xref: /freebsd/sys/dev/ixgbe/ixgbe_common.c (revision 9ca4041b6c93eb90d9f75322d5668f9bd186073b)
19ca4041bSJack F Vogel /******************************************************************************
213705f88SJack F Vogel 
39ca4041bSJack F Vogel   Copyright (c) 2001-2008, Intel Corporation
413705f88SJack F Vogel   All rights reserved.
513705f88SJack F Vogel 
613705f88SJack F Vogel   Redistribution and use in source and binary forms, with or without
713705f88SJack F Vogel   modification, are permitted provided that the following conditions are met:
813705f88SJack F Vogel 
913705f88SJack F Vogel    1. Redistributions of source code must retain the above copyright notice,
1013705f88SJack F Vogel       this list of conditions and the following disclaimer.
1113705f88SJack F Vogel 
1213705f88SJack F Vogel    2. Redistributions in binary form must reproduce the above copyright
1313705f88SJack F Vogel       notice, this list of conditions and the following disclaimer in the
1413705f88SJack F Vogel       documentation and/or other materials provided with the distribution.
1513705f88SJack F Vogel 
1613705f88SJack F Vogel    3. Neither the name of the Intel Corporation nor the names of its
1713705f88SJack F Vogel       contributors may be used to endorse or promote products derived from
1813705f88SJack F Vogel       this software without specific prior written permission.
1913705f88SJack F Vogel 
2013705f88SJack F Vogel   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2113705f88SJack F Vogel   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2213705f88SJack F Vogel   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2313705f88SJack F Vogel   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2413705f88SJack F Vogel   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2513705f88SJack F Vogel   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2613705f88SJack F Vogel   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2713705f88SJack F Vogel   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2813705f88SJack F Vogel   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2913705f88SJack F Vogel   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3013705f88SJack F Vogel   POSSIBILITY OF SUCH DAMAGE.
3113705f88SJack F Vogel 
329ca4041bSJack F Vogel ******************************************************************************/
3313705f88SJack F Vogel /*$FreeBSD$*/
3413705f88SJack F Vogel 
3513705f88SJack F Vogel #include "ixgbe_common.h"
3613705f88SJack F Vogel #include "ixgbe_api.h"
3713705f88SJack F Vogel 
3813705f88SJack F Vogel static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw);
3913705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw);
4013705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw);
4113705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw);
4213705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw);
4313705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw);
4413705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
4513705f88SJack F Vogel                                         u16 count);
4613705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count);
4713705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
4813705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
4913705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
5013705f88SJack F Vogel static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw);
5113705f88SJack F Vogel 
5213705f88SJack F Vogel static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index);
5313705f88SJack F Vogel static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index);
5413705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
5513705f88SJack F Vogel void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr);
569ca4041bSJack F Vogel void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
5713705f88SJack F Vogel 
5813705f88SJack F Vogel /**
599ca4041bSJack F Vogel  *  ixgbe_init_ops_generic - Inits function ptrs
609ca4041bSJack F Vogel  *  @hw: pointer to the hardware structure
6113705f88SJack F Vogel  *
629ca4041bSJack F Vogel  *  Initialize the function pointers.
6313705f88SJack F Vogel  **/
649ca4041bSJack F Vogel s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
6513705f88SJack F Vogel {
669ca4041bSJack F Vogel 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
679ca4041bSJack F Vogel 	struct ixgbe_mac_info *mac = &hw->mac;
689ca4041bSJack F Vogel 	u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC);
6913705f88SJack F Vogel 
7013705f88SJack F Vogel 	/* EEPROM */
719ca4041bSJack F Vogel 	eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic;
729ca4041bSJack F Vogel 	/* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */
739ca4041bSJack F Vogel 	if (eec & (1 << 8))
749ca4041bSJack F Vogel 		eeprom->ops.read = &ixgbe_read_eeprom_generic;
759ca4041bSJack F Vogel 	else
769ca4041bSJack F Vogel 		eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic;
779ca4041bSJack F Vogel 	eeprom->ops.write = &ixgbe_write_eeprom_generic;
789ca4041bSJack F Vogel 	eeprom->ops.validate_checksum =
7913705f88SJack F Vogel 	                              &ixgbe_validate_eeprom_checksum_generic;
809ca4041bSJack F Vogel 	eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic;
819ca4041bSJack F Vogel 
829ca4041bSJack F Vogel 	/* MAC */
839ca4041bSJack F Vogel 	mac->ops.init_hw = &ixgbe_init_hw_generic;
849ca4041bSJack F Vogel 	mac->ops.reset_hw = NULL;
859ca4041bSJack F Vogel 	mac->ops.start_hw = &ixgbe_start_hw_generic;
869ca4041bSJack F Vogel 	mac->ops.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic;
879ca4041bSJack F Vogel 	mac->ops.get_media_type = NULL;
889ca4041bSJack F Vogel 	mac->ops.get_mac_addr = &ixgbe_get_mac_addr_generic;
899ca4041bSJack F Vogel 	mac->ops.stop_adapter = &ixgbe_stop_adapter_generic;
909ca4041bSJack F Vogel 	mac->ops.get_bus_info = &ixgbe_get_bus_info_generic;
919ca4041bSJack F Vogel 	mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_generic;
929ca4041bSJack F Vogel 	mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_generic;
939ca4041bSJack F Vogel 
949ca4041bSJack F Vogel 	/* LEDs */
959ca4041bSJack F Vogel 	mac->ops.led_on = &ixgbe_led_on_generic;
969ca4041bSJack F Vogel 	mac->ops.led_off = &ixgbe_led_off_generic;
979ca4041bSJack F Vogel 	mac->ops.blink_led_start = NULL;
989ca4041bSJack F Vogel 	mac->ops.blink_led_stop = NULL;
999ca4041bSJack F Vogel 
10013705f88SJack F Vogel 	/* RAR, Multicast, VLAN */
1019ca4041bSJack F Vogel 	mac->ops.set_rar = &ixgbe_set_rar_generic;
1029ca4041bSJack F Vogel 	mac->ops.set_vmdq = NULL;
1039ca4041bSJack F Vogel 	mac->ops.init_rx_addrs = &ixgbe_init_rx_addrs_generic;
1049ca4041bSJack F Vogel 	mac->ops.update_uc_addr_list = &ixgbe_update_uc_addr_list_generic;
1059ca4041bSJack F Vogel 	mac->ops.update_mc_addr_list = &ixgbe_update_mc_addr_list_generic;
1069ca4041bSJack F Vogel 	mac->ops.enable_mc = &ixgbe_enable_mc_generic;
1079ca4041bSJack F Vogel 	mac->ops.disable_mc = &ixgbe_disable_mc_generic;
1089ca4041bSJack F Vogel 	mac->ops.clear_vfta = &ixgbe_clear_vfta_generic;
1099ca4041bSJack F Vogel 	mac->ops.set_vfta = &ixgbe_set_vfta_generic;
1109ca4041bSJack F Vogel 
1119ca4041bSJack F Vogel 	/* Flow Control */
1129ca4041bSJack F Vogel 	mac->ops.setup_fc = NULL;
1139ca4041bSJack F Vogel 
1149ca4041bSJack F Vogel 	/* Link */
1159ca4041bSJack F Vogel 	mac->ops.get_link_capabilities = NULL;
1169ca4041bSJack F Vogel 	mac->ops.setup_link = NULL;
1179ca4041bSJack F Vogel 	mac->ops.setup_link_speed = NULL;
1189ca4041bSJack F Vogel 	mac->ops.check_link = NULL;
11913705f88SJack F Vogel 
12013705f88SJack F Vogel 	return IXGBE_SUCCESS;
12113705f88SJack F Vogel }
12213705f88SJack F Vogel 
12313705f88SJack F Vogel /**
1249ca4041bSJack F Vogel  *  ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
12513705f88SJack F Vogel  *  @hw: pointer to hardware structure
12613705f88SJack F Vogel  *
12713705f88SJack F Vogel  *  Starts the hardware by filling the bus info structure and media type, clears
12813705f88SJack F Vogel  *  all on chip counters, initializes receive address registers, multicast
12913705f88SJack F Vogel  *  table, VLAN filter table, calls routine to set up link and flow control
13013705f88SJack F Vogel  *  settings, and leaves transmit and receive units disabled and uninitialized
13113705f88SJack F Vogel  **/
13213705f88SJack F Vogel s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
13313705f88SJack F Vogel {
13413705f88SJack F Vogel 	u32 ctrl_ext;
13513705f88SJack F Vogel 
13613705f88SJack F Vogel 	/* Set the media type */
1379ca4041bSJack F Vogel 	hw->phy.media_type = hw->mac.ops.get_media_type(hw);
13813705f88SJack F Vogel 
13913705f88SJack F Vogel 	/* Set bus info */
1409ca4041bSJack F Vogel 	hw->mac.ops.get_bus_info(hw);
14113705f88SJack F Vogel 
14213705f88SJack F Vogel 	/* Identify the PHY */
1439ca4041bSJack F Vogel 	hw->phy.ops.identify(hw);
14413705f88SJack F Vogel 
14513705f88SJack F Vogel 	/*
14613705f88SJack F Vogel 	 * Store MAC address from RAR0, clear receive address registers, and
14713705f88SJack F Vogel 	 * clear the multicast table
14813705f88SJack F Vogel 	 */
1499ca4041bSJack F Vogel 	hw->mac.ops.init_rx_addrs(hw);
15013705f88SJack F Vogel 
15113705f88SJack F Vogel 	/* Clear the VLAN filter table */
1529ca4041bSJack F Vogel 	hw->mac.ops.clear_vfta(hw);
15313705f88SJack F Vogel 
15413705f88SJack F Vogel 	/* Set up link */
1559ca4041bSJack F Vogel 	hw->mac.ops.setup_link(hw);
15613705f88SJack F Vogel 
15713705f88SJack F Vogel 	/* Clear statistics registers */
1589ca4041bSJack F Vogel 	hw->mac.ops.clear_hw_cntrs(hw);
15913705f88SJack F Vogel 
16013705f88SJack F Vogel 	/* Set No Snoop Disable */
16113705f88SJack F Vogel 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
16213705f88SJack F Vogel 	ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS;
16313705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
1649ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
16513705f88SJack F Vogel 
16613705f88SJack F Vogel 	/* Clear adapter stopped flag */
16713705f88SJack F Vogel 	hw->adapter_stopped = FALSE;
16813705f88SJack F Vogel 
16913705f88SJack F Vogel 	return IXGBE_SUCCESS;
17013705f88SJack F Vogel }
17113705f88SJack F Vogel 
17213705f88SJack F Vogel /**
17313705f88SJack F Vogel  *  ixgbe_init_hw_generic - Generic hardware initialization
17413705f88SJack F Vogel  *  @hw: pointer to hardware structure
17513705f88SJack F Vogel  *
1769ca4041bSJack F Vogel  *  Initialize the hardware by resetting the hardware, filling the bus info
17713705f88SJack F Vogel  *  structure and media type, clears all on chip counters, initializes receive
17813705f88SJack F Vogel  *  address registers, multicast table, VLAN filter table, calls routine to set
17913705f88SJack F Vogel  *  up link and flow control settings, and leaves transmit and receive units
18013705f88SJack F Vogel  *  disabled and uninitialized
18113705f88SJack F Vogel  **/
18213705f88SJack F Vogel s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
18313705f88SJack F Vogel {
18413705f88SJack F Vogel 	/* Reset the hardware */
1859ca4041bSJack F Vogel 	hw->mac.ops.reset_hw(hw);
18613705f88SJack F Vogel 
18713705f88SJack F Vogel 	/* Start the HW */
1889ca4041bSJack F Vogel 	hw->mac.ops.start_hw(hw);
18913705f88SJack F Vogel 
19013705f88SJack F Vogel 	return IXGBE_SUCCESS;
19113705f88SJack F Vogel }
19213705f88SJack F Vogel 
19313705f88SJack F Vogel /**
19413705f88SJack F Vogel  *  ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters
19513705f88SJack F Vogel  *  @hw: pointer to hardware structure
19613705f88SJack F Vogel  *
19713705f88SJack F Vogel  *  Clears all hardware statistics counters by reading them from the hardware
19813705f88SJack F Vogel  *  Statistics counters are clear on read.
19913705f88SJack F Vogel  **/
20013705f88SJack F Vogel s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
20113705f88SJack F Vogel {
20213705f88SJack F Vogel 	u16 i = 0;
20313705f88SJack F Vogel 
20413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_CRCERRS);
20513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_ILLERRC);
20613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_ERRBC);
20713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MSPDC);
20813705f88SJack F Vogel 	for (i = 0; i < 8; i++)
20913705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_MPC(i));
21013705f88SJack F Vogel 
21113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MLFC);
21213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MRFC);
21313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RLEC);
21413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_LXONTXC);
21513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_LXONRXC);
21613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
21713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
21813705f88SJack F Vogel 
21913705f88SJack F Vogel 	for (i = 0; i < 8; i++) {
22013705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
22113705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
22213705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
22313705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
22413705f88SJack F Vogel 	}
22513705f88SJack F Vogel 
22613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC64);
22713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC127);
22813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC255);
22913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC511);
23013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC1023);
23113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PRC1522);
23213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GPRC);
23313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_BPRC);
23413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MPRC);
23513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GPTC);
23613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GORCL);
23713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GORCH);
23813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GOTCL);
23913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_GOTCH);
24013705f88SJack F Vogel 	for (i = 0; i < 8; i++)
24113705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_RNBC(i));
24213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RUC);
24313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RFC);
24413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_ROC);
24513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_RJC);
24613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MNGPRC);
24713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MNGPDC);
24813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MNGPTC);
24913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TORL);
25013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TORH);
25113705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TPR);
25213705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_TPT);
25313705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC64);
25413705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC127);
25513705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC255);
25613705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC511);
25713705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC1023);
25813705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_PTC1522);
25913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_MPTC);
26013705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_BPTC);
26113705f88SJack F Vogel 	for (i = 0; i < 16; i++) {
26213705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QPRC(i));
26313705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QBRC(i));
26413705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QPTC(i));
26513705f88SJack F Vogel 		IXGBE_READ_REG(hw, IXGBE_QBTC(i));
26613705f88SJack F Vogel 	}
26713705f88SJack F Vogel 
26813705f88SJack F Vogel 	return IXGBE_SUCCESS;
26913705f88SJack F Vogel }
27013705f88SJack F Vogel 
27113705f88SJack F Vogel /**
2729ca4041bSJack F Vogel  *  ixgbe_read_pba_num - Reads part number from EEPROM
2739ca4041bSJack F Vogel  *  @hw: pointer to hardware structure
2749ca4041bSJack F Vogel  *  @pba_num: stores the part number from the EEPROM
2759ca4041bSJack F Vogel  *
2769ca4041bSJack F Vogel  *  Reads the part number from the EEPROM.
2779ca4041bSJack F Vogel  **/
2789ca4041bSJack F Vogel s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num)
2799ca4041bSJack F Vogel {
2809ca4041bSJack F Vogel 	s32 ret_val;
2819ca4041bSJack F Vogel 	u16 data;
2829ca4041bSJack F Vogel 
2839ca4041bSJack F Vogel 	DEBUGFUNC("ixgbe_read_pba_num_generic");
2849ca4041bSJack F Vogel 
2859ca4041bSJack F Vogel 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
2869ca4041bSJack F Vogel 	if (ret_val) {
2879ca4041bSJack F Vogel 		DEBUGOUT("NVM Read Error\n");
2889ca4041bSJack F Vogel 		return ret_val;
2899ca4041bSJack F Vogel 	}
2909ca4041bSJack F Vogel 	*pba_num = (u32)(data << 16);
2919ca4041bSJack F Vogel 
2929ca4041bSJack F Vogel 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data);
2939ca4041bSJack F Vogel 	if (ret_val) {
2949ca4041bSJack F Vogel 		DEBUGOUT("NVM Read Error\n");
2959ca4041bSJack F Vogel 		return ret_val;
2969ca4041bSJack F Vogel 	}
2979ca4041bSJack F Vogel 	*pba_num |= data;
2989ca4041bSJack F Vogel 
2999ca4041bSJack F Vogel 	return IXGBE_SUCCESS;
3009ca4041bSJack F Vogel }
3019ca4041bSJack F Vogel 
3029ca4041bSJack F Vogel /**
30313705f88SJack F Vogel  *  ixgbe_get_mac_addr_generic - Generic get MAC address
30413705f88SJack F Vogel  *  @hw: pointer to hardware structure
30513705f88SJack F Vogel  *  @mac_addr: Adapter MAC address
30613705f88SJack F Vogel  *
30713705f88SJack F Vogel  *  Reads the adapter's MAC address from first Receive Address Register (RAR0)
30813705f88SJack F Vogel  *  A reset of the adapter must be performed prior to calling this function
30913705f88SJack F Vogel  *  in order for the MAC address to have been loaded from the EEPROM into RAR0
31013705f88SJack F Vogel  **/
31113705f88SJack F Vogel s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr)
31213705f88SJack F Vogel {
31313705f88SJack F Vogel 	u32 rar_high;
31413705f88SJack F Vogel 	u32 rar_low;
31513705f88SJack F Vogel 	u16 i;
31613705f88SJack F Vogel 
31713705f88SJack F Vogel 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0));
31813705f88SJack F Vogel 	rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0));
31913705f88SJack F Vogel 
32013705f88SJack F Vogel 	for (i = 0; i < 4; i++)
32113705f88SJack F Vogel 		mac_addr[i] = (u8)(rar_low >> (i*8));
32213705f88SJack F Vogel 
32313705f88SJack F Vogel 	for (i = 0; i < 2; i++)
32413705f88SJack F Vogel 		mac_addr[i+4] = (u8)(rar_high >> (i*8));
32513705f88SJack F Vogel 
32613705f88SJack F Vogel 	return IXGBE_SUCCESS;
32713705f88SJack F Vogel }
32813705f88SJack F Vogel 
32913705f88SJack F Vogel /**
33013705f88SJack F Vogel  *  ixgbe_get_bus_info_generic - Generic set PCI bus info
33113705f88SJack F Vogel  *  @hw: pointer to hardware structure
33213705f88SJack F Vogel  *
33313705f88SJack F Vogel  *  Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure
33413705f88SJack F Vogel  **/
33513705f88SJack F Vogel s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
33613705f88SJack F Vogel {
33713705f88SJack F Vogel 	u16 link_status;
33813705f88SJack F Vogel 
33913705f88SJack F Vogel 	hw->bus.type = ixgbe_bus_type_pci_express;
34013705f88SJack F Vogel 
34113705f88SJack F Vogel 	/* Get the negotiated link width and speed from PCI config space */
34213705f88SJack F Vogel 	link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS);
34313705f88SJack F Vogel 
34413705f88SJack F Vogel 	switch (link_status & IXGBE_PCI_LINK_WIDTH) {
34513705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_1:
34613705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x1;
34713705f88SJack F Vogel 		break;
34813705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_2:
34913705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x2;
35013705f88SJack F Vogel 		break;
35113705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_4:
35213705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x4;
35313705f88SJack F Vogel 		break;
35413705f88SJack F Vogel 	case IXGBE_PCI_LINK_WIDTH_8:
35513705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_pcie_x8;
35613705f88SJack F Vogel 		break;
35713705f88SJack F Vogel 	default:
35813705f88SJack F Vogel 		hw->bus.width = ixgbe_bus_width_unknown;
35913705f88SJack F Vogel 		break;
36013705f88SJack F Vogel 	}
36113705f88SJack F Vogel 
36213705f88SJack F Vogel 	switch (link_status & IXGBE_PCI_LINK_SPEED) {
36313705f88SJack F Vogel 	case IXGBE_PCI_LINK_SPEED_2500:
36413705f88SJack F Vogel 		hw->bus.speed = ixgbe_bus_speed_2500;
36513705f88SJack F Vogel 		break;
36613705f88SJack F Vogel 	case IXGBE_PCI_LINK_SPEED_5000:
36713705f88SJack F Vogel 		hw->bus.speed = ixgbe_bus_speed_5000;
36813705f88SJack F Vogel 		break;
36913705f88SJack F Vogel 	default:
37013705f88SJack F Vogel 		hw->bus.speed = ixgbe_bus_speed_unknown;
37113705f88SJack F Vogel 		break;
37213705f88SJack F Vogel 	}
37313705f88SJack F Vogel 
37413705f88SJack F Vogel 	return IXGBE_SUCCESS;
37513705f88SJack F Vogel }
37613705f88SJack F Vogel 
37713705f88SJack F Vogel /**
3789ca4041bSJack F Vogel  *  ixgbe_stop_adapter_generic - Generic stop Tx/Rx units
37913705f88SJack F Vogel  *  @hw: pointer to hardware structure
38013705f88SJack F Vogel  *
38113705f88SJack F Vogel  *  Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts,
38213705f88SJack F Vogel  *  disables transmit and receive units. The adapter_stopped flag is used by
38313705f88SJack F Vogel  *  the shared code and drivers to determine if the adapter is in a stopped
38413705f88SJack F Vogel  *  state and should not touch the hardware.
38513705f88SJack F Vogel  **/
38613705f88SJack F Vogel s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
38713705f88SJack F Vogel {
38813705f88SJack F Vogel 	u32 number_of_queues;
38913705f88SJack F Vogel 	u32 reg_val;
39013705f88SJack F Vogel 	u16 i;
39113705f88SJack F Vogel 
39213705f88SJack F Vogel 	/*
39313705f88SJack F Vogel 	 * Set the adapter_stopped flag so other driver functions stop touching
39413705f88SJack F Vogel 	 * the hardware
39513705f88SJack F Vogel 	 */
39613705f88SJack F Vogel 	hw->adapter_stopped = TRUE;
39713705f88SJack F Vogel 
39813705f88SJack F Vogel 	/* Disable the receive unit */
39913705f88SJack F Vogel 	reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
40013705f88SJack F Vogel 	reg_val &= ~(IXGBE_RXCTRL_RXEN);
40113705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val);
4029ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
40313705f88SJack F Vogel 	msec_delay(2);
40413705f88SJack F Vogel 
40513705f88SJack F Vogel 	/* Clear interrupt mask to stop from interrupts being generated */
40613705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
40713705f88SJack F Vogel 
40813705f88SJack F Vogel 	/* Clear any pending interrupts */
40913705f88SJack F Vogel 	IXGBE_READ_REG(hw, IXGBE_EICR);
41013705f88SJack F Vogel 
41113705f88SJack F Vogel 	/* Disable the transmit unit.  Each queue must be disabled. */
4129ca4041bSJack F Vogel 	number_of_queues = hw->mac.max_tx_queues;
41313705f88SJack F Vogel 	for (i = 0; i < number_of_queues; i++) {
41413705f88SJack F Vogel 		reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
41513705f88SJack F Vogel 		if (reg_val & IXGBE_TXDCTL_ENABLE) {
41613705f88SJack F Vogel 			reg_val &= ~IXGBE_TXDCTL_ENABLE;
41713705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), reg_val);
41813705f88SJack F Vogel 		}
41913705f88SJack F Vogel 	}
42013705f88SJack F Vogel 
4219ca4041bSJack F Vogel 	/*
4229ca4041bSJack F Vogel 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
4239ca4041bSJack F Vogel 	 * access and verify no pending requests
4249ca4041bSJack F Vogel 	 */
4259ca4041bSJack F Vogel 	if (ixgbe_disable_pcie_master(hw) != IXGBE_SUCCESS) {
4269ca4041bSJack F Vogel 		DEBUGOUT("PCI-E Master disable polling has failed.\n");
4279ca4041bSJack F Vogel 	}
4289ca4041bSJack F Vogel 
42913705f88SJack F Vogel 	return IXGBE_SUCCESS;
43013705f88SJack F Vogel }
43113705f88SJack F Vogel 
43213705f88SJack F Vogel /**
43313705f88SJack F Vogel  *  ixgbe_led_on_generic - Turns on the software controllable LEDs.
43413705f88SJack F Vogel  *  @hw: pointer to hardware structure
43513705f88SJack F Vogel  *  @index: led number to turn on
43613705f88SJack F Vogel  **/
43713705f88SJack F Vogel s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index)
43813705f88SJack F Vogel {
43913705f88SJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
44013705f88SJack F Vogel 
44113705f88SJack F Vogel 	/* To turn on the LED, set mode to ON. */
44213705f88SJack F Vogel 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
44313705f88SJack F Vogel 	led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index);
44413705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
4459ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
44613705f88SJack F Vogel 
44713705f88SJack F Vogel 	return IXGBE_SUCCESS;
44813705f88SJack F Vogel }
44913705f88SJack F Vogel 
45013705f88SJack F Vogel /**
45113705f88SJack F Vogel  *  ixgbe_led_off_generic - Turns off the software controllable LEDs.
45213705f88SJack F Vogel  *  @hw: pointer to hardware structure
45313705f88SJack F Vogel  *  @index: led number to turn off
45413705f88SJack F Vogel  **/
45513705f88SJack F Vogel s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index)
45613705f88SJack F Vogel {
45713705f88SJack F Vogel 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
45813705f88SJack F Vogel 
45913705f88SJack F Vogel 	/* To turn off the LED, set mode to OFF. */
46013705f88SJack F Vogel 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
46113705f88SJack F Vogel 	led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index);
46213705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
4639ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
46413705f88SJack F Vogel 
46513705f88SJack F Vogel 	return IXGBE_SUCCESS;
46613705f88SJack F Vogel }
46713705f88SJack F Vogel 
46813705f88SJack F Vogel /**
46913705f88SJack F Vogel  *  ixgbe_init_eeprom_params_generic - Initialize EEPROM params
47013705f88SJack F Vogel  *  @hw: pointer to hardware structure
47113705f88SJack F Vogel  *
47213705f88SJack F Vogel  *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
47313705f88SJack F Vogel  *  ixgbe_hw struct in order to set up EEPROM access.
47413705f88SJack F Vogel  **/
47513705f88SJack F Vogel s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
47613705f88SJack F Vogel {
47713705f88SJack F Vogel 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
47813705f88SJack F Vogel 	u32 eec;
47913705f88SJack F Vogel 	u16 eeprom_size;
48013705f88SJack F Vogel 
48113705f88SJack F Vogel 	if (eeprom->type == ixgbe_eeprom_uninitialized) {
48213705f88SJack F Vogel 		eeprom->type = ixgbe_eeprom_none;
48313705f88SJack F Vogel 
48413705f88SJack F Vogel 		/*
48513705f88SJack F Vogel 		 * Check for EEPROM present first.
48613705f88SJack F Vogel 		 * If not present leave as none
48713705f88SJack F Vogel 		 */
48813705f88SJack F Vogel 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
48913705f88SJack F Vogel 		if (eec & IXGBE_EEC_PRES) {
49013705f88SJack F Vogel 			eeprom->type = ixgbe_eeprom_spi;
49113705f88SJack F Vogel 
49213705f88SJack F Vogel 			/*
49313705f88SJack F Vogel 			 * SPI EEPROM is assumed here.  This code would need to
49413705f88SJack F Vogel 			 * change if a future EEPROM is not SPI.
49513705f88SJack F Vogel 			 */
49613705f88SJack F Vogel 			eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
49713705f88SJack F Vogel 					    IXGBE_EEC_SIZE_SHIFT);
49813705f88SJack F Vogel 			eeprom->word_size = 1 << (eeprom_size +
49913705f88SJack F Vogel 						  IXGBE_EEPROM_WORD_SIZE_SHIFT);
50013705f88SJack F Vogel 		}
50113705f88SJack F Vogel 
50213705f88SJack F Vogel 		if (eec & IXGBE_EEC_ADDR_SIZE)
50313705f88SJack F Vogel 			eeprom->address_bits = 16;
50413705f88SJack F Vogel 		else
50513705f88SJack F Vogel 			eeprom->address_bits = 8;
50613705f88SJack F Vogel 		DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: "
50713705f88SJack F Vogel 			  "%d\n", eeprom->type, eeprom->word_size,
50813705f88SJack F Vogel 			  eeprom->address_bits);
50913705f88SJack F Vogel 	}
51013705f88SJack F Vogel 
51113705f88SJack F Vogel 	return IXGBE_SUCCESS;
51213705f88SJack F Vogel }
51313705f88SJack F Vogel 
51413705f88SJack F Vogel /**
51513705f88SJack F Vogel  *  ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
51613705f88SJack F Vogel  *  @hw: pointer to hardware structure
51713705f88SJack F Vogel  *  @offset: offset within the EEPROM to be written to
51813705f88SJack F Vogel  *  @data: 16 bit word to be written to the EEPROM
51913705f88SJack F Vogel  *
52013705f88SJack F Vogel  *  If ixgbe_eeprom_update_checksum is not called after this function, the
52113705f88SJack F Vogel  *  EEPROM will most likely contain an invalid checksum.
52213705f88SJack F Vogel  **/
52313705f88SJack F Vogel s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
52413705f88SJack F Vogel {
52513705f88SJack F Vogel 	s32 status;
52613705f88SJack F Vogel 	u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI;
52713705f88SJack F Vogel 
5289ca4041bSJack F Vogel 	hw->eeprom.ops.init_params(hw);
5299ca4041bSJack F Vogel 
5309ca4041bSJack F Vogel 	if (offset >= hw->eeprom.word_size) {
5319ca4041bSJack F Vogel 		status = IXGBE_ERR_EEPROM;
5329ca4041bSJack F Vogel 		goto out;
5339ca4041bSJack F Vogel 	}
5349ca4041bSJack F Vogel 
53513705f88SJack F Vogel 	/* Prepare the EEPROM for writing  */
53613705f88SJack F Vogel 	status = ixgbe_acquire_eeprom(hw);
53713705f88SJack F Vogel 
53813705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
53913705f88SJack F Vogel 		if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) {
54013705f88SJack F Vogel 			ixgbe_release_eeprom(hw);
54113705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
54213705f88SJack F Vogel 		}
54313705f88SJack F Vogel 	}
54413705f88SJack F Vogel 
54513705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
54613705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
54713705f88SJack F Vogel 
54813705f88SJack F Vogel 		/*  Send the WRITE ENABLE command (8 bit opcode )  */
54913705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI,
55013705f88SJack F Vogel 		                            IXGBE_EEPROM_OPCODE_BITS);
55113705f88SJack F Vogel 
55213705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
55313705f88SJack F Vogel 
55413705f88SJack F Vogel 		/*
55513705f88SJack F Vogel 		 * Some SPI eeproms use the 8th address bit embedded in the
55613705f88SJack F Vogel 		 * opcode
55713705f88SJack F Vogel 		 */
55813705f88SJack F Vogel 		if ((hw->eeprom.address_bits == 8) && (offset >= 128))
55913705f88SJack F Vogel 			write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
56013705f88SJack F Vogel 
56113705f88SJack F Vogel 		/* Send the Write command (8-bit opcode + addr) */
56213705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, write_opcode,
56313705f88SJack F Vogel 		                            IXGBE_EEPROM_OPCODE_BITS);
56413705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
56513705f88SJack F Vogel 		                            hw->eeprom.address_bits);
56613705f88SJack F Vogel 
56713705f88SJack F Vogel 		/* Send the data */
56813705f88SJack F Vogel 		data = (data >> 8) | (data << 8);
56913705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, data, 16);
57013705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
57113705f88SJack F Vogel 
57213705f88SJack F Vogel 		msec_delay(10);
57313705f88SJack F Vogel 
57413705f88SJack F Vogel 		/* Done with writing - release the EEPROM */
57513705f88SJack F Vogel 		ixgbe_release_eeprom(hw);
57613705f88SJack F Vogel 	}
57713705f88SJack F Vogel 
5789ca4041bSJack F Vogel out:
57913705f88SJack F Vogel 	return status;
58013705f88SJack F Vogel }
58113705f88SJack F Vogel 
58213705f88SJack F Vogel /**
58313705f88SJack F Vogel  *  ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
58413705f88SJack F Vogel  *  @hw: pointer to hardware structure
58513705f88SJack F Vogel  *  @offset: offset within the EEPROM to be read
58613705f88SJack F Vogel  *  @data: read 16 bit value from EEPROM
58713705f88SJack F Vogel  *
58813705f88SJack F Vogel  *  Reads 16 bit value from EEPROM through bit-bang method
58913705f88SJack F Vogel  **/
59013705f88SJack F Vogel s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
59113705f88SJack F Vogel                                        u16 *data)
59213705f88SJack F Vogel {
59313705f88SJack F Vogel 	s32 status;
59413705f88SJack F Vogel 	u16 word_in;
59513705f88SJack F Vogel 	u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI;
59613705f88SJack F Vogel 
5979ca4041bSJack F Vogel 	hw->eeprom.ops.init_params(hw);
5989ca4041bSJack F Vogel 
5999ca4041bSJack F Vogel 	if (offset >= hw->eeprom.word_size) {
6009ca4041bSJack F Vogel 		status = IXGBE_ERR_EEPROM;
6019ca4041bSJack F Vogel 		goto out;
6029ca4041bSJack F Vogel 	}
6039ca4041bSJack F Vogel 
60413705f88SJack F Vogel 	/* Prepare the EEPROM for reading  */
60513705f88SJack F Vogel 	status = ixgbe_acquire_eeprom(hw);
60613705f88SJack F Vogel 
60713705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
60813705f88SJack F Vogel 		if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) {
60913705f88SJack F Vogel 			ixgbe_release_eeprom(hw);
61013705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
61113705f88SJack F Vogel 		}
61213705f88SJack F Vogel 	}
61313705f88SJack F Vogel 
61413705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
61513705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
61613705f88SJack F Vogel 
61713705f88SJack F Vogel 		/*
61813705f88SJack F Vogel 		 * Some SPI eeproms use the 8th address bit embedded in the
61913705f88SJack F Vogel 		 * opcode
62013705f88SJack F Vogel 		 */
62113705f88SJack F Vogel 		if ((hw->eeprom.address_bits == 8) && (offset >= 128))
62213705f88SJack F Vogel 			read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
62313705f88SJack F Vogel 
62413705f88SJack F Vogel 		/* Send the READ command (opcode + addr) */
62513705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, read_opcode,
62613705f88SJack F Vogel 		                            IXGBE_EEPROM_OPCODE_BITS);
62713705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
62813705f88SJack F Vogel 		                            hw->eeprom.address_bits);
62913705f88SJack F Vogel 
63013705f88SJack F Vogel 		/* Read the data. */
63113705f88SJack F Vogel 		word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
63213705f88SJack F Vogel 		*data = (word_in >> 8) | (word_in << 8);
63313705f88SJack F Vogel 
63413705f88SJack F Vogel 		/* End this read operation */
63513705f88SJack F Vogel 		ixgbe_release_eeprom(hw);
63613705f88SJack F Vogel 	}
63713705f88SJack F Vogel 
6389ca4041bSJack F Vogel out:
63913705f88SJack F Vogel 	return status;
64013705f88SJack F Vogel }
64113705f88SJack F Vogel 
64213705f88SJack F Vogel /**
64313705f88SJack F Vogel  *  ixgbe_read_eeprom_generic - Read EEPROM word using EERD
64413705f88SJack F Vogel  *  @hw: pointer to hardware structure
64513705f88SJack F Vogel  *  @offset: offset of  word in the EEPROM to read
64613705f88SJack F Vogel  *  @data: word read from the EEPROM
64713705f88SJack F Vogel  *
64813705f88SJack F Vogel  *  Reads a 16 bit word from the EEPROM using the EERD register.
64913705f88SJack F Vogel  **/
65013705f88SJack F Vogel s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
65113705f88SJack F Vogel {
65213705f88SJack F Vogel 	u32 eerd;
65313705f88SJack F Vogel 	s32 status;
65413705f88SJack F Vogel 
6559ca4041bSJack F Vogel 	hw->eeprom.ops.init_params(hw);
6569ca4041bSJack F Vogel 
6579ca4041bSJack F Vogel 	if (offset >= hw->eeprom.word_size) {
6589ca4041bSJack F Vogel 		status = IXGBE_ERR_EEPROM;
6599ca4041bSJack F Vogel 		goto out;
6609ca4041bSJack F Vogel 	}
6619ca4041bSJack F Vogel 
66213705f88SJack F Vogel 	eerd = (offset << IXGBE_EEPROM_READ_ADDR_SHIFT) +
66313705f88SJack F Vogel 	       IXGBE_EEPROM_READ_REG_START;
66413705f88SJack F Vogel 
66513705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd);
66613705f88SJack F Vogel 	status = ixgbe_poll_eeprom_eerd_done(hw);
66713705f88SJack F Vogel 
66813705f88SJack F Vogel 	if (status == IXGBE_SUCCESS)
66913705f88SJack F Vogel 		*data = (IXGBE_READ_REG(hw, IXGBE_EERD) >>
67013705f88SJack F Vogel 		         IXGBE_EEPROM_READ_REG_DATA);
67113705f88SJack F Vogel 	else
67213705f88SJack F Vogel 		DEBUGOUT("Eeprom read timed out\n");
67313705f88SJack F Vogel 
6749ca4041bSJack F Vogel out:
67513705f88SJack F Vogel 	return status;
67613705f88SJack F Vogel }
67713705f88SJack F Vogel 
67813705f88SJack F Vogel /**
67913705f88SJack F Vogel  *  ixgbe_poll_eeprom_eerd_done - Poll EERD status
68013705f88SJack F Vogel  *  @hw: pointer to hardware structure
68113705f88SJack F Vogel  *
68213705f88SJack F Vogel  *  Polls the status bit (bit 1) of the EERD to determine when the read is done.
68313705f88SJack F Vogel  **/
68413705f88SJack F Vogel static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw)
68513705f88SJack F Vogel {
68613705f88SJack F Vogel 	u32 i;
68713705f88SJack F Vogel 	u32 reg;
68813705f88SJack F Vogel 	s32 status = IXGBE_ERR_EEPROM;
68913705f88SJack F Vogel 
69013705f88SJack F Vogel 	for (i = 0; i < IXGBE_EERD_ATTEMPTS; i++) {
69113705f88SJack F Vogel 		reg = IXGBE_READ_REG(hw, IXGBE_EERD);
69213705f88SJack F Vogel 		if (reg & IXGBE_EEPROM_READ_REG_DONE) {
69313705f88SJack F Vogel 			status = IXGBE_SUCCESS;
69413705f88SJack F Vogel 			break;
69513705f88SJack F Vogel 		}
69613705f88SJack F Vogel 		usec_delay(5);
69713705f88SJack F Vogel 	}
69813705f88SJack F Vogel 	return status;
69913705f88SJack F Vogel }
70013705f88SJack F Vogel 
70113705f88SJack F Vogel /**
70213705f88SJack F Vogel  *  ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang
70313705f88SJack F Vogel  *  @hw: pointer to hardware structure
70413705f88SJack F Vogel  *
70513705f88SJack F Vogel  *  Prepares EEPROM for access using bit-bang method. This function should
70613705f88SJack F Vogel  *  be called before issuing a command to the EEPROM.
70713705f88SJack F Vogel  **/
70813705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
70913705f88SJack F Vogel {
71013705f88SJack F Vogel 	s32 status = IXGBE_SUCCESS;
71113705f88SJack F Vogel 	u32 eec;
71213705f88SJack F Vogel 	u32 i;
71313705f88SJack F Vogel 
71413705f88SJack F Vogel 	if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS)
71513705f88SJack F Vogel 		status = IXGBE_ERR_SWFW_SYNC;
71613705f88SJack F Vogel 
71713705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
71813705f88SJack F Vogel 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
71913705f88SJack F Vogel 
72013705f88SJack F Vogel 		/* Request EEPROM Access */
72113705f88SJack F Vogel 		eec |= IXGBE_EEC_REQ;
72213705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
72313705f88SJack F Vogel 
72413705f88SJack F Vogel 		for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
72513705f88SJack F Vogel 			eec = IXGBE_READ_REG(hw, IXGBE_EEC);
72613705f88SJack F Vogel 			if (eec & IXGBE_EEC_GNT)
72713705f88SJack F Vogel 				break;
72813705f88SJack F Vogel 			usec_delay(5);
72913705f88SJack F Vogel 		}
73013705f88SJack F Vogel 
7319ca4041bSJack F Vogel 		/* Release if grant not acquired */
73213705f88SJack F Vogel 		if (!(eec & IXGBE_EEC_GNT)) {
73313705f88SJack F Vogel 			eec &= ~IXGBE_EEC_REQ;
73413705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
73513705f88SJack F Vogel 			DEBUGOUT("Could not acquire EEPROM grant\n");
73613705f88SJack F Vogel 
73713705f88SJack F Vogel 			ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
73813705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
73913705f88SJack F Vogel 		}
74013705f88SJack F Vogel 	}
74113705f88SJack F Vogel 
74213705f88SJack F Vogel 	/* Setup EEPROM for Read/Write */
74313705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
74413705f88SJack F Vogel 		/* Clear CS and SK */
74513705f88SJack F Vogel 		eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
74613705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
74713705f88SJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
74813705f88SJack F Vogel 		usec_delay(1);
74913705f88SJack F Vogel 	}
75013705f88SJack F Vogel 	return status;
75113705f88SJack F Vogel }
75213705f88SJack F Vogel 
75313705f88SJack F Vogel /**
75413705f88SJack F Vogel  *  ixgbe_get_eeprom_semaphore - Get hardware semaphore
75513705f88SJack F Vogel  *  @hw: pointer to hardware structure
75613705f88SJack F Vogel  *
75713705f88SJack F Vogel  *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method
75813705f88SJack F Vogel  **/
75913705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
76013705f88SJack F Vogel {
76113705f88SJack F Vogel 	s32 status = IXGBE_ERR_EEPROM;
76213705f88SJack F Vogel 	u32 timeout;
76313705f88SJack F Vogel 	u32 i;
76413705f88SJack F Vogel 	u32 swsm;
76513705f88SJack F Vogel 
76613705f88SJack F Vogel 	/* Set timeout value based on size of EEPROM */
76713705f88SJack F Vogel 	timeout = hw->eeprom.word_size + 1;
76813705f88SJack F Vogel 
76913705f88SJack F Vogel 	/* Get SMBI software semaphore between device drivers first */
77013705f88SJack F Vogel 	for (i = 0; i < timeout; i++) {
77113705f88SJack F Vogel 		/*
77213705f88SJack F Vogel 		 * If the SMBI bit is 0 when we read it, then the bit will be
77313705f88SJack F Vogel 		 * set and we have the semaphore
77413705f88SJack F Vogel 		 */
77513705f88SJack F Vogel 		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
77613705f88SJack F Vogel 		if (!(swsm & IXGBE_SWSM_SMBI)) {
77713705f88SJack F Vogel 			status = IXGBE_SUCCESS;
77813705f88SJack F Vogel 			break;
77913705f88SJack F Vogel 		}
78013705f88SJack F Vogel 		msec_delay(1);
78113705f88SJack F Vogel 	}
78213705f88SJack F Vogel 
78313705f88SJack F Vogel 	/* Now get the semaphore between SW/FW through the SWESMBI bit */
78413705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
78513705f88SJack F Vogel 		for (i = 0; i < timeout; i++) {
78613705f88SJack F Vogel 			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
78713705f88SJack F Vogel 
78813705f88SJack F Vogel 			/* Set the SW EEPROM semaphore bit to request access */
78913705f88SJack F Vogel 			swsm |= IXGBE_SWSM_SWESMBI;
79013705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
79113705f88SJack F Vogel 
79213705f88SJack F Vogel 			/*
79313705f88SJack F Vogel 			 * If we set the bit successfully then we got the
79413705f88SJack F Vogel 			 * semaphore.
79513705f88SJack F Vogel 			 */
79613705f88SJack F Vogel 			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
79713705f88SJack F Vogel 			if (swsm & IXGBE_SWSM_SWESMBI)
79813705f88SJack F Vogel 				break;
79913705f88SJack F Vogel 
80013705f88SJack F Vogel 			usec_delay(50);
80113705f88SJack F Vogel 		}
80213705f88SJack F Vogel 
80313705f88SJack F Vogel 		/*
80413705f88SJack F Vogel 		 * Release semaphores and return error if SW EEPROM semaphore
80513705f88SJack F Vogel 		 * was not granted because we don't have access to the EEPROM
80613705f88SJack F Vogel 		 */
80713705f88SJack F Vogel 		if (i >= timeout) {
80813705f88SJack F Vogel 			DEBUGOUT("Driver can't access the Eeprom - Semaphore "
80913705f88SJack F Vogel 			         "not granted.\n");
81013705f88SJack F Vogel 			ixgbe_release_eeprom_semaphore(hw);
81113705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM;
81213705f88SJack F Vogel 		}
81313705f88SJack F Vogel 	}
81413705f88SJack F Vogel 
81513705f88SJack F Vogel 	return status;
81613705f88SJack F Vogel }
81713705f88SJack F Vogel 
81813705f88SJack F Vogel /**
81913705f88SJack F Vogel  *  ixgbe_release_eeprom_semaphore - Release hardware semaphore
82013705f88SJack F Vogel  *  @hw: pointer to hardware structure
82113705f88SJack F Vogel  *
82213705f88SJack F Vogel  *  This function clears hardware semaphore bits.
82313705f88SJack F Vogel  **/
82413705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw)
82513705f88SJack F Vogel {
82613705f88SJack F Vogel 	u32 swsm;
82713705f88SJack F Vogel 
82813705f88SJack F Vogel 	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
82913705f88SJack F Vogel 
83013705f88SJack F Vogel 	/* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */
83113705f88SJack F Vogel 	swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI);
83213705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
8339ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
83413705f88SJack F Vogel }
83513705f88SJack F Vogel 
83613705f88SJack F Vogel /**
83713705f88SJack F Vogel  *  ixgbe_ready_eeprom - Polls for EEPROM ready
83813705f88SJack F Vogel  *  @hw: pointer to hardware structure
83913705f88SJack F Vogel  **/
84013705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
84113705f88SJack F Vogel {
84213705f88SJack F Vogel 	s32 status = IXGBE_SUCCESS;
84313705f88SJack F Vogel 	u16 i;
84413705f88SJack F Vogel 	u8 spi_stat_reg;
84513705f88SJack F Vogel 
84613705f88SJack F Vogel 	/*
84713705f88SJack F Vogel 	 * Read "Status Register" repeatedly until the LSB is cleared.  The
84813705f88SJack F Vogel 	 * EEPROM will signal that the command has been completed by clearing
84913705f88SJack F Vogel 	 * bit 0 of the internal status register.  If it's not cleared within
85013705f88SJack F Vogel 	 * 5 milliseconds, then error out.
85113705f88SJack F Vogel 	 */
85213705f88SJack F Vogel 	for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) {
85313705f88SJack F Vogel 		ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI,
85413705f88SJack F Vogel 		                            IXGBE_EEPROM_OPCODE_BITS);
85513705f88SJack F Vogel 		spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8);
85613705f88SJack F Vogel 		if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI))
85713705f88SJack F Vogel 			break;
85813705f88SJack F Vogel 
85913705f88SJack F Vogel 		usec_delay(5);
86013705f88SJack F Vogel 		ixgbe_standby_eeprom(hw);
86113705f88SJack F Vogel 	};
86213705f88SJack F Vogel 
86313705f88SJack F Vogel 	/*
86413705f88SJack F Vogel 	 * On some parts, SPI write time could vary from 0-20mSec on 3.3V
86513705f88SJack F Vogel 	 * devices (and only 0-5mSec on 5V devices)
86613705f88SJack F Vogel 	 */
86713705f88SJack F Vogel 	if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) {
86813705f88SJack F Vogel 		DEBUGOUT("SPI EEPROM Status error\n");
86913705f88SJack F Vogel 		status = IXGBE_ERR_EEPROM;
87013705f88SJack F Vogel 	}
87113705f88SJack F Vogel 
87213705f88SJack F Vogel 	return status;
87313705f88SJack F Vogel }
87413705f88SJack F Vogel 
87513705f88SJack F Vogel /**
87613705f88SJack F Vogel  *  ixgbe_standby_eeprom - Returns EEPROM to a "standby" state
87713705f88SJack F Vogel  *  @hw: pointer to hardware structure
87813705f88SJack F Vogel  **/
87913705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw)
88013705f88SJack F Vogel {
88113705f88SJack F Vogel 	u32 eec;
88213705f88SJack F Vogel 
88313705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
88413705f88SJack F Vogel 
88513705f88SJack F Vogel 	/* Toggle CS to flush commands */
88613705f88SJack F Vogel 	eec |= IXGBE_EEC_CS;
88713705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
88813705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
88913705f88SJack F Vogel 	usec_delay(1);
89013705f88SJack F Vogel 	eec &= ~IXGBE_EEC_CS;
89113705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
89213705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
89313705f88SJack F Vogel 	usec_delay(1);
89413705f88SJack F Vogel }
89513705f88SJack F Vogel 
89613705f88SJack F Vogel /**
89713705f88SJack F Vogel  *  ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM.
89813705f88SJack F Vogel  *  @hw: pointer to hardware structure
89913705f88SJack F Vogel  *  @data: data to send to the EEPROM
90013705f88SJack F Vogel  *  @count: number of bits to shift out
90113705f88SJack F Vogel  **/
90213705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
90313705f88SJack F Vogel                                         u16 count)
90413705f88SJack F Vogel {
90513705f88SJack F Vogel 	u32 eec;
90613705f88SJack F Vogel 	u32 mask;
90713705f88SJack F Vogel 	u32 i;
90813705f88SJack F Vogel 
90913705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
91013705f88SJack F Vogel 
91113705f88SJack F Vogel 	/*
91213705f88SJack F Vogel 	 * Mask is used to shift "count" bits of "data" out to the EEPROM
91313705f88SJack F Vogel 	 * one bit at a time.  Determine the starting bit based on count
91413705f88SJack F Vogel 	 */
91513705f88SJack F Vogel 	mask = 0x01 << (count - 1);
91613705f88SJack F Vogel 
91713705f88SJack F Vogel 	for (i = 0; i < count; i++) {
91813705f88SJack F Vogel 		/*
91913705f88SJack F Vogel 		 * A "1" is shifted out to the EEPROM by setting bit "DI" to a
92013705f88SJack F Vogel 		 * "1", and then raising and then lowering the clock (the SK
92113705f88SJack F Vogel 		 * bit controls the clock input to the EEPROM).  A "0" is
92213705f88SJack F Vogel 		 * shifted out to the EEPROM by setting "DI" to "0" and then
92313705f88SJack F Vogel 		 * raising and then lowering the clock.
92413705f88SJack F Vogel 		 */
92513705f88SJack F Vogel 		if (data & mask)
92613705f88SJack F Vogel 			eec |= IXGBE_EEC_DI;
92713705f88SJack F Vogel 		else
92813705f88SJack F Vogel 			eec &= ~IXGBE_EEC_DI;
92913705f88SJack F Vogel 
93013705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
93113705f88SJack F Vogel 		IXGBE_WRITE_FLUSH(hw);
93213705f88SJack F Vogel 
93313705f88SJack F Vogel 		usec_delay(1);
93413705f88SJack F Vogel 
93513705f88SJack F Vogel 		ixgbe_raise_eeprom_clk(hw, &eec);
93613705f88SJack F Vogel 		ixgbe_lower_eeprom_clk(hw, &eec);
93713705f88SJack F Vogel 
93813705f88SJack F Vogel 		/*
93913705f88SJack F Vogel 		 * Shift mask to signify next bit of data to shift in to the
94013705f88SJack F Vogel 		 * EEPROM
94113705f88SJack F Vogel 		 */
94213705f88SJack F Vogel 		mask = mask >> 1;
94313705f88SJack F Vogel 	};
94413705f88SJack F Vogel 
94513705f88SJack F Vogel 	/* We leave the "DI" bit set to "0" when we leave this routine. */
94613705f88SJack F Vogel 	eec &= ~IXGBE_EEC_DI;
94713705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
94813705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
94913705f88SJack F Vogel }
95013705f88SJack F Vogel 
95113705f88SJack F Vogel /**
95213705f88SJack F Vogel  *  ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM
95313705f88SJack F Vogel  *  @hw: pointer to hardware structure
95413705f88SJack F Vogel  **/
95513705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
95613705f88SJack F Vogel {
95713705f88SJack F Vogel 	u32 eec;
95813705f88SJack F Vogel 	u32 i;
95913705f88SJack F Vogel 	u16 data = 0;
96013705f88SJack F Vogel 
96113705f88SJack F Vogel 	/*
96213705f88SJack F Vogel 	 * In order to read a register from the EEPROM, we need to shift
96313705f88SJack F Vogel 	 * 'count' bits in from the EEPROM. Bits are "shifted in" by raising
96413705f88SJack F Vogel 	 * the clock input to the EEPROM (setting the SK bit), and then reading
96513705f88SJack F Vogel 	 * the value of the "DO" bit.  During this "shifting in" process the
96613705f88SJack F Vogel 	 * "DI" bit should always be clear.
96713705f88SJack F Vogel 	 */
96813705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
96913705f88SJack F Vogel 
97013705f88SJack F Vogel 	eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI);
97113705f88SJack F Vogel 
97213705f88SJack F Vogel 	for (i = 0; i < count; i++) {
97313705f88SJack F Vogel 		data = data << 1;
97413705f88SJack F Vogel 		ixgbe_raise_eeprom_clk(hw, &eec);
97513705f88SJack F Vogel 
97613705f88SJack F Vogel 		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
97713705f88SJack F Vogel 
97813705f88SJack F Vogel 		eec &= ~(IXGBE_EEC_DI);
97913705f88SJack F Vogel 		if (eec & IXGBE_EEC_DO)
98013705f88SJack F Vogel 			data |= 1;
98113705f88SJack F Vogel 
98213705f88SJack F Vogel 		ixgbe_lower_eeprom_clk(hw, &eec);
98313705f88SJack F Vogel 	}
98413705f88SJack F Vogel 
98513705f88SJack F Vogel 	return data;
98613705f88SJack F Vogel }
98713705f88SJack F Vogel 
98813705f88SJack F Vogel /**
98913705f88SJack F Vogel  *  ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input.
99013705f88SJack F Vogel  *  @hw: pointer to hardware structure
99113705f88SJack F Vogel  *  @eec: EEC register's current value
99213705f88SJack F Vogel  **/
99313705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
99413705f88SJack F Vogel {
99513705f88SJack F Vogel 	/*
99613705f88SJack F Vogel 	 * Raise the clock input to the EEPROM
99713705f88SJack F Vogel 	 * (setting the SK bit), then delay
99813705f88SJack F Vogel 	 */
99913705f88SJack F Vogel 	*eec = *eec | IXGBE_EEC_SK;
100013705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
100113705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
100213705f88SJack F Vogel 	usec_delay(1);
100313705f88SJack F Vogel }
100413705f88SJack F Vogel 
100513705f88SJack F Vogel /**
100613705f88SJack F Vogel  *  ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input.
100713705f88SJack F Vogel  *  @hw: pointer to hardware structure
100813705f88SJack F Vogel  *  @eecd: EECD's current value
100913705f88SJack F Vogel  **/
101013705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
101113705f88SJack F Vogel {
101213705f88SJack F Vogel 	/*
101313705f88SJack F Vogel 	 * Lower the clock input to the EEPROM (clearing the SK bit), then
101413705f88SJack F Vogel 	 * delay
101513705f88SJack F Vogel 	 */
101613705f88SJack F Vogel 	*eec = *eec & ~IXGBE_EEC_SK;
101713705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
101813705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
101913705f88SJack F Vogel 	usec_delay(1);
102013705f88SJack F Vogel }
102113705f88SJack F Vogel 
102213705f88SJack F Vogel /**
102313705f88SJack F Vogel  *  ixgbe_release_eeprom - Release EEPROM, release semaphores
102413705f88SJack F Vogel  *  @hw: pointer to hardware structure
102513705f88SJack F Vogel  **/
102613705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
102713705f88SJack F Vogel {
102813705f88SJack F Vogel 	u32 eec;
102913705f88SJack F Vogel 
103013705f88SJack F Vogel 	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
103113705f88SJack F Vogel 
103213705f88SJack F Vogel 	eec |= IXGBE_EEC_CS;  /* Pull CS high */
103313705f88SJack F Vogel 	eec &= ~IXGBE_EEC_SK; /* Lower SCK */
103413705f88SJack F Vogel 
103513705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
103613705f88SJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
103713705f88SJack F Vogel 
103813705f88SJack F Vogel 	usec_delay(1);
103913705f88SJack F Vogel 
104013705f88SJack F Vogel 	/* Stop requesting EEPROM access */
104113705f88SJack F Vogel 	eec &= ~IXGBE_EEC_REQ;
104213705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
104313705f88SJack F Vogel 
104413705f88SJack F Vogel 	ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
104513705f88SJack F Vogel }
104613705f88SJack F Vogel 
104713705f88SJack F Vogel /**
104813705f88SJack F Vogel  *  ixgbe_calc_eeprom_checksum - Calculates and returns the checksum
104913705f88SJack F Vogel  *  @hw: pointer to hardware structure
105013705f88SJack F Vogel  **/
105113705f88SJack F Vogel static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw)
105213705f88SJack F Vogel {
105313705f88SJack F Vogel 	u16 i;
105413705f88SJack F Vogel 	u16 j;
105513705f88SJack F Vogel 	u16 checksum = 0;
105613705f88SJack F Vogel 	u16 length = 0;
105713705f88SJack F Vogel 	u16 pointer = 0;
105813705f88SJack F Vogel 	u16 word = 0;
105913705f88SJack F Vogel 
106013705f88SJack F Vogel 	/* Include 0x0-0x3F in the checksum */
106113705f88SJack F Vogel 	for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
10629ca4041bSJack F Vogel 		if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) {
106313705f88SJack F Vogel 			DEBUGOUT("EEPROM read failed\n");
106413705f88SJack F Vogel 			break;
106513705f88SJack F Vogel 		}
106613705f88SJack F Vogel 		checksum += word;
106713705f88SJack F Vogel 	}
106813705f88SJack F Vogel 
106913705f88SJack F Vogel 	/* Include all data from pointers except for the fw pointer */
107013705f88SJack F Vogel 	for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
10719ca4041bSJack F Vogel 		hw->eeprom.ops.read(hw, i, &pointer);
107213705f88SJack F Vogel 
107313705f88SJack F Vogel 		/* Make sure the pointer seems valid */
107413705f88SJack F Vogel 		if (pointer != 0xFFFF && pointer != 0) {
10759ca4041bSJack F Vogel 			hw->eeprom.ops.read(hw, pointer, &length);
107613705f88SJack F Vogel 
107713705f88SJack F Vogel 			if (length != 0xFFFF && length != 0) {
107813705f88SJack F Vogel 				for (j = pointer+1; j <= pointer+length; j++) {
10799ca4041bSJack F Vogel 					hw->eeprom.ops.read(hw, j, &word);
108013705f88SJack F Vogel 					checksum += word;
108113705f88SJack F Vogel 				}
108213705f88SJack F Vogel 			}
108313705f88SJack F Vogel 		}
108413705f88SJack F Vogel 	}
108513705f88SJack F Vogel 
108613705f88SJack F Vogel 	checksum = (u16)IXGBE_EEPROM_SUM - checksum;
108713705f88SJack F Vogel 
108813705f88SJack F Vogel 	return checksum;
108913705f88SJack F Vogel }
109013705f88SJack F Vogel 
109113705f88SJack F Vogel /**
109213705f88SJack F Vogel  *  ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum
109313705f88SJack F Vogel  *  @hw: pointer to hardware structure
109413705f88SJack F Vogel  *  @checksum_val: calculated checksum
109513705f88SJack F Vogel  *
109613705f88SJack F Vogel  *  Performs checksum calculation and validates the EEPROM checksum.  If the
109713705f88SJack F Vogel  *  caller does not need checksum_val, the value can be NULL.
109813705f88SJack F Vogel  **/
109913705f88SJack F Vogel s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
110013705f88SJack F Vogel                                            u16 *checksum_val)
110113705f88SJack F Vogel {
110213705f88SJack F Vogel 	s32 status;
110313705f88SJack F Vogel 	u16 checksum;
110413705f88SJack F Vogel 	u16 read_checksum = 0;
110513705f88SJack F Vogel 
110613705f88SJack F Vogel 	/*
110713705f88SJack F Vogel 	 * Read the first word from the EEPROM. If this times out or fails, do
110813705f88SJack F Vogel 	 * not continue or we could be in for a very long wait while every
110913705f88SJack F Vogel 	 * EEPROM read fails
111013705f88SJack F Vogel 	 */
11119ca4041bSJack F Vogel 	status = hw->eeprom.ops.read(hw, 0, &checksum);
111213705f88SJack F Vogel 
111313705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
111413705f88SJack F Vogel 		checksum = ixgbe_calc_eeprom_checksum(hw);
111513705f88SJack F Vogel 
11169ca4041bSJack F Vogel 		hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
111713705f88SJack F Vogel 
111813705f88SJack F Vogel 		/*
111913705f88SJack F Vogel 		 * Verify read checksum from EEPROM is the same as
112013705f88SJack F Vogel 		 * calculated checksum
112113705f88SJack F Vogel 		 */
11229ca4041bSJack F Vogel 		if (read_checksum != checksum)
112313705f88SJack F Vogel 			status = IXGBE_ERR_EEPROM_CHECKSUM;
112413705f88SJack F Vogel 
112513705f88SJack F Vogel 		/* If the user cares, return the calculated checksum */
11269ca4041bSJack F Vogel 		if (checksum_val)
112713705f88SJack F Vogel 			*checksum_val = checksum;
112813705f88SJack F Vogel 	} else {
112913705f88SJack F Vogel 		DEBUGOUT("EEPROM read failed\n");
113013705f88SJack F Vogel 	}
113113705f88SJack F Vogel 
113213705f88SJack F Vogel 	return status;
113313705f88SJack F Vogel }
113413705f88SJack F Vogel 
113513705f88SJack F Vogel /**
11369ca4041bSJack F Vogel  *  ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum
113713705f88SJack F Vogel  *  @hw: pointer to hardware structure
113813705f88SJack F Vogel  **/
113913705f88SJack F Vogel s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
114013705f88SJack F Vogel {
114113705f88SJack F Vogel 	s32 status;
114213705f88SJack F Vogel 	u16 checksum;
114313705f88SJack F Vogel 
114413705f88SJack F Vogel 	/*
114513705f88SJack F Vogel 	 * Read the first word from the EEPROM. If this times out or fails, do
114613705f88SJack F Vogel 	 * not continue or we could be in for a very long wait while every
114713705f88SJack F Vogel 	 * EEPROM read fails
114813705f88SJack F Vogel 	 */
11499ca4041bSJack F Vogel 	status = hw->eeprom.ops.read(hw, 0, &checksum);
115013705f88SJack F Vogel 
115113705f88SJack F Vogel 	if (status == IXGBE_SUCCESS) {
115213705f88SJack F Vogel 		checksum = ixgbe_calc_eeprom_checksum(hw);
11539ca4041bSJack F Vogel 		status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM,
115413705f88SJack F Vogel 		                            checksum);
115513705f88SJack F Vogel 	} else {
115613705f88SJack F Vogel 		DEBUGOUT("EEPROM read failed\n");
115713705f88SJack F Vogel 	}
115813705f88SJack F Vogel 
115913705f88SJack F Vogel 	return status;
116013705f88SJack F Vogel }
116113705f88SJack F Vogel 
116213705f88SJack F Vogel /**
116313705f88SJack F Vogel  *  ixgbe_validate_mac_addr - Validate MAC address
116413705f88SJack F Vogel  *  @mac_addr: pointer to MAC address.
116513705f88SJack F Vogel  *
116613705f88SJack F Vogel  *  Tests a MAC address to ensure it is a valid Individual Address
116713705f88SJack F Vogel  **/
116813705f88SJack F Vogel s32 ixgbe_validate_mac_addr(u8 *mac_addr)
116913705f88SJack F Vogel {
117013705f88SJack F Vogel 	s32 status = IXGBE_SUCCESS;
117113705f88SJack F Vogel 
117213705f88SJack F Vogel 	/* Make sure it is not a multicast address */
117313705f88SJack F Vogel 	if (IXGBE_IS_MULTICAST(mac_addr)) {
117413705f88SJack F Vogel 		DEBUGOUT("MAC address is multicast\n");
117513705f88SJack F Vogel 		status = IXGBE_ERR_INVALID_MAC_ADDR;
117613705f88SJack F Vogel 	/* Not a broadcast address */
117713705f88SJack F Vogel 	} else if (IXGBE_IS_BROADCAST(mac_addr)) {
117813705f88SJack F Vogel 		DEBUGOUT("MAC address is broadcast\n");
117913705f88SJack F Vogel 		status = IXGBE_ERR_INVALID_MAC_ADDR;
118013705f88SJack F Vogel 	/* Reject the zero address */
118113705f88SJack F Vogel 	} else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 &&
118213705f88SJack F Vogel 	           mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) {
118313705f88SJack F Vogel 		DEBUGOUT("MAC address is all zeros\n");
118413705f88SJack F Vogel 		status = IXGBE_ERR_INVALID_MAC_ADDR;
118513705f88SJack F Vogel 	}
118613705f88SJack F Vogel 	return status;
118713705f88SJack F Vogel }
118813705f88SJack F Vogel 
118913705f88SJack F Vogel /**
11909ca4041bSJack F Vogel  *  ixgbe_set_rar_generic - Set Rx address register
119113705f88SJack F Vogel  *  @hw: pointer to hardware structure
119213705f88SJack F Vogel  *  @index: Receive address register to write
11939ca4041bSJack F Vogel  *  @addr: Address to put into receive address register
11949ca4041bSJack F Vogel  *  @vmdq: VMDq "set" or "pool" index
119513705f88SJack F Vogel  *  @enable_addr: set flag that address is active
119613705f88SJack F Vogel  *
119713705f88SJack F Vogel  *  Puts an ethernet address into a receive address register.
119813705f88SJack F Vogel  **/
11999ca4041bSJack F Vogel s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
120013705f88SJack F Vogel                           u32 enable_addr)
120113705f88SJack F Vogel {
120213705f88SJack F Vogel 	u32 rar_low, rar_high;
12039ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
120413705f88SJack F Vogel 
12059ca4041bSJack F Vogel 	/* setup VMDq pool selection before this RAR gets enabled */
12069ca4041bSJack F Vogel 	hw->mac.ops.set_vmdq(hw, index, vmdq);
12079ca4041bSJack F Vogel 
12089ca4041bSJack F Vogel 	/* Make sure we are using a valid rar index range */
12099ca4041bSJack F Vogel 	if (index < rar_entries) {
121013705f88SJack F Vogel 		/*
12119ca4041bSJack F Vogel 		 * HW expects these in little endian so we reverse the byte
12129ca4041bSJack F Vogel 		 * order from network order (big endian) to little endian
121313705f88SJack F Vogel 		 */
121413705f88SJack F Vogel 		rar_low = ((u32)addr[0] |
121513705f88SJack F Vogel 		           ((u32)addr[1] << 8) |
121613705f88SJack F Vogel 		           ((u32)addr[2] << 16) |
121713705f88SJack F Vogel 		           ((u32)addr[3] << 24));
12189ca4041bSJack F Vogel 		/*
12199ca4041bSJack F Vogel 		 * Some parts put the VMDq setting in the extra RAH bits,
12209ca4041bSJack F Vogel 		 * so save everything except the lower 16 bits that hold part
12219ca4041bSJack F Vogel 		 * of the address and the address valid bit.
12229ca4041bSJack F Vogel 		 */
12239ca4041bSJack F Vogel 		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
12249ca4041bSJack F Vogel 		rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
12259ca4041bSJack F Vogel 		rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8));
122613705f88SJack F Vogel 
122713705f88SJack F Vogel 		if (enable_addr != 0)
122813705f88SJack F Vogel 			rar_high |= IXGBE_RAH_AV;
122913705f88SJack F Vogel 
123013705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
123113705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
12329ca4041bSJack F Vogel 	} else {
12339ca4041bSJack F Vogel 		DEBUGOUT("Current RAR index is out of range.");
12349ca4041bSJack F Vogel 	}
123513705f88SJack F Vogel 
123613705f88SJack F Vogel 	return IXGBE_SUCCESS;
123713705f88SJack F Vogel }
123813705f88SJack F Vogel 
123913705f88SJack F Vogel /**
12409ca4041bSJack F Vogel  *  ixgbe_enable_rar - Enable Rx address register
124113705f88SJack F Vogel  *  @hw: pointer to hardware structure
124213705f88SJack F Vogel  *  @index: index into the RAR table
124313705f88SJack F Vogel  *
124413705f88SJack F Vogel  *  Enables the select receive address register.
124513705f88SJack F Vogel  **/
124613705f88SJack F Vogel static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index)
124713705f88SJack F Vogel {
124813705f88SJack F Vogel 	u32 rar_high;
124913705f88SJack F Vogel 
125013705f88SJack F Vogel 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
125113705f88SJack F Vogel 	rar_high |= IXGBE_RAH_AV;
125213705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
125313705f88SJack F Vogel }
125413705f88SJack F Vogel 
125513705f88SJack F Vogel /**
12569ca4041bSJack F Vogel  *  ixgbe_disable_rar - Disable Rx address register
125713705f88SJack F Vogel  *  @hw: pointer to hardware structure
125813705f88SJack F Vogel  *  @index: index into the RAR table
125913705f88SJack F Vogel  *
126013705f88SJack F Vogel  *  Disables the select receive address register.
126113705f88SJack F Vogel  **/
126213705f88SJack F Vogel static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index)
126313705f88SJack F Vogel {
126413705f88SJack F Vogel 	u32 rar_high;
126513705f88SJack F Vogel 
126613705f88SJack F Vogel 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
126713705f88SJack F Vogel 	rar_high &= (~IXGBE_RAH_AV);
126813705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
126913705f88SJack F Vogel }
127013705f88SJack F Vogel 
127113705f88SJack F Vogel /**
127213705f88SJack F Vogel  *  ixgbe_init_rx_addrs_generic - Initializes receive address filters.
127313705f88SJack F Vogel  *  @hw: pointer to hardware structure
127413705f88SJack F Vogel  *
127513705f88SJack F Vogel  *  Places the MAC address in receive address register 0 and clears the rest
12769ca4041bSJack F Vogel  *  of the receive address registers. Clears the multicast table. Assumes
127713705f88SJack F Vogel  *  the receiver is in reset when the routine is called.
127813705f88SJack F Vogel  **/
127913705f88SJack F Vogel s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
128013705f88SJack F Vogel {
128113705f88SJack F Vogel 	u32 i;
12829ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
128313705f88SJack F Vogel 
128413705f88SJack F Vogel 	/*
128513705f88SJack F Vogel 	 * If the current mac address is valid, assume it is a software override
128613705f88SJack F Vogel 	 * to the permanent address.
128713705f88SJack F Vogel 	 * Otherwise, use the permanent address from the eeprom.
128813705f88SJack F Vogel 	 */
128913705f88SJack F Vogel 	if (ixgbe_validate_mac_addr(hw->mac.addr) ==
129013705f88SJack F Vogel 	    IXGBE_ERR_INVALID_MAC_ADDR) {
129113705f88SJack F Vogel 		/* Get the MAC address from the RAR0 for later reference */
12929ca4041bSJack F Vogel 		hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
129313705f88SJack F Vogel 
129413705f88SJack F Vogel 		DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ",
129513705f88SJack F Vogel 		          hw->mac.addr[0], hw->mac.addr[1],
129613705f88SJack F Vogel 		          hw->mac.addr[2]);
129713705f88SJack F Vogel 		DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3],
129813705f88SJack F Vogel 		          hw->mac.addr[4], hw->mac.addr[5]);
129913705f88SJack F Vogel 	} else {
130013705f88SJack F Vogel 		/* Setup the receive address. */
130113705f88SJack F Vogel 		DEBUGOUT("Overriding MAC Address in RAR[0]\n");
130213705f88SJack F Vogel 		DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ",
130313705f88SJack F Vogel 		          hw->mac.addr[0], hw->mac.addr[1],
130413705f88SJack F Vogel 		          hw->mac.addr[2]);
130513705f88SJack F Vogel 		DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3],
130613705f88SJack F Vogel 		          hw->mac.addr[4], hw->mac.addr[5]);
130713705f88SJack F Vogel 
13089ca4041bSJack F Vogel 		hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
130913705f88SJack F Vogel 	}
13109ca4041bSJack F Vogel 	hw->addr_ctrl.overflow_promisc = 0;
131113705f88SJack F Vogel 
131213705f88SJack F Vogel 	hw->addr_ctrl.rar_used_count = 1;
131313705f88SJack F Vogel 
131413705f88SJack F Vogel 	/* Zero out the other receive addresses. */
13159ca4041bSJack F Vogel 	DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1);
131613705f88SJack F Vogel 	for (i = 1; i < rar_entries; i++) {
131713705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
131813705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
131913705f88SJack F Vogel 	}
132013705f88SJack F Vogel 
132113705f88SJack F Vogel 	/* Clear the MTA */
132213705f88SJack F Vogel 	hw->addr_ctrl.mc_addr_in_rar_count = 0;
132313705f88SJack F Vogel 	hw->addr_ctrl.mta_in_use = 0;
132413705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
132513705f88SJack F Vogel 
132613705f88SJack F Vogel 	DEBUGOUT(" Clearing MTA\n");
13279ca4041bSJack F Vogel 	for (i = 0; i < hw->mac.mcft_size; i++)
132813705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
132913705f88SJack F Vogel 
133013705f88SJack F Vogel 	return IXGBE_SUCCESS;
133113705f88SJack F Vogel }
133213705f88SJack F Vogel 
133313705f88SJack F Vogel /**
13349ca4041bSJack F Vogel  *  ixgbe_add_uc_addr - Adds a secondary unicast address.
13359ca4041bSJack F Vogel  *  @hw: pointer to hardware structure
13369ca4041bSJack F Vogel  *  @addr: new address
13379ca4041bSJack F Vogel  *
13389ca4041bSJack F Vogel  *  Adds it to unused receive address register or goes into promiscuous mode.
13399ca4041bSJack F Vogel  **/
13409ca4041bSJack F Vogel void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
13419ca4041bSJack F Vogel {
13429ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
13439ca4041bSJack F Vogel 	u32 rar;
13449ca4041bSJack F Vogel 
13459ca4041bSJack F Vogel 	DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n",
13469ca4041bSJack F Vogel 	          addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
13479ca4041bSJack F Vogel 
13489ca4041bSJack F Vogel 	/*
13499ca4041bSJack F Vogel 	 * Place this address in the RAR if there is room,
13509ca4041bSJack F Vogel 	 * else put the controller into promiscuous mode
13519ca4041bSJack F Vogel 	 */
13529ca4041bSJack F Vogel 	if (hw->addr_ctrl.rar_used_count < rar_entries) {
13539ca4041bSJack F Vogel 		rar = hw->addr_ctrl.rar_used_count -
13549ca4041bSJack F Vogel 		      hw->addr_ctrl.mc_addr_in_rar_count;
13559ca4041bSJack F Vogel 		hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
13569ca4041bSJack F Vogel 		DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar);
13579ca4041bSJack F Vogel 		hw->addr_ctrl.rar_used_count++;
13589ca4041bSJack F Vogel 	} else {
13599ca4041bSJack F Vogel 		hw->addr_ctrl.overflow_promisc++;
13609ca4041bSJack F Vogel 	}
13619ca4041bSJack F Vogel 
13629ca4041bSJack F Vogel 	DEBUGOUT("ixgbe_add_uc_addr Complete\n");
13639ca4041bSJack F Vogel }
13649ca4041bSJack F Vogel 
13659ca4041bSJack F Vogel /**
13669ca4041bSJack F Vogel  *  ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses
13679ca4041bSJack F Vogel  *  @hw: pointer to hardware structure
13689ca4041bSJack F Vogel  *  @addr_list: the list of new addresses
13699ca4041bSJack F Vogel  *  @addr_count: number of addresses
13709ca4041bSJack F Vogel  *  @next: iterator function to walk the address list
13719ca4041bSJack F Vogel  *
13729ca4041bSJack F Vogel  *  The given list replaces any existing list.  Clears the secondary addrs from
13739ca4041bSJack F Vogel  *  receive address registers.  Uses unused receive address registers for the
13749ca4041bSJack F Vogel  *  first secondary addresses, and falls back to promiscuous mode as needed.
13759ca4041bSJack F Vogel  *
13769ca4041bSJack F Vogel  *  Drivers using secondary unicast addresses must set user_set_promisc when
13779ca4041bSJack F Vogel  *  manually putting the device into promiscuous mode.
13789ca4041bSJack F Vogel  **/
13799ca4041bSJack F Vogel s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
13809ca4041bSJack F Vogel                                       u32 addr_count, ixgbe_mc_addr_itr next)
13819ca4041bSJack F Vogel {
13829ca4041bSJack F Vogel 	u8 *addr;
13839ca4041bSJack F Vogel 	u32 i;
13849ca4041bSJack F Vogel 	u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc;
13859ca4041bSJack F Vogel 	u32 uc_addr_in_use;
13869ca4041bSJack F Vogel 	u32 fctrl;
13879ca4041bSJack F Vogel 	u32 vmdq;
13889ca4041bSJack F Vogel 
13899ca4041bSJack F Vogel 	/*
13909ca4041bSJack F Vogel 	 * Clear accounting of old secondary address list,
13919ca4041bSJack F Vogel 	 * don't count RAR[0]
13929ca4041bSJack F Vogel 	 */
13939ca4041bSJack F Vogel 	uc_addr_in_use = hw->addr_ctrl.rar_used_count -
13949ca4041bSJack F Vogel 	                 hw->addr_ctrl.mc_addr_in_rar_count - 1;
13959ca4041bSJack F Vogel 	hw->addr_ctrl.rar_used_count -= uc_addr_in_use;
13969ca4041bSJack F Vogel 	hw->addr_ctrl.overflow_promisc = 0;
13979ca4041bSJack F Vogel 
13989ca4041bSJack F Vogel 	/* Zero out the other receive addresses */
13999ca4041bSJack F Vogel 	DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use);
14009ca4041bSJack F Vogel 	for (i = 1; i <= uc_addr_in_use; i++) {
14019ca4041bSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
14029ca4041bSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
14039ca4041bSJack F Vogel 	}
14049ca4041bSJack F Vogel 
14059ca4041bSJack F Vogel 	/* Add the new addresses */
14069ca4041bSJack F Vogel 	for (i = 0; i < addr_count; i++) {
14079ca4041bSJack F Vogel 		DEBUGOUT(" Adding the secondary addresses:\n");
14089ca4041bSJack F Vogel 		addr = next(hw, &addr_list, &vmdq);
14099ca4041bSJack F Vogel 		ixgbe_add_uc_addr(hw, addr, vmdq);
14109ca4041bSJack F Vogel 	}
14119ca4041bSJack F Vogel 
14129ca4041bSJack F Vogel 	if (hw->addr_ctrl.overflow_promisc) {
14139ca4041bSJack F Vogel 		/* enable promisc if not already in overflow or set by user */
14149ca4041bSJack F Vogel 		if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) {
14159ca4041bSJack F Vogel 			DEBUGOUT( " Entering address overflow promisc mode\n");
14169ca4041bSJack F Vogel 			fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
14179ca4041bSJack F Vogel 			fctrl |= IXGBE_FCTRL_UPE;
14189ca4041bSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
14199ca4041bSJack F Vogel 		}
14209ca4041bSJack F Vogel 	} else {
14219ca4041bSJack F Vogel 		/* only disable if set by overflow, not by user */
14229ca4041bSJack F Vogel 		if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) {
14239ca4041bSJack F Vogel 			DEBUGOUT(" Leaving address overflow promisc mode\n");
14249ca4041bSJack F Vogel 			fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
14259ca4041bSJack F Vogel 			fctrl &= ~IXGBE_FCTRL_UPE;
14269ca4041bSJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
14279ca4041bSJack F Vogel 		}
14289ca4041bSJack F Vogel 	}
14299ca4041bSJack F Vogel 
14309ca4041bSJack F Vogel 	DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n");
14319ca4041bSJack F Vogel 	return IXGBE_SUCCESS;
14329ca4041bSJack F Vogel }
14339ca4041bSJack F Vogel 
14349ca4041bSJack F Vogel /**
143513705f88SJack F Vogel  *  ixgbe_mta_vector - Determines bit-vector in multicast table to set
143613705f88SJack F Vogel  *  @hw: pointer to hardware structure
143713705f88SJack F Vogel  *  @mc_addr: the multicast address
143813705f88SJack F Vogel  *
143913705f88SJack F Vogel  *  Extracts the 12 bits, from a multicast address, to determine which
144013705f88SJack F Vogel  *  bit-vector to set in the multicast table. The hardware uses 12 bits, from
144113705f88SJack F Vogel  *  incoming rx multicast addresses, to determine the bit-vector to check in
144213705f88SJack F Vogel  *  the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set
14439ca4041bSJack F Vogel  *  by the MO field of the MCSTCTRL. The MO field is set during initialization
144413705f88SJack F Vogel  *  to mc_filter_type.
144513705f88SJack F Vogel  **/
144613705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr)
144713705f88SJack F Vogel {
144813705f88SJack F Vogel 	u32 vector = 0;
144913705f88SJack F Vogel 
145013705f88SJack F Vogel 	switch (hw->mac.mc_filter_type) {
145113705f88SJack F Vogel 	case 0:   /* use bits [47:36] of the address */
145213705f88SJack F Vogel 		vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
145313705f88SJack F Vogel 		break;
145413705f88SJack F Vogel 	case 1:   /* use bits [46:35] of the address */
145513705f88SJack F Vogel 		vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
145613705f88SJack F Vogel 		break;
145713705f88SJack F Vogel 	case 2:   /* use bits [45:34] of the address */
145813705f88SJack F Vogel 		vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
145913705f88SJack F Vogel 		break;
146013705f88SJack F Vogel 	case 3:   /* use bits [43:32] of the address */
146113705f88SJack F Vogel 		vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
146213705f88SJack F Vogel 		break;
146313705f88SJack F Vogel 	default:  /* Invalid mc_filter_type */
146413705f88SJack F Vogel 		DEBUGOUT("MC filter type param set incorrectly\n");
146513705f88SJack F Vogel 		ASSERT(0);
146613705f88SJack F Vogel 		break;
146713705f88SJack F Vogel 	}
146813705f88SJack F Vogel 
146913705f88SJack F Vogel 	/* vector can only be 12-bits or boundary will be exceeded */
147013705f88SJack F Vogel 	vector &= 0xFFF;
147113705f88SJack F Vogel 	return vector;
147213705f88SJack F Vogel }
147313705f88SJack F Vogel 
147413705f88SJack F Vogel /**
147513705f88SJack F Vogel  *  ixgbe_set_mta - Set bit-vector in multicast table
147613705f88SJack F Vogel  *  @hw: pointer to hardware structure
147713705f88SJack F Vogel  *  @hash_value: Multicast address hash value
147813705f88SJack F Vogel  *
147913705f88SJack F Vogel  *  Sets the bit-vector in the multicast table.
148013705f88SJack F Vogel  **/
148113705f88SJack F Vogel void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr)
148213705f88SJack F Vogel {
148313705f88SJack F Vogel 	u32 vector;
148413705f88SJack F Vogel 	u32 vector_bit;
148513705f88SJack F Vogel 	u32 vector_reg;
148613705f88SJack F Vogel 	u32 mta_reg;
148713705f88SJack F Vogel 
148813705f88SJack F Vogel 	hw->addr_ctrl.mta_in_use++;
148913705f88SJack F Vogel 
149013705f88SJack F Vogel 	vector = ixgbe_mta_vector(hw, mc_addr);
149113705f88SJack F Vogel 	DEBUGOUT1(" bit-vector = 0x%03X\n", vector);
149213705f88SJack F Vogel 
149313705f88SJack F Vogel 	/*
149413705f88SJack F Vogel 	 * The MTA is a register array of 128 32-bit registers. It is treated
149513705f88SJack F Vogel 	 * like an array of 4096 bits.  We want to set bit
149613705f88SJack F Vogel 	 * BitArray[vector_value]. So we figure out what register the bit is
149713705f88SJack F Vogel 	 * in, read it, OR in the new bit, then write back the new value.  The
149813705f88SJack F Vogel 	 * register is determined by the upper 7 bits of the vector value and
149913705f88SJack F Vogel 	 * the bit within that register are determined by the lower 5 bits of
150013705f88SJack F Vogel 	 * the value.
150113705f88SJack F Vogel 	 */
150213705f88SJack F Vogel 	vector_reg = (vector >> 5) & 0x7F;
150313705f88SJack F Vogel 	vector_bit = vector & 0x1F;
150413705f88SJack F Vogel 	mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg));
150513705f88SJack F Vogel 	mta_reg |= (1 << vector_bit);
150613705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg);
150713705f88SJack F Vogel }
150813705f88SJack F Vogel 
150913705f88SJack F Vogel /**
151013705f88SJack F Vogel  *  ixgbe_add_mc_addr - Adds a multicast address.
151113705f88SJack F Vogel  *  @hw: pointer to hardware structure
151213705f88SJack F Vogel  *  @mc_addr: new multicast address
151313705f88SJack F Vogel  *
151413705f88SJack F Vogel  *  Adds it to unused receive address register or to the multicast table.
151513705f88SJack F Vogel  **/
151613705f88SJack F Vogel void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr)
151713705f88SJack F Vogel {
15189ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
15199ca4041bSJack F Vogel 	u32 rar;
152013705f88SJack F Vogel 
152113705f88SJack F Vogel 	DEBUGOUT6(" MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n",
152213705f88SJack F Vogel 	          mc_addr[0], mc_addr[1], mc_addr[2],
152313705f88SJack F Vogel 	          mc_addr[3], mc_addr[4], mc_addr[5]);
152413705f88SJack F Vogel 
152513705f88SJack F Vogel 	/*
152613705f88SJack F Vogel 	 * Place this multicast address in the RAR if there is room,
152713705f88SJack F Vogel 	 * else put it in the MTA
152813705f88SJack F Vogel 	 */
152913705f88SJack F Vogel 	if (hw->addr_ctrl.rar_used_count < rar_entries) {
15309ca4041bSJack F Vogel 		/* use RAR from the end up for multicast */
15319ca4041bSJack F Vogel 		rar = rar_entries - hw->addr_ctrl.mc_addr_in_rar_count - 1;
15329ca4041bSJack F Vogel 		hw->mac.ops.set_rar(hw, rar, mc_addr, 0, IXGBE_RAH_AV);
15339ca4041bSJack F Vogel 		DEBUGOUT1("Added a multicast address to RAR[%d]\n", rar);
153413705f88SJack F Vogel 		hw->addr_ctrl.rar_used_count++;
153513705f88SJack F Vogel 		hw->addr_ctrl.mc_addr_in_rar_count++;
153613705f88SJack F Vogel 	} else {
153713705f88SJack F Vogel 		ixgbe_set_mta(hw, mc_addr);
153813705f88SJack F Vogel 	}
153913705f88SJack F Vogel 
154013705f88SJack F Vogel 	DEBUGOUT("ixgbe_add_mc_addr Complete\n");
154113705f88SJack F Vogel }
154213705f88SJack F Vogel 
154313705f88SJack F Vogel /**
154413705f88SJack F Vogel  *  ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses
154513705f88SJack F Vogel  *  @hw: pointer to hardware structure
154613705f88SJack F Vogel  *  @mc_addr_list: the list of new multicast addresses
154713705f88SJack F Vogel  *  @mc_addr_count: number of addresses
15489ca4041bSJack F Vogel  *  @next: iterator function to walk the multicast address list
154913705f88SJack F Vogel  *
155013705f88SJack F Vogel  *  The given list replaces any existing list. Clears the MC addrs from receive
15519ca4041bSJack F Vogel  *  address registers and the multicast table. Uses unused receive address
155213705f88SJack F Vogel  *  registers for the first multicast addresses, and hashes the rest into the
155313705f88SJack F Vogel  *  multicast table.
155413705f88SJack F Vogel  **/
155513705f88SJack F Vogel s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
15569ca4041bSJack F Vogel                                       u32 mc_addr_count, ixgbe_mc_addr_itr next)
155713705f88SJack F Vogel {
155813705f88SJack F Vogel 	u32 i;
15599ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
15609ca4041bSJack F Vogel 	u32 vmdq;
156113705f88SJack F Vogel 
156213705f88SJack F Vogel 	/*
156313705f88SJack F Vogel 	 * Set the new number of MC addresses that we are being requested to
156413705f88SJack F Vogel 	 * use.
156513705f88SJack F Vogel 	 */
156613705f88SJack F Vogel 	hw->addr_ctrl.num_mc_addrs = mc_addr_count;
156713705f88SJack F Vogel 	hw->addr_ctrl.rar_used_count -= hw->addr_ctrl.mc_addr_in_rar_count;
156813705f88SJack F Vogel 	hw->addr_ctrl.mc_addr_in_rar_count = 0;
156913705f88SJack F Vogel 	hw->addr_ctrl.mta_in_use = 0;
157013705f88SJack F Vogel 
157113705f88SJack F Vogel 	/* Zero out the other receive addresses. */
15729ca4041bSJack F Vogel 	DEBUGOUT2("Clearing RAR[%d-%d]\n", hw->addr_ctrl.rar_used_count,
15739ca4041bSJack F Vogel 	          rar_entries - 1);
157413705f88SJack F Vogel 	for (i = hw->addr_ctrl.rar_used_count; i < rar_entries; i++) {
157513705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
157613705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
157713705f88SJack F Vogel 	}
157813705f88SJack F Vogel 
157913705f88SJack F Vogel 	/* Clear the MTA */
158013705f88SJack F Vogel 	DEBUGOUT(" Clearing MTA\n");
15819ca4041bSJack F Vogel 	for (i = 0; i < hw->mac.mcft_size; i++)
158213705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
158313705f88SJack F Vogel 
158413705f88SJack F Vogel 	/* Add the new addresses */
158513705f88SJack F Vogel 	for (i = 0; i < mc_addr_count; i++) {
158613705f88SJack F Vogel 		DEBUGOUT(" Adding the multicast addresses:\n");
15879ca4041bSJack F Vogel 		ixgbe_add_mc_addr(hw, next(hw, &mc_addr_list, &vmdq));
158813705f88SJack F Vogel 	}
158913705f88SJack F Vogel 
159013705f88SJack F Vogel 	/* Enable mta */
159113705f88SJack F Vogel 	if (hw->addr_ctrl.mta_in_use > 0)
159213705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL,
159313705f88SJack F Vogel 		                IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type);
159413705f88SJack F Vogel 
159513705f88SJack F Vogel 	DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n");
159613705f88SJack F Vogel 	return IXGBE_SUCCESS;
159713705f88SJack F Vogel }
159813705f88SJack F Vogel 
159913705f88SJack F Vogel /**
160013705f88SJack F Vogel  *  ixgbe_enable_mc_generic - Enable multicast address in RAR
160113705f88SJack F Vogel  *  @hw: pointer to hardware structure
160213705f88SJack F Vogel  *
160313705f88SJack F Vogel  *  Enables multicast address in RAR and the use of the multicast hash table.
160413705f88SJack F Vogel  **/
160513705f88SJack F Vogel s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
160613705f88SJack F Vogel {
160713705f88SJack F Vogel 	u32 i;
16089ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
160913705f88SJack F Vogel 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
161013705f88SJack F Vogel 
161113705f88SJack F Vogel 	if (a->mc_addr_in_rar_count > 0)
16129ca4041bSJack F Vogel 		for (i = (rar_entries - a->mc_addr_in_rar_count);
16139ca4041bSJack F Vogel 		     i < rar_entries; i++)
161413705f88SJack F Vogel 			ixgbe_enable_rar(hw, i);
161513705f88SJack F Vogel 
161613705f88SJack F Vogel 	if (a->mta_in_use > 0)
161713705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE |
161813705f88SJack F Vogel 		                hw->mac.mc_filter_type);
161913705f88SJack F Vogel 
162013705f88SJack F Vogel 	return IXGBE_SUCCESS;
162113705f88SJack F Vogel }
162213705f88SJack F Vogel 
162313705f88SJack F Vogel /**
16249ca4041bSJack F Vogel  *  ixgbe_disable_mc_generic - Disable multicast address in RAR
162513705f88SJack F Vogel  *  @hw: pointer to hardware structure
162613705f88SJack F Vogel  *
162713705f88SJack F Vogel  *  Disables multicast address in RAR and the use of the multicast hash table.
162813705f88SJack F Vogel  **/
162913705f88SJack F Vogel s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
163013705f88SJack F Vogel {
163113705f88SJack F Vogel 	u32 i;
16329ca4041bSJack F Vogel 	u32 rar_entries = hw->mac.num_rar_entries;
163313705f88SJack F Vogel 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
163413705f88SJack F Vogel 
163513705f88SJack F Vogel 	if (a->mc_addr_in_rar_count > 0)
16369ca4041bSJack F Vogel 		for (i = (rar_entries - a->mc_addr_in_rar_count);
16379ca4041bSJack F Vogel 		     i < rar_entries; i++)
163813705f88SJack F Vogel 			ixgbe_disable_rar(hw, i);
163913705f88SJack F Vogel 
164013705f88SJack F Vogel 	if (a->mta_in_use > 0)
164113705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
164213705f88SJack F Vogel 
164313705f88SJack F Vogel 	return IXGBE_SUCCESS;
164413705f88SJack F Vogel }
164513705f88SJack F Vogel 
164613705f88SJack F Vogel /**
164713705f88SJack F Vogel  *  ixgbe_clear_vfta_generic - Clear VLAN filter table
164813705f88SJack F Vogel  *  @hw: pointer to hardware structure
164913705f88SJack F Vogel  *
165013705f88SJack F Vogel  *  Clears the VLAN filer table, and the VMDq index associated with the filter
165113705f88SJack F Vogel  **/
165213705f88SJack F Vogel s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw)
165313705f88SJack F Vogel {
165413705f88SJack F Vogel 	u32 offset;
165513705f88SJack F Vogel 	u32 vlanbyte;
165613705f88SJack F Vogel 
16579ca4041bSJack F Vogel 	for (offset = 0; offset < hw->mac.vft_size; offset++)
165813705f88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
165913705f88SJack F Vogel 
166013705f88SJack F Vogel 	for (vlanbyte = 0; vlanbyte < 4; vlanbyte++)
16619ca4041bSJack F Vogel 		for (offset = 0; offset < hw->mac.vft_size; offset++)
166213705f88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset),
166313705f88SJack F Vogel 			                0);
166413705f88SJack F Vogel 
166513705f88SJack F Vogel 	return IXGBE_SUCCESS;
166613705f88SJack F Vogel }
166713705f88SJack F Vogel 
166813705f88SJack F Vogel /**
166913705f88SJack F Vogel  *  ixgbe_set_vfta_generic - Set VLAN filter table
167013705f88SJack F Vogel  *  @hw: pointer to hardware structure
167113705f88SJack F Vogel  *  @vlan: VLAN id to write to VLAN filter
167213705f88SJack F Vogel  *  @vind: VMDq output index that maps queue to VLAN id in VFTA
167313705f88SJack F Vogel  *  @vlan_on: boolean flag to turn on/off VLAN in VFTA
167413705f88SJack F Vogel  *
167513705f88SJack F Vogel  *  Turn on/off specified VLAN in the VLAN filter table.
167613705f88SJack F Vogel  **/
167713705f88SJack F Vogel s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
167813705f88SJack F Vogel                            bool vlan_on)
167913705f88SJack F Vogel {
168013705f88SJack F Vogel 	u32 VftaIndex;
168113705f88SJack F Vogel 	u32 BitOffset;
168213705f88SJack F Vogel 	u32 VftaReg;
168313705f88SJack F Vogel 	u32 VftaByte;
168413705f88SJack F Vogel 
168513705f88SJack F Vogel 	/* Determine 32-bit word position in array */
168613705f88SJack F Vogel 	VftaIndex = (vlan >> 5) & 0x7F;   /* upper seven bits */
168713705f88SJack F Vogel 
168813705f88SJack F Vogel 	/* Determine the location of the (VMD) queue index */
168913705f88SJack F Vogel 	VftaByte =  ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */
169013705f88SJack F Vogel 	BitOffset = (vlan & 0x7) << 2;    /* lower 3 bits indicate nibble */
169113705f88SJack F Vogel 
169213705f88SJack F Vogel 	/* Set the nibble for VMD queue index */
169313705f88SJack F Vogel 	VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex));
169413705f88SJack F Vogel 	VftaReg &= (~(0x0F << BitOffset));
169513705f88SJack F Vogel 	VftaReg |= (vind << BitOffset);
169613705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex), VftaReg);
169713705f88SJack F Vogel 
169813705f88SJack F Vogel 	/* Determine the location of the bit for this VLAN id */
169913705f88SJack F Vogel 	BitOffset = vlan & 0x1F;   /* lower five bits */
170013705f88SJack F Vogel 
170113705f88SJack F Vogel 	VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTA(VftaIndex));
170213705f88SJack F Vogel 	if (vlan_on)
170313705f88SJack F Vogel 		/* Turn on this VLAN id */
170413705f88SJack F Vogel 		VftaReg |= (1 << BitOffset);
170513705f88SJack F Vogel 	else
170613705f88SJack F Vogel 		/* Turn off this VLAN id */
170713705f88SJack F Vogel 		VftaReg &= ~(1 << BitOffset);
170813705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_VFTA(VftaIndex), VftaReg);
170913705f88SJack F Vogel 
171013705f88SJack F Vogel 	return IXGBE_SUCCESS;
171113705f88SJack F Vogel }
171213705f88SJack F Vogel 
171313705f88SJack F Vogel /**
171413705f88SJack F Vogel  *  ixgbe_disable_pcie_master - Disable PCI-express master access
171513705f88SJack F Vogel  *  @hw: pointer to hardware structure
171613705f88SJack F Vogel  *
171713705f88SJack F Vogel  *  Disables PCI-Express master access and verifies there are no pending
171813705f88SJack F Vogel  *  requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable
171913705f88SJack F Vogel  *  bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS
172013705f88SJack F Vogel  *  is returned signifying master requests disabled.
172113705f88SJack F Vogel  **/
172213705f88SJack F Vogel s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
172313705f88SJack F Vogel {
172413705f88SJack F Vogel 	u32 ctrl;
172513705f88SJack F Vogel 	s32 i;
172613705f88SJack F Vogel 	s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
172713705f88SJack F Vogel 
172813705f88SJack F Vogel 	ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
172913705f88SJack F Vogel 	ctrl |= IXGBE_CTRL_GIO_DIS;
173013705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
173113705f88SJack F Vogel 
173213705f88SJack F Vogel 	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
173313705f88SJack F Vogel 		if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) {
173413705f88SJack F Vogel 			status = IXGBE_SUCCESS;
173513705f88SJack F Vogel 			break;
173613705f88SJack F Vogel 		}
173713705f88SJack F Vogel 		usec_delay(100);
173813705f88SJack F Vogel 	}
173913705f88SJack F Vogel 
174013705f88SJack F Vogel 	return status;
174113705f88SJack F Vogel }
174213705f88SJack F Vogel 
174313705f88SJack F Vogel 
174413705f88SJack F Vogel /**
17459ca4041bSJack F Vogel  *  ixgbe_acquire_swfw_sync - Acquire SWFW semaphore
174613705f88SJack F Vogel  *  @hw: pointer to hardware structure
17479ca4041bSJack F Vogel  *  @mask: Mask to specify which semaphore to acquire
174813705f88SJack F Vogel  *
17499ca4041bSJack F Vogel  *  Acquires the SWFW semaphore thought the GSSR register for the specified
175013705f88SJack F Vogel  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
175113705f88SJack F Vogel  **/
175213705f88SJack F Vogel s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
175313705f88SJack F Vogel {
175413705f88SJack F Vogel 	u32 gssr;
175513705f88SJack F Vogel 	u32 swmask = mask;
175613705f88SJack F Vogel 	u32 fwmask = mask << 5;
175713705f88SJack F Vogel 	s32 timeout = 200;
175813705f88SJack F Vogel 
175913705f88SJack F Vogel 	while (timeout) {
176013705f88SJack F Vogel 		if (ixgbe_get_eeprom_semaphore(hw))
176113705f88SJack F Vogel 			return -IXGBE_ERR_SWFW_SYNC;
176213705f88SJack F Vogel 
176313705f88SJack F Vogel 		gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
176413705f88SJack F Vogel 		if (!(gssr & (fwmask | swmask)))
176513705f88SJack F Vogel 			break;
176613705f88SJack F Vogel 
176713705f88SJack F Vogel 		/*
176813705f88SJack F Vogel 		 * Firmware currently using resource (fwmask) or other software
176913705f88SJack F Vogel 		 * thread currently using resource (swmask)
177013705f88SJack F Vogel 		 */
177113705f88SJack F Vogel 		ixgbe_release_eeprom_semaphore(hw);
177213705f88SJack F Vogel 		msec_delay(5);
177313705f88SJack F Vogel 		timeout--;
177413705f88SJack F Vogel 	}
177513705f88SJack F Vogel 
177613705f88SJack F Vogel 	if (!timeout) {
177713705f88SJack F Vogel 		DEBUGOUT("Driver can't access resource, GSSR timeout.\n");
177813705f88SJack F Vogel 		return -IXGBE_ERR_SWFW_SYNC;
177913705f88SJack F Vogel 	}
178013705f88SJack F Vogel 
178113705f88SJack F Vogel 	gssr |= swmask;
178213705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
178313705f88SJack F Vogel 
178413705f88SJack F Vogel 	ixgbe_release_eeprom_semaphore(hw);
178513705f88SJack F Vogel 	return IXGBE_SUCCESS;
178613705f88SJack F Vogel }
178713705f88SJack F Vogel 
178813705f88SJack F Vogel /**
178913705f88SJack F Vogel  *  ixgbe_release_swfw_sync - Release SWFW semaphore
179013705f88SJack F Vogel  *  @hw: pointer to hardware structure
17919ca4041bSJack F Vogel  *  @mask: Mask to specify which semaphore to release
179213705f88SJack F Vogel  *
17939ca4041bSJack F Vogel  *  Releases the SWFW semaphore thought the GSSR register for the specified
179413705f88SJack F Vogel  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
179513705f88SJack F Vogel  **/
179613705f88SJack F Vogel void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
179713705f88SJack F Vogel {
179813705f88SJack F Vogel 	u32 gssr;
179913705f88SJack F Vogel 	u32 swmask = mask;
180013705f88SJack F Vogel 
180113705f88SJack F Vogel 	ixgbe_get_eeprom_semaphore(hw);
180213705f88SJack F Vogel 
180313705f88SJack F Vogel 	gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
180413705f88SJack F Vogel 	gssr &= ~swmask;
180513705f88SJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
180613705f88SJack F Vogel 
180713705f88SJack F Vogel 	ixgbe_release_eeprom_semaphore(hw);
180813705f88SJack F Vogel }
180913705f88SJack F Vogel 
18109ca4041bSJack F Vogel /**
18119ca4041bSJack F Vogel  *  ixgbe_read_analog_reg8_generic - Reads 8 bit Atlas analog register
18129ca4041bSJack F Vogel  *  @hw: pointer to hardware structure
18139ca4041bSJack F Vogel  *  @reg: analog register to read
18149ca4041bSJack F Vogel  *  @val: read value
18159ca4041bSJack F Vogel  *
18169ca4041bSJack F Vogel  *  Performs read operation to Atlas analog register specified.
18179ca4041bSJack F Vogel  **/
18189ca4041bSJack F Vogel s32 ixgbe_read_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 *val)
18199ca4041bSJack F Vogel {
18209ca4041bSJack F Vogel 	u32  atlas_ctl;
18219ca4041bSJack F Vogel 
18229ca4041bSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, IXGBE_ATLASCTL_WRITE_CMD | (reg << 8));
18239ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
18249ca4041bSJack F Vogel 	usec_delay(10);
18259ca4041bSJack F Vogel 	atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL);
18269ca4041bSJack F Vogel 	*val = (u8)atlas_ctl;
18279ca4041bSJack F Vogel 
18289ca4041bSJack F Vogel 	return IXGBE_SUCCESS;
18299ca4041bSJack F Vogel }
18309ca4041bSJack F Vogel 
18319ca4041bSJack F Vogel /**
18329ca4041bSJack F Vogel  *  ixgbe_write_analog_reg8_generic - Writes 8 bit Atlas analog register
18339ca4041bSJack F Vogel  *  @hw: pointer to hardware structure
18349ca4041bSJack F Vogel  *  @reg: atlas register to write
18359ca4041bSJack F Vogel  *  @val: value to write
18369ca4041bSJack F Vogel  *
18379ca4041bSJack F Vogel  *  Performs write operation to Atlas analog register specified.
18389ca4041bSJack F Vogel  **/
18399ca4041bSJack F Vogel s32 ixgbe_write_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 val)
18409ca4041bSJack F Vogel {
18419ca4041bSJack F Vogel 	u32  atlas_ctl;
18429ca4041bSJack F Vogel 
18439ca4041bSJack F Vogel 	atlas_ctl = (reg << 8) | val;
18449ca4041bSJack F Vogel 	IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl);
18459ca4041bSJack F Vogel 	IXGBE_WRITE_FLUSH(hw);
18469ca4041bSJack F Vogel 	usec_delay(10);
18479ca4041bSJack F Vogel 
18489ca4041bSJack F Vogel 	return IXGBE_SUCCESS;
18499ca4041bSJack F Vogel }
18509ca4041bSJack F Vogel 
1851