mirror of
				https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
				synced 2025-10-31 08:08:51 +01:00 
			
		
		
		
	Fixed MTP to work with TWRP
This commit is contained in:
		
						commit
						f6dfaef42e
					
				
					 50820 changed files with 20846062 additions and 0 deletions
				
			
		
							
								
								
									
										83
									
								
								drivers/net/ethernet/atheros/Kconfig
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								drivers/net/ethernet/atheros/Kconfig
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,83 @@ | |||
| # | ||||
| # Atheros device configuration | ||||
| # | ||||
| 
 | ||||
| config NET_VENDOR_ATHEROS | ||||
| 	bool "Atheros devices" | ||||
| 	default y | ||||
| 	depends on PCI | ||||
| 	---help--- | ||||
| 	  If you have a network (Ethernet) card belonging to this class, say Y | ||||
| 	  and read the Ethernet-HOWTO, available from | ||||
| 	  <http://www.tldp.org/docs.html#howto>. | ||||
| 
 | ||||
| 	  Note that the answer to this question doesn't directly affect the | ||||
| 	  kernel: saying N will just cause the configurator to skip all | ||||
| 	  the questions about Atheros devices. If you say Y, you will be asked | ||||
| 	  for your specific card in the following questions. | ||||
| 
 | ||||
| if NET_VENDOR_ATHEROS | ||||
| 
 | ||||
| config ATL2 | ||||
| 	tristate "Atheros L2 Fast Ethernet support" | ||||
| 	depends on PCI | ||||
| 	select CRC32 | ||||
| 	select MII | ||||
| 	---help--- | ||||
| 	  This driver supports the Atheros L2 fast ethernet adapter. | ||||
| 
 | ||||
| 	  To compile this driver as a module, choose M here.  The module | ||||
| 	  will be called atl2. | ||||
| 
 | ||||
| config ATL1 | ||||
| 	tristate "Atheros/Attansic L1 Gigabit Ethernet support" | ||||
| 	depends on PCI | ||||
| 	select CRC32 | ||||
| 	select MII | ||||
| 	---help--- | ||||
| 	  This driver supports the Atheros/Attansic L1 gigabit ethernet | ||||
| 	  adapter. | ||||
| 
 | ||||
| 	  To compile this driver as a module, choose M here.  The module | ||||
| 	  will be called atl1. | ||||
| 
 | ||||
| config ATL1E | ||||
| 	tristate "Atheros L1E Gigabit Ethernet support" | ||||
| 	depends on PCI | ||||
| 	select CRC32 | ||||
| 	select MII | ||||
| 	---help--- | ||||
| 	  This driver supports the Atheros L1E gigabit ethernet adapter. | ||||
| 
 | ||||
| 	  To compile this driver as a module, choose M here.  The module | ||||
| 	  will be called atl1e. | ||||
| 
 | ||||
| config ATL1C | ||||
| 	tristate "Atheros L1C Gigabit Ethernet support" | ||||
| 	depends on PCI | ||||
| 	select CRC32 | ||||
| 	select MII | ||||
| 	---help--- | ||||
| 	  This driver supports the Atheros L1C gigabit ethernet adapter. | ||||
| 
 | ||||
| 	  To compile this driver as a module, choose M here.  The module | ||||
| 	  will be called atl1c. | ||||
| 
 | ||||
| config ALX | ||||
| 	tristate "Qualcomm Atheros AR816x/AR817x support" | ||||
| 	depends on PCI | ||||
| 	select CRC32 | ||||
| 	select MDIO | ||||
| 	help | ||||
| 	  This driver supports the Qualcomm Atheros L1F ethernet adapter, | ||||
| 	  i.e. the following chipsets: | ||||
| 
 | ||||
| 	  1969:1091 - AR8161 Gigabit Ethernet | ||||
| 	  1969:1090 - AR8162 Fast Ethernet | ||||
| 	  1969:10A1 - AR8171 Gigabit Ethernet | ||||
| 	  1969:10A0 - AR8172 Fast Ethernet | ||||
| 
 | ||||
| 	  To compile this driver as a module, choose M here.  The module | ||||
| 	  will be called alx. | ||||
| 
 | ||||
| endif # NET_VENDOR_ATHEROS | ||||
							
								
								
									
										9
									
								
								drivers/net/ethernet/atheros/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								drivers/net/ethernet/atheros/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| #
 | ||||
| # Makefile for the Atheros network device drivers.
 | ||||
| #
 | ||||
| 
 | ||||
| obj-$(CONFIG_ATL1) += atlx/ | ||||
| obj-$(CONFIG_ATL2) += atlx/ | ||||
| obj-$(CONFIG_ATL1E) += atl1e/ | ||||
| obj-$(CONFIG_ATL1C) += atl1c/ | ||||
| obj-$(CONFIG_ALX) += alx/ | ||||
							
								
								
									
										3
									
								
								drivers/net/ethernet/atheros/alx/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								drivers/net/ethernet/atheros/alx/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| obj-$(CONFIG_ALX) += alx.o | ||||
| alx-objs := main.o ethtool.o hw.o | ||||
| ccflags-y += -D__CHECK_ENDIAN__ | ||||
							
								
								
									
										117
									
								
								drivers/net/ethernet/atheros/alx/alx.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								drivers/net/ethernet/atheros/alx/alx.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,117 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2013 Johannes Berg <johannes@sipsolutions.net> | ||||
|  * | ||||
|  *  This file is free software: you may copy, redistribute and/or modify it | ||||
|  *  under the terms of the GNU General Public License as published by the | ||||
|  *  Free Software Foundation, either version 2 of the License, or (at your | ||||
|  *  option) any later version. | ||||
|  * | ||||
|  *  This file is distributed in the hope that it will be useful, but | ||||
|  *  WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  *  General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * | ||||
|  * This file incorporates work covered by the following copyright and | ||||
|  * permission notice: | ||||
|  * | ||||
|  * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||||
|  * | ||||
|  * Permission to use, copy, modify, and/or distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _ALX_H_ | ||||
| #define _ALX_H_ | ||||
| 
 | ||||
| #include <linux/types.h> | ||||
| #include <linux/etherdevice.h> | ||||
| #include <linux/dma-mapping.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include "hw.h" | ||||
| 
 | ||||
| #define ALX_WATCHDOG_TIME   (5 * HZ) | ||||
| 
 | ||||
| struct alx_buffer { | ||||
| 	struct sk_buff *skb; | ||||
| 	DEFINE_DMA_UNMAP_ADDR(dma); | ||||
| 	DEFINE_DMA_UNMAP_LEN(size); | ||||
| }; | ||||
| 
 | ||||
| struct alx_rx_queue { | ||||
| 	struct alx_rrd *rrd; | ||||
| 	dma_addr_t rrd_dma; | ||||
| 
 | ||||
| 	struct alx_rfd *rfd; | ||||
| 	dma_addr_t rfd_dma; | ||||
| 
 | ||||
| 	struct alx_buffer *bufs; | ||||
| 
 | ||||
| 	u16 write_idx, read_idx; | ||||
| 	u16 rrd_read_idx; | ||||
| }; | ||||
| #define ALX_RX_ALLOC_THRESH	32 | ||||
| 
 | ||||
| struct alx_tx_queue { | ||||
| 	struct alx_txd *tpd; | ||||
| 	dma_addr_t tpd_dma; | ||||
| 	struct alx_buffer *bufs; | ||||
| 	u16 write_idx, read_idx; | ||||
| }; | ||||
| 
 | ||||
| #define ALX_DEFAULT_TX_WORK 128 | ||||
| 
 | ||||
| enum alx_device_quirks { | ||||
| 	ALX_DEV_QUIRK_MSI_INTX_DISABLE_BUG = BIT(0), | ||||
| }; | ||||
| 
 | ||||
| struct alx_priv { | ||||
| 	struct net_device *dev; | ||||
| 
 | ||||
| 	struct alx_hw hw; | ||||
| 
 | ||||
| 	/* all descriptor memory */ | ||||
| 	struct { | ||||
| 		dma_addr_t dma; | ||||
| 		void *virt; | ||||
| 		unsigned int size; | ||||
| 	} descmem; | ||||
| 
 | ||||
| 	/* protect int_mask updates */ | ||||
| 	spinlock_t irq_lock; | ||||
| 	u32 int_mask; | ||||
| 
 | ||||
| 	unsigned int tx_ringsz; | ||||
| 	unsigned int rx_ringsz; | ||||
| 	unsigned int rxbuf_size; | ||||
| 
 | ||||
| 	struct napi_struct napi; | ||||
| 	struct alx_tx_queue txq; | ||||
| 	struct alx_rx_queue rxq; | ||||
| 
 | ||||
| 	struct work_struct link_check_wk; | ||||
| 	struct work_struct reset_wk; | ||||
| 
 | ||||
| 	u16 msg_enable; | ||||
| 
 | ||||
| 	bool msi; | ||||
| 
 | ||||
| 	/* protects hw.stats */ | ||||
| 	spinlock_t stats_lock; | ||||
| }; | ||||
| 
 | ||||
| extern const struct ethtool_ops alx_ethtool_ops; | ||||
| extern const char alx_drv_name[]; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										313
									
								
								drivers/net/ethernet/atheros/alx/ethtool.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								drivers/net/ethernet/atheros/alx/ethtool.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,313 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2013 Johannes Berg <johannes@sipsolutions.net> | ||||
|  * | ||||
|  *  This file is free software: you may copy, redistribute and/or modify it | ||||
|  *  under the terms of the GNU General Public License as published by the | ||||
|  *  Free Software Foundation, either version 2 of the License, or (at your | ||||
|  *  option) any later version. | ||||
|  * | ||||
|  *  This file is distributed in the hope that it will be useful, but | ||||
|  *  WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  *  General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * | ||||
|  * This file incorporates work covered by the following copyright and | ||||
|  * permission notice: | ||||
|  * | ||||
|  * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||||
|  * | ||||
|  * Permission to use, copy, modify, and/or distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/pci.h> | ||||
| #include <linux/ip.h> | ||||
| #include <linux/tcp.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/etherdevice.h> | ||||
| #include <linux/ethtool.h> | ||||
| #include <linux/mdio.h> | ||||
| #include <linux/interrupt.h> | ||||
| #include <asm/byteorder.h> | ||||
| 
 | ||||
| #include "alx.h" | ||||
| #include "reg.h" | ||||
| #include "hw.h" | ||||
| 
 | ||||
| /* The order of these strings must match the order of the fields in
 | ||||
|  * struct alx_hw_stats | ||||
|  * See hw.h | ||||
|  */ | ||||
| static const char alx_gstrings_stats[][ETH_GSTRING_LEN] = { | ||||
| 	"rx_packets", | ||||
| 	"rx_bcast_packets", | ||||
| 	"rx_mcast_packets", | ||||
| 	"rx_pause_packets", | ||||
| 	"rx_ctrl_packets", | ||||
| 	"rx_fcs_errors", | ||||
| 	"rx_length_errors", | ||||
| 	"rx_bytes", | ||||
| 	"rx_runt_packets", | ||||
| 	"rx_fragments", | ||||
| 	"rx_64B_or_less_packets", | ||||
| 	"rx_65B_to_127B_packets", | ||||
| 	"rx_128B_to_255B_packets", | ||||
| 	"rx_256B_to_511B_packets", | ||||
| 	"rx_512B_to_1023B_packets", | ||||
| 	"rx_1024B_to_1518B_packets", | ||||
| 	"rx_1519B_to_mtu_packets", | ||||
| 	"rx_oversize_packets", | ||||
| 	"rx_rxf_ov_drop_packets", | ||||
| 	"rx_rrd_ov_drop_packets", | ||||
| 	"rx_align_errors", | ||||
| 	"rx_bcast_bytes", | ||||
| 	"rx_mcast_bytes", | ||||
| 	"rx_address_errors", | ||||
| 	"tx_packets", | ||||
| 	"tx_bcast_packets", | ||||
| 	"tx_mcast_packets", | ||||
| 	"tx_pause_packets", | ||||
| 	"tx_exc_defer_packets", | ||||
| 	"tx_ctrl_packets", | ||||
| 	"tx_defer_packets", | ||||
| 	"tx_bytes", | ||||
| 	"tx_64B_or_less_packets", | ||||
| 	"tx_65B_to_127B_packets", | ||||
| 	"tx_128B_to_255B_packets", | ||||
| 	"tx_256B_to_511B_packets", | ||||
| 	"tx_512B_to_1023B_packets", | ||||
| 	"tx_1024B_to_1518B_packets", | ||||
| 	"tx_1519B_to_mtu_packets", | ||||
| 	"tx_single_collision", | ||||
| 	"tx_multiple_collisions", | ||||
| 	"tx_late_collision", | ||||
| 	"tx_abort_collision", | ||||
| 	"tx_underrun", | ||||
| 	"tx_trd_eop", | ||||
| 	"tx_length_errors", | ||||
| 	"tx_trunc_packets", | ||||
| 	"tx_bcast_bytes", | ||||
| 	"tx_mcast_bytes", | ||||
| 	"tx_update", | ||||
| }; | ||||
| 
 | ||||
| #define ALX_NUM_STATS ARRAY_SIZE(alx_gstrings_stats) | ||||
| 
 | ||||
| 
 | ||||
| static u32 alx_get_supported_speeds(struct alx_hw *hw) | ||||
| { | ||||
| 	u32 supported = SUPPORTED_10baseT_Half | | ||||
| 			SUPPORTED_10baseT_Full | | ||||
| 			SUPPORTED_100baseT_Half | | ||||
| 			SUPPORTED_100baseT_Full; | ||||
| 
 | ||||
| 	if (alx_hw_giga(hw)) | ||||
| 		supported |= SUPPORTED_1000baseT_Full; | ||||
| 
 | ||||
| 	BUILD_BUG_ON(SUPPORTED_10baseT_Half != ADVERTISED_10baseT_Half); | ||||
| 	BUILD_BUG_ON(SUPPORTED_10baseT_Full != ADVERTISED_10baseT_Full); | ||||
| 	BUILD_BUG_ON(SUPPORTED_100baseT_Half != ADVERTISED_100baseT_Half); | ||||
| 	BUILD_BUG_ON(SUPPORTED_100baseT_Full != ADVERTISED_100baseT_Full); | ||||
| 	BUILD_BUG_ON(SUPPORTED_1000baseT_Full != ADVERTISED_1000baseT_Full); | ||||
| 
 | ||||
| 	return supported; | ||||
| } | ||||
| 
 | ||||
| static int alx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | ||||
| { | ||||
| 	struct alx_priv *alx = netdev_priv(netdev); | ||||
| 	struct alx_hw *hw = &alx->hw; | ||||
| 
 | ||||
| 	ecmd->supported = SUPPORTED_Autoneg | | ||||
| 			  SUPPORTED_TP | | ||||
| 			  SUPPORTED_Pause | | ||||
| 			  SUPPORTED_Asym_Pause; | ||||
| 	if (alx_hw_giga(hw)) | ||||
| 		ecmd->supported |= SUPPORTED_1000baseT_Full; | ||||
| 	ecmd->supported |= alx_get_supported_speeds(hw); | ||||
| 
 | ||||
| 	ecmd->advertising = ADVERTISED_TP; | ||||
| 	if (hw->adv_cfg & ADVERTISED_Autoneg) | ||||
| 		ecmd->advertising |= hw->adv_cfg; | ||||
| 
 | ||||
| 	ecmd->port = PORT_TP; | ||||
| 	ecmd->phy_address = 0; | ||||
| 
 | ||||
| 	if (hw->adv_cfg & ADVERTISED_Autoneg) | ||||
| 		ecmd->autoneg = AUTONEG_ENABLE; | ||||
| 	else | ||||
| 		ecmd->autoneg = AUTONEG_DISABLE; | ||||
| 	ecmd->transceiver = XCVR_INTERNAL; | ||||
| 
 | ||||
| 	if (hw->flowctrl & ALX_FC_ANEG && hw->adv_cfg & ADVERTISED_Autoneg) { | ||||
| 		if (hw->flowctrl & ALX_FC_RX) { | ||||
| 			ecmd->advertising |= ADVERTISED_Pause; | ||||
| 
 | ||||
| 			if (!(hw->flowctrl & ALX_FC_TX)) | ||||
| 				ecmd->advertising |= ADVERTISED_Asym_Pause; | ||||
| 		} else if (hw->flowctrl & ALX_FC_TX) { | ||||
| 			ecmd->advertising |= ADVERTISED_Asym_Pause; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ethtool_cmd_speed_set(ecmd, hw->link_speed); | ||||
| 	ecmd->duplex = hw->duplex; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int alx_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | ||||
| { | ||||
| 	struct alx_priv *alx = netdev_priv(netdev); | ||||
| 	struct alx_hw *hw = &alx->hw; | ||||
| 	u32 adv_cfg; | ||||
| 
 | ||||
| 	ASSERT_RTNL(); | ||||
| 
 | ||||
| 	if (ecmd->autoneg == AUTONEG_ENABLE) { | ||||
| 		if (ecmd->advertising & ~alx_get_supported_speeds(hw)) | ||||
| 			return -EINVAL; | ||||
| 		adv_cfg = ecmd->advertising | ADVERTISED_Autoneg; | ||||
| 	} else { | ||||
| 		adv_cfg = alx_speed_to_ethadv(ethtool_cmd_speed(ecmd), | ||||
| 					      ecmd->duplex); | ||||
| 
 | ||||
| 		if (!adv_cfg || adv_cfg == ADVERTISED_1000baseT_Full) | ||||
| 			return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	hw->adv_cfg = adv_cfg; | ||||
| 	return alx_setup_speed_duplex(hw, adv_cfg, hw->flowctrl); | ||||
| } | ||||
| 
 | ||||
| static void alx_get_pauseparam(struct net_device *netdev, | ||||
| 			       struct ethtool_pauseparam *pause) | ||||
| { | ||||
| 	struct alx_priv *alx = netdev_priv(netdev); | ||||
| 	struct alx_hw *hw = &alx->hw; | ||||
| 
 | ||||
| 	pause->autoneg = !!(hw->flowctrl & ALX_FC_ANEG && | ||||
| 			    hw->adv_cfg & ADVERTISED_Autoneg); | ||||
| 	pause->tx_pause = !!(hw->flowctrl & ALX_FC_TX); | ||||
| 	pause->rx_pause = !!(hw->flowctrl & ALX_FC_RX); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int alx_set_pauseparam(struct net_device *netdev, | ||||
| 			      struct ethtool_pauseparam *pause) | ||||
| { | ||||
| 	struct alx_priv *alx = netdev_priv(netdev); | ||||
| 	struct alx_hw *hw = &alx->hw; | ||||
| 	int err = 0; | ||||
| 	bool reconfig_phy = false; | ||||
| 	u8 fc = 0; | ||||
| 
 | ||||
| 	if (pause->tx_pause) | ||||
| 		fc |= ALX_FC_TX; | ||||
| 	if (pause->rx_pause) | ||||
| 		fc |= ALX_FC_RX; | ||||
| 	if (pause->autoneg) | ||||
| 		fc |= ALX_FC_ANEG; | ||||
| 
 | ||||
| 	ASSERT_RTNL(); | ||||
| 
 | ||||
| 	/* restart auto-neg for auto-mode */ | ||||
| 	if (hw->adv_cfg & ADVERTISED_Autoneg) { | ||||
| 		if (!((fc ^ hw->flowctrl) & ALX_FC_ANEG)) | ||||
| 			reconfig_phy = true; | ||||
| 		if (fc & hw->flowctrl & ALX_FC_ANEG && | ||||
| 		    (fc ^ hw->flowctrl) & (ALX_FC_RX | ALX_FC_TX)) | ||||
| 			reconfig_phy = true; | ||||
| 	} | ||||
| 
 | ||||
| 	if (reconfig_phy) { | ||||
| 		err = alx_setup_speed_duplex(hw, hw->adv_cfg, fc); | ||||
| 		if (err) | ||||
| 			return err; | ||||
| 	} | ||||
| 
 | ||||
| 	/* flow control on mac */ | ||||
| 	if ((fc ^ hw->flowctrl) & (ALX_FC_RX | ALX_FC_TX)) | ||||
| 		alx_cfg_mac_flowcontrol(hw, fc); | ||||
| 
 | ||||
| 	hw->flowctrl = fc; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static u32 alx_get_msglevel(struct net_device *netdev) | ||||
| { | ||||
| 	struct alx_priv *alx = netdev_priv(netdev); | ||||
| 
 | ||||
| 	return alx->msg_enable; | ||||
| } | ||||
| 
 | ||||
| static void alx_set_msglevel(struct net_device *netdev, u32 data) | ||||
| { | ||||
| 	struct alx_priv *alx = netdev_priv(netdev); | ||||
| 
 | ||||
| 	alx->msg_enable = data; | ||||
| } | ||||
| 
 | ||||
| static void alx_get_ethtool_stats(struct net_device *netdev, | ||||
| 				  struct ethtool_stats *estats, u64 *data) | ||||
| { | ||||
| 	struct alx_priv *alx = netdev_priv(netdev); | ||||
| 	struct alx_hw *hw = &alx->hw; | ||||
| 
 | ||||
| 	spin_lock(&alx->stats_lock); | ||||
| 
 | ||||
| 	alx_update_hw_stats(hw); | ||||
| 	BUILD_BUG_ON(sizeof(hw->stats) - offsetof(struct alx_hw_stats, rx_ok) < | ||||
| 		     ALX_NUM_STATS * sizeof(u64)); | ||||
| 	memcpy(data, &hw->stats.rx_ok, ALX_NUM_STATS * sizeof(u64)); | ||||
| 
 | ||||
| 	spin_unlock(&alx->stats_lock); | ||||
| } | ||||
| 
 | ||||
| static void alx_get_strings(struct net_device *netdev, u32 stringset, u8 *buf) | ||||
| { | ||||
| 	switch (stringset) { | ||||
| 	case ETH_SS_STATS: | ||||
| 		memcpy(buf, &alx_gstrings_stats, sizeof(alx_gstrings_stats)); | ||||
| 		break; | ||||
| 	default: | ||||
| 		WARN_ON(1); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int alx_get_sset_count(struct net_device *netdev, int sset) | ||||
| { | ||||
| 	switch (sset) { | ||||
| 	case ETH_SS_STATS: | ||||
| 		return ALX_NUM_STATS; | ||||
| 	default: | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| const struct ethtool_ops alx_ethtool_ops = { | ||||
| 	.get_settings	= alx_get_settings, | ||||
| 	.set_settings	= alx_set_settings, | ||||
| 	.get_pauseparam	= alx_get_pauseparam, | ||||
| 	.set_pauseparam	= alx_set_pauseparam, | ||||
| 	.get_msglevel	= alx_get_msglevel, | ||||
| 	.set_msglevel	= alx_set_msglevel, | ||||
| 	.get_link	= ethtool_op_get_link, | ||||
| 	.get_strings	= alx_get_strings, | ||||
| 	.get_sset_count	= alx_get_sset_count, | ||||
| 	.get_ethtool_stats	= alx_get_ethtool_stats, | ||||
| }; | ||||
							
								
								
									
										1110
									
								
								drivers/net/ethernet/atheros/alx/hw.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1110
									
								
								drivers/net/ethernet/atheros/alx/hw.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										581
									
								
								drivers/net/ethernet/atheros/alx/hw.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										581
									
								
								drivers/net/ethernet/atheros/alx/hw.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,581 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2013 Johannes Berg <johannes@sipsolutions.net> | ||||
|  * | ||||
|  *  This file is free software: you may copy, redistribute and/or modify it | ||||
|  *  under the terms of the GNU General Public License as published by the | ||||
|  *  Free Software Foundation, either version 2 of the License, or (at your | ||||
|  *  option) any later version. | ||||
|  * | ||||
|  *  This file is distributed in the hope that it will be useful, but | ||||
|  *  WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  *  General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * | ||||
|  * This file incorporates work covered by the following copyright and | ||||
|  * permission notice: | ||||
|  * | ||||
|  * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||||
|  * | ||||
|  * Permission to use, copy, modify, and/or distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef ALX_HW_H_ | ||||
| #define ALX_HW_H_ | ||||
| #include <linux/types.h> | ||||
| #include <linux/mdio.h> | ||||
| #include <linux/pci.h> | ||||
| #include "reg.h" | ||||
| 
 | ||||
| /* Transmit Packet Descriptor, contains 4 32-bit words.
 | ||||
|  * | ||||
|  *   31               16               0 | ||||
|  *   +----------------+----------------+ | ||||
|  *   |    vlan-tag    |   buf length   | | ||||
|  *   +----------------+----------------+ | ||||
|  *   |              Word 1             | | ||||
|  *   +----------------+----------------+ | ||||
|  *   |      Word 2: buf addr lo        | | ||||
|  *   +----------------+----------------+ | ||||
|  *   |      Word 3: buf addr hi        | | ||||
|  *   +----------------+----------------+ | ||||
|  * | ||||
|  * Word 2 and 3 combine to form a 64-bit buffer address | ||||
|  * | ||||
|  * Word 1 has three forms, depending on the state of bit 8/12/13: | ||||
|  * if bit8 =='1', the definition is just for custom checksum offload. | ||||
|  * if bit8 == '0' && bit12 == '1' && bit13 == '1', the *FIRST* descriptor | ||||
|  *     for the skb is special for LSO V2, Word 2 become total skb length , | ||||
|  *     Word 3 is meaningless. | ||||
|  * other condition, the definition is for general skb or ip/tcp/udp | ||||
|  *     checksum or LSO(TSO) offload. | ||||
|  * | ||||
|  * Here is the depiction: | ||||
|  * | ||||
|  *   0-+                                  0-+ | ||||
|  *   1 |                                  1 | | ||||
|  *   2 |                                  2 | | ||||
|  *   3 |    Payload offset                3 |    L4 header offset | ||||
|  *   4 |        (7:0)                     4 |        (7:0) | ||||
|  *   5 |                                  5 | | ||||
|  *   6 |                                  6 | | ||||
|  *   7-+                                  7-+ | ||||
|  *   8      Custom csum enable = 1        8      Custom csum enable = 0 | ||||
|  *   9      General IPv4 checksum         9      General IPv4 checksum | ||||
|  *   10     General TCP checksum          10     General TCP checksum | ||||
|  *   11     General UDP checksum          11     General UDP checksum | ||||
|  *   12     Large Send Segment enable     12     Large Send Segment enable | ||||
|  *   13     Large Send Segment type       13     Large Send Segment type | ||||
|  *   14     VLAN tagged                   14     VLAN tagged | ||||
|  *   15     Insert VLAN tag               15     Insert VLAN tag | ||||
|  *   16     IPv4 packet                   16     IPv4 packet | ||||
|  *   17     Ethernet frame type           17     Ethernet frame type | ||||
|  *   18-+                                 18-+ | ||||
|  *   19 |                                 19 | | ||||
|  *   20 |                                 20 | | ||||
|  *   21 |   Custom csum offset            21 | | ||||
|  *   22 |       (25:18)                   22 | | ||||
|  *   23 |                                 23 |   MSS (30:18) | ||||
|  *   24 |                                 24 | | ||||
|  *   25-+                                 25 | | ||||
|  *   26-+                                 26 | | ||||
|  *   27 |                                 27 | | ||||
|  *   28 |   Reserved                      28 | | ||||
|  *   29 |                                 29 | | ||||
|  *   30-+                                 30-+ | ||||
|  *   31     End of packet                 31     End of packet | ||||
|  */ | ||||
| struct alx_txd { | ||||
| 	__le16 len; | ||||
| 	__le16 vlan_tag; | ||||
| 	__le32 word1; | ||||
| 	union { | ||||
| 		__le64 addr; | ||||
| 		struct { | ||||
| 			__le32 pkt_len; | ||||
| 			__le32 resvd; | ||||
| 		} l; | ||||
| 	} adrl; | ||||
| } __packed; | ||||
| 
 | ||||
| /* tpd word 1 */ | ||||
| #define TPD_CXSUMSTART_MASK		0x00FF | ||||
| #define TPD_CXSUMSTART_SHIFT		0 | ||||
| #define TPD_L4HDROFFSET_MASK		0x00FF | ||||
| #define TPD_L4HDROFFSET_SHIFT		0 | ||||
| #define TPD_CXSUM_EN_MASK		0x0001 | ||||
| #define TPD_CXSUM_EN_SHIFT		8 | ||||
| #define TPD_IP_XSUM_MASK		0x0001 | ||||
| #define TPD_IP_XSUM_SHIFT		9 | ||||
| #define TPD_TCP_XSUM_MASK		0x0001 | ||||
| #define TPD_TCP_XSUM_SHIFT		10 | ||||
| #define TPD_UDP_XSUM_MASK		0x0001 | ||||
| #define TPD_UDP_XSUM_SHIFT		11 | ||||
| #define TPD_LSO_EN_MASK			0x0001 | ||||
| #define TPD_LSO_EN_SHIFT		12 | ||||
| #define TPD_LSO_V2_MASK			0x0001 | ||||
| #define TPD_LSO_V2_SHIFT		13 | ||||
| #define TPD_VLTAGGED_MASK		0x0001 | ||||
| #define TPD_VLTAGGED_SHIFT		14 | ||||
| #define TPD_INS_VLTAG_MASK		0x0001 | ||||
| #define TPD_INS_VLTAG_SHIFT		15 | ||||
| #define TPD_IPV4_MASK			0x0001 | ||||
| #define TPD_IPV4_SHIFT			16 | ||||
| #define TPD_ETHTYPE_MASK		0x0001 | ||||
| #define TPD_ETHTYPE_SHIFT		17 | ||||
| #define TPD_CXSUMOFFSET_MASK		0x00FF | ||||
| #define TPD_CXSUMOFFSET_SHIFT		18 | ||||
| #define TPD_MSS_MASK			0x1FFF | ||||
| #define TPD_MSS_SHIFT			18 | ||||
| #define TPD_EOP_MASK			0x0001 | ||||
| #define TPD_EOP_SHIFT			31 | ||||
| 
 | ||||
| #define DESC_GET(_x, _name) ((_x) >> _name##SHIFT & _name##MASK) | ||||
| 
 | ||||
| /* Receive Free Descriptor */ | ||||
| struct alx_rfd { | ||||
| 	__le64 addr;		/* data buffer address, length is
 | ||||
| 				 * declared in register --- every | ||||
| 				 * buffer has the same size | ||||
| 				 */ | ||||
| } __packed; | ||||
| 
 | ||||
| /* Receive Return Descriptor, contains 4 32-bit words.
 | ||||
|  * | ||||
|  *   31               16               0 | ||||
|  *   +----------------+----------------+ | ||||
|  *   |              Word 0             | | ||||
|  *   +----------------+----------------+ | ||||
|  *   |     Word 1: RSS Hash value      | | ||||
|  *   +----------------+----------------+ | ||||
|  *   |              Word 2             | | ||||
|  *   +----------------+----------------+ | ||||
|  *   |              Word 3             | | ||||
|  *   +----------------+----------------+ | ||||
|  * | ||||
|  * Word 0 depiction         &            Word 2 depiction: | ||||
|  * | ||||
|  *   0--+                                 0--+ | ||||
|  *   1  |                                 1  | | ||||
|  *   2  |                                 2  | | ||||
|  *   3  |                                 3  | | ||||
|  *   4  |                                 4  | | ||||
|  *   5  |                                 5  | | ||||
|  *   6  |                                 6  | | ||||
|  *   7  |    IP payload checksum          7  |     VLAN tag | ||||
|  *   8  |         (15:0)                  8  |      (15:0) | ||||
|  *   9  |                                 9  | | ||||
|  *   10 |                                 10 | | ||||
|  *   11 |                                 11 | | ||||
|  *   12 |                                 12 | | ||||
|  *   13 |                                 13 | | ||||
|  *   14 |                                 14 | | ||||
|  *   15-+                                 15-+ | ||||
|  *   16-+                                 16-+ | ||||
|  *   17 |     Number of RFDs              17 | | ||||
|  *   18 |        (19:16)                  18 | | ||||
|  *   19-+                                 19 |     Protocol ID | ||||
|  *   20-+                                 20 |      (23:16) | ||||
|  *   21 |                                 21 | | ||||
|  *   22 |                                 22 | | ||||
|  *   23 |                                 23-+ | ||||
|  *   24 |                                 24 |     Reserved | ||||
|  *   25 |     Start index of RFD-ring     25-+ | ||||
|  *   26 |         (31:20)                 26 |     RSS Q-num (27:25) | ||||
|  *   27 |                                 27-+ | ||||
|  *   28 |                                 28-+ | ||||
|  *   29 |                                 29 |     RSS Hash algorithm | ||||
|  *   30 |                                 30 |      (31:28) | ||||
|  *   31-+                                 31-+ | ||||
|  * | ||||
|  * Word 3 depiction: | ||||
|  * | ||||
|  *   0--+ | ||||
|  *   1  | | ||||
|  *   2  | | ||||
|  *   3  | | ||||
|  *   4  | | ||||
|  *   5  | | ||||
|  *   6  | | ||||
|  *   7  |    Packet length (include FCS) | ||||
|  *   8  |         (13:0) | ||||
|  *   9  | | ||||
|  *   10 | | ||||
|  *   11 | | ||||
|  *   12 | | ||||
|  *   13-+ | ||||
|  *   14      L4 Header checksum error | ||||
|  *   15      IPv4 checksum error | ||||
|  *   16      VLAN tagged | ||||
|  *   17-+ | ||||
|  *   18 |    Protocol ID (19:17) | ||||
|  *   19-+ | ||||
|  *   20      Receive error summary | ||||
|  *   21      FCS(CRC) error | ||||
|  *   22      Frame alignment error | ||||
|  *   23      Truncated packet | ||||
|  *   24      Runt packet | ||||
|  *   25      Incomplete packet due to insufficient rx-desc | ||||
|  *   26      Broadcast packet | ||||
|  *   27      Multicast packet | ||||
|  *   28      Ethernet type (EII or 802.3) | ||||
|  *   29      FIFO overflow | ||||
|  *   30      Length error (for 802.3, length field mismatch with actual len) | ||||
|  *   31      Updated, indicate to driver that this RRD is refreshed. | ||||
|  */ | ||||
| struct alx_rrd { | ||||
| 	__le32 word0; | ||||
| 	__le32 rss_hash; | ||||
| 	__le32 word2; | ||||
| 	__le32 word3; | ||||
| } __packed; | ||||
| 
 | ||||
| /* rrd word 0 */ | ||||
| #define RRD_XSUM_MASK		0xFFFF | ||||
| #define RRD_XSUM_SHIFT		0 | ||||
| #define RRD_NOR_MASK		0x000F | ||||
| #define RRD_NOR_SHIFT		16 | ||||
| #define RRD_SI_MASK		0x0FFF | ||||
| #define RRD_SI_SHIFT		20 | ||||
| 
 | ||||
| /* rrd word 2 */ | ||||
| #define RRD_VLTAG_MASK		0xFFFF | ||||
| #define RRD_VLTAG_SHIFT		0 | ||||
| #define RRD_PID_MASK		0x00FF | ||||
| #define RRD_PID_SHIFT		16 | ||||
| /* non-ip packet */ | ||||
| #define RRD_PID_NONIP		0 | ||||
| /* ipv4(only) */ | ||||
| #define RRD_PID_IPV4		1 | ||||
| /* tcp/ipv6 */ | ||||
| #define RRD_PID_IPV6TCP		2 | ||||
| /* tcp/ipv4 */ | ||||
| #define RRD_PID_IPV4TCP		3 | ||||
| /* udp/ipv6 */ | ||||
| #define RRD_PID_IPV6UDP		4 | ||||
| /* udp/ipv4 */ | ||||
| #define RRD_PID_IPV4UDP		5 | ||||
| /* ipv6(only) */ | ||||
| #define RRD_PID_IPV6		6 | ||||
| /* LLDP packet */ | ||||
| #define RRD_PID_LLDP		7 | ||||
| /* 1588 packet */ | ||||
| #define RRD_PID_1588		8 | ||||
| #define RRD_RSSQ_MASK		0x0007 | ||||
| #define RRD_RSSQ_SHIFT		25 | ||||
| #define RRD_RSSALG_MASK		0x000F | ||||
| #define RRD_RSSALG_SHIFT	28 | ||||
| #define RRD_RSSALG_TCPV6	0x1 | ||||
| #define RRD_RSSALG_IPV6		0x2 | ||||
| #define RRD_RSSALG_TCPV4	0x4 | ||||
| #define RRD_RSSALG_IPV4		0x8 | ||||
| 
 | ||||
| /* rrd word 3 */ | ||||
| #define RRD_PKTLEN_MASK		0x3FFF | ||||
| #define RRD_PKTLEN_SHIFT	0 | ||||
| #define RRD_ERR_L4_MASK		0x0001 | ||||
| #define RRD_ERR_L4_SHIFT	14 | ||||
| #define RRD_ERR_IPV4_MASK	0x0001 | ||||
| #define RRD_ERR_IPV4_SHIFT	15 | ||||
| #define RRD_VLTAGGED_MASK	0x0001 | ||||
| #define RRD_VLTAGGED_SHIFT	16 | ||||
| #define RRD_OLD_PID_MASK	0x0007 | ||||
| #define RRD_OLD_PID_SHIFT	17 | ||||
| #define RRD_ERR_RES_MASK	0x0001 | ||||
| #define RRD_ERR_RES_SHIFT	20 | ||||
| #define RRD_ERR_FCS_MASK	0x0001 | ||||
| #define RRD_ERR_FCS_SHIFT	21 | ||||
| #define RRD_ERR_FAE_MASK	0x0001 | ||||
| #define RRD_ERR_FAE_SHIFT	22 | ||||
| #define RRD_ERR_TRUNC_MASK	0x0001 | ||||
| #define RRD_ERR_TRUNC_SHIFT	23 | ||||
| #define RRD_ERR_RUNT_MASK	0x0001 | ||||
| #define RRD_ERR_RUNT_SHIFT	24 | ||||
| #define RRD_ERR_ICMP_MASK	0x0001 | ||||
| #define RRD_ERR_ICMP_SHIFT	25 | ||||
| #define RRD_BCAST_MASK		0x0001 | ||||
| #define RRD_BCAST_SHIFT		26 | ||||
| #define RRD_MCAST_MASK		0x0001 | ||||
| #define RRD_MCAST_SHIFT		27 | ||||
| #define RRD_ETHTYPE_MASK	0x0001 | ||||
| #define RRD_ETHTYPE_SHIFT	28 | ||||
| #define RRD_ERR_FIFOV_MASK	0x0001 | ||||
| #define RRD_ERR_FIFOV_SHIFT	29 | ||||
| #define RRD_ERR_LEN_MASK	0x0001 | ||||
| #define RRD_ERR_LEN_SHIFT	30 | ||||
| #define RRD_UPDATED_MASK	0x0001 | ||||
| #define RRD_UPDATED_SHIFT	31 | ||||
| 
 | ||||
| 
 | ||||
| #define ALX_MAX_SETUP_LNK_CYCLE	50 | ||||
| 
 | ||||
| /* for FlowControl */ | ||||
| #define ALX_FC_RX		0x01 | ||||
| #define ALX_FC_TX		0x02 | ||||
| #define ALX_FC_ANEG		0x04 | ||||
| 
 | ||||
| /* for sleep control */ | ||||
| #define ALX_SLEEP_WOL_PHY	0x00000001 | ||||
| #define ALX_SLEEP_WOL_MAGIC	0x00000002 | ||||
| #define ALX_SLEEP_CIFS		0x00000004 | ||||
| #define ALX_SLEEP_ACTIVE	(ALX_SLEEP_WOL_PHY | \ | ||||
| 				 ALX_SLEEP_WOL_MAGIC | \ | ||||
| 				 ALX_SLEEP_CIFS) | ||||
| 
 | ||||
| /* for RSS hash type */ | ||||
| #define ALX_RSS_HASH_TYPE_IPV4		0x1 | ||||
| #define ALX_RSS_HASH_TYPE_IPV4_TCP	0x2 | ||||
| #define ALX_RSS_HASH_TYPE_IPV6		0x4 | ||||
| #define ALX_RSS_HASH_TYPE_IPV6_TCP	0x8 | ||||
| #define ALX_RSS_HASH_TYPE_ALL		(ALX_RSS_HASH_TYPE_IPV4 | \ | ||||
| 					 ALX_RSS_HASH_TYPE_IPV4_TCP | \ | ||||
| 					 ALX_RSS_HASH_TYPE_IPV6 | \ | ||||
| 					 ALX_RSS_HASH_TYPE_IPV6_TCP) | ||||
| #define ALX_DEF_RXBUF_SIZE	1536 | ||||
| #define ALX_MAX_JUMBO_PKT_SIZE	(9*1024) | ||||
| #define ALX_MAX_TSO_PKT_SIZE	(7*1024) | ||||
| #define ALX_MAX_FRAME_SIZE	ALX_MAX_JUMBO_PKT_SIZE | ||||
| #define ALX_MIN_FRAME_SIZE	68 | ||||
| #define ALX_RAW_MTU(_mtu)	(_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN) | ||||
| 
 | ||||
| #define ALX_MAX_RX_QUEUES	8 | ||||
| #define ALX_MAX_TX_QUEUES	4 | ||||
| #define ALX_MAX_HANDLED_INTRS	5 | ||||
| 
 | ||||
| #define ALX_ISR_MISC		(ALX_ISR_PCIE_LNKDOWN | \ | ||||
| 				 ALX_ISR_DMAW | \ | ||||
| 				 ALX_ISR_DMAR | \ | ||||
| 				 ALX_ISR_SMB | \ | ||||
| 				 ALX_ISR_MANU | \ | ||||
| 				 ALX_ISR_TIMER) | ||||
| 
 | ||||
| #define ALX_ISR_FATAL		(ALX_ISR_PCIE_LNKDOWN | \ | ||||
| 				 ALX_ISR_DMAW | ALX_ISR_DMAR) | ||||
| 
 | ||||
| #define ALX_ISR_ALERT		(ALX_ISR_RXF_OV | \ | ||||
| 				 ALX_ISR_TXF_UR | \ | ||||
| 				 ALX_ISR_RFD_UR) | ||||
| 
 | ||||
| #define ALX_ISR_ALL_QUEUES	(ALX_ISR_TX_Q0 | \ | ||||
| 				 ALX_ISR_TX_Q1 | \ | ||||
| 				 ALX_ISR_TX_Q2 | \ | ||||
| 				 ALX_ISR_TX_Q3 | \ | ||||
| 				 ALX_ISR_RX_Q0 | \ | ||||
| 				 ALX_ISR_RX_Q1 | \ | ||||
| 				 ALX_ISR_RX_Q2 | \ | ||||
| 				 ALX_ISR_RX_Q3 | \ | ||||
| 				 ALX_ISR_RX_Q4 | \ | ||||
| 				 ALX_ISR_RX_Q5 | \ | ||||
| 				 ALX_ISR_RX_Q6 | \ | ||||
| 				 ALX_ISR_RX_Q7) | ||||
| 
 | ||||
| /* Statistics counters collected by the MAC
 | ||||
|  * | ||||
|  * The order of the fields must match the strings in alx_gstrings_stats | ||||
|  * All stats fields should be u64 | ||||
|  * See ethtool.c | ||||
|  */ | ||||
| struct alx_hw_stats { | ||||
| 	/* rx */ | ||||
| 	u64 rx_ok;		/* good RX packets */ | ||||
| 	u64 rx_bcast;		/* good RX broadcast packets */ | ||||
| 	u64 rx_mcast;		/* good RX multicast packets */ | ||||
| 	u64 rx_pause;		/* RX pause frames */ | ||||
| 	u64 rx_ctrl;		/* RX control packets other than pause frames */ | ||||
| 	u64 rx_fcs_err;		/* RX packets with bad FCS */ | ||||
| 	u64 rx_len_err;		/* RX packets with length != actual size */ | ||||
| 	u64 rx_byte_cnt;	/* good bytes received. FCS is NOT included */ | ||||
| 	u64 rx_runt;		/* RX packets < 64 bytes with good FCS */ | ||||
| 	u64 rx_frag;		/* RX packets < 64 bytes with bad FCS */ | ||||
| 	u64 rx_sz_64B;		/* 64 byte RX packets */ | ||||
| 	u64 rx_sz_127B;		/* 65-127 byte RX packets */ | ||||
| 	u64 rx_sz_255B;		/* 128-255 byte RX packets */ | ||||
| 	u64 rx_sz_511B;		/* 256-511 byte RX packets */ | ||||
| 	u64 rx_sz_1023B;	/* 512-1023 byte RX packets */ | ||||
| 	u64 rx_sz_1518B;	/* 1024-1518 byte RX packets */ | ||||
| 	u64 rx_sz_max;		/* 1519 byte to MTU RX packets */ | ||||
| 	u64 rx_ov_sz;		/* truncated RX packets, size > MTU */ | ||||
| 	u64 rx_ov_rxf;		/* frames dropped due to RX FIFO overflow */ | ||||
| 	u64 rx_ov_rrd;		/* frames dropped due to RRD overflow */ | ||||
| 	u64 rx_align_err;	/* alignment errors */ | ||||
| 	u64 rx_bc_byte_cnt;	/* RX broadcast bytes, excluding FCS */ | ||||
| 	u64 rx_mc_byte_cnt;	/* RX multicast bytes, excluding FCS */ | ||||
| 	u64 rx_err_addr;	/* packets dropped due to address filtering */ | ||||
| 
 | ||||
| 	/* tx */ | ||||
| 	u64 tx_ok;		/* good TX packets */ | ||||
| 	u64 tx_bcast;		/* good TX broadcast packets */ | ||||
| 	u64 tx_mcast;		/* good TX multicast packets */ | ||||
| 	u64 tx_pause;		/* TX pause frames */ | ||||
| 	u64 tx_exc_defer;	/* TX packets deferred excessively */ | ||||
| 	u64 tx_ctrl;		/* TX control frames, excluding pause frames */ | ||||
| 	u64 tx_defer;		/* TX packets deferred */ | ||||
| 	u64 tx_byte_cnt;	/* bytes transmitted, FCS is NOT included */ | ||||
| 	u64 tx_sz_64B;		/* 64 byte TX packets */ | ||||
| 	u64 tx_sz_127B;		/* 65-127 byte TX packets */ | ||||
| 	u64 tx_sz_255B;		/* 128-255 byte TX packets */ | ||||
| 	u64 tx_sz_511B;		/* 256-511 byte TX packets */ | ||||
| 	u64 tx_sz_1023B;	/* 512-1023 byte TX packets */ | ||||
| 	u64 tx_sz_1518B;	/* 1024-1518 byte TX packets */ | ||||
| 	u64 tx_sz_max;		/* 1519 byte to MTU TX packets */ | ||||
| 	u64 tx_single_col;	/* packets TX after a single collision */ | ||||
| 	u64 tx_multi_col;	/* packets TX after multiple collisions */ | ||||
| 	u64 tx_late_col;	/* TX packets with late collisions */ | ||||
| 	u64 tx_abort_col;	/* TX packets aborted w/excessive collisions */ | ||||
| 	u64 tx_underrun;	/* TX packets aborted due to TX FIFO underrun
 | ||||
| 				 * or TRD FIFO underrun | ||||
| 				 */ | ||||
| 	u64 tx_trd_eop;		/* reads beyond the EOP into the next frame
 | ||||
| 				 * when TRD was not written timely | ||||
| 				 */ | ||||
| 	u64 tx_len_err;		/* TX packets where length != actual size */ | ||||
| 	u64 tx_trunc;		/* TX packets truncated due to size > MTU */ | ||||
| 	u64 tx_bc_byte_cnt;	/* broadcast bytes transmitted, excluding FCS */ | ||||
| 	u64 tx_mc_byte_cnt;	/* multicast bytes transmitted, excluding FCS */ | ||||
| 	u64 update; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /* maximum interrupt vectors for msix */ | ||||
| #define ALX_MAX_MSIX_INTRS	16 | ||||
| 
 | ||||
| #define ALX_GET_FIELD(_data, _field)					\ | ||||
| 	(((_data) >> _field ## _SHIFT) & _field ## _MASK) | ||||
| 
 | ||||
| #define ALX_SET_FIELD(_data, _field, _value)	do {			\ | ||||
| 		(_data) &= ~(_field ## _MASK << _field ## _SHIFT);	\ | ||||
| 		(_data) |= ((_value) & _field ## _MASK) << _field ## _SHIFT;\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| struct alx_hw { | ||||
| 	struct pci_dev *pdev; | ||||
| 	u8 __iomem *hw_addr; | ||||
| 
 | ||||
| 	/* current & permanent mac addr */ | ||||
| 	u8 mac_addr[ETH_ALEN]; | ||||
| 	u8 perm_addr[ETH_ALEN]; | ||||
| 
 | ||||
| 	u16 mtu; | ||||
| 	u16 imt; | ||||
| 	u8 dma_chnl; | ||||
| 	u8 max_dma_chnl; | ||||
| 	/* tpd threshold to trig INT */ | ||||
| 	u32 ith_tpd; | ||||
| 	u32 rx_ctrl; | ||||
| 	u32 mc_hash[2]; | ||||
| 
 | ||||
| 	u32 smb_timer; | ||||
| 	/* SPEED_* + DUPLEX_*, SPEED_UNKNOWN if link is down */ | ||||
| 	int link_speed; | ||||
| 	u8 duplex; | ||||
| 
 | ||||
| 	/* auto-neg advertisement or force mode config */ | ||||
| 	u8 flowctrl; | ||||
| 	u32 adv_cfg; | ||||
| 
 | ||||
| 	spinlock_t mdio_lock; | ||||
| 	struct mdio_if_info mdio; | ||||
| 	u16 phy_id[2]; | ||||
| 
 | ||||
| 	/* PHY link patch flag */ | ||||
| 	bool lnk_patch; | ||||
| 
 | ||||
| 	/* cumulated stats from the hardware (registers are cleared on read) */ | ||||
| 	struct alx_hw_stats stats; | ||||
| }; | ||||
| 
 | ||||
| static inline int alx_hw_revision(struct alx_hw *hw) | ||||
| { | ||||
| 	return hw->pdev->revision >> ALX_PCI_REVID_SHIFT; | ||||
| } | ||||
| 
 | ||||
| static inline bool alx_hw_with_cr(struct alx_hw *hw) | ||||
| { | ||||
| 	return hw->pdev->revision & 1; | ||||
| } | ||||
| 
 | ||||
| static inline bool alx_hw_giga(struct alx_hw *hw) | ||||
| { | ||||
| 	return hw->pdev->device & 1; | ||||
| } | ||||
| 
 | ||||
| static inline void alx_write_mem8(struct alx_hw *hw, u32 reg, u8 val) | ||||
| { | ||||
| 	writeb(val, hw->hw_addr + reg); | ||||
| } | ||||
| 
 | ||||
| static inline void alx_write_mem16(struct alx_hw *hw, u32 reg, u16 val) | ||||
| { | ||||
| 	writew(val, hw->hw_addr + reg); | ||||
| } | ||||
| 
 | ||||
| static inline u16 alx_read_mem16(struct alx_hw *hw, u32 reg) | ||||
| { | ||||
| 	return readw(hw->hw_addr + reg); | ||||
| } | ||||
| 
 | ||||
| static inline void alx_write_mem32(struct alx_hw *hw, u32 reg, u32 val) | ||||
| { | ||||
| 	writel(val, hw->hw_addr + reg); | ||||
| } | ||||
| 
 | ||||
| static inline u32 alx_read_mem32(struct alx_hw *hw, u32 reg) | ||||
| { | ||||
| 	return readl(hw->hw_addr + reg); | ||||
| } | ||||
| 
 | ||||
| static inline void alx_post_write(struct alx_hw *hw) | ||||
| { | ||||
| 	readl(hw->hw_addr); | ||||
| } | ||||
| 
 | ||||
| int alx_get_perm_macaddr(struct alx_hw *hw, u8 *addr); | ||||
| void alx_reset_phy(struct alx_hw *hw); | ||||
| void alx_reset_pcie(struct alx_hw *hw); | ||||
| void alx_enable_aspm(struct alx_hw *hw, bool l0s_en, bool l1_en); | ||||
| int alx_setup_speed_duplex(struct alx_hw *hw, u32 ethadv, u8 flowctrl); | ||||
| void alx_post_phy_link(struct alx_hw *hw); | ||||
| int alx_read_phy_reg(struct alx_hw *hw, u16 reg, u16 *phy_data); | ||||
| int alx_write_phy_reg(struct alx_hw *hw, u16 reg, u16 phy_data); | ||||
| int alx_read_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 *pdata); | ||||
| int alx_write_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 data); | ||||
| int alx_read_phy_link(struct alx_hw *hw); | ||||
| int alx_clear_phy_intr(struct alx_hw *hw); | ||||
| void alx_cfg_mac_flowcontrol(struct alx_hw *hw, u8 fc); | ||||
| void alx_start_mac(struct alx_hw *hw); | ||||
| int alx_reset_mac(struct alx_hw *hw); | ||||
| void alx_set_macaddr(struct alx_hw *hw, const u8 *addr); | ||||
| bool alx_phy_configured(struct alx_hw *hw); | ||||
| void alx_configure_basic(struct alx_hw *hw); | ||||
| void alx_disable_rss(struct alx_hw *hw); | ||||
| bool alx_get_phy_info(struct alx_hw *hw); | ||||
| void alx_update_hw_stats(struct alx_hw *hw); | ||||
| 
 | ||||
| static inline u32 alx_speed_to_ethadv(int speed, u8 duplex) | ||||
| { | ||||
| 	if (speed == SPEED_1000 && duplex == DUPLEX_FULL) | ||||
| 		return ADVERTISED_1000baseT_Full; | ||||
| 	if (speed == SPEED_100 && duplex == DUPLEX_FULL) | ||||
| 		return ADVERTISED_100baseT_Full; | ||||
| 	if (speed == SPEED_100 && duplex== DUPLEX_HALF) | ||||
| 		return ADVERTISED_100baseT_Half; | ||||
| 	if (speed == SPEED_10 && duplex == DUPLEX_FULL) | ||||
| 		return ADVERTISED_10baseT_Full; | ||||
| 	if (speed == SPEED_10 && duplex == DUPLEX_HALF) | ||||
| 		return ADVERTISED_10baseT_Half; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										1559
									
								
								drivers/net/ethernet/atheros/alx/main.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1559
									
								
								drivers/net/ethernet/atheros/alx/main.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										854
									
								
								drivers/net/ethernet/atheros/alx/reg.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										854
									
								
								drivers/net/ethernet/atheros/alx/reg.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,854 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2013 Johannes Berg <johannes@sipsolutions.net> | ||||
|  * | ||||
|  *  This file is free software: you may copy, redistribute and/or modify it | ||||
|  *  under the terms of the GNU General Public License as published by the | ||||
|  *  Free Software Foundation, either version 2 of the License, or (at your | ||||
|  *  option) any later version. | ||||
|  * | ||||
|  *  This file is distributed in the hope that it will be useful, but | ||||
|  *  WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  *  General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * | ||||
|  * This file incorporates work covered by the following copyright and | ||||
|  * permission notice: | ||||
|  * | ||||
|  * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||||
|  * | ||||
|  * Permission to use, copy, modify, and/or distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef ALX_REG_H | ||||
| #define ALX_REG_H | ||||
| 
 | ||||
| #define ALX_DEV_ID_AR8161				0x1091 | ||||
| #define ALX_DEV_ID_E2200				0xe091 | ||||
| #define ALX_DEV_ID_AR8162				0x1090 | ||||
| #define ALX_DEV_ID_AR8171				0x10A1 | ||||
| #define ALX_DEV_ID_AR8172				0x10A0 | ||||
| 
 | ||||
| /* rev definition,
 | ||||
|  * bit(0): with xD support | ||||
|  * bit(1): with Card Reader function | ||||
|  * bit(7:2): real revision | ||||
|  */ | ||||
| #define ALX_PCI_REVID_SHIFT				3 | ||||
| #define ALX_REV_A0					0 | ||||
| #define ALX_REV_A1					1 | ||||
| #define ALX_REV_B0					2 | ||||
| #define ALX_REV_C0					3 | ||||
| 
 | ||||
| #define ALX_DEV_CTRL					0x0060 | ||||
| #define ALX_DEV_CTRL_MAXRRS_MIN				2 | ||||
| 
 | ||||
| #define ALX_MSIX_MASK					0x0090 | ||||
| 
 | ||||
| #define ALX_UE_SVRT					0x010C | ||||
| #define ALX_UE_SVRT_FCPROTERR				BIT(13) | ||||
| #define ALX_UE_SVRT_DLPROTERR				BIT(4) | ||||
| 
 | ||||
| /* eeprom & flash load register */ | ||||
| #define ALX_EFLD					0x0204 | ||||
| #define ALX_EFLD_F_EXIST				BIT(10) | ||||
| #define ALX_EFLD_E_EXIST				BIT(9) | ||||
| #define ALX_EFLD_STAT					BIT(5) | ||||
| #define ALX_EFLD_START					BIT(0) | ||||
| 
 | ||||
| /* eFuse load register */ | ||||
| #define ALX_SLD						0x0218 | ||||
| #define ALX_SLD_STAT					BIT(12) | ||||
| #define ALX_SLD_START					BIT(11) | ||||
| #define ALX_SLD_MAX_TO					100 | ||||
| 
 | ||||
| #define ALX_PDLL_TRNS1					0x1104 | ||||
| #define ALX_PDLL_TRNS1_D3PLLOFF_EN			BIT(11) | ||||
| 
 | ||||
| #define ALX_PMCTRL					0x12F8 | ||||
| #define ALX_PMCTRL_HOTRST_WTEN				BIT(31) | ||||
| /* bit30: L0s/L1 controlled by MAC based on throughput(setting in 15A0) */ | ||||
| #define ALX_PMCTRL_ASPM_FCEN				BIT(30) | ||||
| #define ALX_PMCTRL_SADLY_EN				BIT(29) | ||||
| #define ALX_PMCTRL_LCKDET_TIMER_MASK			0xF | ||||
| #define ALX_PMCTRL_LCKDET_TIMER_SHIFT			24 | ||||
| #define ALX_PMCTRL_LCKDET_TIMER_DEF			0xC | ||||
| /* bit[23:20] if pm_request_l1 time > @, then enter L0s not L1 */ | ||||
| #define ALX_PMCTRL_L1REQ_TO_MASK			0xF | ||||
| #define ALX_PMCTRL_L1REQ_TO_SHIFT			20 | ||||
| #define ALX_PMCTRL_L1REG_TO_DEF				0xF | ||||
| #define ALX_PMCTRL_TXL1_AFTER_L0S			BIT(19) | ||||
| #define ALX_PMCTRL_L1_TIMER_MASK			0x7 | ||||
| #define ALX_PMCTRL_L1_TIMER_SHIFT			16 | ||||
| #define ALX_PMCTRL_L1_TIMER_16US			4 | ||||
| #define ALX_PMCTRL_RCVR_WT_1US				BIT(15) | ||||
| /* bit13: enable pcie clk switch in L1 state */ | ||||
| #define ALX_PMCTRL_L1_CLKSW_EN				BIT(13) | ||||
| #define ALX_PMCTRL_L0S_EN				BIT(12) | ||||
| #define ALX_PMCTRL_RXL1_AFTER_L0S			BIT(11) | ||||
| #define ALX_PMCTRL_L1_BUFSRX_EN				BIT(7) | ||||
| /* bit6: power down serdes RX */ | ||||
| #define ALX_PMCTRL_L1_SRDSRX_PWD			BIT(6) | ||||
| #define ALX_PMCTRL_L1_SRDSPLL_EN			BIT(5) | ||||
| #define ALX_PMCTRL_L1_SRDS_EN				BIT(4) | ||||
| #define ALX_PMCTRL_L1_EN				BIT(3) | ||||
| 
 | ||||
| /*******************************************************/ | ||||
| /* following registers are mapped only to memory space */ | ||||
| /*******************************************************/ | ||||
| 
 | ||||
| #define ALX_MASTER					0x1400 | ||||
| /* bit12: 1:alwys select pclk from serdes, not sw to 25M */ | ||||
| #define ALX_MASTER_PCLKSEL_SRDS				BIT(12) | ||||
| /* bit11: irq moduration for rx */ | ||||
| #define ALX_MASTER_IRQMOD2_EN				BIT(11) | ||||
| /* bit10: irq moduration for tx/rx */ | ||||
| #define ALX_MASTER_IRQMOD1_EN				BIT(10) | ||||
| #define ALX_MASTER_SYSALVTIMER_EN			BIT(7) | ||||
| #define ALX_MASTER_OOB_DIS				BIT(6) | ||||
| /* bit5: wakeup without pcie clk */ | ||||
| #define ALX_MASTER_WAKEN_25M				BIT(5) | ||||
| /* bit0: MAC & DMA reset */ | ||||
| #define ALX_MASTER_DMA_MAC_RST				BIT(0) | ||||
| #define ALX_DMA_MAC_RST_TO				50 | ||||
| 
 | ||||
| #define ALX_IRQ_MODU_TIMER				0x1408 | ||||
| #define ALX_IRQ_MODU_TIMER1_MASK			0xFFFF | ||||
| #define ALX_IRQ_MODU_TIMER1_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_PHY_CTRL					0x140C | ||||
| #define ALX_PHY_CTRL_100AB_EN				BIT(17) | ||||
| /* bit14: affect MAC & PHY, go to low power sts */ | ||||
| #define ALX_PHY_CTRL_POWER_DOWN				BIT(14) | ||||
| /* bit13: 1:pll always ON, 0:can switch in lpw */ | ||||
| #define ALX_PHY_CTRL_PLL_ON				BIT(13) | ||||
| #define ALX_PHY_CTRL_RST_ANALOG				BIT(12) | ||||
| #define ALX_PHY_CTRL_HIB_PULSE				BIT(11) | ||||
| #define ALX_PHY_CTRL_HIB_EN				BIT(10) | ||||
| #define ALX_PHY_CTRL_IDDQ				BIT(7) | ||||
| #define ALX_PHY_CTRL_GATE_25M				BIT(5) | ||||
| #define ALX_PHY_CTRL_LED_MODE				BIT(2) | ||||
| /* bit0: out of dsp RST state */ | ||||
| #define ALX_PHY_CTRL_DSPRST_OUT				BIT(0) | ||||
| #define ALX_PHY_CTRL_DSPRST_TO				80 | ||||
| #define ALX_PHY_CTRL_CLS	(ALX_PHY_CTRL_LED_MODE | \ | ||||
| 				 ALX_PHY_CTRL_100AB_EN | \ | ||||
| 				 ALX_PHY_CTRL_PLL_ON) | ||||
| 
 | ||||
| #define ALX_MAC_STS					0x1410 | ||||
| #define ALX_MAC_STS_TXQ_BUSY				BIT(3) | ||||
| #define ALX_MAC_STS_RXQ_BUSY				BIT(2) | ||||
| #define ALX_MAC_STS_TXMAC_BUSY				BIT(1) | ||||
| #define ALX_MAC_STS_RXMAC_BUSY				BIT(0) | ||||
| #define ALX_MAC_STS_IDLE	(ALX_MAC_STS_TXQ_BUSY | \ | ||||
| 				 ALX_MAC_STS_RXQ_BUSY | \ | ||||
| 				 ALX_MAC_STS_TXMAC_BUSY | \ | ||||
| 				 ALX_MAC_STS_RXMAC_BUSY) | ||||
| 
 | ||||
| #define ALX_MDIO					0x1414 | ||||
| #define ALX_MDIO_MODE_EXT				BIT(30) | ||||
| #define ALX_MDIO_BUSY					BIT(27) | ||||
| #define ALX_MDIO_CLK_SEL_MASK				0x7 | ||||
| #define ALX_MDIO_CLK_SEL_SHIFT				24 | ||||
| #define ALX_MDIO_CLK_SEL_25MD4				0 | ||||
| #define ALX_MDIO_CLK_SEL_25MD128			7 | ||||
| #define ALX_MDIO_START					BIT(23) | ||||
| #define ALX_MDIO_SPRES_PRMBL				BIT(22) | ||||
| /* bit21: 1:read,0:write */ | ||||
| #define ALX_MDIO_OP_READ				BIT(21) | ||||
| #define ALX_MDIO_REG_MASK				0x1F | ||||
| #define ALX_MDIO_REG_SHIFT				16 | ||||
| #define ALX_MDIO_DATA_MASK				0xFFFF | ||||
| #define ALX_MDIO_DATA_SHIFT				0 | ||||
| #define ALX_MDIO_MAX_AC_TO				120 | ||||
| 
 | ||||
| #define ALX_MDIO_EXTN					0x1448 | ||||
| #define ALX_MDIO_EXTN_DEVAD_MASK			0x1F | ||||
| #define ALX_MDIO_EXTN_DEVAD_SHIFT			16 | ||||
| #define ALX_MDIO_EXTN_REG_MASK				0xFFFF | ||||
| #define ALX_MDIO_EXTN_REG_SHIFT				0 | ||||
| 
 | ||||
| #define ALX_SERDES					0x1424 | ||||
| #define ALX_SERDES_PHYCLK_SLWDWN			BIT(18) | ||||
| #define ALX_SERDES_MACCLK_SLWDWN			BIT(17) | ||||
| 
 | ||||
| #define ALX_LPI_CTRL					0x1440 | ||||
| #define ALX_LPI_CTRL_EN					BIT(0) | ||||
| 
 | ||||
| /* for B0+, bit[13..] for C0+ */ | ||||
| #define ALX_HRTBT_EXT_CTRL				0x1AD0 | ||||
| #define L1F_HRTBT_EXT_CTRL_PERIOD_HIGH_MASK		0x3F | ||||
| #define L1F_HRTBT_EXT_CTRL_PERIOD_HIGH_SHIFT		24 | ||||
| #define L1F_HRTBT_EXT_CTRL_SWOI_STARTUP_PKT_EN		BIT(23) | ||||
| #define L1F_HRTBT_EXT_CTRL_IOAC_2_FRAGMENTED		BIT(22) | ||||
| #define L1F_HRTBT_EXT_CTRL_IOAC_1_FRAGMENTED		BIT(21) | ||||
| #define L1F_HRTBT_EXT_CTRL_IOAC_1_KEEPALIVE_EN		BIT(20) | ||||
| #define L1F_HRTBT_EXT_CTRL_IOAC_1_HAS_VLAN		BIT(19) | ||||
| #define L1F_HRTBT_EXT_CTRL_IOAC_1_IS_8023		BIT(18) | ||||
| #define L1F_HRTBT_EXT_CTRL_IOAC_1_IS_IPV6		BIT(17) | ||||
| #define L1F_HRTBT_EXT_CTRL_IOAC_2_KEEPALIVE_EN		BIT(16) | ||||
| #define L1F_HRTBT_EXT_CTRL_IOAC_2_HAS_VLAN		BIT(15) | ||||
| #define L1F_HRTBT_EXT_CTRL_IOAC_2_IS_8023		BIT(14) | ||||
| #define L1F_HRTBT_EXT_CTRL_IOAC_2_IS_IPV6		BIT(13) | ||||
| #define ALX_HRTBT_EXT_CTRL_NS_EN			BIT(12) | ||||
| #define ALX_HRTBT_EXT_CTRL_FRAG_LEN_MASK		0xFF | ||||
| #define ALX_HRTBT_EXT_CTRL_FRAG_LEN_SHIFT		4 | ||||
| #define ALX_HRTBT_EXT_CTRL_IS_8023			BIT(3) | ||||
| #define ALX_HRTBT_EXT_CTRL_IS_IPV6			BIT(2) | ||||
| #define ALX_HRTBT_EXT_CTRL_WAKEUP_EN			BIT(1) | ||||
| #define ALX_HRTBT_EXT_CTRL_ARP_EN			BIT(0) | ||||
| 
 | ||||
| #define ALX_HRTBT_REM_IPV4_ADDR				0x1AD4 | ||||
| #define ALX_HRTBT_HOST_IPV4_ADDR			0x1478 | ||||
| #define ALX_HRTBT_REM_IPV6_ADDR3			0x1AD8 | ||||
| #define ALX_HRTBT_REM_IPV6_ADDR2			0x1ADC | ||||
| #define ALX_HRTBT_REM_IPV6_ADDR1			0x1AE0 | ||||
| #define ALX_HRTBT_REM_IPV6_ADDR0			0x1AE4 | ||||
| 
 | ||||
| /* 1B8C ~ 1B94 for C0+ */ | ||||
| #define ALX_SWOI_ACER_CTRL				0x1B8C | ||||
| #define ALX_SWOI_ORIG_ACK_NAK_EN			BIT(20) | ||||
| #define ALX_SWOI_ORIG_ACK_NAK_PKT_LEN_MASK		0XFF | ||||
| #define ALX_SWOI_ORIG_ACK_NAK_PKT_LEN_SHIFT		12 | ||||
| #define ALX_SWOI_ORIG_ACK_ADDR_MASK			0XFFF | ||||
| #define ALX_SWOI_ORIG_ACK_ADDR_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_SWOI_IOAC_CTRL_2				0x1B90 | ||||
| #define ALX_SWOI_IOAC_CTRL_2_SWOI_1_FRAG_LEN_MASK	0xFF | ||||
| #define ALX_SWOI_IOAC_CTRL_2_SWOI_1_FRAG_LEN_SHIFT	24 | ||||
| #define ALX_SWOI_IOAC_CTRL_2_SWOI_1_PKT_LEN_MASK	0xFFF | ||||
| #define ALX_SWOI_IOAC_CTRL_2_SWOI_1_PKT_LEN_SHIFT	12 | ||||
| #define ALX_SWOI_IOAC_CTRL_2_SWOI_1_HDR_ADDR_MASK	0xFFF | ||||
| #define ALX_SWOI_IOAC_CTRL_2_SWOI_1_HDR_ADDR_SHIFT	0 | ||||
| 
 | ||||
| #define ALX_SWOI_IOAC_CTRL_3				0x1B94 | ||||
| #define ALX_SWOI_IOAC_CTRL_3_SWOI_2_FRAG_LEN_MASK	0xFF | ||||
| #define ALX_SWOI_IOAC_CTRL_3_SWOI_2_FRAG_LEN_SHIFT	24 | ||||
| #define ALX_SWOI_IOAC_CTRL_3_SWOI_2_PKT_LEN_MASK	0xFFF | ||||
| #define ALX_SWOI_IOAC_CTRL_3_SWOI_2_PKT_LEN_SHIFT	12 | ||||
| #define ALX_SWOI_IOAC_CTRL_3_SWOI_2_HDR_ADDR_MASK	0xFFF | ||||
| #define ALX_SWOI_IOAC_CTRL_3_SWOI_2_HDR_ADDR_SHIFT	0 | ||||
| 
 | ||||
| /* for B0 */ | ||||
| #define ALX_IDLE_DECISN_TIMER				0x1474 | ||||
| /* 1ms */ | ||||
| #define ALX_IDLE_DECISN_TIMER_DEF			0x400 | ||||
| 
 | ||||
| #define ALX_MAC_CTRL					0x1480 | ||||
| #define ALX_MAC_CTRL_FAST_PAUSE				BIT(31) | ||||
| #define ALX_MAC_CTRL_WOLSPED_SWEN			BIT(30) | ||||
| /* bit29: 1:legacy(hi5b), 0:marvl(lo5b)*/ | ||||
| #define ALX_MAC_CTRL_MHASH_ALG_HI5B			BIT(29) | ||||
| #define ALX_MAC_CTRL_BRD_EN				BIT(26) | ||||
| #define ALX_MAC_CTRL_MULTIALL_EN			BIT(25) | ||||
| #define ALX_MAC_CTRL_SPEED_MASK				0x3 | ||||
| #define ALX_MAC_CTRL_SPEED_SHIFT			20 | ||||
| #define ALX_MAC_CTRL_SPEED_10_100			1 | ||||
| #define ALX_MAC_CTRL_SPEED_1000				2 | ||||
| #define ALX_MAC_CTRL_PROMISC_EN				BIT(15) | ||||
| #define ALX_MAC_CTRL_VLANSTRIP				BIT(14) | ||||
| #define ALX_MAC_CTRL_PRMBLEN_MASK			0xF | ||||
| #define ALX_MAC_CTRL_PRMBLEN_SHIFT			10 | ||||
| #define ALX_MAC_CTRL_PCRCE				BIT(7) | ||||
| #define ALX_MAC_CTRL_CRCE				BIT(6) | ||||
| #define ALX_MAC_CTRL_FULLD				BIT(5) | ||||
| #define ALX_MAC_CTRL_RXFC_EN				BIT(3) | ||||
| #define ALX_MAC_CTRL_TXFC_EN				BIT(2) | ||||
| #define ALX_MAC_CTRL_RX_EN				BIT(1) | ||||
| #define ALX_MAC_CTRL_TX_EN				BIT(0) | ||||
| 
 | ||||
| #define ALX_STAD0					0x1488 | ||||
| #define ALX_STAD1					0x148C | ||||
| 
 | ||||
| #define ALX_HASH_TBL0					0x1490 | ||||
| #define ALX_HASH_TBL1					0x1494 | ||||
| 
 | ||||
| #define ALX_MTU						0x149C | ||||
| #define ALX_MTU_JUMBO_TH				1514 | ||||
| #define ALX_MTU_STD_ALGN				1536 | ||||
| 
 | ||||
| #define ALX_SRAM5					0x1524 | ||||
| #define ALX_SRAM_RXF_LEN_MASK				0xFFF | ||||
| #define ALX_SRAM_RXF_LEN_SHIFT				0 | ||||
| #define ALX_SRAM_RXF_LEN_8K				(8*1024) | ||||
| 
 | ||||
| #define ALX_SRAM9					0x1534 | ||||
| #define ALX_SRAM_LOAD_PTR				BIT(0) | ||||
| 
 | ||||
| #define ALX_RX_BASE_ADDR_HI				0x1540 | ||||
| 
 | ||||
| #define ALX_TX_BASE_ADDR_HI				0x1544 | ||||
| 
 | ||||
| #define ALX_RFD_ADDR_LO					0x1550 | ||||
| #define ALX_RFD_RING_SZ					0x1560 | ||||
| #define ALX_RFD_BUF_SZ					0x1564 | ||||
| 
 | ||||
| #define ALX_RRD_ADDR_LO					0x1568 | ||||
| #define ALX_RRD_RING_SZ					0x1578 | ||||
| 
 | ||||
| /* pri3: highest, pri0: lowest */ | ||||
| #define ALX_TPD_PRI3_ADDR_LO				0x14E4 | ||||
| #define ALX_TPD_PRI2_ADDR_LO				0x14E0 | ||||
| #define ALX_TPD_PRI1_ADDR_LO				0x157C | ||||
| #define ALX_TPD_PRI0_ADDR_LO				0x1580 | ||||
| 
 | ||||
| /* producer index is 16bit */ | ||||
| #define ALX_TPD_PRI3_PIDX				0x1618 | ||||
| #define ALX_TPD_PRI2_PIDX				0x161A | ||||
| #define ALX_TPD_PRI1_PIDX				0x15F0 | ||||
| #define ALX_TPD_PRI0_PIDX				0x15F2 | ||||
| 
 | ||||
| /* consumer index is 16bit */ | ||||
| #define ALX_TPD_PRI3_CIDX				0x161C | ||||
| #define ALX_TPD_PRI2_CIDX				0x161E | ||||
| #define ALX_TPD_PRI1_CIDX				0x15F4 | ||||
| #define ALX_TPD_PRI0_CIDX				0x15F6 | ||||
| 
 | ||||
| #define ALX_TPD_RING_SZ					0x1584 | ||||
| 
 | ||||
| #define ALX_TXQ0					0x1590 | ||||
| #define ALX_TXQ0_TXF_BURST_PREF_MASK			0xFFFF | ||||
| #define ALX_TXQ0_TXF_BURST_PREF_SHIFT			16 | ||||
| #define ALX_TXQ_TXF_BURST_PREF_DEF			0x200 | ||||
| #define ALX_TXQ0_LSO_8023_EN				BIT(7) | ||||
| #define ALX_TXQ0_MODE_ENHANCE				BIT(6) | ||||
| #define ALX_TXQ0_EN					BIT(5) | ||||
| #define ALX_TXQ0_SUPT_IPOPT				BIT(4) | ||||
| #define ALX_TXQ0_TPD_BURSTPREF_MASK			0xF | ||||
| #define ALX_TXQ0_TPD_BURSTPREF_SHIFT			0 | ||||
| #define ALX_TXQ_TPD_BURSTPREF_DEF			5 | ||||
| 
 | ||||
| #define ALX_TXQ1					0x1594 | ||||
| /* bit11:  drop large packet, len > (rfd buf) */ | ||||
| #define ALX_TXQ1_ERRLGPKT_DROP_EN			BIT(11) | ||||
| #define ALX_TXQ1_JUMBO_TSO_TH				(7*1024) | ||||
| 
 | ||||
| #define ALX_RXQ0					0x15A0 | ||||
| #define ALX_RXQ0_EN					BIT(31) | ||||
| #define ALX_RXQ0_RSS_HASH_EN				BIT(29) | ||||
| #define ALX_RXQ0_RSS_MODE_MASK				0x3 | ||||
| #define ALX_RXQ0_RSS_MODE_SHIFT				26 | ||||
| #define ALX_RXQ0_RSS_MODE_DIS				0 | ||||
| #define ALX_RXQ0_RSS_MODE_MQMI				3 | ||||
| #define ALX_RXQ0_NUM_RFD_PREF_MASK			0x3F | ||||
| #define ALX_RXQ0_NUM_RFD_PREF_SHIFT			20 | ||||
| #define ALX_RXQ0_NUM_RFD_PREF_DEF			8 | ||||
| #define ALX_RXQ0_IDT_TBL_SIZE_MASK			0x1FF | ||||
| #define ALX_RXQ0_IDT_TBL_SIZE_SHIFT			8 | ||||
| #define ALX_RXQ0_IDT_TBL_SIZE_DEF			0x100 | ||||
| #define ALX_RXQ0_IDT_TBL_SIZE_NORMAL			128 | ||||
| #define ALX_RXQ0_IPV6_PARSE_EN				BIT(7) | ||||
| #define ALX_RXQ0_RSS_HSTYP_MASK				0xF | ||||
| #define ALX_RXQ0_RSS_HSTYP_SHIFT			2 | ||||
| #define ALX_RXQ0_RSS_HSTYP_IPV6_TCP_EN			BIT(5) | ||||
| #define ALX_RXQ0_RSS_HSTYP_IPV6_EN			BIT(4) | ||||
| #define ALX_RXQ0_RSS_HSTYP_IPV4_TCP_EN			BIT(3) | ||||
| #define ALX_RXQ0_RSS_HSTYP_IPV4_EN			BIT(2) | ||||
| #define ALX_RXQ0_RSS_HSTYP_ALL		(ALX_RXQ0_RSS_HSTYP_IPV6_TCP_EN | \ | ||||
| 					 ALX_RXQ0_RSS_HSTYP_IPV4_TCP_EN | \ | ||||
| 					 ALX_RXQ0_RSS_HSTYP_IPV6_EN | \ | ||||
| 					 ALX_RXQ0_RSS_HSTYP_IPV4_EN) | ||||
| #define ALX_RXQ0_ASPM_THRESH_MASK			0x3 | ||||
| #define ALX_RXQ0_ASPM_THRESH_SHIFT			0 | ||||
| #define ALX_RXQ0_ASPM_THRESH_100M			3 | ||||
| 
 | ||||
| #define ALX_RXQ2					0x15A8 | ||||
| #define ALX_RXQ2_RXF_XOFF_THRESH_MASK			0xFFF | ||||
| #define ALX_RXQ2_RXF_XOFF_THRESH_SHIFT			16 | ||||
| #define ALX_RXQ2_RXF_XON_THRESH_MASK			0xFFF | ||||
| #define ALX_RXQ2_RXF_XON_THRESH_SHIFT			0 | ||||
| /* Size = tx-packet(1522) + IPG(12) + SOF(8) + 64(Pause) + IPG(12) + SOF(8) +
 | ||||
|  *        rx-packet(1522) + delay-of-link(64) | ||||
|  *      = 3212. | ||||
|  */ | ||||
| #define ALX_RXQ2_RXF_FLOW_CTRL_RSVD			3212 | ||||
| 
 | ||||
| #define ALX_DMA						0x15C0 | ||||
| #define ALX_DMA_RCHNL_SEL_MASK				0x3 | ||||
| #define ALX_DMA_RCHNL_SEL_SHIFT				26 | ||||
| #define ALX_DMA_WDLY_CNT_MASK				0xF | ||||
| #define ALX_DMA_WDLY_CNT_SHIFT				16 | ||||
| #define ALX_DMA_WDLY_CNT_DEF				4 | ||||
| #define ALX_DMA_RDLY_CNT_MASK				0x1F | ||||
| #define ALX_DMA_RDLY_CNT_SHIFT				11 | ||||
| #define ALX_DMA_RDLY_CNT_DEF				15 | ||||
| /* bit10: 0:tpd with pri, 1: data */ | ||||
| #define ALX_DMA_RREQ_PRI_DATA				BIT(10) | ||||
| #define ALX_DMA_RREQ_BLEN_MASK				0x7 | ||||
| #define ALX_DMA_RREQ_BLEN_SHIFT				4 | ||||
| #define ALX_DMA_RORDER_MODE_MASK			0x7 | ||||
| #define ALX_DMA_RORDER_MODE_SHIFT			0 | ||||
| #define ALX_DMA_RORDER_MODE_OUT				4 | ||||
| 
 | ||||
| #define ALX_WOL0					0x14A0 | ||||
| #define ALX_WOL0_PME_LINK				BIT(5) | ||||
| #define ALX_WOL0_LINK_EN				BIT(4) | ||||
| #define ALX_WOL0_PME_MAGIC_EN				BIT(3) | ||||
| #define ALX_WOL0_MAGIC_EN				BIT(2) | ||||
| 
 | ||||
| #define ALX_RFD_PIDX					0x15E0 | ||||
| 
 | ||||
| #define ALX_RFD_CIDX					0x15F8 | ||||
| 
 | ||||
| /* MIB */ | ||||
| #define ALX_MIB_BASE					0x1700 | ||||
| 
 | ||||
| #define ALX_MIB_RX_OK					(ALX_MIB_BASE + 0) | ||||
| #define ALX_MIB_RX_BCAST				(ALX_MIB_BASE + 4) | ||||
| #define ALX_MIB_RX_MCAST				(ALX_MIB_BASE + 8) | ||||
| #define ALX_MIB_RX_PAUSE				(ALX_MIB_BASE + 12) | ||||
| #define ALX_MIB_RX_CTRL					(ALX_MIB_BASE + 16) | ||||
| #define ALX_MIB_RX_FCS_ERR				(ALX_MIB_BASE + 20) | ||||
| #define ALX_MIB_RX_LEN_ERR				(ALX_MIB_BASE + 24) | ||||
| #define ALX_MIB_RX_BYTE_CNT				(ALX_MIB_BASE + 28) | ||||
| #define ALX_MIB_RX_RUNT					(ALX_MIB_BASE + 32) | ||||
| #define ALX_MIB_RX_FRAG					(ALX_MIB_BASE + 36) | ||||
| #define ALX_MIB_RX_SZ_64B				(ALX_MIB_BASE + 40) | ||||
| #define ALX_MIB_RX_SZ_127B				(ALX_MIB_BASE + 44) | ||||
| #define ALX_MIB_RX_SZ_255B				(ALX_MIB_BASE + 48) | ||||
| #define ALX_MIB_RX_SZ_511B				(ALX_MIB_BASE + 52) | ||||
| #define ALX_MIB_RX_SZ_1023B				(ALX_MIB_BASE + 56) | ||||
| #define ALX_MIB_RX_SZ_1518B				(ALX_MIB_BASE + 60) | ||||
| #define ALX_MIB_RX_SZ_MAX				(ALX_MIB_BASE + 64) | ||||
| #define ALX_MIB_RX_OV_SZ				(ALX_MIB_BASE + 68) | ||||
| #define ALX_MIB_RX_OV_RXF				(ALX_MIB_BASE + 72) | ||||
| #define ALX_MIB_RX_OV_RRD				(ALX_MIB_BASE + 76) | ||||
| #define ALX_MIB_RX_ALIGN_ERR				(ALX_MIB_BASE + 80) | ||||
| #define ALX_MIB_RX_BCCNT				(ALX_MIB_BASE + 84) | ||||
| #define ALX_MIB_RX_MCCNT				(ALX_MIB_BASE + 88) | ||||
| #define ALX_MIB_RX_ERRADDR				(ALX_MIB_BASE + 92) | ||||
| 
 | ||||
| #define ALX_MIB_TX_OK					(ALX_MIB_BASE + 96) | ||||
| #define ALX_MIB_TX_BCAST				(ALX_MIB_BASE + 100) | ||||
| #define ALX_MIB_TX_MCAST				(ALX_MIB_BASE + 104) | ||||
| #define ALX_MIB_TX_PAUSE				(ALX_MIB_BASE + 108) | ||||
| #define ALX_MIB_TX_EXC_DEFER				(ALX_MIB_BASE + 112) | ||||
| #define ALX_MIB_TX_CTRL					(ALX_MIB_BASE + 116) | ||||
| #define ALX_MIB_TX_DEFER				(ALX_MIB_BASE + 120) | ||||
| #define ALX_MIB_TX_BYTE_CNT				(ALX_MIB_BASE + 124) | ||||
| #define ALX_MIB_TX_SZ_64B				(ALX_MIB_BASE + 128) | ||||
| #define ALX_MIB_TX_SZ_127B				(ALX_MIB_BASE + 132) | ||||
| #define ALX_MIB_TX_SZ_255B				(ALX_MIB_BASE + 136) | ||||
| #define ALX_MIB_TX_SZ_511B				(ALX_MIB_BASE + 140) | ||||
| #define ALX_MIB_TX_SZ_1023B				(ALX_MIB_BASE + 144) | ||||
| #define ALX_MIB_TX_SZ_1518B				(ALX_MIB_BASE + 148) | ||||
| #define ALX_MIB_TX_SZ_MAX				(ALX_MIB_BASE + 152) | ||||
| #define ALX_MIB_TX_SINGLE_COL				(ALX_MIB_BASE + 156) | ||||
| #define ALX_MIB_TX_MULTI_COL				(ALX_MIB_BASE + 160) | ||||
| #define ALX_MIB_TX_LATE_COL				(ALX_MIB_BASE + 164) | ||||
| #define ALX_MIB_TX_ABORT_COL				(ALX_MIB_BASE + 168) | ||||
| #define ALX_MIB_TX_UNDERRUN				(ALX_MIB_BASE + 172) | ||||
| #define ALX_MIB_TX_TRD_EOP				(ALX_MIB_BASE + 176) | ||||
| #define ALX_MIB_TX_LEN_ERR				(ALX_MIB_BASE + 180) | ||||
| #define ALX_MIB_TX_TRUNC				(ALX_MIB_BASE + 184) | ||||
| #define ALX_MIB_TX_BCCNT				(ALX_MIB_BASE + 188) | ||||
| #define ALX_MIB_TX_MCCNT				(ALX_MIB_BASE + 192) | ||||
| #define ALX_MIB_UPDATE					(ALX_MIB_BASE + 196) | ||||
| 
 | ||||
| 
 | ||||
| #define ALX_ISR						0x1600 | ||||
| #define ALX_ISR_DIS					BIT(31) | ||||
| #define ALX_ISR_RX_Q7					BIT(30) | ||||
| #define ALX_ISR_RX_Q6					BIT(29) | ||||
| #define ALX_ISR_RX_Q5					BIT(28) | ||||
| #define ALX_ISR_RX_Q4					BIT(27) | ||||
| #define ALX_ISR_PCIE_LNKDOWN				BIT(26) | ||||
| #define ALX_ISR_RX_Q3					BIT(19) | ||||
| #define ALX_ISR_RX_Q2					BIT(18) | ||||
| #define ALX_ISR_RX_Q1					BIT(17) | ||||
| #define ALX_ISR_RX_Q0					BIT(16) | ||||
| #define ALX_ISR_TX_Q0					BIT(15) | ||||
| #define ALX_ISR_PHY					BIT(12) | ||||
| #define ALX_ISR_DMAW					BIT(10) | ||||
| #define ALX_ISR_DMAR					BIT(9) | ||||
| #define ALX_ISR_TXF_UR					BIT(8) | ||||
| #define ALX_ISR_TX_Q3					BIT(7) | ||||
| #define ALX_ISR_TX_Q2					BIT(6) | ||||
| #define ALX_ISR_TX_Q1					BIT(5) | ||||
| #define ALX_ISR_RFD_UR					BIT(4) | ||||
| #define ALX_ISR_RXF_OV					BIT(3) | ||||
| #define ALX_ISR_MANU					BIT(2) | ||||
| #define ALX_ISR_TIMER					BIT(1) | ||||
| #define ALX_ISR_SMB					BIT(0) | ||||
| 
 | ||||
| #define ALX_IMR						0x1604 | ||||
| 
 | ||||
| /* re-send assert msg if SW no response */ | ||||
| #define ALX_INT_RETRIG					0x1608 | ||||
| /* 40ms */ | ||||
| #define ALX_INT_RETRIG_TO				20000 | ||||
| 
 | ||||
| #define ALX_SMB_TIMER					0x15C4 | ||||
| 
 | ||||
| #define ALX_TINT_TPD_THRSHLD				0x15C8 | ||||
| 
 | ||||
| #define ALX_TINT_TIMER					0x15CC | ||||
| 
 | ||||
| #define ALX_CLK_GATE					0x1814 | ||||
| #define ALX_CLK_GATE_RXMAC				BIT(5) | ||||
| #define ALX_CLK_GATE_TXMAC				BIT(4) | ||||
| #define ALX_CLK_GATE_RXQ				BIT(3) | ||||
| #define ALX_CLK_GATE_TXQ				BIT(2) | ||||
| #define ALX_CLK_GATE_DMAR				BIT(1) | ||||
| #define ALX_CLK_GATE_DMAW				BIT(0) | ||||
| #define ALX_CLK_GATE_ALL		(ALX_CLK_GATE_RXMAC | \ | ||||
| 					 ALX_CLK_GATE_TXMAC | \ | ||||
| 					 ALX_CLK_GATE_RXQ | \ | ||||
| 					 ALX_CLK_GATE_TXQ | \ | ||||
| 					 ALX_CLK_GATE_DMAR | \ | ||||
| 					 ALX_CLK_GATE_DMAW) | ||||
| 
 | ||||
| /* interop between drivers */ | ||||
| #define ALX_DRV						0x1804 | ||||
| #define ALX_DRV_PHY_AUTO				BIT(28) | ||||
| #define ALX_DRV_PHY_1000				BIT(27) | ||||
| #define ALX_DRV_PHY_100					BIT(26) | ||||
| #define ALX_DRV_PHY_10					BIT(25) | ||||
| #define ALX_DRV_PHY_DUPLEX				BIT(24) | ||||
| /* bit23: adv Pause */ | ||||
| #define ALX_DRV_PHY_PAUSE				BIT(23) | ||||
| /* bit22: adv Asym Pause */ | ||||
| #define ALX_DRV_PHY_MASK				0xFF | ||||
| #define ALX_DRV_PHY_SHIFT				21 | ||||
| #define ALX_DRV_PHY_UNKNOWN				0 | ||||
| 
 | ||||
| /* flag of phy inited */ | ||||
| #define ALX_PHY_INITED					0x003F | ||||
| 
 | ||||
| /* reg 1830 ~ 186C for C0+, 16 bit map patterns and wake packet detection */ | ||||
| #define ALX_WOL_CTRL2					0x1830 | ||||
| #define ALX_WOL_CTRL2_DATA_STORE			BIT(3) | ||||
| #define ALX_WOL_CTRL2_PTRN_EVT				BIT(2) | ||||
| #define ALX_WOL_CTRL2_PME_PTRN_EN			BIT(1) | ||||
| #define ALX_WOL_CTRL2_PTRN_EN				BIT(0) | ||||
| 
 | ||||
| #define ALX_WOL_CTRL3					0x1834 | ||||
| #define ALX_WOL_CTRL3_PTRN_ADDR_MASK			0xFFFFF | ||||
| #define ALX_WOL_CTRL3_PTRN_ADDR_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_WOL_CTRL4					0x1838 | ||||
| #define ALX_WOL_CTRL4_PT15_MATCH			BIT(31) | ||||
| #define ALX_WOL_CTRL4_PT14_MATCH			BIT(30) | ||||
| #define ALX_WOL_CTRL4_PT13_MATCH			BIT(29) | ||||
| #define ALX_WOL_CTRL4_PT12_MATCH			BIT(28) | ||||
| #define ALX_WOL_CTRL4_PT11_MATCH			BIT(27) | ||||
| #define ALX_WOL_CTRL4_PT10_MATCH			BIT(26) | ||||
| #define ALX_WOL_CTRL4_PT9_MATCH				BIT(25) | ||||
| #define ALX_WOL_CTRL4_PT8_MATCH				BIT(24) | ||||
| #define ALX_WOL_CTRL4_PT7_MATCH				BIT(23) | ||||
| #define ALX_WOL_CTRL4_PT6_MATCH				BIT(22) | ||||
| #define ALX_WOL_CTRL4_PT5_MATCH				BIT(21) | ||||
| #define ALX_WOL_CTRL4_PT4_MATCH				BIT(20) | ||||
| #define ALX_WOL_CTRL4_PT3_MATCH				BIT(19) | ||||
| #define ALX_WOL_CTRL4_PT2_MATCH				BIT(18) | ||||
| #define ALX_WOL_CTRL4_PT1_MATCH				BIT(17) | ||||
| #define ALX_WOL_CTRL4_PT0_MATCH				BIT(16) | ||||
| #define ALX_WOL_CTRL4_PT15_EN				BIT(15) | ||||
| #define ALX_WOL_CTRL4_PT14_EN				BIT(14) | ||||
| #define ALX_WOL_CTRL4_PT13_EN				BIT(13) | ||||
| #define ALX_WOL_CTRL4_PT12_EN				BIT(12) | ||||
| #define ALX_WOL_CTRL4_PT11_EN				BIT(11) | ||||
| #define ALX_WOL_CTRL4_PT10_EN				BIT(10) | ||||
| #define ALX_WOL_CTRL4_PT9_EN				BIT(9) | ||||
| #define ALX_WOL_CTRL4_PT8_EN				BIT(8) | ||||
| #define ALX_WOL_CTRL4_PT7_EN				BIT(7) | ||||
| #define ALX_WOL_CTRL4_PT6_EN				BIT(6) | ||||
| #define ALX_WOL_CTRL4_PT5_EN				BIT(5) | ||||
| #define ALX_WOL_CTRL4_PT4_EN				BIT(4) | ||||
| #define ALX_WOL_CTRL4_PT3_EN				BIT(3) | ||||
| #define ALX_WOL_CTRL4_PT2_EN				BIT(2) | ||||
| #define ALX_WOL_CTRL4_PT1_EN				BIT(1) | ||||
| #define ALX_WOL_CTRL4_PT0_EN				BIT(0) | ||||
| 
 | ||||
| #define ALX_WOL_CTRL5					0x183C | ||||
| #define ALX_WOL_CTRL5_PT3_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT3_LEN_SHIFT			24 | ||||
| #define ALX_WOL_CTRL5_PT2_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT2_LEN_SHIFT			16 | ||||
| #define ALX_WOL_CTRL5_PT1_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT1_LEN_SHIFT			8 | ||||
| #define ALX_WOL_CTRL5_PT0_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT0_LEN_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_WOL_CTRL6					0x1840 | ||||
| #define ALX_WOL_CTRL5_PT7_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT7_LEN_SHIFT			24 | ||||
| #define ALX_WOL_CTRL5_PT6_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT6_LEN_SHIFT			16 | ||||
| #define ALX_WOL_CTRL5_PT5_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT5_LEN_SHIFT			8 | ||||
| #define ALX_WOL_CTRL5_PT4_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT4_LEN_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_WOL_CTRL7					0x1844 | ||||
| #define ALX_WOL_CTRL5_PT11_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT11_LEN_SHIFT			24 | ||||
| #define ALX_WOL_CTRL5_PT10_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT10_LEN_SHIFT			16 | ||||
| #define ALX_WOL_CTRL5_PT9_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT9_LEN_SHIFT			8 | ||||
| #define ALX_WOL_CTRL5_PT8_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT8_LEN_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_WOL_CTRL8					0x1848 | ||||
| #define ALX_WOL_CTRL5_PT15_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT15_LEN_SHIFT			24 | ||||
| #define ALX_WOL_CTRL5_PT14_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT14_LEN_SHIFT			16 | ||||
| #define ALX_WOL_CTRL5_PT13_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT13_LEN_SHIFT			8 | ||||
| #define ALX_WOL_CTRL5_PT12_LEN_MASK			0xFF | ||||
| #define ALX_WOL_CTRL5_PT12_LEN_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_ACER_FIXED_PTN0				0x1850 | ||||
| #define ALX_ACER_FIXED_PTN0_MASK			0xFFFFFFFF | ||||
| #define ALX_ACER_FIXED_PTN0_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_ACER_FIXED_PTN1				0x1854 | ||||
| #define ALX_ACER_FIXED_PTN1_MASK			0xFFFF | ||||
| #define ALX_ACER_FIXED_PTN1_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_ACER_RANDOM_NUM0				0x1858 | ||||
| #define ALX_ACER_RANDOM_NUM0_MASK			0xFFFFFFFF | ||||
| #define ALX_ACER_RANDOM_NUM0_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_ACER_RANDOM_NUM1				0x185C | ||||
| #define ALX_ACER_RANDOM_NUM1_MASK			0xFFFFFFFF | ||||
| #define ALX_ACER_RANDOM_NUM1_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_ACER_RANDOM_NUM2				0x1860 | ||||
| #define ALX_ACER_RANDOM_NUM2_MASK			0xFFFFFFFF | ||||
| #define ALX_ACER_RANDOM_NUM2_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_ACER_RANDOM_NUM3				0x1864 | ||||
| #define ALX_ACER_RANDOM_NUM3_MASK			0xFFFFFFFF | ||||
| #define ALX_ACER_RANDOM_NUM3_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_ACER_MAGIC					0x1868 | ||||
| #define ALX_ACER_MAGIC_EN				BIT(31) | ||||
| #define ALX_ACER_MAGIC_PME_EN				BIT(30) | ||||
| #define ALX_ACER_MAGIC_MATCH				BIT(29) | ||||
| #define ALX_ACER_MAGIC_FF_CHECK				BIT(10) | ||||
| #define ALX_ACER_MAGIC_RAN_LEN_MASK			0x1F | ||||
| #define ALX_ACER_MAGIC_RAN_LEN_SHIFT			5 | ||||
| #define ALX_ACER_MAGIC_FIX_LEN_MASK			0x1F | ||||
| #define ALX_ACER_MAGIC_FIX_LEN_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_ACER_TIMER					0x186C | ||||
| #define ALX_ACER_TIMER_EN				BIT(31) | ||||
| #define ALX_ACER_TIMER_PME_EN				BIT(30) | ||||
| #define ALX_ACER_TIMER_MATCH				BIT(29) | ||||
| #define ALX_ACER_TIMER_THRES_MASK			0x1FFFF | ||||
| #define ALX_ACER_TIMER_THRES_SHIFT			0 | ||||
| #define ALX_ACER_TIMER_THRES_DEF			1 | ||||
| 
 | ||||
| /* RSS definitions */ | ||||
| #define ALX_RSS_KEY0					0x14B0 | ||||
| #define ALX_RSS_KEY1					0x14B4 | ||||
| #define ALX_RSS_KEY2					0x14B8 | ||||
| #define ALX_RSS_KEY3					0x14BC | ||||
| #define ALX_RSS_KEY4					0x14C0 | ||||
| #define ALX_RSS_KEY5					0x14C4 | ||||
| #define ALX_RSS_KEY6					0x14C8 | ||||
| #define ALX_RSS_KEY7					0x14CC | ||||
| #define ALX_RSS_KEY8					0x14D0 | ||||
| #define ALX_RSS_KEY9					0x14D4 | ||||
| 
 | ||||
| #define ALX_RSS_IDT_TBL0				0x1B00 | ||||
| 
 | ||||
| #define ALX_MSI_MAP_TBL1				0x15D0 | ||||
| #define ALX_MSI_MAP_TBL1_TXQ1_SHIFT			20 | ||||
| #define ALX_MSI_MAP_TBL1_TXQ0_SHIFT			16 | ||||
| #define ALX_MSI_MAP_TBL1_RXQ3_SHIFT			12 | ||||
| #define ALX_MSI_MAP_TBL1_RXQ2_SHIFT			8 | ||||
| #define ALX_MSI_MAP_TBL1_RXQ1_SHIFT			4 | ||||
| #define ALX_MSI_MAP_TBL1_RXQ0_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_MSI_MAP_TBL2				0x15D8 | ||||
| #define ALX_MSI_MAP_TBL2_TXQ3_SHIFT			20 | ||||
| #define ALX_MSI_MAP_TBL2_TXQ2_SHIFT			16 | ||||
| #define ALX_MSI_MAP_TBL2_RXQ7_SHIFT			12 | ||||
| #define ALX_MSI_MAP_TBL2_RXQ6_SHIFT			8 | ||||
| #define ALX_MSI_MAP_TBL2_RXQ5_SHIFT			4 | ||||
| #define ALX_MSI_MAP_TBL2_RXQ4_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_MSI_ID_MAP					0x15D4 | ||||
| 
 | ||||
| #define ALX_MSI_RETRANS_TIMER				0x1920 | ||||
| /* bit16: 1:line,0:standard */ | ||||
| #define ALX_MSI_MASK_SEL_LINE				BIT(16) | ||||
| #define ALX_MSI_RETRANS_TM_MASK				0xFFFF | ||||
| #define ALX_MSI_RETRANS_TM_SHIFT			0 | ||||
| 
 | ||||
| /* CR DMA ctrl */ | ||||
| 
 | ||||
| /* TX QoS */ | ||||
| #define ALX_WRR						0x1938 | ||||
| #define ALX_WRR_PRI_MASK				0x3 | ||||
| #define ALX_WRR_PRI_SHIFT				29 | ||||
| #define ALX_WRR_PRI_RESTRICT_NONE			3 | ||||
| #define ALX_WRR_PRI3_MASK				0x1F | ||||
| #define ALX_WRR_PRI3_SHIFT				24 | ||||
| #define ALX_WRR_PRI2_MASK				0x1F | ||||
| #define ALX_WRR_PRI2_SHIFT				16 | ||||
| #define ALX_WRR_PRI1_MASK				0x1F | ||||
| #define ALX_WRR_PRI1_SHIFT				8 | ||||
| #define ALX_WRR_PRI0_MASK				0x1F | ||||
| #define ALX_WRR_PRI0_SHIFT				0 | ||||
| 
 | ||||
| #define ALX_HQTPD					0x193C | ||||
| #define ALX_HQTPD_BURST_EN				BIT(31) | ||||
| #define ALX_HQTPD_Q3_NUMPREF_MASK			0xF | ||||
| #define ALX_HQTPD_Q3_NUMPREF_SHIFT			8 | ||||
| #define ALX_HQTPD_Q2_NUMPREF_MASK			0xF | ||||
| #define ALX_HQTPD_Q2_NUMPREF_SHIFT			4 | ||||
| #define ALX_HQTPD_Q1_NUMPREF_MASK			0xF | ||||
| #define ALX_HQTPD_Q1_NUMPREF_SHIFT			0 | ||||
| 
 | ||||
| #define ALX_MISC					0x19C0 | ||||
| #define ALX_MISC_PSW_OCP_MASK				0x7 | ||||
| #define ALX_MISC_PSW_OCP_SHIFT				21 | ||||
| #define ALX_MISC_PSW_OCP_DEF				0x7 | ||||
| #define ALX_MISC_ISO_EN					BIT(12) | ||||
| #define ALX_MISC_INTNLOSC_OPEN				BIT(3) | ||||
| 
 | ||||
| #define ALX_MSIC2					0x19C8 | ||||
| #define ALX_MSIC2_CALB_START				BIT(0) | ||||
| 
 | ||||
| #define ALX_MISC3					0x19CC | ||||
| /* bit1: 1:Software control 25M */ | ||||
| #define ALX_MISC3_25M_BY_SW				BIT(1) | ||||
| /* bit0: 25M switch to intnl OSC */ | ||||
| #define ALX_MISC3_25M_NOTO_INTNL			BIT(0) | ||||
| 
 | ||||
| /* MSIX tbl in memory space */ | ||||
| #define ALX_MSIX_ENTRY_BASE				0x2000 | ||||
| 
 | ||||
| /********************* PHY regs definition ***************************/ | ||||
| 
 | ||||
| /* PHY Specific Status Register */ | ||||
| #define ALX_MII_GIGA_PSSR				0x11 | ||||
| #define ALX_GIGA_PSSR_SPD_DPLX_RESOLVED			0x0800 | ||||
| #define ALX_GIGA_PSSR_DPLX				0x2000 | ||||
| #define ALX_GIGA_PSSR_SPEED				0xC000 | ||||
| #define ALX_GIGA_PSSR_10MBS				0x0000 | ||||
| #define ALX_GIGA_PSSR_100MBS				0x4000 | ||||
| #define ALX_GIGA_PSSR_1000MBS				0x8000 | ||||
| 
 | ||||
| /* PHY Interrupt Enable Register */ | ||||
| #define ALX_MII_IER					0x12 | ||||
| #define ALX_IER_LINK_UP					0x0400 | ||||
| #define ALX_IER_LINK_DOWN				0x0800 | ||||
| 
 | ||||
| /* PHY Interrupt Status Register */ | ||||
| #define ALX_MII_ISR					0x13 | ||||
| 
 | ||||
| #define ALX_MII_DBG_ADDR				0x1D | ||||
| #define ALX_MII_DBG_DATA				0x1E | ||||
| 
 | ||||
| /***************************** debug port *************************************/ | ||||
| 
 | ||||
| #define ALX_MIIDBG_ANACTRL				0x00 | ||||
| #define ALX_ANACTRL_DEF					0x02EF | ||||
| 
 | ||||
| #define ALX_MIIDBG_SYSMODCTRL				0x04 | ||||
| /* en half bias */ | ||||
| #define ALX_SYSMODCTRL_IECHOADJ_DEF			0xBB8B | ||||
| 
 | ||||
| #define ALX_MIIDBG_SRDSYSMOD				0x05 | ||||
| #define ALX_SRDSYSMOD_DEEMP_EN				0x0040 | ||||
| #define ALX_SRDSYSMOD_DEF				0x2C46 | ||||
| 
 | ||||
| #define ALX_MIIDBG_HIBNEG				0x0B | ||||
| #define ALX_HIBNEG_PSHIB_EN				0x8000 | ||||
| #define ALX_HIBNEG_HIB_PSE				0x1000 | ||||
| #define ALX_HIBNEG_DEF					0xBC40 | ||||
| #define ALX_HIBNEG_NOHIB	(ALX_HIBNEG_DEF & \ | ||||
| 				 ~(ALX_HIBNEG_PSHIB_EN | ALX_HIBNEG_HIB_PSE)) | ||||
| 
 | ||||
| #define ALX_MIIDBG_TST10BTCFG				0x12 | ||||
| #define ALX_TST10BTCFG_DEF				0x4C04 | ||||
| 
 | ||||
| #define ALX_MIIDBG_AZ_ANADECT				0x15 | ||||
| #define ALX_AZ_ANADECT_DEF				0x3220 | ||||
| #define ALX_AZ_ANADECT_LONG				0x3210 | ||||
| 
 | ||||
| #define ALX_MIIDBG_MSE16DB				0x18 | ||||
| #define ALX_MSE16DB_UP					0x05EA | ||||
| #define ALX_MSE16DB_DOWN				0x02EA | ||||
| 
 | ||||
| #define ALX_MIIDBG_MSE20DB				0x1C | ||||
| #define ALX_MSE20DB_TH_MASK				0x7F | ||||
| #define ALX_MSE20DB_TH_SHIFT				2 | ||||
| #define ALX_MSE20DB_TH_DEF				0x2E | ||||
| #define ALX_MSE20DB_TH_HI				0x54 | ||||
| 
 | ||||
| #define ALX_MIIDBG_AGC					0x23 | ||||
| #define ALX_AGC_2_VGA_MASK				0x3FU | ||||
| #define ALX_AGC_2_VGA_SHIFT				8 | ||||
| #define ALX_AGC_LONG1G_LIMT				40 | ||||
| #define ALX_AGC_LONG100M_LIMT				44 | ||||
| 
 | ||||
| #define ALX_MIIDBG_LEGCYPS				0x29 | ||||
| #define ALX_LEGCYPS_EN					0x8000 | ||||
| #define ALX_LEGCYPS_DEF					0x129D | ||||
| 
 | ||||
| #define ALX_MIIDBG_TST100BTCFG				0x36 | ||||
| #define ALX_TST100BTCFG_DEF				0xE12C | ||||
| 
 | ||||
| #define ALX_MIIDBG_GREENCFG				0x3B | ||||
| #define ALX_GREENCFG_DEF				0x7078 | ||||
| 
 | ||||
| #define ALX_MIIDBG_GREENCFG2				0x3D | ||||
| #define ALX_GREENCFG2_BP_GREEN				0x8000 | ||||
| #define ALX_GREENCFG2_GATE_DFSE_EN			0x0080 | ||||
| 
 | ||||
| /******* dev 3 *********/ | ||||
| #define ALX_MIIEXT_PCS					3 | ||||
| 
 | ||||
| #define ALX_MIIEXT_CLDCTRL3				0x8003 | ||||
| #define ALX_CLDCTRL3_BP_CABLE1TH_DET_GT			0x8000 | ||||
| 
 | ||||
| #define ALX_MIIEXT_CLDCTRL5				0x8005 | ||||
| #define ALX_CLDCTRL5_BP_VD_HLFBIAS			0x4000 | ||||
| 
 | ||||
| #define ALX_MIIEXT_CLDCTRL6				0x8006 | ||||
| #define ALX_CLDCTRL6_CAB_LEN_MASK			0xFF | ||||
| #define ALX_CLDCTRL6_CAB_LEN_SHIFT			0 | ||||
| #define ALX_CLDCTRL6_CAB_LEN_SHORT1G			116 | ||||
| #define ALX_CLDCTRL6_CAB_LEN_SHORT100M			152 | ||||
| 
 | ||||
| #define ALX_MIIEXT_VDRVBIAS				0x8062 | ||||
| #define ALX_VDRVBIAS_DEF				0x3 | ||||
| 
 | ||||
| /********* dev 7 **********/ | ||||
| #define ALX_MIIEXT_ANEG					7 | ||||
| 
 | ||||
| #define ALX_MIIEXT_LOCAL_EEEADV				0x3C | ||||
| #define ALX_LOCAL_EEEADV_1000BT				0x0004 | ||||
| #define ALX_LOCAL_EEEADV_100BT				0x0002 | ||||
| 
 | ||||
| #define ALX_MIIEXT_AFE					0x801A | ||||
| #define ALX_AFE_10BT_100M_TH				0x0040 | ||||
| 
 | ||||
| #define ALX_MIIEXT_S3DIG10				0x8023 | ||||
| /* bit0: 1:bypass 10BT rx fifo, 0:original 10BT rx */ | ||||
| #define ALX_MIIEXT_S3DIG10_SL				0x0001 | ||||
| #define ALX_MIIEXT_S3DIG10_DEF				0 | ||||
| 
 | ||||
| #define ALX_MIIEXT_NLP78				0x8027 | ||||
| #define ALX_MIIEXT_NLP78_120M_DEF			0x8A05 | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										2
									
								
								drivers/net/ethernet/atheros/atl1c/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								drivers/net/ethernet/atheros/atl1c/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| obj-$(CONFIG_ATL1C) += atl1c.o | ||||
| atl1c-objs := atl1c_main.o atl1c_hw.o atl1c_ethtool.o | ||||
							
								
								
									
										605
									
								
								drivers/net/ethernet/atheros/atl1c/atl1c.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										605
									
								
								drivers/net/ethernet/atheros/atl1c/atl1c.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,605 @@ | |||
| /*
 | ||||
|  * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved. | ||||
|  * | ||||
|  * Derived from Intel e1000 driver | ||||
|  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the Free | ||||
|  * Software Foundation; either version 2 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., 59 | ||||
|  * Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _ATL1C_H_ | ||||
| #define _ATL1C_H_ | ||||
| 
 | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/pci.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/etherdevice.h> | ||||
| #include <linux/skbuff.h> | ||||
| #include <linux/ioport.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/list.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/sched.h> | ||||
| #include <linux/in.h> | ||||
| #include <linux/ip.h> | ||||
| #include <linux/ipv6.h> | ||||
| #include <linux/udp.h> | ||||
| #include <linux/mii.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/vmalloc.h> | ||||
| #include <linux/pagemap.h> | ||||
| #include <linux/tcp.h> | ||||
| #include <linux/ethtool.h> | ||||
| #include <linux/if_vlan.h> | ||||
| #include <linux/workqueue.h> | ||||
| #include <net/checksum.h> | ||||
| #include <net/ip6_checksum.h> | ||||
| 
 | ||||
| #include "atl1c_hw.h" | ||||
| 
 | ||||
| /* Wake Up Filter Control */ | ||||
| #define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ | ||||
| #define AT_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */ | ||||
| #define AT_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */ | ||||
| #define AT_WUFC_MC   0x00000008 /* Multicast Wakeup Enable */ | ||||
| #define AT_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */ | ||||
| 
 | ||||
| #define AT_VLAN_TO_TAG(_vlan, _tag)	   \ | ||||
| 	_tag =  ((((_vlan) >> 8) & 0xFF)  |\ | ||||
| 		 (((_vlan) & 0xFF) << 8)) | ||||
| 
 | ||||
| #define AT_TAG_TO_VLAN(_tag, _vlan) 	 \ | ||||
| 	_vlan = ((((_tag) >> 8) & 0xFF) |\ | ||||
| 		(((_tag) & 0xFF) << 8)) | ||||
| 
 | ||||
| #define SPEED_0		   0xffff | ||||
| #define HALF_DUPLEX        1 | ||||
| #define FULL_DUPLEX        2 | ||||
| 
 | ||||
| #define AT_RX_BUF_SIZE		(ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN) | ||||
| #define MAX_JUMBO_FRAME_SIZE	(6*1024) | ||||
| 
 | ||||
| #define AT_MAX_RECEIVE_QUEUE    4 | ||||
| #define AT_DEF_RECEIVE_QUEUE	1 | ||||
| #define AT_MAX_TRANSMIT_QUEUE	2 | ||||
| 
 | ||||
| #define AT_DMA_HI_ADDR_MASK     0xffffffff00000000ULL | ||||
| #define AT_DMA_LO_ADDR_MASK     0x00000000ffffffffULL | ||||
| 
 | ||||
| #define AT_TX_WATCHDOG  (5 * HZ) | ||||
| #define AT_MAX_INT_WORK		5 | ||||
| #define AT_TWSI_EEPROM_TIMEOUT 	100 | ||||
| #define AT_HW_MAX_IDLE_DELAY 	10 | ||||
| #define AT_SUSPEND_LINK_TIMEOUT 100 | ||||
| 
 | ||||
| #define AT_ASPM_L0S_TIMER	6 | ||||
| #define AT_ASPM_L1_TIMER	12 | ||||
| #define AT_LCKDET_TIMER		12 | ||||
| 
 | ||||
| #define ATL1C_PCIE_L0S_L1_DISABLE 	0x01 | ||||
| #define ATL1C_PCIE_PHY_RESET		0x02 | ||||
| 
 | ||||
| #define ATL1C_ASPM_L0s_ENABLE		0x0001 | ||||
| #define ATL1C_ASPM_L1_ENABLE		0x0002 | ||||
| 
 | ||||
| #define AT_REGS_LEN	(74 * sizeof(u32)) | ||||
| #define AT_EEPROM_LEN 	512 | ||||
| 
 | ||||
| #define ATL1C_GET_DESC(R, i, type)	(&(((type *)((R)->desc))[i])) | ||||
| #define ATL1C_RFD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_rx_free_desc) | ||||
| #define ATL1C_TPD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_tpd_desc) | ||||
| #define ATL1C_RRD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_recv_ret_status) | ||||
| 
 | ||||
| /* tpd word 1 bit 0:7 General Checksum task offload */ | ||||
| #define TPD_L4HDR_OFFSET_MASK	0x00FF | ||||
| #define TPD_L4HDR_OFFSET_SHIFT	0 | ||||
| 
 | ||||
| /* tpd word 1 bit 0:7 Large Send task offload (IPv4/IPV6) */ | ||||
| #define TPD_TCPHDR_OFFSET_MASK	0x00FF | ||||
| #define TPD_TCPHDR_OFFSET_SHIFT	0 | ||||
| 
 | ||||
| /* tpd word 1 bit 0:7 Custom Checksum task offload */ | ||||
| #define TPD_PLOADOFFSET_MASK	0x00FF | ||||
| #define TPD_PLOADOFFSET_SHIFT	0 | ||||
| 
 | ||||
| /* tpd word 1 bit 8:17 */ | ||||
| #define TPD_CCSUM_EN_MASK	0x0001 | ||||
| #define TPD_CCSUM_EN_SHIFT	8 | ||||
| #define TPD_IP_CSUM_MASK	0x0001 | ||||
| #define TPD_IP_CSUM_SHIFT	9 | ||||
| #define TPD_TCP_CSUM_MASK	0x0001 | ||||
| #define TPD_TCP_CSUM_SHIFT	10 | ||||
| #define TPD_UDP_CSUM_MASK	0x0001 | ||||
| #define TPD_UDP_CSUM_SHIFT	11 | ||||
| #define TPD_LSO_EN_MASK		0x0001	/* TCP Large Send Offload */ | ||||
| #define TPD_LSO_EN_SHIFT	12 | ||||
| #define TPD_LSO_VER_MASK	0x0001 | ||||
| #define TPD_LSO_VER_SHIFT	13 	/* 0 : ipv4; 1 : ipv4/ipv6 */ | ||||
| #define TPD_CON_VTAG_MASK	0x0001 | ||||
| #define TPD_CON_VTAG_SHIFT	14 | ||||
| #define TPD_INS_VTAG_MASK	0x0001 | ||||
| #define TPD_INS_VTAG_SHIFT	15 | ||||
| #define TPD_IPV4_PACKET_MASK	0x0001  /* valid when LSO VER  is 1 */ | ||||
| #define TPD_IPV4_PACKET_SHIFT	16 | ||||
| #define TPD_ETH_TYPE_MASK	0x0001 | ||||
| #define TPD_ETH_TYPE_SHIFT	17	/* 0 : 802.3 frame; 1 : Ethernet */ | ||||
| 
 | ||||
| /* tpd word 18:25 Custom Checksum task offload */ | ||||
| #define TPD_CCSUM_OFFSET_MASK	0x00FF | ||||
| #define TPD_CCSUM_OFFSET_SHIFT	18 | ||||
| #define TPD_CCSUM_EPAD_MASK	0x0001 | ||||
| #define TPD_CCSUM_EPAD_SHIFT	30 | ||||
| 
 | ||||
| /* tpd word 18:30 Large Send task offload (IPv4/IPV6) */ | ||||
| #define TPD_MSS_MASK            0x1FFF | ||||
| #define TPD_MSS_SHIFT		18 | ||||
| 
 | ||||
| #define TPD_EOP_MASK		0x0001 | ||||
| #define TPD_EOP_SHIFT		31 | ||||
| 
 | ||||
| struct atl1c_tpd_desc { | ||||
| 	__le16	buffer_len; /* include 4-byte CRC */ | ||||
| 	__le16	vlan_tag; | ||||
| 	__le32	word1; | ||||
| 	__le64	buffer_addr; | ||||
| }; | ||||
| 
 | ||||
| struct atl1c_tpd_ext_desc { | ||||
| 	u32 reservd_0; | ||||
| 	__le32 word1; | ||||
| 	__le32 pkt_len; | ||||
| 	u32 reservd_1; | ||||
| }; | ||||
| /* rrs word 0 bit 0:31 */ | ||||
| #define RRS_RX_CSUM_MASK	0xFFFF | ||||
| #define RRS_RX_CSUM_SHIFT	0 | ||||
| #define RRS_RX_RFD_CNT_MASK	0x000F | ||||
| #define RRS_RX_RFD_CNT_SHIFT	16 | ||||
| #define RRS_RX_RFD_INDEX_MASK	0x0FFF | ||||
| #define RRS_RX_RFD_INDEX_SHIFT	20 | ||||
| 
 | ||||
| /* rrs flag bit 0:16 */ | ||||
| #define RRS_HEAD_LEN_MASK	0x00FF | ||||
| #define RRS_HEAD_LEN_SHIFT	0 | ||||
| #define RRS_HDS_TYPE_MASK	0x0003 | ||||
| #define RRS_HDS_TYPE_SHIFT	8 | ||||
| #define RRS_CPU_NUM_MASK	0x0003 | ||||
| #define	RRS_CPU_NUM_SHIFT	10 | ||||
| #define RRS_HASH_FLG_MASK	0x000F | ||||
| #define RRS_HASH_FLG_SHIFT	12 | ||||
| 
 | ||||
| #define RRS_HDS_TYPE_HEAD	1 | ||||
| #define RRS_HDS_TYPE_DATA	2 | ||||
| 
 | ||||
| #define RRS_IS_NO_HDS_TYPE(flag) \ | ||||
| 	((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == 0) | ||||
| 
 | ||||
| #define RRS_IS_HDS_HEAD(flag) \ | ||||
| 	((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \ | ||||
| 			RRS_HDS_TYPE_HEAD) | ||||
| 
 | ||||
| #define RRS_IS_HDS_DATA(flag) \ | ||||
| 	((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \ | ||||
| 			RRS_HDS_TYPE_DATA) | ||||
| 
 | ||||
| /* rrs word 3 bit 0:31 */ | ||||
| #define RRS_PKT_SIZE_MASK	0x3FFF | ||||
| #define RRS_PKT_SIZE_SHIFT	0 | ||||
| #define RRS_ERR_L4_CSUM_MASK	0x0001 | ||||
| #define RRS_ERR_L4_CSUM_SHIFT	14 | ||||
| #define RRS_ERR_IP_CSUM_MASK	0x0001 | ||||
| #define RRS_ERR_IP_CSUM_SHIFT	15 | ||||
| #define RRS_VLAN_INS_MASK	0x0001 | ||||
| #define RRS_VLAN_INS_SHIFT	16 | ||||
| #define RRS_PROT_ID_MASK	0x0007 | ||||
| #define RRS_PROT_ID_SHIFT	17 | ||||
| #define RRS_RX_ERR_SUM_MASK	0x0001 | ||||
| #define RRS_RX_ERR_SUM_SHIFT	20 | ||||
| #define RRS_RX_ERR_CRC_MASK	0x0001 | ||||
| #define RRS_RX_ERR_CRC_SHIFT	21 | ||||
| #define RRS_RX_ERR_FAE_MASK	0x0001 | ||||
| #define RRS_RX_ERR_FAE_SHIFT	22 | ||||
| #define RRS_RX_ERR_TRUNC_MASK	0x0001 | ||||
| #define RRS_RX_ERR_TRUNC_SHIFT	23 | ||||
| #define RRS_RX_ERR_RUNC_MASK	0x0001 | ||||
| #define RRS_RX_ERR_RUNC_SHIFT	24 | ||||
| #define RRS_RX_ERR_ICMP_MASK	0x0001 | ||||
| #define RRS_RX_ERR_ICMP_SHIFT	25 | ||||
| #define RRS_PACKET_BCAST_MASK	0x0001 | ||||
| #define RRS_PACKET_BCAST_SHIFT	26 | ||||
| #define RRS_PACKET_MCAST_MASK	0x0001 | ||||
| #define RRS_PACKET_MCAST_SHIFT	27 | ||||
| #define RRS_PACKET_TYPE_MASK	0x0001 | ||||
| #define RRS_PACKET_TYPE_SHIFT	28 | ||||
| #define RRS_FIFO_FULL_MASK	0x0001 | ||||
| #define RRS_FIFO_FULL_SHIFT	29 | ||||
| #define RRS_802_3_LEN_ERR_MASK 	0x0001 | ||||
| #define RRS_802_3_LEN_ERR_SHIFT 30 | ||||
| #define RRS_RXD_UPDATED_MASK	0x0001 | ||||
| #define RRS_RXD_UPDATED_SHIFT	31 | ||||
| 
 | ||||
| #define RRS_ERR_L4_CSUM         0x00004000 | ||||
| #define RRS_ERR_IP_CSUM         0x00008000 | ||||
| #define RRS_VLAN_INS            0x00010000 | ||||
| #define RRS_RX_ERR_SUM          0x00100000 | ||||
| #define RRS_RX_ERR_CRC          0x00200000 | ||||
| #define RRS_802_3_LEN_ERR	0x40000000 | ||||
| #define RRS_RXD_UPDATED		0x80000000 | ||||
| 
 | ||||
| #define RRS_PACKET_TYPE_802_3  	1 | ||||
| #define RRS_PACKET_TYPE_ETH	0 | ||||
| #define RRS_PACKET_IS_ETH(word) \ | ||||
| 	((((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK) == \ | ||||
| 			RRS_PACKET_TYPE_ETH) | ||||
| #define RRS_RXD_IS_VALID(word) \ | ||||
| 	((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1) | ||||
| 
 | ||||
| #define RRS_PACKET_PROT_IS_IPV4_ONLY(word) \ | ||||
| 	((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 1) | ||||
| #define RRS_PACKET_PROT_IS_IPV6_ONLY(word) \ | ||||
| 	((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 6) | ||||
| 
 | ||||
| struct atl1c_recv_ret_status { | ||||
| 	__le32  word0; | ||||
| 	__le32	rss_hash; | ||||
| 	__le16	vlan_tag; | ||||
| 	__le16	flag; | ||||
| 	__le32	word3; | ||||
| }; | ||||
| 
 | ||||
| /* RFD descriptor */ | ||||
| struct atl1c_rx_free_desc { | ||||
| 	__le64	buffer_addr; | ||||
| }; | ||||
| 
 | ||||
| /* DMA Order Settings */ | ||||
| enum atl1c_dma_order { | ||||
| 	atl1c_dma_ord_in = 1, | ||||
| 	atl1c_dma_ord_enh = 2, | ||||
| 	atl1c_dma_ord_out = 4 | ||||
| }; | ||||
| 
 | ||||
| enum atl1c_dma_rcb { | ||||
| 	atl1c_rcb_64 = 0, | ||||
| 	atl1c_rcb_128 = 1 | ||||
| }; | ||||
| 
 | ||||
| enum atl1c_mac_speed { | ||||
| 	atl1c_mac_speed_0 = 0, | ||||
| 	atl1c_mac_speed_10_100 = 1, | ||||
| 	atl1c_mac_speed_1000 = 2 | ||||
| }; | ||||
| 
 | ||||
| enum atl1c_dma_req_block { | ||||
| 	atl1c_dma_req_128 = 0, | ||||
| 	atl1c_dma_req_256 = 1, | ||||
| 	atl1c_dma_req_512 = 2, | ||||
| 	atl1c_dma_req_1024 = 3, | ||||
| 	atl1c_dma_req_2048 = 4, | ||||
| 	atl1c_dma_req_4096 = 5 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| enum atl1c_nic_type { | ||||
| 	athr_l1c = 0, | ||||
| 	athr_l2c = 1, | ||||
| 	athr_l2c_b, | ||||
| 	athr_l2c_b2, | ||||
| 	athr_l1d, | ||||
| 	athr_l1d_2, | ||||
| }; | ||||
| 
 | ||||
| enum atl1c_trans_queue { | ||||
| 	atl1c_trans_normal = 0, | ||||
| 	atl1c_trans_high = 1 | ||||
| }; | ||||
| 
 | ||||
| struct atl1c_hw_stats { | ||||
| 	/* rx */ | ||||
| 	unsigned long rx_ok;		/* The number of good packet received. */ | ||||
| 	unsigned long rx_bcast;		/* The number of good broadcast packet received. */ | ||||
| 	unsigned long rx_mcast;		/* The number of good multicast packet received. */ | ||||
| 	unsigned long rx_pause;		/* The number of Pause packet received. */ | ||||
| 	unsigned long rx_ctrl;		/* The number of Control packet received other than Pause frame. */ | ||||
| 	unsigned long rx_fcs_err;	/* The number of packets with bad FCS. */ | ||||
| 	unsigned long rx_len_err;	/* The number of packets with mismatch of length field and actual size. */ | ||||
| 	unsigned long rx_byte_cnt;	/* The number of bytes of good packet received. FCS is NOT included. */ | ||||
| 	unsigned long rx_runt;		/* The number of packets received that are less than 64 byte long and with good FCS. */ | ||||
| 	unsigned long rx_frag;		/* The number of packets received that are less than 64 byte long and with bad FCS. */ | ||||
| 	unsigned long rx_sz_64;		/* The number of good and bad packets received that are 64 byte long. */ | ||||
| 	unsigned long rx_sz_65_127;	/* The number of good and bad packets received that are between 65 and 127-byte long. */ | ||||
| 	unsigned long rx_sz_128_255;	/* The number of good and bad packets received that are between 128 and 255-byte long. */ | ||||
| 	unsigned long rx_sz_256_511;	/* The number of good and bad packets received that are between 256 and 511-byte long. */ | ||||
| 	unsigned long rx_sz_512_1023;	/* The number of good and bad packets received that are between 512 and 1023-byte long. */ | ||||
| 	unsigned long rx_sz_1024_1518;	/* The number of good and bad packets received that are between 1024 and 1518-byte long. */ | ||||
| 	unsigned long rx_sz_1519_max;	/* The number of good and bad packets received that are between 1519-byte and MTU. */ | ||||
| 	unsigned long rx_sz_ov;		/* The number of good and bad packets received that are more than MTU size truncated by Selene. */ | ||||
| 	unsigned long rx_rxf_ov;	/* The number of frame dropped due to occurrence of RX FIFO overflow. */ | ||||
| 	unsigned long rx_rrd_ov;	/* The number of frame dropped due to occurrence of RRD overflow. */ | ||||
| 	unsigned long rx_align_err;	/* Alignment Error */ | ||||
| 	unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */ | ||||
| 	unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */ | ||||
| 	unsigned long rx_err_addr;	/* The number of packets dropped due to address filtering. */ | ||||
| 
 | ||||
| 	/* tx */ | ||||
| 	unsigned long tx_ok;		/* The number of good packet transmitted. */ | ||||
| 	unsigned long tx_bcast;		/* The number of good broadcast packet transmitted. */ | ||||
| 	unsigned long tx_mcast;		/* The number of good multicast packet transmitted. */ | ||||
| 	unsigned long tx_pause;		/* The number of Pause packet transmitted. */ | ||||
| 	unsigned long tx_exc_defer;	/* The number of packets transmitted with excessive deferral. */ | ||||
| 	unsigned long tx_ctrl;		/* The number of packets transmitted is a control frame, excluding Pause frame. */ | ||||
| 	unsigned long tx_defer;		/* The number of packets transmitted that is deferred. */ | ||||
| 	unsigned long tx_byte_cnt;	/* The number of bytes of data transmitted. FCS is NOT included. */ | ||||
| 	unsigned long tx_sz_64;		/* The number of good and bad packets transmitted that are 64 byte long. */ | ||||
| 	unsigned long tx_sz_65_127;	/* The number of good and bad packets transmitted that are between 65 and 127-byte long. */ | ||||
| 	unsigned long tx_sz_128_255;	/* The number of good and bad packets transmitted that are between 128 and 255-byte long. */ | ||||
| 	unsigned long tx_sz_256_511;	/* The number of good and bad packets transmitted that are between 256 and 511-byte long. */ | ||||
| 	unsigned long tx_sz_512_1023;	/* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */ | ||||
| 	unsigned long tx_sz_1024_1518;	/* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */ | ||||
| 	unsigned long tx_sz_1519_max;	/* The number of good and bad packets transmitted that are between 1519-byte and MTU. */ | ||||
| 	unsigned long tx_1_col;		/* The number of packets subsequently transmitted successfully with a single prior collision. */ | ||||
| 	unsigned long tx_2_col;		/* The number of packets subsequently transmitted successfully with multiple prior collisions. */ | ||||
| 	unsigned long tx_late_col;	/* The number of packets transmitted with late collisions. */ | ||||
| 	unsigned long tx_abort_col;	/* The number of transmit packets aborted due to excessive collisions. */ | ||||
| 	unsigned long tx_underrun;	/* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */ | ||||
| 	unsigned long tx_rd_eop;	/* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */ | ||||
| 	unsigned long tx_len_err;	/* The number of transmit packets with length field does NOT match the actual frame size. */ | ||||
| 	unsigned long tx_trunc;		/* The number of transmit packets truncated due to size exceeding MTU. */ | ||||
| 	unsigned long tx_bcast_byte;	/* The byte count of broadcast packet transmitted, excluding FCS. */ | ||||
| 	unsigned long tx_mcast_byte;	/* The byte count of multicast packet transmitted, excluding FCS. */ | ||||
| }; | ||||
| 
 | ||||
| struct atl1c_hw { | ||||
| 	u8 __iomem      *hw_addr;            /* inner register address */ | ||||
| 	struct atl1c_adapter *adapter; | ||||
| 	enum atl1c_nic_type  nic_type; | ||||
| 	enum atl1c_dma_order dma_order; | ||||
| 	enum atl1c_dma_rcb   rcb_value; | ||||
| 	enum atl1c_dma_req_block dmar_block; | ||||
| 
 | ||||
| 	u16 device_id; | ||||
| 	u16 vendor_id; | ||||
| 	u16 subsystem_id; | ||||
| 	u16 subsystem_vendor_id; | ||||
| 	u8 revision_id; | ||||
| 	u16 phy_id1; | ||||
| 	u16 phy_id2; | ||||
| 
 | ||||
| 	u32 intr_mask; | ||||
| 
 | ||||
| 	u8 preamble_len; | ||||
| 	u16 max_frame_size; | ||||
| 	u16 min_frame_size; | ||||
| 
 | ||||
| 	enum atl1c_mac_speed mac_speed; | ||||
| 	bool mac_duplex; | ||||
| 	bool hibernate; | ||||
| 	u16 media_type; | ||||
| #define MEDIA_TYPE_AUTO_SENSOR  0 | ||||
| #define MEDIA_TYPE_100M_FULL    1 | ||||
| #define MEDIA_TYPE_100M_HALF    2 | ||||
| #define MEDIA_TYPE_10M_FULL     3 | ||||
| #define MEDIA_TYPE_10M_HALF     4 | ||||
| 
 | ||||
| 	u16 autoneg_advertised; | ||||
| 	u16 mii_autoneg_adv_reg; | ||||
| 	u16 mii_1000t_ctrl_reg; | ||||
| 
 | ||||
| 	u16 tx_imt;	/* TX Interrupt Moderator timer ( 2us resolution) */ | ||||
| 	u16 rx_imt;	/* RX Interrupt Moderator timer ( 2us resolution) */ | ||||
| 	u16 ict;        /* Interrupt Clear timer (2us resolution) */ | ||||
| 	u16 ctrl_flags; | ||||
| #define ATL1C_INTR_CLEAR_ON_READ	0x0001 | ||||
| #define ATL1C_INTR_MODRT_ENABLE	 	0x0002 | ||||
| #define ATL1C_CMB_ENABLE		0x0004 | ||||
| #define ATL1C_SMB_ENABLE		0x0010 | ||||
| #define ATL1C_TXQ_MODE_ENHANCE		0x0020 | ||||
| #define ATL1C_RX_IPV6_CHKSUM		0x0040 | ||||
| #define ATL1C_ASPM_L0S_SUPPORT		0x0080 | ||||
| #define ATL1C_ASPM_L1_SUPPORT		0x0100 | ||||
| #define ATL1C_ASPM_CTRL_MON		0x0200 | ||||
| #define ATL1C_HIB_DISABLE		0x0400 | ||||
| #define ATL1C_APS_MODE_ENABLE           0x0800 | ||||
| #define ATL1C_LINK_EXT_SYNC             0x1000 | ||||
| #define ATL1C_CLK_GATING_EN             0x2000 | ||||
| #define ATL1C_FPGA_VERSION              0x8000 | ||||
| 	u16 link_cap_flags; | ||||
| #define ATL1C_LINK_CAP_1000M		0x0001 | ||||
| 	u32 smb_timer; | ||||
| 
 | ||||
| 	u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
 | ||||
| 			  interrupt request */ | ||||
| 	u16 tpd_thresh; | ||||
| 	u8 tpd_burst;   /* Number of TPD to prefetch in cache-aligned burst. */ | ||||
| 	u8 rfd_burst; | ||||
| 	u32 base_cpu; | ||||
| 	u32 indirect_tab; | ||||
| 	u8 mac_addr[ETH_ALEN]; | ||||
| 	u8 perm_mac_addr[ETH_ALEN]; | ||||
| 
 | ||||
| 	bool phy_configured; | ||||
| 	bool re_autoneg; | ||||
| 	bool emi_ca; | ||||
| 	bool msi_lnkpatch;	/* link patch for specific platforms */ | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * atl1c_ring_header represents a single, contiguous block of DMA space | ||||
|  * mapped for the three descriptor rings (tpd, rfd, rrd) described below | ||||
|  */ | ||||
| struct atl1c_ring_header { | ||||
| 	void *desc;		/* virtual address */ | ||||
| 	dma_addr_t dma;		/* physical address*/ | ||||
| 	unsigned int size;	/* length in bytes */ | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * atl1c_buffer is wrapper around a pointer to a socket buffer | ||||
|  * so a DMA handle can be stored along with the skb | ||||
|  */ | ||||
| struct atl1c_buffer { | ||||
| 	struct sk_buff *skb;	/* socket buffer */ | ||||
| 	u16 length;		/* rx buffer length */ | ||||
| 	u16 flags;		/* information of buffer */ | ||||
| #define ATL1C_BUFFER_FREE		0x0001 | ||||
| #define ATL1C_BUFFER_BUSY		0x0002 | ||||
| #define ATL1C_BUFFER_STATE_MASK		0x0003 | ||||
| 
 | ||||
| #define ATL1C_PCIMAP_SINGLE		0x0004 | ||||
| #define ATL1C_PCIMAP_PAGE		0x0008 | ||||
| #define ATL1C_PCIMAP_TYPE_MASK		0x000C | ||||
| 
 | ||||
| #define ATL1C_PCIMAP_TODEVICE		0x0010 | ||||
| #define ATL1C_PCIMAP_FROMDEVICE		0x0020 | ||||
| #define ATL1C_PCIMAP_DIRECTION_MASK	0x0030 | ||||
| 	dma_addr_t dma; | ||||
| }; | ||||
| 
 | ||||
| #define ATL1C_SET_BUFFER_STATE(buff, state) do {	\ | ||||
| 	((buff)->flags) &= ~ATL1C_BUFFER_STATE_MASK;	\ | ||||
| 	((buff)->flags) |= (state);			\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define ATL1C_SET_PCIMAP_TYPE(buff, type, direction) do {	\ | ||||
| 	((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK;		\ | ||||
| 	((buff)->flags) |= (type);				\ | ||||
| 	((buff)->flags) &= ~ATL1C_PCIMAP_DIRECTION_MASK;	\ | ||||
| 	((buff)->flags) |= (direction);				\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| /* transimit packet descriptor (tpd) ring */ | ||||
| struct atl1c_tpd_ring { | ||||
| 	void *desc;		/* descriptor ring virtual address */ | ||||
| 	dma_addr_t dma;		/* descriptor ring physical address */ | ||||
| 	u16 size;		/* descriptor ring length in bytes */ | ||||
| 	u16 count;		/* number of descriptors in the ring */ | ||||
| 	u16 next_to_use; 	/* this is protectd by adapter->tx_lock */ | ||||
| 	atomic_t next_to_clean; | ||||
| 	struct atl1c_buffer *buffer_info; | ||||
| }; | ||||
| 
 | ||||
| /* receive free descriptor (rfd) ring */ | ||||
| struct atl1c_rfd_ring { | ||||
| 	void *desc;		/* descriptor ring virtual address */ | ||||
| 	dma_addr_t dma;		/* descriptor ring physical address */ | ||||
| 	u16 size;		/* descriptor ring length in bytes */ | ||||
| 	u16 count;		/* number of descriptors in the ring */ | ||||
| 	u16 next_to_use; | ||||
| 	u16 next_to_clean; | ||||
| 	struct atl1c_buffer *buffer_info; | ||||
| }; | ||||
| 
 | ||||
| /* receive return descriptor (rrd) ring */ | ||||
| struct atl1c_rrd_ring { | ||||
| 	void *desc;		/* descriptor ring virtual address */ | ||||
| 	dma_addr_t dma;		/* descriptor ring physical address */ | ||||
| 	u16 size;		/* descriptor ring length in bytes */ | ||||
| 	u16 count;		/* number of descriptors in the ring */ | ||||
| 	u16 next_to_use; | ||||
| 	u16 next_to_clean; | ||||
| }; | ||||
| 
 | ||||
| /* board specific private data structure */ | ||||
| struct atl1c_adapter { | ||||
| 	struct net_device   *netdev; | ||||
| 	struct pci_dev      *pdev; | ||||
| 	struct napi_struct  napi; | ||||
| 	struct page         *rx_page; | ||||
| 	unsigned int	    rx_page_offset; | ||||
| 	unsigned int	    rx_frag_size; | ||||
| 	struct atl1c_hw        hw; | ||||
| 	struct atl1c_hw_stats  hw_stats; | ||||
| 	struct mii_if_info  mii;    /* MII interface info */ | ||||
| 	u16 rx_buffer_len; | ||||
| 
 | ||||
| 	unsigned long flags; | ||||
| #define __AT_TESTING        0x0001 | ||||
| #define __AT_RESETTING      0x0002 | ||||
| #define __AT_DOWN           0x0003 | ||||
| 	unsigned long work_event; | ||||
| #define	ATL1C_WORK_EVENT_RESET		0 | ||||
| #define	ATL1C_WORK_EVENT_LINK_CHANGE	1 | ||||
| 	u32 msg_enable; | ||||
| 
 | ||||
| 	bool have_msi; | ||||
| 	u32 wol; | ||||
| 	u16 link_speed; | ||||
| 	u16 link_duplex; | ||||
| 
 | ||||
| 	spinlock_t mdio_lock; | ||||
| 	spinlock_t tx_lock; | ||||
| 	atomic_t irq_sem; | ||||
| 
 | ||||
| 	struct work_struct common_task; | ||||
| 	struct timer_list watchdog_timer; | ||||
| 	struct timer_list phy_config_timer; | ||||
| 
 | ||||
| 	/* All Descriptor memory */ | ||||
| 	struct atl1c_ring_header ring_header; | ||||
| 	struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE]; | ||||
| 	struct atl1c_rfd_ring rfd_ring; | ||||
| 	struct atl1c_rrd_ring rrd_ring; | ||||
| 	u32 bd_number;     /* board number;*/ | ||||
| }; | ||||
| 
 | ||||
| #define AT_WRITE_REG(a, reg, value) ( \ | ||||
| 		writel((value), ((a)->hw_addr + reg))) | ||||
| 
 | ||||
| #define AT_WRITE_FLUSH(a) (\ | ||||
| 		readl((a)->hw_addr)) | ||||
| 
 | ||||
| #define AT_READ_REG(a, reg, pdata) do {					\ | ||||
| 		if (unlikely((a)->hibernate)) {				\ | ||||
| 			readl((a)->hw_addr + reg);			\ | ||||
| 			*(u32 *)pdata = readl((a)->hw_addr + reg);	\ | ||||
| 		} else {						\ | ||||
| 			*(u32 *)pdata = readl((a)->hw_addr + reg);	\ | ||||
| 		}							\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define AT_WRITE_REGB(a, reg, value) (\ | ||||
| 		writeb((value), ((a)->hw_addr + reg))) | ||||
| 
 | ||||
| #define AT_READ_REGB(a, reg) (\ | ||||
| 		readb((a)->hw_addr + reg)) | ||||
| 
 | ||||
| #define AT_WRITE_REGW(a, reg, value) (\ | ||||
| 		writew((value), ((a)->hw_addr + reg))) | ||||
| 
 | ||||
| #define AT_READ_REGW(a, reg, pdata) do {				\ | ||||
| 		if (unlikely((a)->hibernate)) {				\ | ||||
| 			readw((a)->hw_addr + reg);			\ | ||||
| 			*(u16 *)pdata = readw((a)->hw_addr + reg);	\ | ||||
| 		} else {						\ | ||||
| 			*(u16 *)pdata = readw((a)->hw_addr + reg);	\ | ||||
| 		}							\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \ | ||||
| 		writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))) | ||||
| 
 | ||||
| #define AT_READ_REG_ARRAY(a, reg, offset) ( \ | ||||
| 		readl(((a)->hw_addr + reg) + ((offset) << 2))) | ||||
| 
 | ||||
| extern char atl1c_driver_name[]; | ||||
| extern char atl1c_driver_version[]; | ||||
| 
 | ||||
| void atl1c_reinit_locked(struct atl1c_adapter *adapter); | ||||
| s32 atl1c_reset_hw(struct atl1c_hw *hw); | ||||
| void atl1c_set_ethtool_ops(struct net_device *netdev); | ||||
| #endif /* _ATL1C_H_ */ | ||||
							
								
								
									
										309
									
								
								drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										309
									
								
								drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,309 @@ | |||
| /*
 | ||||
|  * Copyright(c) 2009 - 2009 Atheros Corporation. All rights reserved. | ||||
|  * | ||||
|  * Derived from Intel e1000 driver | ||||
|  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the Free | ||||
|  * Software Foundation; either version 2 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., 59 | ||||
|  * Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/ethtool.h> | ||||
| #include <linux/slab.h> | ||||
| 
 | ||||
| #include "atl1c.h" | ||||
| 
 | ||||
| static int atl1c_get_settings(struct net_device *netdev, | ||||
| 			      struct ethtool_cmd *ecmd) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = netdev_priv(netdev); | ||||
| 	struct atl1c_hw *hw = &adapter->hw; | ||||
| 
 | ||||
| 	ecmd->supported = (SUPPORTED_10baseT_Half  | | ||||
| 			   SUPPORTED_10baseT_Full  | | ||||
| 			   SUPPORTED_100baseT_Half | | ||||
| 			   SUPPORTED_100baseT_Full | | ||||
| 			   SUPPORTED_Autoneg       | | ||||
| 			   SUPPORTED_TP); | ||||
| 	if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) | ||||
| 		ecmd->supported |= SUPPORTED_1000baseT_Full; | ||||
| 
 | ||||
| 	ecmd->advertising = ADVERTISED_TP; | ||||
| 
 | ||||
| 	ecmd->advertising |= hw->autoneg_advertised; | ||||
| 
 | ||||
| 	ecmd->port = PORT_TP; | ||||
| 	ecmd->phy_address = 0; | ||||
| 	ecmd->transceiver = XCVR_INTERNAL; | ||||
| 
 | ||||
| 	if (adapter->link_speed != SPEED_0) { | ||||
| 		ethtool_cmd_speed_set(ecmd, adapter->link_speed); | ||||
| 		if (adapter->link_duplex == FULL_DUPLEX) | ||||
| 			ecmd->duplex = DUPLEX_FULL; | ||||
| 		else | ||||
| 			ecmd->duplex = DUPLEX_HALF; | ||||
| 	} else { | ||||
| 		ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); | ||||
| 		ecmd->duplex = DUPLEX_UNKNOWN; | ||||
| 	} | ||||
| 
 | ||||
| 	ecmd->autoneg = AUTONEG_ENABLE; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int atl1c_set_settings(struct net_device *netdev, | ||||
| 			      struct ethtool_cmd *ecmd) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = netdev_priv(netdev); | ||||
| 	struct atl1c_hw *hw = &adapter->hw; | ||||
| 	u16  autoneg_advertised; | ||||
| 
 | ||||
| 	while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) | ||||
| 		msleep(1); | ||||
| 
 | ||||
| 	if (ecmd->autoneg == AUTONEG_ENABLE) { | ||||
| 		autoneg_advertised = ADVERTISED_Autoneg; | ||||
| 	} else { | ||||
| 		u32 speed = ethtool_cmd_speed(ecmd); | ||||
| 		if (speed == SPEED_1000) { | ||||
| 			if (ecmd->duplex != DUPLEX_FULL) { | ||||
| 				if (netif_msg_link(adapter)) | ||||
| 					dev_warn(&adapter->pdev->dev, | ||||
| 						"1000M half is invalid\n"); | ||||
| 				clear_bit(__AT_RESETTING, &adapter->flags); | ||||
| 				return -EINVAL; | ||||
| 			} | ||||
| 			autoneg_advertised = ADVERTISED_1000baseT_Full; | ||||
| 		} else if (speed == SPEED_100) { | ||||
| 			if (ecmd->duplex == DUPLEX_FULL) | ||||
| 				autoneg_advertised = ADVERTISED_100baseT_Full; | ||||
| 			else | ||||
| 				autoneg_advertised = ADVERTISED_100baseT_Half; | ||||
| 		} else { | ||||
| 			if (ecmd->duplex == DUPLEX_FULL) | ||||
| 				autoneg_advertised = ADVERTISED_10baseT_Full; | ||||
| 			else | ||||
| 				autoneg_advertised = ADVERTISED_10baseT_Half; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (hw->autoneg_advertised != autoneg_advertised) { | ||||
| 		hw->autoneg_advertised = autoneg_advertised; | ||||
| 		if (atl1c_restart_autoneg(hw) != 0) { | ||||
| 			if (netif_msg_link(adapter)) | ||||
| 				dev_warn(&adapter->pdev->dev, | ||||
| 					"ethtool speed/duplex setting failed\n"); | ||||
| 			clear_bit(__AT_RESETTING, &adapter->flags); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 	} | ||||
| 	clear_bit(__AT_RESETTING, &adapter->flags); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static u32 atl1c_get_msglevel(struct net_device *netdev) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = netdev_priv(netdev); | ||||
| 	return adapter->msg_enable; | ||||
| } | ||||
| 
 | ||||
| static void atl1c_set_msglevel(struct net_device *netdev, u32 data) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = netdev_priv(netdev); | ||||
| 	adapter->msg_enable = data; | ||||
| } | ||||
| 
 | ||||
| static int atl1c_get_regs_len(struct net_device *netdev) | ||||
| { | ||||
| 	return AT_REGS_LEN; | ||||
| } | ||||
| 
 | ||||
| static void atl1c_get_regs(struct net_device *netdev, | ||||
| 			   struct ethtool_regs *regs, void *p) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = netdev_priv(netdev); | ||||
| 	struct atl1c_hw *hw = &adapter->hw; | ||||
| 	u32 *regs_buff = p; | ||||
| 	u16 phy_data; | ||||
| 
 | ||||
| 	memset(p, 0, AT_REGS_LEN); | ||||
| 
 | ||||
| 	regs->version = 1; | ||||
| 	AT_READ_REG(hw, REG_PM_CTRL, 		  p++); | ||||
| 	AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL,  p++); | ||||
| 	AT_READ_REG(hw, REG_TWSI_CTRL, 		  p++); | ||||
| 	AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL,   p++); | ||||
| 	AT_READ_REG(hw, REG_MASTER_CTRL, 	  p++); | ||||
| 	AT_READ_REG(hw, REG_MANUAL_TIMER_INIT,    p++); | ||||
| 	AT_READ_REG(hw, REG_IRQ_MODRT_TIMER_INIT, p++); | ||||
| 	AT_READ_REG(hw, REG_GPHY_CTRL, 		  p++); | ||||
| 	AT_READ_REG(hw, REG_LINK_CTRL, 		  p++); | ||||
| 	AT_READ_REG(hw, REG_IDLE_STATUS, 	  p++); | ||||
| 	AT_READ_REG(hw, REG_MDIO_CTRL, 		  p++); | ||||
| 	AT_READ_REG(hw, REG_SERDES,		  p++); | ||||
| 	AT_READ_REG(hw, REG_MAC_CTRL, 		  p++); | ||||
| 	AT_READ_REG(hw, REG_MAC_IPG_IFG, 	  p++); | ||||
| 	AT_READ_REG(hw, REG_MAC_STA_ADDR, 	  p++); | ||||
| 	AT_READ_REG(hw, REG_MAC_STA_ADDR+4, 	  p++); | ||||
| 	AT_READ_REG(hw, REG_RX_HASH_TABLE, 	  p++); | ||||
| 	AT_READ_REG(hw, REG_RX_HASH_TABLE+4, 	  p++); | ||||
| 	AT_READ_REG(hw, REG_RXQ_CTRL, 		  p++); | ||||
| 	AT_READ_REG(hw, REG_TXQ_CTRL, 		  p++); | ||||
| 	AT_READ_REG(hw, REG_MTU, 		  p++); | ||||
| 	AT_READ_REG(hw, REG_WOL_CTRL, 		  p++); | ||||
| 
 | ||||
| 	atl1c_read_phy_reg(hw, MII_BMCR, &phy_data); | ||||
| 	regs_buff[AT_REGS_LEN/sizeof(u32) - 2] = (u32) phy_data; | ||||
| 	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); | ||||
| 	regs_buff[AT_REGS_LEN/sizeof(u32) - 1] = (u32) phy_data; | ||||
| } | ||||
| 
 | ||||
| static int atl1c_get_eeprom_len(struct net_device *netdev) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = netdev_priv(netdev); | ||||
| 
 | ||||
| 	if (atl1c_check_eeprom_exist(&adapter->hw)) | ||||
| 		return AT_EEPROM_LEN; | ||||
| 	else | ||||
| 		return 0; | ||||
| } | ||||
| 
 | ||||
| static int atl1c_get_eeprom(struct net_device *netdev, | ||||
| 		struct ethtool_eeprom *eeprom, u8 *bytes) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = netdev_priv(netdev); | ||||
| 	struct atl1c_hw *hw = &adapter->hw; | ||||
| 	u32 *eeprom_buff; | ||||
| 	int first_dword, last_dword; | ||||
| 	int ret_val = 0; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (eeprom->len == 0) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	if (!atl1c_check_eeprom_exist(hw)) /* not exist */ | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	eeprom->magic = adapter->pdev->vendor | | ||||
| 			(adapter->pdev->device << 16); | ||||
| 
 | ||||
| 	first_dword = eeprom->offset >> 2; | ||||
| 	last_dword = (eeprom->offset + eeprom->len - 1) >> 2; | ||||
| 
 | ||||
| 	eeprom_buff = kmalloc(sizeof(u32) * | ||||
| 			(last_dword - first_dword + 1), GFP_KERNEL); | ||||
| 	if (eeprom_buff == NULL) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	for (i = first_dword; i < last_dword; i++) { | ||||
| 		if (!atl1c_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) { | ||||
| 			kfree(eeprom_buff); | ||||
| 			return -EIO; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3), | ||||
| 			eeprom->len); | ||||
| 	kfree(eeprom_buff); | ||||
| 
 | ||||
| 	return ret_val; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void atl1c_get_drvinfo(struct net_device *netdev, | ||||
| 		struct ethtool_drvinfo *drvinfo) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = netdev_priv(netdev); | ||||
| 
 | ||||
| 	strlcpy(drvinfo->driver,  atl1c_driver_name, sizeof(drvinfo->driver)); | ||||
| 	strlcpy(drvinfo->version, atl1c_driver_version, | ||||
| 		sizeof(drvinfo->version)); | ||||
| 	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), | ||||
| 		sizeof(drvinfo->bus_info)); | ||||
| 	drvinfo->n_stats = 0; | ||||
| 	drvinfo->testinfo_len = 0; | ||||
| 	drvinfo->regdump_len = atl1c_get_regs_len(netdev); | ||||
| 	drvinfo->eedump_len = atl1c_get_eeprom_len(netdev); | ||||
| } | ||||
| 
 | ||||
| static void atl1c_get_wol(struct net_device *netdev, | ||||
| 			  struct ethtool_wolinfo *wol) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = netdev_priv(netdev); | ||||
| 
 | ||||
| 	wol->supported = WAKE_MAGIC | WAKE_PHY; | ||||
| 	wol->wolopts = 0; | ||||
| 
 | ||||
| 	if (adapter->wol & AT_WUFC_EX) | ||||
| 		wol->wolopts |= WAKE_UCAST; | ||||
| 	if (adapter->wol & AT_WUFC_MC) | ||||
| 		wol->wolopts |= WAKE_MCAST; | ||||
| 	if (adapter->wol & AT_WUFC_BC) | ||||
| 		wol->wolopts |= WAKE_BCAST; | ||||
| 	if (adapter->wol & AT_WUFC_MAG) | ||||
| 		wol->wolopts |= WAKE_MAGIC; | ||||
| 	if (adapter->wol & AT_WUFC_LNKC) | ||||
| 		wol->wolopts |= WAKE_PHY; | ||||
| } | ||||
| 
 | ||||
| static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = netdev_priv(netdev); | ||||
| 
 | ||||
| 	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | | ||||
| 			    WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)) | ||||
| 		return -EOPNOTSUPP; | ||||
| 	/* these settings will always override what we currently have */ | ||||
| 	adapter->wol = 0; | ||||
| 
 | ||||
| 	if (wol->wolopts & WAKE_MAGIC) | ||||
| 		adapter->wol |= AT_WUFC_MAG; | ||||
| 	if (wol->wolopts & WAKE_PHY) | ||||
| 		adapter->wol |= AT_WUFC_LNKC; | ||||
| 
 | ||||
| 	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int atl1c_nway_reset(struct net_device *netdev) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = netdev_priv(netdev); | ||||
| 	if (netif_running(netdev)) | ||||
| 		atl1c_reinit_locked(adapter); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static const struct ethtool_ops atl1c_ethtool_ops = { | ||||
| 	.get_settings           = atl1c_get_settings, | ||||
| 	.set_settings           = atl1c_set_settings, | ||||
| 	.get_drvinfo            = atl1c_get_drvinfo, | ||||
| 	.get_regs_len           = atl1c_get_regs_len, | ||||
| 	.get_regs               = atl1c_get_regs, | ||||
| 	.get_wol                = atl1c_get_wol, | ||||
| 	.set_wol                = atl1c_set_wol, | ||||
| 	.get_msglevel           = atl1c_get_msglevel, | ||||
| 	.set_msglevel           = atl1c_set_msglevel, | ||||
| 	.nway_reset             = atl1c_nway_reset, | ||||
| 	.get_link               = ethtool_op_get_link, | ||||
| 	.get_eeprom_len         = atl1c_get_eeprom_len, | ||||
| 	.get_eeprom             = atl1c_get_eeprom, | ||||
| }; | ||||
| 
 | ||||
| void atl1c_set_ethtool_ops(struct net_device *netdev) | ||||
| { | ||||
| 	netdev->ethtool_ops = &atl1c_ethtool_ops; | ||||
| } | ||||
							
								
								
									
										863
									
								
								drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										863
									
								
								drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,863 @@ | |||
| /*
 | ||||
|  * Copyright(c) 2007 Atheros Corporation. All rights reserved. | ||||
|  * | ||||
|  * Derived from Intel e1000 driver | ||||
|  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the Free | ||||
|  * Software Foundation; either version 2 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., 59 | ||||
|  * Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||
|  */ | ||||
| #include <linux/pci.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/mii.h> | ||||
| #include <linux/crc32.h> | ||||
| 
 | ||||
| #include "atl1c.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * check_eeprom_exist | ||||
|  * return 1 if eeprom exist | ||||
|  */ | ||||
| int atl1c_check_eeprom_exist(struct atl1c_hw *hw) | ||||
| { | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	AT_READ_REG(hw, REG_TWSI_DEBUG, &data); | ||||
| 	if (data & TWSI_DEBUG_DEV_EXIST) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	AT_READ_REG(hw, REG_MASTER_CTRL, &data); | ||||
| 	if (data & MASTER_CTRL_OTP_SEL) | ||||
| 		return 1; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr) | ||||
| { | ||||
| 	u32 value; | ||||
| 	/*
 | ||||
| 	 * 00-0B-6A-F6-00-DC | ||||
| 	 * 0:  6AF600DC 1: 000B | ||||
| 	 * low dword | ||||
| 	 */ | ||||
| 	value = mac_addr[2] << 24 | | ||||
| 		mac_addr[3] << 16 | | ||||
| 		mac_addr[4] << 8  | | ||||
| 		mac_addr[5]; | ||||
| 	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); | ||||
| 	/* hight dword */ | ||||
| 	value = mac_addr[0] << 8 | | ||||
| 		mac_addr[1]; | ||||
| 	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); | ||||
| } | ||||
| 
 | ||||
| /* read mac address from hardware register */ | ||||
| static bool atl1c_read_current_addr(struct atl1c_hw *hw, u8 *eth_addr) | ||||
| { | ||||
| 	u32 addr[2]; | ||||
| 
 | ||||
| 	AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]); | ||||
| 	AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]); | ||||
| 
 | ||||
| 	*(u32 *) ð_addr[2] = htonl(addr[0]); | ||||
| 	*(u16 *) ð_addr[0] = htons((u16)addr[1]); | ||||
| 
 | ||||
| 	return is_valid_ether_addr(eth_addr); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * atl1c_get_permanent_address | ||||
|  * return 0 if get valid mac address, | ||||
|  */ | ||||
| static int atl1c_get_permanent_address(struct atl1c_hw *hw) | ||||
| { | ||||
| 	u32 i; | ||||
| 	u32 otp_ctrl_data; | ||||
| 	u32 twsi_ctrl_data; | ||||
| 	u16 phy_data; | ||||
| 	bool raise_vol = false; | ||||
| 
 | ||||
| 	/* MAC-address from BIOS is the 1st priority */ | ||||
| 	if (atl1c_read_current_addr(hw, hw->perm_mac_addr)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* init */ | ||||
| 	AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data); | ||||
| 	if (atl1c_check_eeprom_exist(hw)) { | ||||
| 		if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) { | ||||
| 			/* Enable OTP CLK */ | ||||
| 			if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) { | ||||
| 				otp_ctrl_data |= OTP_CTRL_CLK_EN; | ||||
| 				AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); | ||||
| 				AT_WRITE_FLUSH(hw); | ||||
| 				msleep(1); | ||||
| 			} | ||||
| 		} | ||||
| 		/* raise voltage temporally for l2cb */ | ||||
| 		if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { | ||||
| 			atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data); | ||||
| 			phy_data &= ~ANACTRL_HB_EN; | ||||
| 			atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data); | ||||
| 			atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); | ||||
| 			phy_data |= VOLT_CTRL_SWLOWEST; | ||||
| 			atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); | ||||
| 			udelay(20); | ||||
| 			raise_vol = true; | ||||
| 		} | ||||
| 
 | ||||
| 		AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); | ||||
| 		twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART; | ||||
| 		AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data); | ||||
| 		for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) { | ||||
| 			msleep(10); | ||||
| 			AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); | ||||
| 			if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0) | ||||
| 				break; | ||||
| 		} | ||||
| 		if (i >= AT_TWSI_EEPROM_TIMEOUT) | ||||
| 			return -1; | ||||
| 	} | ||||
| 	/* Disable OTP_CLK */ | ||||
| 	if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) { | ||||
| 		otp_ctrl_data &= ~OTP_CTRL_CLK_EN; | ||||
| 		AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); | ||||
| 		msleep(1); | ||||
| 	} | ||||
| 	if (raise_vol) { | ||||
| 		atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data); | ||||
| 		phy_data |= ANACTRL_HB_EN; | ||||
| 		atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data); | ||||
| 		atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); | ||||
| 		phy_data &= ~VOLT_CTRL_SWLOWEST; | ||||
| 		atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); | ||||
| 		udelay(20); | ||||
| 	} | ||||
| 
 | ||||
| 	if (atl1c_read_current_addr(hw, hw->perm_mac_addr)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value) | ||||
| { | ||||
| 	int i; | ||||
| 	bool ret = false; | ||||
| 	u32 otp_ctrl_data; | ||||
| 	u32 control; | ||||
| 	u32 data; | ||||
| 
 | ||||
| 	if (offset & 3) | ||||
| 		return ret; /* address do not align */ | ||||
| 
 | ||||
| 	AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data); | ||||
| 	if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) | ||||
| 		AT_WRITE_REG(hw, REG_OTP_CTRL, | ||||
| 				(otp_ctrl_data | OTP_CTRL_CLK_EN)); | ||||
| 
 | ||||
| 	AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0); | ||||
| 	control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT; | ||||
| 	AT_WRITE_REG(hw, REG_EEPROM_CTRL, control); | ||||
| 
 | ||||
| 	for (i = 0; i < 10; i++) { | ||||
| 		udelay(100); | ||||
| 		AT_READ_REG(hw, REG_EEPROM_CTRL, &control); | ||||
| 		if (control & EEPROM_CTRL_RW) | ||||
| 			break; | ||||
| 	} | ||||
| 	if (control & EEPROM_CTRL_RW) { | ||||
| 		AT_READ_REG(hw, REG_EEPROM_CTRL, &data); | ||||
| 		AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value); | ||||
| 		data = data & 0xFFFF; | ||||
| 		*p_value = swab32((data << 16) | (*p_value >> 16)); | ||||
| 		ret = true; | ||||
| 	} | ||||
| 	if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) | ||||
| 		AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| /*
 | ||||
|  * Reads the adapter's MAC address from the EEPROM | ||||
|  * | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  */ | ||||
| int atl1c_read_mac_addr(struct atl1c_hw *hw) | ||||
| { | ||||
| 	int err = 0; | ||||
| 
 | ||||
| 	err = atl1c_get_permanent_address(hw); | ||||
| 	if (err) | ||||
| 		eth_random_addr(hw->perm_mac_addr); | ||||
| 
 | ||||
| 	memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr)); | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * atl1c_hash_mc_addr | ||||
|  *  purpose | ||||
|  *      set hash value for a multicast address | ||||
|  *      hash calcu processing : | ||||
|  *          1. calcu 32bit CRC for multicast address | ||||
|  *          2. reverse crc with MSB to LSB | ||||
|  */ | ||||
| u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr) | ||||
| { | ||||
| 	u32 crc32; | ||||
| 	u32 value = 0; | ||||
| 	int i; | ||||
| 
 | ||||
| 	crc32 = ether_crc_le(6, mc_addr); | ||||
| 	for (i = 0; i < 32; i++) | ||||
| 		value |= (((crc32 >> i) & 1) << (31 - i)); | ||||
| 
 | ||||
| 	return value; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Sets the bit in the multicast table corresponding to the hash value. | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  * hash_value - Multicast address hash value | ||||
|  */ | ||||
| void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value) | ||||
| { | ||||
| 	u32 hash_bit, hash_reg; | ||||
| 	u32 mta; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * The HASH Table  is a register array of 2 32-bit registers. | ||||
| 	 * It is treated like an array of 64 bits.  We want to set | ||||
| 	 * bit BitArray[hash_value]. So we figure out what register | ||||
| 	 * the bit is in, read it, OR in the new bit, then write | ||||
| 	 * back the new value.  The register is determined by the | ||||
| 	 * upper bit of the hash value and the bit within that | ||||
| 	 * register are determined by the lower 5 bits of the value. | ||||
| 	 */ | ||||
| 	hash_reg = (hash_value >> 31) & 0x1; | ||||
| 	hash_bit = (hash_value >> 26) & 0x1F; | ||||
| 
 | ||||
| 	mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg); | ||||
| 
 | ||||
| 	mta |= (1 << hash_bit); | ||||
| 
 | ||||
| 	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * wait mdio module be idle | ||||
|  * return true: idle | ||||
|  *        false: still busy | ||||
|  */ | ||||
| bool atl1c_wait_mdio_idle(struct atl1c_hw *hw) | ||||
| { | ||||
| 	u32 val; | ||||
| 	int i; | ||||
| 
 | ||||
| 	for (i = 0; i < MDIO_MAX_AC_TO; i++) { | ||||
| 		AT_READ_REG(hw, REG_MDIO_CTRL, &val); | ||||
| 		if (!(val & (MDIO_CTRL_BUSY | MDIO_CTRL_START))) | ||||
| 			break; | ||||
| 		udelay(10); | ||||
| 	} | ||||
| 
 | ||||
| 	return i != MDIO_MAX_AC_TO; | ||||
| } | ||||
| 
 | ||||
| void atl1c_stop_phy_polling(struct atl1c_hw *hw) | ||||
| { | ||||
| 	if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) | ||||
| 		return; | ||||
| 
 | ||||
| 	AT_WRITE_REG(hw, REG_MDIO_CTRL, 0); | ||||
| 	atl1c_wait_mdio_idle(hw); | ||||
| } | ||||
| 
 | ||||
| void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel) | ||||
| { | ||||
| 	u32 val; | ||||
| 
 | ||||
| 	if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) | ||||
| 		return; | ||||
| 
 | ||||
| 	val = MDIO_CTRL_SPRES_PRMBL | | ||||
| 		FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | | ||||
| 		FIELDX(MDIO_CTRL_REG, 1) | | ||||
| 		MDIO_CTRL_START | | ||||
| 		MDIO_CTRL_OP_READ; | ||||
| 	AT_WRITE_REG(hw, REG_MDIO_CTRL, val); | ||||
| 	atl1c_wait_mdio_idle(hw); | ||||
| 	val |= MDIO_CTRL_AP_EN; | ||||
| 	val &= ~MDIO_CTRL_START; | ||||
| 	AT_WRITE_REG(hw, REG_MDIO_CTRL, val); | ||||
| 	udelay(30); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * atl1c_read_phy_core | ||||
|  * core funtion to read register in PHY via MDIO control regsiter. | ||||
|  * ext: extension register (see IEEE 802.3) | ||||
|  * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0) | ||||
|  * reg: reg to read | ||||
|  */ | ||||
| int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, | ||||
| 			u16 reg, u16 *phy_data) | ||||
| { | ||||
| 	u32 val; | ||||
| 	u16 clk_sel = MDIO_CTRL_CLK_25_4; | ||||
| 
 | ||||
| 	atl1c_stop_phy_polling(hw); | ||||
| 
 | ||||
| 	*phy_data = 0; | ||||
| 
 | ||||
| 	/* only l2c_b2 & l1d_2 could use slow clock */ | ||||
| 	if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) && | ||||
| 		hw->hibernate) | ||||
| 		clk_sel = MDIO_CTRL_CLK_25_128; | ||||
| 	if (ext) { | ||||
| 		val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg); | ||||
| 		AT_WRITE_REG(hw, REG_MDIO_EXTN, val); | ||||
| 		val = MDIO_CTRL_SPRES_PRMBL | | ||||
| 			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | | ||||
| 			MDIO_CTRL_START | | ||||
| 			MDIO_CTRL_MODE_EXT | | ||||
| 			MDIO_CTRL_OP_READ; | ||||
| 	} else { | ||||
| 		val = MDIO_CTRL_SPRES_PRMBL | | ||||
| 			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | | ||||
| 			FIELDX(MDIO_CTRL_REG, reg) | | ||||
| 			MDIO_CTRL_START | | ||||
| 			MDIO_CTRL_OP_READ; | ||||
| 	} | ||||
| 	AT_WRITE_REG(hw, REG_MDIO_CTRL, val); | ||||
| 
 | ||||
| 	if (!atl1c_wait_mdio_idle(hw)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	AT_READ_REG(hw, REG_MDIO_CTRL, &val); | ||||
| 	*phy_data = (u16)FIELD_GETX(val, MDIO_CTRL_DATA); | ||||
| 
 | ||||
| 	atl1c_start_phy_polling(hw, clk_sel); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * atl1c_write_phy_core | ||||
|  * core funtion to write to register in PHY via MDIO control regsiter. | ||||
|  * ext: extension register (see IEEE 802.3) | ||||
|  * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0) | ||||
|  * reg: reg to write | ||||
|  */ | ||||
| int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, | ||||
| 			u16 reg, u16 phy_data) | ||||
| { | ||||
| 	u32 val; | ||||
| 	u16 clk_sel = MDIO_CTRL_CLK_25_4; | ||||
| 
 | ||||
| 	atl1c_stop_phy_polling(hw); | ||||
| 
 | ||||
| 
 | ||||
| 	/* only l2c_b2 & l1d_2 could use slow clock */ | ||||
| 	if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) && | ||||
| 		hw->hibernate) | ||||
| 		clk_sel = MDIO_CTRL_CLK_25_128; | ||||
| 
 | ||||
| 	if (ext) { | ||||
| 		val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg); | ||||
| 		AT_WRITE_REG(hw, REG_MDIO_EXTN, val); | ||||
| 		val = MDIO_CTRL_SPRES_PRMBL | | ||||
| 			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | | ||||
| 			FIELDX(MDIO_CTRL_DATA, phy_data) | | ||||
| 			MDIO_CTRL_START | | ||||
| 			MDIO_CTRL_MODE_EXT; | ||||
| 	} else { | ||||
| 		val = MDIO_CTRL_SPRES_PRMBL | | ||||
| 			FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | | ||||
| 			FIELDX(MDIO_CTRL_DATA, phy_data) | | ||||
| 			FIELDX(MDIO_CTRL_REG, reg) | | ||||
| 			MDIO_CTRL_START; | ||||
| 	} | ||||
| 	AT_WRITE_REG(hw, REG_MDIO_CTRL, val); | ||||
| 
 | ||||
| 	if (!atl1c_wait_mdio_idle(hw)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	atl1c_start_phy_polling(hw, clk_sel); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Reads the value from a PHY register | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  * reg_addr - address of the PHY register to read | ||||
|  */ | ||||
| int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) | ||||
| { | ||||
| 	return atl1c_read_phy_core(hw, false, 0, reg_addr, phy_data); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Writes a value to a PHY register | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  * reg_addr - address of the PHY register to write | ||||
|  * data - data to write to the PHY | ||||
|  */ | ||||
| int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data) | ||||
| { | ||||
| 	return atl1c_write_phy_core(hw, false, 0, reg_addr, phy_data); | ||||
| } | ||||
| 
 | ||||
| /* read from PHY extension register */ | ||||
| int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr, | ||||
| 			u16 reg_addr, u16 *phy_data) | ||||
| { | ||||
| 	return atl1c_read_phy_core(hw, true, dev_addr, reg_addr, phy_data); | ||||
| } | ||||
| 
 | ||||
| /* write to PHY extension register */ | ||||
| int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr, | ||||
| 			u16 reg_addr, u16 phy_data) | ||||
| { | ||||
| 	return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data); | ||||
| } | ||||
| 
 | ||||
| int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) | ||||
| { | ||||
| 	int err; | ||||
| 
 | ||||
| 	err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr); | ||||
| 	if (unlikely(err)) | ||||
| 		return err; | ||||
| 	else | ||||
| 		err = atl1c_read_phy_reg(hw, MII_DBG_DATA, phy_data); | ||||
| 
 | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data) | ||||
| { | ||||
| 	int err; | ||||
| 
 | ||||
| 	err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr); | ||||
| 	if (unlikely(err)) | ||||
| 		return err; | ||||
| 	else | ||||
| 		err = atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); | ||||
| 
 | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Configures PHY autoneg and flow control advertisement settings | ||||
|  * | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  */ | ||||
| static int atl1c_phy_setup_adv(struct atl1c_hw *hw) | ||||
| { | ||||
| 	u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_ALL; | ||||
| 	u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP & | ||||
| 				~GIGA_CR_1000T_SPEED_MASK; | ||||
| 
 | ||||
| 	if (hw->autoneg_advertised & ADVERTISED_10baseT_Half) | ||||
| 		mii_adv_data |= ADVERTISE_10HALF; | ||||
| 	if (hw->autoneg_advertised & ADVERTISED_10baseT_Full) | ||||
| 		mii_adv_data |= ADVERTISE_10FULL; | ||||
| 	if (hw->autoneg_advertised & ADVERTISED_100baseT_Half) | ||||
| 		mii_adv_data |= ADVERTISE_100HALF; | ||||
| 	if (hw->autoneg_advertised & ADVERTISED_100baseT_Full) | ||||
| 		mii_adv_data |= ADVERTISE_100FULL; | ||||
| 
 | ||||
| 	if (hw->autoneg_advertised & ADVERTISED_Autoneg) | ||||
| 		mii_adv_data |= ADVERTISE_10HALF  | ADVERTISE_10FULL | | ||||
| 				ADVERTISE_100HALF | ADVERTISE_100FULL; | ||||
| 
 | ||||
| 	if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) { | ||||
| 		if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half) | ||||
| 			mii_giga_ctrl_data |= ADVERTISE_1000HALF; | ||||
| 		if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full) | ||||
| 			mii_giga_ctrl_data |= ADVERTISE_1000FULL; | ||||
| 		if (hw->autoneg_advertised & ADVERTISED_Autoneg) | ||||
| 			mii_giga_ctrl_data |= ADVERTISE_1000HALF | | ||||
| 					ADVERTISE_1000FULL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 || | ||||
| 	    atl1c_write_phy_reg(hw, MII_CTRL1000, mii_giga_ctrl_data) != 0) | ||||
| 		return -1; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void atl1c_phy_disable(struct atl1c_hw *hw) | ||||
| { | ||||
| 	atl1c_power_saving(hw, 0); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int atl1c_phy_reset(struct atl1c_hw *hw) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = hw->adapter; | ||||
| 	struct pci_dev *pdev = adapter->pdev; | ||||
| 	u16 phy_data; | ||||
| 	u32 phy_ctrl_data, lpi_ctrl; | ||||
| 	int err; | ||||
| 
 | ||||
| 	/* reset PHY core */ | ||||
| 	AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data); | ||||
| 	phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_PHY_IDDQ | | ||||
| 		GPHY_CTRL_GATE_25M_EN | GPHY_CTRL_PWDOWN_HW | GPHY_CTRL_CLS); | ||||
| 	phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST; | ||||
| 	if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) | ||||
| 		phy_ctrl_data |= (GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE); | ||||
| 	else | ||||
| 		phy_ctrl_data &= ~(GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE); | ||||
| 	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data); | ||||
| 	AT_WRITE_FLUSH(hw); | ||||
| 	udelay(10); | ||||
| 	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data | GPHY_CTRL_EXT_RESET); | ||||
| 	AT_WRITE_FLUSH(hw); | ||||
| 	udelay(10 * GPHY_CTRL_EXT_RST_TO);	/* delay 800us */ | ||||
| 
 | ||||
| 	/* switch clock */ | ||||
| 	if (hw->nic_type == athr_l2c_b) { | ||||
| 		atl1c_read_phy_dbg(hw, MIIDBG_CFGLPSPD, &phy_data); | ||||
| 		atl1c_write_phy_dbg(hw, MIIDBG_CFGLPSPD, | ||||
| 			phy_data & ~CFGLPSPD_RSTCNT_CLK125SW); | ||||
| 	} | ||||
| 
 | ||||
| 	/* tx-half amplitude issue fix */ | ||||
| 	if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { | ||||
| 		atl1c_read_phy_dbg(hw, MIIDBG_CABLE1TH_DET, &phy_data); | ||||
| 		phy_data |= CABLE1TH_DET_EN; | ||||
| 		atl1c_write_phy_dbg(hw, MIIDBG_CABLE1TH_DET, phy_data); | ||||
| 	} | ||||
| 
 | ||||
| 	/* clear bit3 of dbgport 3B to lower voltage */ | ||||
| 	if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) { | ||||
| 		if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { | ||||
| 			atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); | ||||
| 			phy_data &= ~VOLT_CTRL_SWLOWEST; | ||||
| 			atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); | ||||
| 		} | ||||
| 		/* power saving config */ | ||||
| 		phy_data = | ||||
| 			hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ? | ||||
| 			L1D_LEGCYPS_DEF : L1C_LEGCYPS_DEF; | ||||
| 		atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, phy_data); | ||||
| 		/* hib */ | ||||
| 		atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, | ||||
| 			SYSMODCTRL_IECHOADJ_DEF); | ||||
| 	} else { | ||||
| 		/* disable pws */ | ||||
| 		atl1c_read_phy_dbg(hw, MIIDBG_LEGCYPS, &phy_data); | ||||
| 		atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, | ||||
| 			phy_data & ~LEGCYPS_EN); | ||||
| 		/* disable hibernate */ | ||||
| 		atl1c_read_phy_dbg(hw, MIIDBG_HIBNEG, &phy_data); | ||||
| 		atl1c_write_phy_dbg(hw, MIIDBG_HIBNEG, | ||||
| 			phy_data & HIBNEG_PSHIB_EN); | ||||
| 	} | ||||
| 	/* disable AZ(EEE) by default */ | ||||
| 	if (hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 || | ||||
| 	    hw->nic_type == athr_l2c_b2) { | ||||
| 		AT_READ_REG(hw, REG_LPI_CTRL, &lpi_ctrl); | ||||
| 		AT_WRITE_REG(hw, REG_LPI_CTRL, lpi_ctrl & ~LPI_CTRL_EN); | ||||
| 		atl1c_write_phy_ext(hw, MIIEXT_ANEG, MIIEXT_LOCAL_EEEADV, 0); | ||||
| 		atl1c_write_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL3, | ||||
| 			L2CB_CLDCTRL3); | ||||
| 	} | ||||
| 
 | ||||
| 	/* other debug port to set */ | ||||
| 	atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, ANACTRL_DEF); | ||||
| 	atl1c_write_phy_dbg(hw, MIIDBG_SRDSYSMOD, SRDSYSMOD_DEF); | ||||
| 	atl1c_write_phy_dbg(hw, MIIDBG_TST10BTCFG, TST10BTCFG_DEF); | ||||
| 	/* UNH-IOL test issue, set bit7 */ | ||||
| 	atl1c_write_phy_dbg(hw, MIIDBG_TST100BTCFG, | ||||
| 		TST100BTCFG_DEF | TST100BTCFG_LITCH_EN); | ||||
| 
 | ||||
| 	/* set phy interrupt mask */ | ||||
| 	phy_data = IER_LINK_UP | IER_LINK_DOWN; | ||||
| 	err = atl1c_write_phy_reg(hw, MII_IER, phy_data); | ||||
| 	if (err) { | ||||
| 		if (netif_msg_hw(adapter)) | ||||
| 			dev_err(&pdev->dev, | ||||
| 				"Error enable PHY linkChange Interrupt\n"); | ||||
| 		return err; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int atl1c_phy_init(struct atl1c_hw *hw) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = hw->adapter; | ||||
| 	struct pci_dev *pdev = adapter->pdev; | ||||
| 	int ret_val; | ||||
| 	u16 mii_bmcr_data = BMCR_RESET; | ||||
| 
 | ||||
| 	if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &hw->phy_id1) != 0) || | ||||
| 		(atl1c_read_phy_reg(hw, MII_PHYSID2, &hw->phy_id2) != 0)) { | ||||
| 		dev_err(&pdev->dev, "Error get phy ID\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	switch (hw->media_type) { | ||||
| 	case MEDIA_TYPE_AUTO_SENSOR: | ||||
| 		ret_val = atl1c_phy_setup_adv(hw); | ||||
| 		if (ret_val) { | ||||
| 			if (netif_msg_link(adapter)) | ||||
| 				dev_err(&pdev->dev, | ||||
| 					"Error Setting up Auto-Negotiation\n"); | ||||
| 			return ret_val; | ||||
| 		} | ||||
| 		mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART; | ||||
| 		break; | ||||
| 	case MEDIA_TYPE_100M_FULL: | ||||
| 		mii_bmcr_data |= BMCR_SPEED100 | BMCR_FULLDPLX; | ||||
| 		break; | ||||
| 	case MEDIA_TYPE_100M_HALF: | ||||
| 		mii_bmcr_data |= BMCR_SPEED100; | ||||
| 		break; | ||||
| 	case MEDIA_TYPE_10M_FULL: | ||||
| 		mii_bmcr_data |= BMCR_FULLDPLX; | ||||
| 		break; | ||||
| 	case MEDIA_TYPE_10M_HALF: | ||||
| 		break; | ||||
| 	default: | ||||
| 		if (netif_msg_link(adapter)) | ||||
| 			dev_err(&pdev->dev, "Wrong Media type %d\n", | ||||
| 				hw->media_type); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 	hw->phy_configured = true; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Detects the current speed and duplex settings of the hardware. | ||||
|  * | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  * speed - Speed of the connection | ||||
|  * duplex - Duplex setting of the connection | ||||
|  */ | ||||
| int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex) | ||||
| { | ||||
| 	int err; | ||||
| 	u16 phy_data; | ||||
| 
 | ||||
| 	/* Read   PHY Specific Status Register (17) */ | ||||
| 	err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data); | ||||
| 	if (err) | ||||
| 		return err; | ||||
| 
 | ||||
| 	if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	switch (phy_data & GIGA_PSSR_SPEED) { | ||||
| 	case GIGA_PSSR_1000MBS: | ||||
| 		*speed = SPEED_1000; | ||||
| 		break; | ||||
| 	case GIGA_PSSR_100MBS: | ||||
| 		*speed = SPEED_100; | ||||
| 		break; | ||||
| 	case  GIGA_PSSR_10MBS: | ||||
| 		*speed = SPEED_10; | ||||
| 		break; | ||||
| 	default: | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (phy_data & GIGA_PSSR_DPLX) | ||||
| 		*duplex = FULL_DUPLEX; | ||||
| 	else | ||||
| 		*duplex = HALF_DUPLEX; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* select one link mode to get lower power consumption */ | ||||
| int atl1c_phy_to_ps_link(struct atl1c_hw *hw) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = hw->adapter; | ||||
| 	struct pci_dev *pdev = adapter->pdev; | ||||
| 	int ret = 0; | ||||
| 	u16 autoneg_advertised = ADVERTISED_10baseT_Half; | ||||
| 	u16 save_autoneg_advertised; | ||||
| 	u16 phy_data; | ||||
| 	u16 mii_lpa_data; | ||||
| 	u16 speed = SPEED_0; | ||||
| 	u16 duplex = FULL_DUPLEX; | ||||
| 	int i; | ||||
| 
 | ||||
| 	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); | ||||
| 	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); | ||||
| 	if (phy_data & BMSR_LSTATUS) { | ||||
| 		atl1c_read_phy_reg(hw, MII_LPA, &mii_lpa_data); | ||||
| 		if (mii_lpa_data & LPA_10FULL) | ||||
| 			autoneg_advertised = ADVERTISED_10baseT_Full; | ||||
| 		else if (mii_lpa_data & LPA_10HALF) | ||||
| 			autoneg_advertised = ADVERTISED_10baseT_Half; | ||||
| 		else if (mii_lpa_data & LPA_100HALF) | ||||
| 			autoneg_advertised = ADVERTISED_100baseT_Half; | ||||
| 		else if (mii_lpa_data & LPA_100FULL) | ||||
| 			autoneg_advertised = ADVERTISED_100baseT_Full; | ||||
| 
 | ||||
| 		save_autoneg_advertised = hw->autoneg_advertised; | ||||
| 		hw->phy_configured = false; | ||||
| 		hw->autoneg_advertised = autoneg_advertised; | ||||
| 		if (atl1c_restart_autoneg(hw) != 0) { | ||||
| 			dev_dbg(&pdev->dev, "phy autoneg failed\n"); | ||||
| 			ret = -1; | ||||
| 		} | ||||
| 		hw->autoneg_advertised = save_autoneg_advertised; | ||||
| 
 | ||||
| 		if (mii_lpa_data) { | ||||
| 			for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) { | ||||
| 				mdelay(100); | ||||
| 				atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); | ||||
| 				atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); | ||||
| 				if (phy_data & BMSR_LSTATUS) { | ||||
| 					if (atl1c_get_speed_and_duplex(hw, &speed, | ||||
| 									&duplex) != 0) | ||||
| 						dev_dbg(&pdev->dev, | ||||
| 							"get speed and duplex failed\n"); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} else { | ||||
| 		speed = SPEED_10; | ||||
| 		duplex = HALF_DUPLEX; | ||||
| 	} | ||||
| 	adapter->link_speed = speed; | ||||
| 	adapter->link_duplex = duplex; | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int atl1c_restart_autoneg(struct atl1c_hw *hw) | ||||
| { | ||||
| 	int err = 0; | ||||
| 	u16 mii_bmcr_data = BMCR_RESET; | ||||
| 
 | ||||
| 	err = atl1c_phy_setup_adv(hw); | ||||
| 	if (err) | ||||
| 		return err; | ||||
| 	mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART; | ||||
| 
 | ||||
| 	return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data); | ||||
| } | ||||
| 
 | ||||
| int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc) | ||||
| { | ||||
| 	struct atl1c_adapter *adapter = hw->adapter; | ||||
| 	struct pci_dev *pdev = adapter->pdev; | ||||
| 	u32 master_ctrl, mac_ctrl, phy_ctrl; | ||||
| 	u32 wol_ctrl, speed; | ||||
| 	u16 phy_data; | ||||
| 
 | ||||
| 	wol_ctrl = 0; | ||||
| 	speed = adapter->link_speed == SPEED_1000 ? | ||||
| 		MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100; | ||||
| 
 | ||||
| 	AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl); | ||||
| 	AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl); | ||||
| 	AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl); | ||||
| 
 | ||||
| 	master_ctrl &= ~MASTER_CTRL_CLK_SEL_DIS; | ||||
| 	mac_ctrl = FIELD_SETX(mac_ctrl, MAC_CTRL_SPEED, speed); | ||||
| 	mac_ctrl &= ~(MAC_CTRL_DUPLX | MAC_CTRL_RX_EN | MAC_CTRL_TX_EN); | ||||
| 	if (adapter->link_duplex == FULL_DUPLEX) | ||||
| 		mac_ctrl |= MAC_CTRL_DUPLX; | ||||
| 	phy_ctrl &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS); | ||||
| 	phy_ctrl |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE | | ||||
| 		GPHY_CTRL_HIB_EN; | ||||
| 	if (!wufc) { /* without WoL */ | ||||
| 		master_ctrl |= MASTER_CTRL_CLK_SEL_DIS; | ||||
| 		phy_ctrl |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW; | ||||
| 		AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl); | ||||
| 		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl); | ||||
| 		AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl); | ||||
| 		AT_WRITE_REG(hw, REG_WOL_CTRL, 0); | ||||
| 		hw->phy_configured = false; /* re-init PHY when resume */ | ||||
| 		return 0; | ||||
| 	} | ||||
| 	phy_ctrl |= GPHY_CTRL_EXT_RESET; | ||||
| 	if (wufc & AT_WUFC_MAG) { | ||||
| 		mac_ctrl |= MAC_CTRL_RX_EN | MAC_CTRL_BC_EN; | ||||
| 		wol_ctrl |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN; | ||||
| 		if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V11) | ||||
| 			wol_ctrl |= WOL_PATTERN_EN | WOL_PATTERN_PME_EN; | ||||
| 	} | ||||
| 	if (wufc & AT_WUFC_LNKC) { | ||||
| 		wol_ctrl |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; | ||||
| 		if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) { | ||||
| 			dev_dbg(&pdev->dev, "%s: write phy MII_IER failed.\n", | ||||
| 				atl1c_driver_name); | ||||
| 		} | ||||
| 	} | ||||
| 	/* clear PHY interrupt */ | ||||
| 	atl1c_read_phy_reg(hw, MII_ISR, &phy_data); | ||||
| 
 | ||||
| 	dev_dbg(&pdev->dev, "%s: suspend MAC=%x,MASTER=%x,PHY=0x%x,WOL=%x\n", | ||||
| 		atl1c_driver_name, mac_ctrl, master_ctrl, phy_ctrl, wol_ctrl); | ||||
| 	AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl); | ||||
| 	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl); | ||||
| 	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl); | ||||
| 	AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* configure phy after Link change Event */ | ||||
| void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed) | ||||
| { | ||||
| 	u16 phy_val; | ||||
| 	bool adj_thresh = false; | ||||
| 
 | ||||
| 	if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 || | ||||
| 	    hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2) | ||||
| 		adj_thresh = true; | ||||
| 
 | ||||
| 	if (link_speed != SPEED_0) { /* link up */ | ||||
| 		/* az with brcm, half-amp */ | ||||
| 		if (hw->nic_type == athr_l1d_2) { | ||||
| 			atl1c_read_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL6, | ||||
| 				&phy_val); | ||||
| 			phy_val = FIELD_GETX(phy_val, CLDCTRL6_CAB_LEN); | ||||
| 			phy_val = phy_val > CLDCTRL6_CAB_LEN_SHORT ? | ||||
| 				AZ_ANADECT_LONG : AZ_ANADECT_DEF; | ||||
| 			atl1c_write_phy_dbg(hw, MIIDBG_AZ_ANADECT, phy_val); | ||||
| 		} | ||||
| 		/* threshold adjust */ | ||||
| 		if (adj_thresh && link_speed == SPEED_100 && hw->msi_lnkpatch) { | ||||
| 			atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, L1D_MSE16DB_UP); | ||||
| 			atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, | ||||
| 				L1D_SYSMODCTRL_IECHOADJ_DEF); | ||||
| 		} | ||||
| 	} else { /* link down */ | ||||
| 		if (adj_thresh && hw->msi_lnkpatch) { | ||||
| 			atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, | ||||
| 				SYSMODCTRL_IECHOADJ_DEF); | ||||
| 			atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, | ||||
| 				L1D_MSE16DB_DOWN); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										1024
									
								
								drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1024
									
								
								drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										2803
									
								
								drivers/net/ethernet/atheros/atl1c/atl1c_main.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2803
									
								
								drivers/net/ethernet/atheros/atl1c/atl1c_main.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										2
									
								
								drivers/net/ethernet/atheros/atl1e/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								drivers/net/ethernet/atheros/atl1e/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| obj-$(CONFIG_ATL1E)	+= atl1e.o | ||||
| atl1e-objs		+= atl1e_main.o atl1e_hw.o atl1e_ethtool.o atl1e_param.o | ||||
							
								
								
									
										507
									
								
								drivers/net/ethernet/atheros/atl1e/atl1e.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										507
									
								
								drivers/net/ethernet/atheros/atl1e/atl1e.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,507 @@ | |||
| /*
 | ||||
|  * Copyright(c) 2007 Atheros Corporation. All rights reserved. | ||||
|  * Copyright(c) 2007 xiong huang <xiong.huang@atheros.com> | ||||
|  * | ||||
|  * Derived from Intel e1000 driver | ||||
|  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the Free | ||||
|  * Software Foundation; either version 2 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., 59 | ||||
|  * Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _ATL1E_H_ | ||||
| #define _ATL1E_H_ | ||||
| 
 | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/pci.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/etherdevice.h> | ||||
| #include <linux/skbuff.h> | ||||
| #include <linux/ioport.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/list.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/sched.h> | ||||
| #include <linux/in.h> | ||||
| #include <linux/ip.h> | ||||
| #include <linux/ipv6.h> | ||||
| #include <linux/udp.h> | ||||
| #include <linux/mii.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/vmalloc.h> | ||||
| #include <linux/pagemap.h> | ||||
| #include <linux/tcp.h> | ||||
| #include <linux/ethtool.h> | ||||
| #include <linux/if_vlan.h> | ||||
| #include <linux/workqueue.h> | ||||
| #include <net/checksum.h> | ||||
| #include <net/ip6_checksum.h> | ||||
| 
 | ||||
| #include "atl1e_hw.h" | ||||
| 
 | ||||
| #define PCI_REG_COMMAND	 0x04    /* PCI Command Register */ | ||||
| #define CMD_IO_SPACE	 0x0001 | ||||
| #define CMD_MEMORY_SPACE 0x0002 | ||||
| #define CMD_BUS_MASTER   0x0004 | ||||
| 
 | ||||
| #define BAR_0   0 | ||||
| #define BAR_1   1 | ||||
| #define BAR_5   5 | ||||
| 
 | ||||
| /* Wake Up Filter Control */ | ||||
| #define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ | ||||
| #define AT_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */ | ||||
| #define AT_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */ | ||||
| #define AT_WUFC_MC   0x00000008 /* Multicast Wakeup Enable */ | ||||
| #define AT_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */ | ||||
| 
 | ||||
| #define SPEED_0		   0xffff | ||||
| #define HALF_DUPLEX        1 | ||||
| #define FULL_DUPLEX        2 | ||||
| 
 | ||||
| /* Error Codes */ | ||||
| #define AT_ERR_EEPROM      1 | ||||
| #define AT_ERR_PHY         2 | ||||
| #define AT_ERR_CONFIG      3 | ||||
| #define AT_ERR_PARAM       4 | ||||
| #define AT_ERR_MAC_TYPE    5 | ||||
| #define AT_ERR_PHY_TYPE    6 | ||||
| #define AT_ERR_PHY_SPEED   7 | ||||
| #define AT_ERR_PHY_RES     8 | ||||
| #define AT_ERR_TIMEOUT     9 | ||||
| 
 | ||||
| #define MAX_JUMBO_FRAME_SIZE 0x2000 | ||||
| 
 | ||||
| #define AT_VLAN_TAG_TO_TPD_TAG(_vlan, _tpd)    \ | ||||
| 	_tpd = (((_vlan) << (4)) | (((_vlan) >> 13) & 7) |\ | ||||
| 		 (((_vlan) >> 9) & 8)) | ||||
| 
 | ||||
| #define AT_TPD_TAG_TO_VLAN_TAG(_tpd, _vlan)    \ | ||||
| 	_vlan = (((_tpd) >> 8) | (((_tpd) & 0x77) << 9) |\ | ||||
| 		   (((_tdp) & 0x88) << 5)) | ||||
| 
 | ||||
| #define AT_MAX_RECEIVE_QUEUE    4 | ||||
| #define AT_PAGE_NUM_PER_QUEUE   2 | ||||
| 
 | ||||
| #define AT_DMA_HI_ADDR_MASK     0xffffffff00000000ULL | ||||
| #define AT_DMA_LO_ADDR_MASK     0x00000000ffffffffULL | ||||
| 
 | ||||
| #define AT_TX_WATCHDOG  (5 * HZ) | ||||
| #define AT_MAX_INT_WORK		10 | ||||
| #define AT_TWSI_EEPROM_TIMEOUT 	100 | ||||
| #define AT_HW_MAX_IDLE_DELAY 	10 | ||||
| #define AT_SUSPEND_LINK_TIMEOUT 28 | ||||
| 
 | ||||
| #define AT_REGS_LEN	75 | ||||
| #define AT_EEPROM_LEN 	512 | ||||
| #define AT_ADV_MASK	(ADVERTISE_10_HALF  |\ | ||||
| 			 ADVERTISE_10_FULL  |\ | ||||
| 			 ADVERTISE_100_HALF |\ | ||||
| 			 ADVERTISE_100_FULL |\ | ||||
| 			 ADVERTISE_1000_FULL) | ||||
| 
 | ||||
| /* tpd word 2 */ | ||||
| #define TPD_BUFLEN_MASK 	0x3FFF | ||||
| #define TPD_BUFLEN_SHIFT        0 | ||||
| #define TPD_DMAINT_MASK		0x0001 | ||||
| #define TPD_DMAINT_SHIFT        14 | ||||
| #define TPD_PKTNT_MASK          0x0001 | ||||
| #define TPD_PKTINT_SHIFT        15 | ||||
| #define TPD_VLANTAG_MASK        0xFFFF | ||||
| #define TPD_VLAN_SHIFT          16 | ||||
| 
 | ||||
| /* tpd word 3 bits 0:4 */ | ||||
| #define TPD_EOP_MASK            0x0001 | ||||
| #define TPD_EOP_SHIFT           0 | ||||
| #define TPD_IP_VERSION_MASK	0x0001 | ||||
| #define TPD_IP_VERSION_SHIFT	1	/* 0 : IPV4, 1 : IPV6 */ | ||||
| #define TPD_INS_VL_TAG_MASK	0x0001 | ||||
| #define TPD_INS_VL_TAG_SHIFT	2 | ||||
| #define TPD_CC_SEGMENT_EN_MASK	0x0001 | ||||
| #define TPD_CC_SEGMENT_EN_SHIFT	3 | ||||
| #define TPD_SEGMENT_EN_MASK     0x0001 | ||||
| #define TPD_SEGMENT_EN_SHIFT    4 | ||||
| 
 | ||||
| /* tdp word 3 bits 5:7 if ip version is 0 */ | ||||
| #define TPD_IP_CSUM_MASK        0x0001 | ||||
| #define TPD_IP_CSUM_SHIFT       5 | ||||
| #define TPD_TCP_CSUM_MASK       0x0001 | ||||
| #define TPD_TCP_CSUM_SHIFT      6 | ||||
| #define TPD_UDP_CSUM_MASK       0x0001 | ||||
| #define TPD_UDP_CSUM_SHIFT      7 | ||||
| 
 | ||||
| /* tdp word 3 bits 5:7 if ip version is 1 */ | ||||
| #define TPD_V6_IPHLLO_MASK	0x0007 | ||||
| #define TPD_V6_IPHLLO_SHIFT	7 | ||||
| 
 | ||||
| /* tpd word 3 bits 8:9 bit */ | ||||
| #define TPD_VL_TAGGED_MASK      0x0001 | ||||
| #define TPD_VL_TAGGED_SHIFT     8 | ||||
| #define TPD_ETHTYPE_MASK        0x0001 | ||||
| #define TPD_ETHTYPE_SHIFT       9 | ||||
| 
 | ||||
| /* tdp word 3 bits 10:13 if ip version is 0 */ | ||||
| #define TDP_V4_IPHL_MASK	0x000F | ||||
| #define TPD_V4_IPHL_SHIFT	10 | ||||
| 
 | ||||
| /* tdp word 3 bits 10:13 if ip version is 1 */ | ||||
| #define TPD_V6_IPHLHI_MASK	0x000F | ||||
| #define TPD_V6_IPHLHI_SHIFT	10 | ||||
| 
 | ||||
| /* tpd word 3 bit 14:31 if segment enabled */ | ||||
| #define TPD_TCPHDRLEN_MASK      0x000F | ||||
| #define TPD_TCPHDRLEN_SHIFT     14 | ||||
| #define TPD_HDRFLAG_MASK        0x0001 | ||||
| #define TPD_HDRFLAG_SHIFT       18 | ||||
| #define TPD_MSS_MASK            0x1FFF | ||||
| #define TPD_MSS_SHIFT           19 | ||||
| 
 | ||||
| /* tdp word 3 bit 16:31 if custom csum enabled */ | ||||
| #define TPD_PLOADOFFSET_MASK    0x00FF | ||||
| #define TPD_PLOADOFFSET_SHIFT   16 | ||||
| #define TPD_CCSUMOFFSET_MASK    0x00FF | ||||
| #define TPD_CCSUMOFFSET_SHIFT   24 | ||||
| 
 | ||||
| struct atl1e_tpd_desc { | ||||
| 	__le64 buffer_addr; | ||||
| 	__le32 word2; | ||||
| 	__le32 word3; | ||||
| }; | ||||
| 
 | ||||
| /* how about 0x2000 */ | ||||
| #define MAX_TX_BUF_LEN      0x2000 | ||||
| #define MAX_TX_BUF_SHIFT    13 | ||||
| #define MAX_TSO_SEG_SIZE    0x3c00 | ||||
| 
 | ||||
| /* rrs word 1 bit 0:31 */ | ||||
| #define RRS_RX_CSUM_MASK	0xFFFF | ||||
| #define RRS_RX_CSUM_SHIFT	0 | ||||
| #define RRS_PKT_SIZE_MASK	0x3FFF | ||||
| #define RRS_PKT_SIZE_SHIFT	16 | ||||
| #define RRS_CPU_NUM_MASK	0x0003 | ||||
| #define	RRS_CPU_NUM_SHIFT	30 | ||||
| 
 | ||||
| #define	RRS_IS_RSS_IPV4		0x0001 | ||||
| #define RRS_IS_RSS_IPV4_TCP	0x0002 | ||||
| #define RRS_IS_RSS_IPV6		0x0004 | ||||
| #define RRS_IS_RSS_IPV6_TCP	0x0008 | ||||
| #define RRS_IS_IPV6		0x0010 | ||||
| #define RRS_IS_IP_FRAG		0x0020 | ||||
| #define RRS_IS_IP_DF		0x0040 | ||||
| #define RRS_IS_802_3		0x0080 | ||||
| #define RRS_IS_VLAN_TAG		0x0100 | ||||
| #define RRS_IS_ERR_FRAME	0x0200 | ||||
| #define RRS_IS_IPV4		0x0400 | ||||
| #define RRS_IS_UDP		0x0800 | ||||
| #define RRS_IS_TCP		0x1000 | ||||
| #define RRS_IS_BCAST		0x2000 | ||||
| #define RRS_IS_MCAST		0x4000 | ||||
| #define RRS_IS_PAUSE		0x8000 | ||||
| 
 | ||||
| #define RRS_ERR_BAD_CRC		0x0001 | ||||
| #define RRS_ERR_CODE		0x0002 | ||||
| #define RRS_ERR_DRIBBLE		0x0004 | ||||
| #define RRS_ERR_RUNT		0x0008 | ||||
| #define RRS_ERR_RX_OVERFLOW	0x0010 | ||||
| #define RRS_ERR_TRUNC		0x0020 | ||||
| #define RRS_ERR_IP_CSUM		0x0040 | ||||
| #define RRS_ERR_L4_CSUM		0x0080 | ||||
| #define RRS_ERR_LENGTH		0x0100 | ||||
| #define RRS_ERR_DES_ADDR	0x0200 | ||||
| 
 | ||||
| struct atl1e_recv_ret_status { | ||||
| 	u16 seq_num; | ||||
| 	u16 hash_lo; | ||||
| 	__le32	word1; | ||||
| 	u16 pkt_flag; | ||||
| 	u16 err_flag; | ||||
| 	u16 hash_hi; | ||||
| 	u16 vtag; | ||||
| }; | ||||
| 
 | ||||
| enum atl1e_dma_req_block { | ||||
| 	atl1e_dma_req_128 = 0, | ||||
| 	atl1e_dma_req_256 = 1, | ||||
| 	atl1e_dma_req_512 = 2, | ||||
| 	atl1e_dma_req_1024 = 3, | ||||
| 	atl1e_dma_req_2048 = 4, | ||||
| 	atl1e_dma_req_4096 = 5 | ||||
| }; | ||||
| 
 | ||||
| enum atl1e_rrs_type { | ||||
| 	atl1e_rrs_disable = 0, | ||||
| 	atl1e_rrs_ipv4 = 1, | ||||
| 	atl1e_rrs_ipv4_tcp = 2, | ||||
| 	atl1e_rrs_ipv6 = 4, | ||||
| 	atl1e_rrs_ipv6_tcp = 8 | ||||
| }; | ||||
| 
 | ||||
| enum atl1e_nic_type { | ||||
| 	athr_l1e = 0, | ||||
| 	athr_l2e_revA = 1, | ||||
| 	athr_l2e_revB = 2 | ||||
| }; | ||||
| 
 | ||||
| struct atl1e_hw_stats { | ||||
| 	/* rx */ | ||||
| 	unsigned long rx_ok;	      /* The number of good packet received. */ | ||||
| 	unsigned long rx_bcast;       /* The number of good broadcast packet received. */ | ||||
| 	unsigned long rx_mcast;       /* The number of good multicast packet received. */ | ||||
| 	unsigned long rx_pause;       /* The number of Pause packet received. */ | ||||
| 	unsigned long rx_ctrl;        /* The number of Control packet received other than Pause frame. */ | ||||
| 	unsigned long rx_fcs_err;     /* The number of packets with bad FCS. */ | ||||
| 	unsigned long rx_len_err;     /* The number of packets with mismatch of length field and actual size. */ | ||||
| 	unsigned long rx_byte_cnt;    /* The number of bytes of good packet received. FCS is NOT included. */ | ||||
| 	unsigned long rx_runt;        /* The number of packets received that are less than 64 byte long and with good FCS. */ | ||||
| 	unsigned long rx_frag;        /* The number of packets received that are less than 64 byte long and with bad FCS. */ | ||||
| 	unsigned long rx_sz_64;       /* The number of good and bad packets received that are 64 byte long. */ | ||||
| 	unsigned long rx_sz_65_127;   /* The number of good and bad packets received that are between 65 and 127-byte long. */ | ||||
| 	unsigned long rx_sz_128_255;  /* The number of good and bad packets received that are between 128 and 255-byte long. */ | ||||
| 	unsigned long rx_sz_256_511;  /* The number of good and bad packets received that are between 256 and 511-byte long. */ | ||||
| 	unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */ | ||||
| 	unsigned long rx_sz_1024_1518;    /* The number of good and bad packets received that are between 1024 and 1518-byte long. */ | ||||
| 	unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */ | ||||
| 	unsigned long rx_sz_ov;       /* The number of good and bad packets received that are more than MTU size truncated by Selene. */ | ||||
| 	unsigned long rx_rxf_ov;      /* The number of frame dropped due to occurrence of RX FIFO overflow. */ | ||||
| 	unsigned long rx_rrd_ov;      /* The number of frame dropped due to occurrence of RRD overflow. */ | ||||
| 	unsigned long rx_align_err;   /* Alignment Error */ | ||||
| 	unsigned long rx_bcast_byte_cnt;  /* The byte count of broadcast packet received, excluding FCS. */ | ||||
| 	unsigned long rx_mcast_byte_cnt;  /* The byte count of multicast packet received, excluding FCS. */ | ||||
| 	unsigned long rx_err_addr;    /* The number of packets dropped due to address filtering. */ | ||||
| 
 | ||||
| 	/* tx */ | ||||
| 	unsigned long tx_ok;      /* The number of good packet transmitted. */ | ||||
| 	unsigned long tx_bcast;       /* The number of good broadcast packet transmitted. */ | ||||
| 	unsigned long tx_mcast;       /* The number of good multicast packet transmitted. */ | ||||
| 	unsigned long tx_pause;       /* The number of Pause packet transmitted. */ | ||||
| 	unsigned long tx_exc_defer;   /* The number of packets transmitted with excessive deferral. */ | ||||
| 	unsigned long tx_ctrl;        /* The number of packets transmitted is a control frame, excluding Pause frame. */ | ||||
| 	unsigned long tx_defer;       /* The number of packets transmitted that is deferred. */ | ||||
| 	unsigned long tx_byte_cnt;    /* The number of bytes of data transmitted. FCS is NOT included. */ | ||||
| 	unsigned long tx_sz_64;       /* The number of good and bad packets transmitted that are 64 byte long. */ | ||||
| 	unsigned long tx_sz_65_127;   /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */ | ||||
| 	unsigned long tx_sz_128_255;  /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */ | ||||
| 	unsigned long tx_sz_256_511;  /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */ | ||||
| 	unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */ | ||||
| 	unsigned long tx_sz_1024_1518;    /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */ | ||||
| 	unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */ | ||||
| 	unsigned long tx_1_col;       /* The number of packets subsequently transmitted successfully with a single prior collision. */ | ||||
| 	unsigned long tx_2_col;       /* The number of packets subsequently transmitted successfully with multiple prior collisions. */ | ||||
| 	unsigned long tx_late_col;    /* The number of packets transmitted with late collisions. */ | ||||
| 	unsigned long tx_abort_col;   /* The number of transmit packets aborted due to excessive collisions. */ | ||||
| 	unsigned long tx_underrun;    /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */ | ||||
| 	unsigned long tx_rd_eop;      /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */ | ||||
| 	unsigned long tx_len_err;     /* The number of transmit packets with length field does NOT match the actual frame size. */ | ||||
| 	unsigned long tx_trunc;       /* The number of transmit packets truncated due to size exceeding MTU. */ | ||||
| 	unsigned long tx_bcast_byte;  /* The byte count of broadcast packet transmitted, excluding FCS. */ | ||||
| 	unsigned long tx_mcast_byte;  /* The byte count of multicast packet transmitted, excluding FCS. */ | ||||
| }; | ||||
| 
 | ||||
| struct atl1e_hw { | ||||
| 	u8 __iomem      *hw_addr;            /* inner register address */ | ||||
| 	resource_size_t mem_rang; | ||||
| 	struct atl1e_adapter *adapter; | ||||
| 	enum atl1e_nic_type  nic_type; | ||||
| 	u16 device_id; | ||||
| 	u16 vendor_id; | ||||
| 	u16 subsystem_id; | ||||
| 	u16 subsystem_vendor_id; | ||||
| 	u8  revision_id; | ||||
| 	u16 pci_cmd_word; | ||||
| 	u8 mac_addr[ETH_ALEN]; | ||||
| 	u8 perm_mac_addr[ETH_ALEN]; | ||||
| 	u8 preamble_len; | ||||
| 	u16 max_frame_size; | ||||
| 	u16 rx_jumbo_th; | ||||
| 	u16 tx_jumbo_th; | ||||
| 
 | ||||
| 	u16 media_type; | ||||
| #define MEDIA_TYPE_AUTO_SENSOR  0 | ||||
| #define MEDIA_TYPE_100M_FULL    1 | ||||
| #define MEDIA_TYPE_100M_HALF    2 | ||||
| #define MEDIA_TYPE_10M_FULL     3 | ||||
| #define MEDIA_TYPE_10M_HALF     4 | ||||
| 
 | ||||
| 	u16 autoneg_advertised; | ||||
| #define ADVERTISE_10_HALF               0x0001 | ||||
| #define ADVERTISE_10_FULL               0x0002 | ||||
| #define ADVERTISE_100_HALF              0x0004 | ||||
| #define ADVERTISE_100_FULL              0x0008 | ||||
| #define ADVERTISE_1000_HALF             0x0010 /* Not used, just FYI */ | ||||
| #define ADVERTISE_1000_FULL             0x0020 | ||||
| 	u16 mii_autoneg_adv_reg; | ||||
| 	u16 mii_1000t_ctrl_reg; | ||||
| 
 | ||||
| 	u16 imt;        /* Interrupt Moderator timer ( 2us resolution) */ | ||||
| 	u16 ict;        /* Interrupt Clear timer (2us resolution) */ | ||||
| 	u32 smb_timer; | ||||
| 	u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
 | ||||
| 			  interrupt request */ | ||||
| 	u16 tpd_thresh; | ||||
| 	u16 rx_count_down; /* 2us resolution */ | ||||
| 	u16 tx_count_down; | ||||
| 
 | ||||
| 	u8 tpd_burst;   /* Number of TPD to prefetch in cache-aligned burst. */ | ||||
| 	enum atl1e_rrs_type rrs_type; | ||||
| 	u32 base_cpu; | ||||
| 	u32 indirect_tab; | ||||
| 
 | ||||
| 	enum atl1e_dma_req_block dmar_block; | ||||
| 	enum atl1e_dma_req_block dmaw_block; | ||||
| 	u8 dmaw_dly_cnt; | ||||
| 	u8 dmar_dly_cnt; | ||||
| 
 | ||||
| 	bool phy_configured; | ||||
| 	bool re_autoneg; | ||||
| 	bool emi_ca; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * wrapper around a pointer to a socket buffer, | ||||
|  * so a DMA handle can be stored along with the buffer | ||||
|  */ | ||||
| struct atl1e_tx_buffer { | ||||
| 	struct sk_buff *skb; | ||||
| 	u16 flags; | ||||
| #define ATL1E_TX_PCIMAP_SINGLE		0x0001 | ||||
| #define ATL1E_TX_PCIMAP_PAGE		0x0002 | ||||
| #define ATL1E_TX_PCIMAP_TYPE_MASK	0x0003 | ||||
| 	u16 length; | ||||
| 	dma_addr_t dma; | ||||
| }; | ||||
| 
 | ||||
| #define ATL1E_SET_PCIMAP_TYPE(tx_buff, type) do {		\ | ||||
| 	((tx_buff)->flags) &= ~ATL1E_TX_PCIMAP_TYPE_MASK;	\ | ||||
| 	((tx_buff)->flags) |= (type);				\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| struct atl1e_rx_page { | ||||
| 	dma_addr_t	dma;    /* receive rage DMA address */ | ||||
| 	u8		*addr;   /* receive rage virtual address */ | ||||
| 	dma_addr_t	write_offset_dma;  /* the DMA address which contain the
 | ||||
| 					      receive data offset in the page */ | ||||
| 	u32		*write_offset_addr; /* the virtaul address which contain
 | ||||
| 					     the receive data offset in the page */ | ||||
| 	u32		read_offset;       /* the offset where we have read */ | ||||
| }; | ||||
| 
 | ||||
| struct atl1e_rx_page_desc { | ||||
| 	struct atl1e_rx_page   rx_page[AT_PAGE_NUM_PER_QUEUE]; | ||||
| 	u8  rx_using; | ||||
| 	u16 rx_nxseq; | ||||
| }; | ||||
| 
 | ||||
| /* transmit packet descriptor (tpd) ring */ | ||||
| struct atl1e_tx_ring { | ||||
| 	struct atl1e_tpd_desc *desc;  /* descriptor ring virtual address  */ | ||||
| 	dma_addr_t	   dma;    /* descriptor ring physical address */ | ||||
| 	u16       	   count;  /* the count of transmit rings  */ | ||||
| 	rwlock_t	   tx_lock; | ||||
| 	u16		   next_to_use; | ||||
| 	atomic_t	   next_to_clean; | ||||
| 	struct atl1e_tx_buffer *tx_buffer; | ||||
| 	dma_addr_t	   cmb_dma; | ||||
| 	u32		   *cmb; | ||||
| }; | ||||
| 
 | ||||
| /* receive packet descriptor ring */ | ||||
| struct atl1e_rx_ring { | ||||
| 	void        	*desc; | ||||
| 	dma_addr_t  	dma; | ||||
| 	int         	size; | ||||
| 	u32	    	page_size; /* bytes length of rxf page */ | ||||
| 	u32		real_page_size; /* real_page_size = page_size + jumbo + aliagn */ | ||||
| 	struct atl1e_rx_page_desc	rx_page_desc[AT_MAX_RECEIVE_QUEUE]; | ||||
| }; | ||||
| 
 | ||||
| /* board specific private data structure */ | ||||
| struct atl1e_adapter { | ||||
| 	struct net_device   *netdev; | ||||
| 	struct pci_dev      *pdev; | ||||
| 	struct napi_struct  napi; | ||||
| 	struct mii_if_info  mii;    /* MII interface info */ | ||||
| 	struct atl1e_hw        hw; | ||||
| 	struct atl1e_hw_stats  hw_stats; | ||||
| 
 | ||||
| 	u32 wol; | ||||
| 	u16 link_speed; | ||||
| 	u16 link_duplex; | ||||
| 
 | ||||
| 	spinlock_t mdio_lock; | ||||
| 	spinlock_t tx_lock; | ||||
| 	atomic_t irq_sem; | ||||
| 
 | ||||
| 	struct work_struct reset_task; | ||||
| 	struct work_struct link_chg_task; | ||||
| 	struct timer_list watchdog_timer; | ||||
| 	struct timer_list phy_config_timer; | ||||
| 
 | ||||
| 	/* All Descriptor memory */ | ||||
| 	dma_addr_t  	ring_dma; | ||||
| 	void     	*ring_vir_addr; | ||||
| 	u32             ring_size; | ||||
| 
 | ||||
| 	struct atl1e_tx_ring tx_ring; | ||||
| 	struct atl1e_rx_ring rx_ring; | ||||
| 	int num_rx_queues; | ||||
| 	unsigned long flags; | ||||
| #define __AT_TESTING        0x0001 | ||||
| #define __AT_RESETTING      0x0002 | ||||
| #define __AT_DOWN           0x0003 | ||||
| 
 | ||||
| 	u32 bd_number;     /* board number;*/ | ||||
| 	u32 pci_state[16]; | ||||
| 	u32 *config_space; | ||||
| }; | ||||
| 
 | ||||
| #define AT_WRITE_REG(a, reg, value) ( \ | ||||
| 		writel((value), ((a)->hw_addr + reg))) | ||||
| 
 | ||||
| #define AT_WRITE_FLUSH(a) (\ | ||||
| 		readl((a)->hw_addr)) | ||||
| 
 | ||||
| #define AT_READ_REG(a, reg) ( \ | ||||
| 		readl((a)->hw_addr + reg)) | ||||
| 
 | ||||
| #define AT_WRITE_REGB(a, reg, value) (\ | ||||
| 		writeb((value), ((a)->hw_addr + reg))) | ||||
| 
 | ||||
| #define AT_READ_REGB(a, reg) (\ | ||||
| 		readb((a)->hw_addr + reg)) | ||||
| 
 | ||||
| #define AT_WRITE_REGW(a, reg, value) (\ | ||||
| 		writew((value), ((a)->hw_addr + reg))) | ||||
| 
 | ||||
| #define AT_READ_REGW(a, reg) (\ | ||||
| 		readw((a)->hw_addr + reg)) | ||||
| 
 | ||||
| #define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \ | ||||
| 		writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))) | ||||
| 
 | ||||
| #define AT_READ_REG_ARRAY(a, reg, offset) ( \ | ||||
| 		readl(((a)->hw_addr + reg) + ((offset) << 2))) | ||||
| 
 | ||||
| extern char atl1e_driver_name[]; | ||||
| extern char atl1e_driver_version[]; | ||||
| 
 | ||||
| void atl1e_check_options(struct atl1e_adapter *adapter); | ||||
| int atl1e_up(struct atl1e_adapter *adapter); | ||||
| void atl1e_down(struct atl1e_adapter *adapter); | ||||
| void atl1e_reinit_locked(struct atl1e_adapter *adapter); | ||||
| s32 atl1e_reset_hw(struct atl1e_hw *hw); | ||||
| void atl1e_set_ethtool_ops(struct net_device *netdev); | ||||
| #endif /* _ATL1_E_H_ */ | ||||
							
								
								
									
										392
									
								
								drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										392
									
								
								drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,392 @@ | |||
| /*
 | ||||
|  * Copyright(c) 2007 Atheros Corporation. All rights reserved. | ||||
|  * | ||||
|  * Derived from Intel e1000 driver | ||||
|  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the Free | ||||
|  * Software Foundation; either version 2 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., 59 | ||||
|  * Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/ethtool.h> | ||||
| #include <linux/slab.h> | ||||
| 
 | ||||
| #include "atl1e.h" | ||||
| 
 | ||||
| static int atl1e_get_settings(struct net_device *netdev, | ||||
| 			      struct ethtool_cmd *ecmd) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = netdev_priv(netdev); | ||||
| 	struct atl1e_hw *hw = &adapter->hw; | ||||
| 
 | ||||
| 	ecmd->supported = (SUPPORTED_10baseT_Half  | | ||||
| 			   SUPPORTED_10baseT_Full  | | ||||
| 			   SUPPORTED_100baseT_Half | | ||||
| 			   SUPPORTED_100baseT_Full | | ||||
| 			   SUPPORTED_Autoneg       | | ||||
| 			   SUPPORTED_TP); | ||||
| 	if (hw->nic_type == athr_l1e) | ||||
| 		ecmd->supported |= SUPPORTED_1000baseT_Full; | ||||
| 
 | ||||
| 	ecmd->advertising = ADVERTISED_TP; | ||||
| 
 | ||||
| 	ecmd->advertising |= ADVERTISED_Autoneg; | ||||
| 	ecmd->advertising |= hw->autoneg_advertised; | ||||
| 
 | ||||
| 	ecmd->port = PORT_TP; | ||||
| 	ecmd->phy_address = 0; | ||||
| 	ecmd->transceiver = XCVR_INTERNAL; | ||||
| 
 | ||||
| 	if (adapter->link_speed != SPEED_0) { | ||||
| 		ethtool_cmd_speed_set(ecmd, adapter->link_speed); | ||||
| 		if (adapter->link_duplex == FULL_DUPLEX) | ||||
| 			ecmd->duplex = DUPLEX_FULL; | ||||
| 		else | ||||
| 			ecmd->duplex = DUPLEX_HALF; | ||||
| 	} else { | ||||
| 		ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); | ||||
| 		ecmd->duplex = DUPLEX_UNKNOWN; | ||||
| 	} | ||||
| 
 | ||||
| 	ecmd->autoneg = AUTONEG_ENABLE; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int atl1e_set_settings(struct net_device *netdev, | ||||
| 			      struct ethtool_cmd *ecmd) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = netdev_priv(netdev); | ||||
| 	struct atl1e_hw *hw = &adapter->hw; | ||||
| 
 | ||||
| 	while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) | ||||
| 		msleep(1); | ||||
| 
 | ||||
| 	if (ecmd->autoneg == AUTONEG_ENABLE) { | ||||
| 		u16 adv4, adv9; | ||||
| 
 | ||||
| 		if ((ecmd->advertising&ADVERTISE_1000_FULL)) { | ||||
| 			if (hw->nic_type == athr_l1e) { | ||||
| 				hw->autoneg_advertised = | ||||
| 					ecmd->advertising & AT_ADV_MASK; | ||||
| 			} else { | ||||
| 				clear_bit(__AT_RESETTING, &adapter->flags); | ||||
| 				return -EINVAL; | ||||
| 			} | ||||
| 		} else if (ecmd->advertising&ADVERTISE_1000_HALF) { | ||||
| 			clear_bit(__AT_RESETTING, &adapter->flags); | ||||
| 			return -EINVAL; | ||||
| 		} else { | ||||
| 			hw->autoneg_advertised = | ||||
| 				ecmd->advertising & AT_ADV_MASK; | ||||
| 		} | ||||
| 		ecmd->advertising = hw->autoneg_advertised | | ||||
| 				    ADVERTISED_TP | ADVERTISED_Autoneg; | ||||
| 
 | ||||
| 		adv4 = hw->mii_autoneg_adv_reg & ~ADVERTISE_ALL; | ||||
| 		adv9 = hw->mii_1000t_ctrl_reg & ~MII_AT001_CR_1000T_SPEED_MASK; | ||||
| 		if (hw->autoneg_advertised & ADVERTISE_10_HALF) | ||||
| 			adv4 |= ADVERTISE_10HALF; | ||||
| 		if (hw->autoneg_advertised & ADVERTISE_10_FULL) | ||||
| 			adv4 |= ADVERTISE_10FULL; | ||||
| 		if (hw->autoneg_advertised & ADVERTISE_100_HALF) | ||||
| 			adv4 |= ADVERTISE_100HALF; | ||||
| 		if (hw->autoneg_advertised & ADVERTISE_100_FULL) | ||||
| 			adv4 |= ADVERTISE_100FULL; | ||||
| 		if (hw->autoneg_advertised & ADVERTISE_1000_FULL) | ||||
| 			adv9 |= ADVERTISE_1000FULL; | ||||
| 
 | ||||
| 		if (adv4 != hw->mii_autoneg_adv_reg || | ||||
| 				adv9 != hw->mii_1000t_ctrl_reg) { | ||||
| 			hw->mii_autoneg_adv_reg = adv4; | ||||
| 			hw->mii_1000t_ctrl_reg = adv9; | ||||
| 			hw->re_autoneg = true; | ||||
| 		} | ||||
| 
 | ||||
| 	} else { | ||||
| 		clear_bit(__AT_RESETTING, &adapter->flags); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	/* reset the link */ | ||||
| 
 | ||||
| 	if (netif_running(adapter->netdev)) { | ||||
| 		atl1e_down(adapter); | ||||
| 		atl1e_up(adapter); | ||||
| 	} else | ||||
| 		atl1e_reset_hw(&adapter->hw); | ||||
| 
 | ||||
| 	clear_bit(__AT_RESETTING, &adapter->flags); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static u32 atl1e_get_msglevel(struct net_device *netdev) | ||||
| { | ||||
| #ifdef DBG | ||||
| 	return 1; | ||||
| #else | ||||
| 	return 0; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| static int atl1e_get_regs_len(struct net_device *netdev) | ||||
| { | ||||
| 	return AT_REGS_LEN * sizeof(u32); | ||||
| } | ||||
| 
 | ||||
| static void atl1e_get_regs(struct net_device *netdev, | ||||
| 			   struct ethtool_regs *regs, void *p) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = netdev_priv(netdev); | ||||
| 	struct atl1e_hw *hw = &adapter->hw; | ||||
| 	u32 *regs_buff = p; | ||||
| 	u16 phy_data; | ||||
| 
 | ||||
| 	memset(p, 0, AT_REGS_LEN * sizeof(u32)); | ||||
| 
 | ||||
| 	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; | ||||
| 
 | ||||
| 	regs_buff[0]  = AT_READ_REG(hw, REG_VPD_CAP); | ||||
| 	regs_buff[1]  = AT_READ_REG(hw, REG_SPI_FLASH_CTRL); | ||||
| 	regs_buff[2]  = AT_READ_REG(hw, REG_SPI_FLASH_CONFIG); | ||||
| 	regs_buff[3]  = AT_READ_REG(hw, REG_TWSI_CTRL); | ||||
| 	regs_buff[4]  = AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL); | ||||
| 	regs_buff[5]  = AT_READ_REG(hw, REG_MASTER_CTRL); | ||||
| 	regs_buff[6]  = AT_READ_REG(hw, REG_MANUAL_TIMER_INIT); | ||||
| 	regs_buff[7]  = AT_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT); | ||||
| 	regs_buff[8]  = AT_READ_REG(hw, REG_GPHY_CTRL); | ||||
| 	regs_buff[9]  = AT_READ_REG(hw, REG_CMBDISDMA_TIMER); | ||||
| 	regs_buff[10] = AT_READ_REG(hw, REG_IDLE_STATUS); | ||||
| 	regs_buff[11] = AT_READ_REG(hw, REG_MDIO_CTRL); | ||||
| 	regs_buff[12] = AT_READ_REG(hw, REG_SERDES_LOCK); | ||||
| 	regs_buff[13] = AT_READ_REG(hw, REG_MAC_CTRL); | ||||
| 	regs_buff[14] = AT_READ_REG(hw, REG_MAC_IPG_IFG); | ||||
| 	regs_buff[15] = AT_READ_REG(hw, REG_MAC_STA_ADDR); | ||||
| 	regs_buff[16] = AT_READ_REG(hw, REG_MAC_STA_ADDR+4); | ||||
| 	regs_buff[17] = AT_READ_REG(hw, REG_RX_HASH_TABLE); | ||||
| 	regs_buff[18] = AT_READ_REG(hw, REG_RX_HASH_TABLE+4); | ||||
| 	regs_buff[19] = AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL); | ||||
| 	regs_buff[20] = AT_READ_REG(hw, REG_MTU); | ||||
| 	regs_buff[21] = AT_READ_REG(hw, REG_WOL_CTRL); | ||||
| 	regs_buff[22] = AT_READ_REG(hw, REG_SRAM_TRD_ADDR); | ||||
| 	regs_buff[23] = AT_READ_REG(hw, REG_SRAM_TRD_LEN); | ||||
| 	regs_buff[24] = AT_READ_REG(hw, REG_SRAM_RXF_ADDR); | ||||
| 	regs_buff[25] = AT_READ_REG(hw, REG_SRAM_RXF_LEN); | ||||
| 	regs_buff[26] = AT_READ_REG(hw, REG_SRAM_TXF_ADDR); | ||||
| 	regs_buff[27] = AT_READ_REG(hw, REG_SRAM_TXF_LEN); | ||||
| 	regs_buff[28] = AT_READ_REG(hw, REG_SRAM_TCPH_ADDR); | ||||
| 	regs_buff[29] = AT_READ_REG(hw, REG_SRAM_PKTH_ADDR); | ||||
| 
 | ||||
| 	atl1e_read_phy_reg(hw, MII_BMCR, &phy_data); | ||||
| 	regs_buff[73] = (u32)phy_data; | ||||
| 	atl1e_read_phy_reg(hw, MII_BMSR, &phy_data); | ||||
| 	regs_buff[74] = (u32)phy_data; | ||||
| } | ||||
| 
 | ||||
| static int atl1e_get_eeprom_len(struct net_device *netdev) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = netdev_priv(netdev); | ||||
| 
 | ||||
| 	if (!atl1e_check_eeprom_exist(&adapter->hw)) | ||||
| 		return AT_EEPROM_LEN; | ||||
| 	else | ||||
| 		return 0; | ||||
| } | ||||
| 
 | ||||
| static int atl1e_get_eeprom(struct net_device *netdev, | ||||
| 		struct ethtool_eeprom *eeprom, u8 *bytes) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = netdev_priv(netdev); | ||||
| 	struct atl1e_hw *hw = &adapter->hw; | ||||
| 	u32 *eeprom_buff; | ||||
| 	int first_dword, last_dword; | ||||
| 	int ret_val = 0; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (eeprom->len == 0) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	if (atl1e_check_eeprom_exist(hw)) /* not exist */ | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	eeprom->magic = hw->vendor_id | (hw->device_id << 16); | ||||
| 
 | ||||
| 	first_dword = eeprom->offset >> 2; | ||||
| 	last_dword = (eeprom->offset + eeprom->len - 1) >> 2; | ||||
| 
 | ||||
| 	eeprom_buff = kmalloc(sizeof(u32) * | ||||
| 			(last_dword - first_dword + 1), GFP_KERNEL); | ||||
| 	if (eeprom_buff == NULL) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	for (i = first_dword; i < last_dword; i++) { | ||||
| 		if (!atl1e_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) { | ||||
| 			kfree(eeprom_buff); | ||||
| 			return -EIO; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3), | ||||
| 			eeprom->len); | ||||
| 	kfree(eeprom_buff); | ||||
| 
 | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| static int atl1e_set_eeprom(struct net_device *netdev, | ||||
| 			    struct ethtool_eeprom *eeprom, u8 *bytes) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = netdev_priv(netdev); | ||||
| 	struct atl1e_hw *hw = &adapter->hw; | ||||
| 	u32 *eeprom_buff; | ||||
| 	u32 *ptr; | ||||
| 	int first_dword, last_dword; | ||||
| 	int ret_val = 0; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (eeprom->len == 0) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	first_dword = eeprom->offset >> 2; | ||||
| 	last_dword = (eeprom->offset + eeprom->len - 1) >> 2; | ||||
| 	eeprom_buff = kmalloc(AT_EEPROM_LEN, GFP_KERNEL); | ||||
| 	if (eeprom_buff == NULL) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	ptr = eeprom_buff; | ||||
| 
 | ||||
| 	if (eeprom->offset & 3) { | ||||
| 		/* need read/modify/write of first changed EEPROM word */ | ||||
| 		/* only the second byte of the word is being modified */ | ||||
| 		if (!atl1e_read_eeprom(hw, first_dword * 4, &(eeprom_buff[0]))) { | ||||
| 			ret_val = -EIO; | ||||
| 			goto out; | ||||
| 		} | ||||
| 		ptr++; | ||||
| 	} | ||||
| 	if (((eeprom->offset + eeprom->len) & 3)) { | ||||
| 		/* need read/modify/write of last changed EEPROM word */ | ||||
| 		/* only the first byte of the word is being modified */ | ||||
| 
 | ||||
| 		if (!atl1e_read_eeprom(hw, last_dword * 4, | ||||
| 				&(eeprom_buff[last_dword - first_dword]))) { | ||||
| 			ret_val = -EIO; | ||||
| 			goto out; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Device's eeprom is always little-endian, word addressable */ | ||||
| 	memcpy(ptr, bytes, eeprom->len); | ||||
| 
 | ||||
| 	for (i = 0; i < last_dword - first_dword + 1; i++) { | ||||
| 		if (!atl1e_write_eeprom(hw, ((first_dword + i) * 4), | ||||
| 				  eeprom_buff[i])) { | ||||
| 			ret_val = -EIO; | ||||
| 			goto out; | ||||
| 		} | ||||
| 	} | ||||
| out: | ||||
| 	kfree(eeprom_buff); | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| static void atl1e_get_drvinfo(struct net_device *netdev, | ||||
| 		struct ethtool_drvinfo *drvinfo) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = netdev_priv(netdev); | ||||
| 
 | ||||
| 	strlcpy(drvinfo->driver,  atl1e_driver_name, sizeof(drvinfo->driver)); | ||||
| 	strlcpy(drvinfo->version, atl1e_driver_version, | ||||
| 		sizeof(drvinfo->version)); | ||||
| 	strlcpy(drvinfo->fw_version, "L1e", sizeof(drvinfo->fw_version)); | ||||
| 	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), | ||||
| 		sizeof(drvinfo->bus_info)); | ||||
| 	drvinfo->n_stats = 0; | ||||
| 	drvinfo->testinfo_len = 0; | ||||
| 	drvinfo->regdump_len = atl1e_get_regs_len(netdev); | ||||
| 	drvinfo->eedump_len = atl1e_get_eeprom_len(netdev); | ||||
| } | ||||
| 
 | ||||
| static void atl1e_get_wol(struct net_device *netdev, | ||||
| 			  struct ethtool_wolinfo *wol) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = netdev_priv(netdev); | ||||
| 
 | ||||
| 	wol->supported = WAKE_MAGIC | WAKE_PHY; | ||||
| 	wol->wolopts = 0; | ||||
| 
 | ||||
| 	if (adapter->wol & AT_WUFC_EX) | ||||
| 		wol->wolopts |= WAKE_UCAST; | ||||
| 	if (adapter->wol & AT_WUFC_MC) | ||||
| 		wol->wolopts |= WAKE_MCAST; | ||||
| 	if (adapter->wol & AT_WUFC_BC) | ||||
| 		wol->wolopts |= WAKE_BCAST; | ||||
| 	if (adapter->wol & AT_WUFC_MAG) | ||||
| 		wol->wolopts |= WAKE_MAGIC; | ||||
| 	if (adapter->wol & AT_WUFC_LNKC) | ||||
| 		wol->wolopts |= WAKE_PHY; | ||||
| } | ||||
| 
 | ||||
| static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = netdev_priv(netdev); | ||||
| 
 | ||||
| 	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | | ||||
| 			    WAKE_UCAST | WAKE_MCAST | WAKE_BCAST)) | ||||
| 		return -EOPNOTSUPP; | ||||
| 	/* these settings will always override what we currently have */ | ||||
| 	adapter->wol = 0; | ||||
| 
 | ||||
| 	if (wol->wolopts & WAKE_MAGIC) | ||||
| 		adapter->wol |= AT_WUFC_MAG; | ||||
| 	if (wol->wolopts & WAKE_PHY) | ||||
| 		adapter->wol |= AT_WUFC_LNKC; | ||||
| 
 | ||||
| 	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int atl1e_nway_reset(struct net_device *netdev) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = netdev_priv(netdev); | ||||
| 	if (netif_running(netdev)) | ||||
| 		atl1e_reinit_locked(adapter); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static const struct ethtool_ops atl1e_ethtool_ops = { | ||||
| 	.get_settings           = atl1e_get_settings, | ||||
| 	.set_settings           = atl1e_set_settings, | ||||
| 	.get_drvinfo            = atl1e_get_drvinfo, | ||||
| 	.get_regs_len           = atl1e_get_regs_len, | ||||
| 	.get_regs               = atl1e_get_regs, | ||||
| 	.get_wol                = atl1e_get_wol, | ||||
| 	.set_wol                = atl1e_set_wol, | ||||
| 	.get_msglevel           = atl1e_get_msglevel, | ||||
| 	.nway_reset             = atl1e_nway_reset, | ||||
| 	.get_link               = ethtool_op_get_link, | ||||
| 	.get_eeprom_len         = atl1e_get_eeprom_len, | ||||
| 	.get_eeprom             = atl1e_get_eeprom, | ||||
| 	.set_eeprom             = atl1e_set_eeprom, | ||||
| }; | ||||
| 
 | ||||
| void atl1e_set_ethtool_ops(struct net_device *netdev) | ||||
| { | ||||
| 	netdev->ethtool_ops = &atl1e_ethtool_ops; | ||||
| } | ||||
							
								
								
									
										650
									
								
								drivers/net/ethernet/atheros/atl1e/atl1e_hw.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										650
									
								
								drivers/net/ethernet/atheros/atl1e/atl1e_hw.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,650 @@ | |||
| /*
 | ||||
|  * Copyright(c) 2007 Atheros Corporation. All rights reserved. | ||||
|  * | ||||
|  * Derived from Intel e1000 driver | ||||
|  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the Free | ||||
|  * Software Foundation; either version 2 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., 59 | ||||
|  * Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||
|  */ | ||||
| #include <linux/pci.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/mii.h> | ||||
| #include <linux/crc32.h> | ||||
| 
 | ||||
| #include "atl1e.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * check_eeprom_exist | ||||
|  * return 0 if eeprom exist | ||||
|  */ | ||||
| int atl1e_check_eeprom_exist(struct atl1e_hw *hw) | ||||
| { | ||||
| 	u32 value; | ||||
| 
 | ||||
| 	value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL); | ||||
| 	if (value & SPI_FLASH_CTRL_EN_VPD) { | ||||
| 		value &= ~SPI_FLASH_CTRL_EN_VPD; | ||||
| 		AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value); | ||||
| 	} | ||||
| 	value = AT_READ_REGW(hw, REG_PCIE_CAP_LIST); | ||||
| 	return ((value & 0xFF00) == 0x6C00) ? 0 : 1; | ||||
| } | ||||
| 
 | ||||
| void atl1e_hw_set_mac_addr(struct atl1e_hw *hw) | ||||
| { | ||||
| 	u32 value; | ||||
| 	/*
 | ||||
| 	 * 00-0B-6A-F6-00-DC | ||||
| 	 * 0:  6AF600DC 1: 000B | ||||
| 	 * low dword | ||||
| 	 */ | ||||
| 	value = (((u32)hw->mac_addr[2]) << 24) | | ||||
| 		(((u32)hw->mac_addr[3]) << 16) | | ||||
| 		(((u32)hw->mac_addr[4]) << 8)  | | ||||
| 		(((u32)hw->mac_addr[5])) ; | ||||
| 	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); | ||||
| 	/* hight dword */ | ||||
| 	value = (((u32)hw->mac_addr[0]) << 8) | | ||||
| 		(((u32)hw->mac_addr[1])) ; | ||||
| 	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * atl1e_get_permanent_address | ||||
|  * return 0 if get valid mac address, | ||||
|  */ | ||||
| static int atl1e_get_permanent_address(struct atl1e_hw *hw) | ||||
| { | ||||
| 	u32 addr[2]; | ||||
| 	u32 i; | ||||
| 	u32 twsi_ctrl_data; | ||||
| 	u8  eth_addr[ETH_ALEN]; | ||||
| 
 | ||||
| 	if (is_valid_ether_addr(hw->perm_mac_addr)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* init */ | ||||
| 	addr[0] = addr[1] = 0; | ||||
| 
 | ||||
| 	if (!atl1e_check_eeprom_exist(hw)) { | ||||
| 		/* eeprom exist */ | ||||
| 		twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL); | ||||
| 		twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART; | ||||
| 		AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data); | ||||
| 		for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) { | ||||
| 			msleep(10); | ||||
| 			twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL); | ||||
| 			if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0) | ||||
| 				break; | ||||
| 		} | ||||
| 		if (i >= AT_TWSI_EEPROM_TIMEOUT) | ||||
| 			return AT_ERR_TIMEOUT; | ||||
| 	} | ||||
| 
 | ||||
| 	/* maybe MAC-address is from BIOS */ | ||||
| 	addr[0] = AT_READ_REG(hw, REG_MAC_STA_ADDR); | ||||
| 	addr[1] = AT_READ_REG(hw, REG_MAC_STA_ADDR + 4); | ||||
| 	*(u32 *) ð_addr[2] = swab32(addr[0]); | ||||
| 	*(u16 *) ð_addr[0] = swab16(*(u16 *)&addr[1]); | ||||
| 
 | ||||
| 	if (is_valid_ether_addr(eth_addr)) { | ||||
| 		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN); | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	return AT_ERR_EEPROM; | ||||
| } | ||||
| 
 | ||||
| bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value) | ||||
| { | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value) | ||||
| { | ||||
| 	int i; | ||||
| 	u32 control; | ||||
| 
 | ||||
| 	if (offset & 3) | ||||
| 		return false; /* address do not align */ | ||||
| 
 | ||||
| 	AT_WRITE_REG(hw, REG_VPD_DATA, 0); | ||||
| 	control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT; | ||||
| 	AT_WRITE_REG(hw, REG_VPD_CAP, control); | ||||
| 
 | ||||
| 	for (i = 0; i < 10; i++) { | ||||
| 		msleep(2); | ||||
| 		control = AT_READ_REG(hw, REG_VPD_CAP); | ||||
| 		if (control & VPD_CAP_VPD_FLAG) | ||||
| 			break; | ||||
| 	} | ||||
| 	if (control & VPD_CAP_VPD_FLAG) { | ||||
| 		*p_value = AT_READ_REG(hw, REG_VPD_DATA); | ||||
| 		return true; | ||||
| 	} | ||||
| 	return false; /* timeout */ | ||||
| } | ||||
| 
 | ||||
| void atl1e_force_ps(struct atl1e_hw *hw) | ||||
| { | ||||
| 	AT_WRITE_REGW(hw, REG_GPHY_CTRL, | ||||
| 			GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Reads the adapter's MAC address from the EEPROM | ||||
|  * | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  */ | ||||
| int atl1e_read_mac_addr(struct atl1e_hw *hw) | ||||
| { | ||||
| 	int err = 0; | ||||
| 
 | ||||
| 	err = atl1e_get_permanent_address(hw); | ||||
| 	if (err) | ||||
| 		return AT_ERR_EEPROM; | ||||
| 	memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr)); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * atl1e_hash_mc_addr | ||||
|  *  purpose | ||||
|  *      set hash value for a multicast address | ||||
|  */ | ||||
| u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr) | ||||
| { | ||||
| 	u32 crc32; | ||||
| 	u32 value = 0; | ||||
| 	int i; | ||||
| 
 | ||||
| 	crc32 = ether_crc_le(6, mc_addr); | ||||
| 	for (i = 0; i < 32; i++) | ||||
| 		value |= (((crc32 >> i) & 1) << (31 - i)); | ||||
| 
 | ||||
| 	return value; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Sets the bit in the multicast table corresponding to the hash value. | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  * hash_value - Multicast address hash value | ||||
|  */ | ||||
| void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value) | ||||
| { | ||||
| 	u32 hash_bit, hash_reg; | ||||
| 	u32 mta; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * The HASH Table  is a register array of 2 32-bit registers. | ||||
| 	 * It is treated like an array of 64 bits.  We want to set | ||||
| 	 * bit BitArray[hash_value]. So we figure out what register | ||||
| 	 * the bit is in, read it, OR in the new bit, then write | ||||
| 	 * back the new value.  The register is determined by the | ||||
| 	 * upper 7 bits of the hash value and the bit within that | ||||
| 	 * register are determined by the lower 5 bits of the value. | ||||
| 	 */ | ||||
| 	hash_reg = (hash_value >> 31) & 0x1; | ||||
| 	hash_bit = (hash_value >> 26) & 0x1F; | ||||
| 
 | ||||
| 	mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg); | ||||
| 
 | ||||
| 	mta |= (1 << hash_bit); | ||||
| 
 | ||||
| 	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta); | ||||
| } | ||||
| /*
 | ||||
|  * Reads the value from a PHY register | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  * reg_addr - address of the PHY register to read | ||||
|  */ | ||||
| int atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data) | ||||
| { | ||||
| 	u32 val; | ||||
| 	int i; | ||||
| 
 | ||||
| 	val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT | | ||||
| 		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | | ||||
| 		MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; | ||||
| 
 | ||||
| 	AT_WRITE_REG(hw, REG_MDIO_CTRL, val); | ||||
| 
 | ||||
| 	wmb(); | ||||
| 
 | ||||
| 	for (i = 0; i < MDIO_WAIT_TIMES; i++) { | ||||
| 		udelay(2); | ||||
| 		val = AT_READ_REG(hw, REG_MDIO_CTRL); | ||||
| 		if (!(val & (MDIO_START | MDIO_BUSY))) | ||||
| 			break; | ||||
| 		wmb(); | ||||
| 	} | ||||
| 	if (!(val & (MDIO_START | MDIO_BUSY))) { | ||||
| 		*phy_data = (u16)val; | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	return AT_ERR_PHY; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Writes a value to a PHY register | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  * reg_addr - address of the PHY register to write | ||||
|  * data - data to write to the PHY | ||||
|  */ | ||||
| int atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data) | ||||
| { | ||||
| 	int i; | ||||
| 	u32 val; | ||||
| 
 | ||||
| 	val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT | | ||||
| 	       (reg_addr&MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT | | ||||
| 	       MDIO_SUP_PREAMBLE | | ||||
| 	       MDIO_START | | ||||
| 	       MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; | ||||
| 
 | ||||
| 	AT_WRITE_REG(hw, REG_MDIO_CTRL, val); | ||||
| 	wmb(); | ||||
| 
 | ||||
| 	for (i = 0; i < MDIO_WAIT_TIMES; i++) { | ||||
| 		udelay(2); | ||||
| 		val = AT_READ_REG(hw, REG_MDIO_CTRL); | ||||
| 		if (!(val & (MDIO_START | MDIO_BUSY))) | ||||
| 			break; | ||||
| 		wmb(); | ||||
| 	} | ||||
| 
 | ||||
| 	if (!(val & (MDIO_START | MDIO_BUSY))) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	return AT_ERR_PHY; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * atl1e_init_pcie - init PCIE module | ||||
|  */ | ||||
| static void atl1e_init_pcie(struct atl1e_hw *hw) | ||||
| { | ||||
| 	u32 value; | ||||
| 	/* comment 2lines below to save more power when sususpend
 | ||||
| 	   value = LTSSM_TEST_MODE_DEF; | ||||
| 	   AT_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value); | ||||
| 	 */ | ||||
| 
 | ||||
| 	/* pcie flow control mode change */ | ||||
| 	value = AT_READ_REG(hw, 0x1008); | ||||
| 	value |= 0x8000; | ||||
| 	AT_WRITE_REG(hw, 0x1008, value); | ||||
| } | ||||
| /*
 | ||||
|  * Configures PHY autoneg and flow control advertisement settings | ||||
|  * | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  */ | ||||
| static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw) | ||||
| { | ||||
| 	s32 ret_val; | ||||
| 	u16 mii_autoneg_adv_reg; | ||||
| 	u16 mii_1000t_ctrl_reg; | ||||
| 
 | ||||
| 	if (0 != hw->mii_autoneg_adv_reg) | ||||
| 		return 0; | ||||
| 	/* Read the MII Auto-Neg Advertisement Register (Address 4/9). */ | ||||
| 	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK; | ||||
| 	mii_1000t_ctrl_reg  = MII_AT001_CR_1000T_DEFAULT_CAP_MASK; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Need to parse autoneg_advertised  and set up | ||||
| 	 * the appropriate PHY registers.  First we will parse for | ||||
| 	 * autoneg_advertised software override.  Since we can advertise | ||||
| 	 * a plethora of combinations, we need to check each bit | ||||
| 	 * individually. | ||||
| 	 */ | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * First we clear all the 10/100 mb speed bits in the Auto-Neg | ||||
| 	 * Advertisement Register (Address 4) and the 1000 mb speed bits in | ||||
| 	 * the  1000Base-T control Register (Address 9). | ||||
| 	 */ | ||||
| 	mii_autoneg_adv_reg &= ~ADVERTISE_ALL; | ||||
| 	mii_1000t_ctrl_reg  &= ~MII_AT001_CR_1000T_SPEED_MASK; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Need to parse MediaType and setup the | ||||
| 	 * appropriate PHY registers. | ||||
| 	 */ | ||||
| 	switch (hw->media_type) { | ||||
| 	case MEDIA_TYPE_AUTO_SENSOR: | ||||
| 		mii_autoneg_adv_reg |= ADVERTISE_ALL; | ||||
| 		hw->autoneg_advertised = ADVERTISE_ALL; | ||||
| 		if (hw->nic_type == athr_l1e) { | ||||
| 			mii_1000t_ctrl_reg |= ADVERTISE_1000FULL; | ||||
| 			hw->autoneg_advertised |= ADVERTISE_1000_FULL; | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 	case MEDIA_TYPE_100M_FULL: | ||||
| 		mii_autoneg_adv_reg   |= ADVERTISE_100FULL; | ||||
| 		hw->autoneg_advertised = ADVERTISE_100_FULL; | ||||
| 		break; | ||||
| 
 | ||||
| 	case MEDIA_TYPE_100M_HALF: | ||||
| 		mii_autoneg_adv_reg   |= ADVERTISE_100_HALF; | ||||
| 		hw->autoneg_advertised = ADVERTISE_100_HALF; | ||||
| 		break; | ||||
| 
 | ||||
| 	case MEDIA_TYPE_10M_FULL: | ||||
| 		mii_autoneg_adv_reg   |= ADVERTISE_10_FULL; | ||||
| 		hw->autoneg_advertised = ADVERTISE_10_FULL; | ||||
| 		break; | ||||
| 
 | ||||
| 	default: | ||||
| 		mii_autoneg_adv_reg   |= ADVERTISE_10_HALF; | ||||
| 		hw->autoneg_advertised = ADVERTISE_10_HALF; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	/* flow control fixed to enable all */ | ||||
| 	mii_autoneg_adv_reg |= (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); | ||||
| 
 | ||||
| 	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg; | ||||
| 	hw->mii_1000t_ctrl_reg  = mii_1000t_ctrl_reg; | ||||
| 
 | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 
 | ||||
| 	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) { | ||||
| 		ret_val = atl1e_write_phy_reg(hw, MII_CTRL1000, | ||||
| 					   mii_1000t_ctrl_reg); | ||||
| 		if (ret_val) | ||||
| 			return ret_val; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Resets the PHY and make all config validate | ||||
|  * | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  * | ||||
|  * Sets bit 15 and 12 of the MII control regiser (for F001 bug) | ||||
|  */ | ||||
| int atl1e_phy_commit(struct atl1e_hw *hw) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = hw->adapter; | ||||
| 	int ret_val; | ||||
| 	u16 phy_data; | ||||
| 
 | ||||
| 	phy_data = BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART; | ||||
| 
 | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data); | ||||
| 	if (ret_val) { | ||||
| 		u32 val; | ||||
| 		int i; | ||||
| 		/**************************************
 | ||||
| 		 * pcie serdes link may be down ! | ||||
| 		 **************************************/ | ||||
| 		for (i = 0; i < 25; i++) { | ||||
| 			msleep(1); | ||||
| 			val = AT_READ_REG(hw, REG_MDIO_CTRL); | ||||
| 			if (!(val & (MDIO_START | MDIO_BUSY))) | ||||
| 				break; | ||||
| 		} | ||||
| 
 | ||||
| 		if (0 != (val & (MDIO_START | MDIO_BUSY))) { | ||||
| 			netdev_err(adapter->netdev, | ||||
| 				   "pcie linkdown at least for 25ms\n"); | ||||
| 			return ret_val; | ||||
| 		} | ||||
| 
 | ||||
| 		netdev_err(adapter->netdev, "pcie linkup after %d ms\n", i); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int atl1e_phy_init(struct atl1e_hw *hw) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = hw->adapter; | ||||
| 	s32 ret_val; | ||||
| 	u16 phy_val; | ||||
| 
 | ||||
| 	if (hw->phy_configured) { | ||||
| 		if (hw->re_autoneg) { | ||||
| 			hw->re_autoneg = false; | ||||
| 			return atl1e_restart_autoneg(hw); | ||||
| 		} | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	/* RESET GPHY Core */ | ||||
| 	AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT); | ||||
| 	msleep(2); | ||||
| 	AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT | | ||||
| 		      GPHY_CTRL_EXT_RESET); | ||||
| 	msleep(2); | ||||
| 
 | ||||
| 	/* patches */ | ||||
| 	/* p1. eable hibernation mode */ | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0xB); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0xBC00); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 	/* p2. set Class A/B for all modes */ | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 	phy_val = 0x02ef; | ||||
| 	/* remove Class AB */ | ||||
| 	/* phy_val = hw->emi_ca ? 0x02ef : 0x02df; */ | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, phy_val); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 	/* p3. 10B ??? */ | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x12); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x4C04); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 	/* p4. 1000T power */ | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x4); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x8BBB); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 
 | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x5); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x2C46); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 
 | ||||
| 	msleep(1); | ||||
| 
 | ||||
| 	/*Enable PHY LinkChange Interrupt */ | ||||
| 	ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00); | ||||
| 	if (ret_val) { | ||||
| 		netdev_err(adapter->netdev, | ||||
| 			   "Error enable PHY linkChange Interrupt\n"); | ||||
| 		return ret_val; | ||||
| 	} | ||||
| 	/* setup AutoNeg parameters */ | ||||
| 	ret_val = atl1e_phy_setup_autoneg_adv(hw); | ||||
| 	if (ret_val) { | ||||
| 		netdev_err(adapter->netdev, | ||||
| 			   "Error Setting up Auto-Negotiation\n"); | ||||
| 		return ret_val; | ||||
| 	} | ||||
| 	/* SW.Reset & En-Auto-Neg to restart Auto-Neg*/ | ||||
| 	netdev_dbg(adapter->netdev, "Restarting Auto-Negotiation\n"); | ||||
| 	ret_val = atl1e_phy_commit(hw); | ||||
| 	if (ret_val) { | ||||
| 		netdev_err(adapter->netdev, "Error resetting the phy\n"); | ||||
| 		return ret_val; | ||||
| 	} | ||||
| 
 | ||||
| 	hw->phy_configured = true; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Reset the transmit and receive units; mask and clear all interrupts. | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  * return : 0  or  idle status (if error) | ||||
|  */ | ||||
| int atl1e_reset_hw(struct atl1e_hw *hw) | ||||
| { | ||||
| 	struct atl1e_adapter *adapter = hw->adapter; | ||||
| 	struct pci_dev *pdev = adapter->pdev; | ||||
| 
 | ||||
| 	u32 idle_status_data = 0; | ||||
| 	u16 pci_cfg_cmd_word = 0; | ||||
| 	int timeout = 0; | ||||
| 
 | ||||
| 	/* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */ | ||||
| 	pci_read_config_word(pdev, PCI_REG_COMMAND, &pci_cfg_cmd_word); | ||||
| 	if ((pci_cfg_cmd_word & (CMD_IO_SPACE | | ||||
| 				CMD_MEMORY_SPACE | CMD_BUS_MASTER)) | ||||
| 			!= (CMD_IO_SPACE | CMD_MEMORY_SPACE | CMD_BUS_MASTER)) { | ||||
| 		pci_cfg_cmd_word |= (CMD_IO_SPACE | | ||||
| 				     CMD_MEMORY_SPACE | CMD_BUS_MASTER); | ||||
| 		pci_write_config_word(pdev, PCI_REG_COMMAND, pci_cfg_cmd_word); | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Issue Soft Reset to the MAC.  This will reset the chip's | ||||
| 	 * transmit, receive, DMA.  It will not effect | ||||
| 	 * the current PCI configuration.  The global reset bit is self- | ||||
| 	 * clearing, and should clear within a microsecond. | ||||
| 	 */ | ||||
| 	AT_WRITE_REG(hw, REG_MASTER_CTRL, | ||||
| 			MASTER_CTRL_LED_MODE | MASTER_CTRL_SOFT_RST); | ||||
| 	wmb(); | ||||
| 	msleep(1); | ||||
| 
 | ||||
| 	/* Wait at least 10ms for All module to be Idle */ | ||||
| 	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { | ||||
| 		idle_status_data = AT_READ_REG(hw, REG_IDLE_STATUS); | ||||
| 		if (idle_status_data == 0) | ||||
| 			break; | ||||
| 		msleep(1); | ||||
| 		cpu_relax(); | ||||
| 	} | ||||
| 
 | ||||
| 	if (timeout >= AT_HW_MAX_IDLE_DELAY) { | ||||
| 		netdev_err(adapter->netdev, | ||||
| 			   "MAC state machine can't be idle since disabled for 10ms second\n"); | ||||
| 		return AT_ERR_TIMEOUT; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Performs basic configuration of the adapter. | ||||
|  * | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  * Assumes that the controller has previously been reset and is in a | ||||
|  * post-reset uninitialized state. Initializes multicast table, | ||||
|  * and  Calls routines to setup link | ||||
|  * Leaves the transmit and receive units disabled and uninitialized. | ||||
|  */ | ||||
| int atl1e_init_hw(struct atl1e_hw *hw) | ||||
| { | ||||
| 	s32 ret_val = 0; | ||||
| 
 | ||||
| 	atl1e_init_pcie(hw); | ||||
| 
 | ||||
| 	/* Zero out the Multicast HASH table */ | ||||
| 	/* clear the old settings from the multicast hash table */ | ||||
| 	AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); | ||||
| 	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); | ||||
| 
 | ||||
| 	ret_val = atl1e_phy_init(hw); | ||||
| 
 | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Detects the current speed and duplex settings of the hardware. | ||||
|  * | ||||
|  * hw - Struct containing variables accessed by shared code | ||||
|  * speed - Speed of the connection | ||||
|  * duplex - Duplex setting of the connection | ||||
|  */ | ||||
| int atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex) | ||||
| { | ||||
| 	int err; | ||||
| 	u16 phy_data; | ||||
| 
 | ||||
| 	/* Read   PHY Specific Status Register (17) */ | ||||
| 	err = atl1e_read_phy_reg(hw, MII_AT001_PSSR, &phy_data); | ||||
| 	if (err) | ||||
| 		return err; | ||||
| 
 | ||||
| 	if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED)) | ||||
| 		return AT_ERR_PHY_RES; | ||||
| 
 | ||||
| 	switch (phy_data & MII_AT001_PSSR_SPEED) { | ||||
| 	case MII_AT001_PSSR_1000MBS: | ||||
| 		*speed = SPEED_1000; | ||||
| 		break; | ||||
| 	case MII_AT001_PSSR_100MBS: | ||||
| 		*speed = SPEED_100; | ||||
| 		break; | ||||
| 	case MII_AT001_PSSR_10MBS: | ||||
| 		*speed = SPEED_10; | ||||
| 		break; | ||||
| 	default: | ||||
| 		return AT_ERR_PHY_SPEED; | ||||
| 	} | ||||
| 
 | ||||
| 	if (phy_data & MII_AT001_PSSR_DPLX) | ||||
| 		*duplex = FULL_DUPLEX; | ||||
| 	else | ||||
| 		*duplex = HALF_DUPLEX; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int atl1e_restart_autoneg(struct atl1e_hw *hw) | ||||
| { | ||||
| 	int err = 0; | ||||
| 
 | ||||
| 	err = atl1e_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg); | ||||
| 	if (err) | ||||
| 		return err; | ||||
| 
 | ||||
| 	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) { | ||||
| 		err = atl1e_write_phy_reg(hw, MII_CTRL1000, | ||||
| 				       hw->mii_1000t_ctrl_reg); | ||||
| 		if (err) | ||||
| 			return err; | ||||
| 	} | ||||
| 
 | ||||
| 	err = atl1e_write_phy_reg(hw, MII_BMCR, | ||||
| 			BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART); | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										690
									
								
								drivers/net/ethernet/atheros/atl1e/atl1e_hw.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										690
									
								
								drivers/net/ethernet/atheros/atl1e/atl1e_hw.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,690 @@ | |||
| /*
 | ||||
|  * Copyright(c) 2007 Atheros Corporation. All rights reserved. | ||||
|  * | ||||
|  * Derived from Intel e1000 driver | ||||
|  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the Free | ||||
|  * Software Foundation; either version 2 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., 59 | ||||
|  * Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _ATHL1E_HW_H_ | ||||
| #define _ATHL1E_HW_H_ | ||||
| 
 | ||||
| #include <linux/types.h> | ||||
| #include <linux/mii.h> | ||||
| 
 | ||||
| struct atl1e_adapter; | ||||
| struct atl1e_hw; | ||||
| 
 | ||||
| /* function prototype */ | ||||
| s32 atl1e_reset_hw(struct atl1e_hw *hw); | ||||
| s32 atl1e_read_mac_addr(struct atl1e_hw *hw); | ||||
| s32 atl1e_init_hw(struct atl1e_hw *hw); | ||||
| s32 atl1e_phy_commit(struct atl1e_hw *hw); | ||||
| s32 atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex); | ||||
| u32 atl1e_auto_get_fc(struct atl1e_adapter *adapter, u16 duplex); | ||||
| u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr); | ||||
| void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value); | ||||
| s32 atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data); | ||||
| s32 atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data); | ||||
| s32 atl1e_validate_mdi_setting(struct atl1e_hw *hw); | ||||
| void atl1e_hw_set_mac_addr(struct atl1e_hw *hw); | ||||
| bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value); | ||||
| bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value); | ||||
| s32 atl1e_phy_enter_power_saving(struct atl1e_hw *hw); | ||||
| s32 atl1e_phy_leave_power_saving(struct atl1e_hw *hw); | ||||
| s32 atl1e_phy_init(struct atl1e_hw *hw); | ||||
| int atl1e_check_eeprom_exist(struct atl1e_hw *hw); | ||||
| void atl1e_force_ps(struct atl1e_hw *hw); | ||||
| s32 atl1e_restart_autoneg(struct atl1e_hw *hw); | ||||
| 
 | ||||
| /* register definition */ | ||||
| #define REG_PM_CTRLSTAT             0x44 | ||||
| 
 | ||||
| #define REG_PCIE_CAP_LIST           0x58 | ||||
| 
 | ||||
| #define REG_DEVICE_CAP              0x5C | ||||
| #define     DEVICE_CAP_MAX_PAYLOAD_MASK     0x7 | ||||
| #define     DEVICE_CAP_MAX_PAYLOAD_SHIFT    0 | ||||
| 
 | ||||
| #define REG_DEVICE_CTRL             0x60 | ||||
| #define     DEVICE_CTRL_MAX_PAYLOAD_MASK    0x7 | ||||
| #define     DEVICE_CTRL_MAX_PAYLOAD_SHIFT   5 | ||||
| #define     DEVICE_CTRL_MAX_RREQ_SZ_MASK    0x7 | ||||
| #define     DEVICE_CTRL_MAX_RREQ_SZ_SHIFT   12 | ||||
| 
 | ||||
| #define REG_VPD_CAP                 0x6C | ||||
| #define     VPD_CAP_ID_MASK                 0xff | ||||
| #define     VPD_CAP_ID_SHIFT                0 | ||||
| #define     VPD_CAP_NEXT_PTR_MASK           0xFF | ||||
| #define     VPD_CAP_NEXT_PTR_SHIFT          8 | ||||
| #define     VPD_CAP_VPD_ADDR_MASK           0x7FFF | ||||
| #define     VPD_CAP_VPD_ADDR_SHIFT          16 | ||||
| #define     VPD_CAP_VPD_FLAG                0x80000000 | ||||
| 
 | ||||
| #define REG_VPD_DATA                0x70 | ||||
| 
 | ||||
| #define REG_SPI_FLASH_CTRL          0x200 | ||||
| #define     SPI_FLASH_CTRL_STS_NON_RDY      0x1 | ||||
| #define     SPI_FLASH_CTRL_STS_WEN          0x2 | ||||
| #define     SPI_FLASH_CTRL_STS_WPEN         0x80 | ||||
| #define     SPI_FLASH_CTRL_DEV_STS_MASK     0xFF | ||||
| #define     SPI_FLASH_CTRL_DEV_STS_SHIFT    0 | ||||
| #define     SPI_FLASH_CTRL_INS_MASK         0x7 | ||||
| #define     SPI_FLASH_CTRL_INS_SHIFT        8 | ||||
| #define     SPI_FLASH_CTRL_START            0x800 | ||||
| #define     SPI_FLASH_CTRL_EN_VPD           0x2000 | ||||
| #define     SPI_FLASH_CTRL_LDSTART          0x8000 | ||||
| #define     SPI_FLASH_CTRL_CS_HI_MASK       0x3 | ||||
| #define     SPI_FLASH_CTRL_CS_HI_SHIFT      16 | ||||
| #define     SPI_FLASH_CTRL_CS_HOLD_MASK     0x3 | ||||
| #define     SPI_FLASH_CTRL_CS_HOLD_SHIFT    18 | ||||
| #define     SPI_FLASH_CTRL_CLK_LO_MASK      0x3 | ||||
| #define     SPI_FLASH_CTRL_CLK_LO_SHIFT     20 | ||||
| #define     SPI_FLASH_CTRL_CLK_HI_MASK      0x3 | ||||
| #define     SPI_FLASH_CTRL_CLK_HI_SHIFT     22 | ||||
| #define     SPI_FLASH_CTRL_CS_SETUP_MASK    0x3 | ||||
| #define     SPI_FLASH_CTRL_CS_SETUP_SHIFT   24 | ||||
| #define     SPI_FLASH_CTRL_EROM_PGSZ_MASK   0x3 | ||||
| #define     SPI_FLASH_CTRL_EROM_PGSZ_SHIFT  26 | ||||
| #define     SPI_FLASH_CTRL_WAIT_READY       0x10000000 | ||||
| 
 | ||||
| #define REG_SPI_ADDR                0x204 | ||||
| 
 | ||||
| #define REG_SPI_DATA                0x208 | ||||
| 
 | ||||
| #define REG_SPI_FLASH_CONFIG        0x20C | ||||
| #define     SPI_FLASH_CONFIG_LD_ADDR_MASK   0xFFFFFF | ||||
| #define     SPI_FLASH_CONFIG_LD_ADDR_SHIFT  0 | ||||
| #define     SPI_FLASH_CONFIG_VPD_ADDR_MASK  0x3 | ||||
| #define     SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24 | ||||
| #define     SPI_FLASH_CONFIG_LD_EXIST       0x4000000 | ||||
| 
 | ||||
| 
 | ||||
| #define REG_SPI_FLASH_OP_PROGRAM    0x210 | ||||
| #define REG_SPI_FLASH_OP_SC_ERASE   0x211 | ||||
| #define REG_SPI_FLASH_OP_CHIP_ERASE 0x212 | ||||
| #define REG_SPI_FLASH_OP_RDID       0x213 | ||||
| #define REG_SPI_FLASH_OP_WREN       0x214 | ||||
| #define REG_SPI_FLASH_OP_RDSR       0x215 | ||||
| #define REG_SPI_FLASH_OP_WRSR       0x216 | ||||
| #define REG_SPI_FLASH_OP_READ       0x217 | ||||
| 
 | ||||
| #define REG_TWSI_CTRL               0x218 | ||||
| #define     TWSI_CTRL_LD_OFFSET_MASK        0xFF | ||||
| #define     TWSI_CTRL_LD_OFFSET_SHIFT       0 | ||||
| #define     TWSI_CTRL_LD_SLV_ADDR_MASK      0x7 | ||||
| #define     TWSI_CTRL_LD_SLV_ADDR_SHIFT     8 | ||||
| #define     TWSI_CTRL_SW_LDSTART            0x800 | ||||
| #define     TWSI_CTRL_HW_LDSTART            0x1000 | ||||
| #define     TWSI_CTRL_SMB_SLV_ADDR_MASK     0x0x7F | ||||
| #define     TWSI_CTRL_SMB_SLV_ADDR_SHIFT    15 | ||||
| #define     TWSI_CTRL_LD_EXIST              0x400000 | ||||
| #define     TWSI_CTRL_READ_FREQ_SEL_MASK    0x3 | ||||
| #define     TWSI_CTRL_READ_FREQ_SEL_SHIFT   23 | ||||
| #define     TWSI_CTRL_FREQ_SEL_100K         0 | ||||
| #define     TWSI_CTRL_FREQ_SEL_200K         1 | ||||
| #define     TWSI_CTRL_FREQ_SEL_300K         2 | ||||
| #define     TWSI_CTRL_FREQ_SEL_400K         3 | ||||
| #define     TWSI_CTRL_SMB_SLV_ADDR | ||||
| #define     TWSI_CTRL_WRITE_FREQ_SEL_MASK   0x3 | ||||
| #define     TWSI_CTRL_WRITE_FREQ_SEL_SHIFT  24 | ||||
| 
 | ||||
| 
 | ||||
| #define REG_PCIE_DEV_MISC_CTRL      0x21C | ||||
| #define     PCIE_DEV_MISC_CTRL_EXT_PIPE     0x2 | ||||
| #define     PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1 | ||||
| #define     PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4 | ||||
| #define     PCIE_DEV_MISC_CTRL_SERDES_ENDIAN    0x8 | ||||
| #define     PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN   0x10 | ||||
| 
 | ||||
| #define REG_PCIE_PHYMISC	    0x1000 | ||||
| #define PCIE_PHYMISC_FORCE_RCV_DET	0x4 | ||||
| 
 | ||||
| #define REG_LTSSM_TEST_MODE         0x12FC | ||||
| #define         LTSSM_TEST_MODE_DEF     0xE000 | ||||
| 
 | ||||
| /* Selene Master Control Register */ | ||||
| #define REG_MASTER_CTRL             0x1400 | ||||
| #define     MASTER_CTRL_SOFT_RST            0x1 | ||||
| #define     MASTER_CTRL_MTIMER_EN           0x2 | ||||
| #define     MASTER_CTRL_ITIMER_EN           0x4 | ||||
| #define     MASTER_CTRL_MANUAL_INT          0x8 | ||||
| #define     MASTER_CTRL_ITIMER2_EN          0x20 | ||||
| #define     MASTER_CTRL_INT_RDCLR           0x40 | ||||
| #define     MASTER_CTRL_LED_MODE	    0x200 | ||||
| #define     MASTER_CTRL_REV_NUM_SHIFT       16 | ||||
| #define     MASTER_CTRL_REV_NUM_MASK        0xff | ||||
| #define     MASTER_CTRL_DEV_ID_SHIFT        24 | ||||
| #define     MASTER_CTRL_DEV_ID_MASK         0xff | ||||
| 
 | ||||
| /* Timer Initial Value Register */ | ||||
| #define REG_MANUAL_TIMER_INIT       0x1404 | ||||
| 
 | ||||
| 
 | ||||
| /* IRQ ModeratorTimer Initial Value Register */ | ||||
| #define REG_IRQ_MODU_TIMER_INIT     0x1408   /* w */ | ||||
| #define REG_IRQ_MODU_TIMER2_INIT    0x140A   /* w */ | ||||
| 
 | ||||
| 
 | ||||
| #define REG_GPHY_CTRL               0x140C | ||||
| #define     GPHY_CTRL_EXT_RESET         1 | ||||
| #define     GPHY_CTRL_PIPE_MOD          2 | ||||
| #define     GPHY_CTRL_TEST_MODE_MASK    3 | ||||
| #define     GPHY_CTRL_TEST_MODE_SHIFT   2 | ||||
| #define     GPHY_CTRL_BERT_START        0x10 | ||||
| #define     GPHY_CTRL_GATE_25M_EN       0x20 | ||||
| #define     GPHY_CTRL_LPW_EXIT          0x40 | ||||
| #define     GPHY_CTRL_PHY_IDDQ          0x80 | ||||
| #define     GPHY_CTRL_PHY_IDDQ_DIS      0x100 | ||||
| #define     GPHY_CTRL_PCLK_SEL_DIS      0x200 | ||||
| #define     GPHY_CTRL_HIB_EN            0x400 | ||||
| #define     GPHY_CTRL_HIB_PULSE         0x800 | ||||
| #define     GPHY_CTRL_SEL_ANA_RST       0x1000 | ||||
| #define     GPHY_CTRL_PHY_PLL_ON        0x2000 | ||||
| #define     GPHY_CTRL_PWDOWN_HW		0x4000 | ||||
| #define     GPHY_CTRL_DEFAULT (\ | ||||
| 		GPHY_CTRL_PHY_PLL_ON	|\ | ||||
| 		GPHY_CTRL_SEL_ANA_RST	|\ | ||||
| 		GPHY_CTRL_HIB_PULSE	|\ | ||||
| 		GPHY_CTRL_HIB_EN) | ||||
| 
 | ||||
| #define     GPHY_CTRL_PW_WOL_DIS (\ | ||||
| 		GPHY_CTRL_PHY_PLL_ON	|\ | ||||
| 		GPHY_CTRL_SEL_ANA_RST	|\ | ||||
| 		GPHY_CTRL_HIB_PULSE	|\ | ||||
| 		GPHY_CTRL_HIB_EN	|\ | ||||
| 		GPHY_CTRL_PWDOWN_HW	|\ | ||||
| 		GPHY_CTRL_PCLK_SEL_DIS	|\ | ||||
| 		GPHY_CTRL_PHY_IDDQ) | ||||
| 
 | ||||
| /* IRQ Anti-Lost Timer Initial Value Register */ | ||||
| #define REG_CMBDISDMA_TIMER         0x140E | ||||
| 
 | ||||
| 
 | ||||
| /* Block IDLE Status Register */ | ||||
| #define REG_IDLE_STATUS  	0x1410 | ||||
| #define     IDLE_STATUS_RXMAC       1    /* 1: RXMAC state machine is in non-IDLE state. 0: RXMAC is idling */ | ||||
| #define     IDLE_STATUS_TXMAC       2    /* 1: TXMAC state machine is in non-IDLE state. 0: TXMAC is idling */ | ||||
| #define     IDLE_STATUS_RXQ         4    /* 1: RXQ state machine is in non-IDLE state.   0: RXQ is idling   */ | ||||
| #define     IDLE_STATUS_TXQ         8    /* 1: TXQ state machine is in non-IDLE state.   0: TXQ is idling   */ | ||||
| #define     IDLE_STATUS_DMAR        0x10 /* 1: DMAR state machine is in non-IDLE state.  0: DMAR is idling  */ | ||||
| #define     IDLE_STATUS_DMAW        0x20 /* 1: DMAW state machine is in non-IDLE state.  0: DMAW is idling  */ | ||||
| #define     IDLE_STATUS_SMB         0x40 /* 1: SMB state machine is in non-IDLE state.   0: SMB is idling   */ | ||||
| #define     IDLE_STATUS_CMB         0x80 /* 1: CMB state machine is in non-IDLE state.   0: CMB is idling   */ | ||||
| 
 | ||||
| /* MDIO Control Register */ | ||||
| #define REG_MDIO_CTRL           0x1414 | ||||
| #define     MDIO_DATA_MASK          0xffff  /* On MDIO write, the 16-bit control data to write to PHY MII management register */ | ||||
| #define     MDIO_DATA_SHIFT         0       /* On MDIO read, the 16-bit status data that was read from the PHY MII management register*/ | ||||
| #define     MDIO_REG_ADDR_MASK      0x1f    /* MDIO register address */ | ||||
| #define     MDIO_REG_ADDR_SHIFT     16 | ||||
| #define     MDIO_RW                 0x200000      /* 1: read, 0: write */ | ||||
| #define     MDIO_SUP_PREAMBLE       0x400000      /* Suppress preamble */ | ||||
| #define     MDIO_START              0x800000      /* Write 1 to initiate the MDIO master. And this bit is self cleared after one cycle*/ | ||||
| #define     MDIO_CLK_SEL_SHIFT      24 | ||||
| #define     MDIO_CLK_25_4           0 | ||||
| #define     MDIO_CLK_25_6           2 | ||||
| #define     MDIO_CLK_25_8           3 | ||||
| #define     MDIO_CLK_25_10          4 | ||||
| #define     MDIO_CLK_25_14          5 | ||||
| #define     MDIO_CLK_25_20          6 | ||||
| #define     MDIO_CLK_25_28          7 | ||||
| #define     MDIO_BUSY               0x8000000 | ||||
| #define     MDIO_AP_EN              0x10000000 | ||||
| #define MDIO_WAIT_TIMES         10 | ||||
| 
 | ||||
| /* MII PHY Status Register */ | ||||
| #define REG_PHY_STATUS           0x1418 | ||||
| #define     PHY_STATUS_100M	      0x20000 | ||||
| #define     PHY_STATUS_EMI_CA	      0x40000 | ||||
| 
 | ||||
| /* BIST Control and Status Register0 (for the Packet Memory) */ | ||||
| #define REG_BIST0_CTRL              0x141c | ||||
| #define     BIST0_NOW                   0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */ | ||||
| /* BIST process and reset to zero when BIST is done */ | ||||
| #define     BIST0_SRAM_FAIL             0x2 /* 1: The SRAM failure is un-repairable because it has address */ | ||||
| /* decoder failure or more than 1 cell stuck-to-x failure */ | ||||
| #define     BIST0_FUSE_FLAG             0x4 /* 1: Indicating one cell has been fixed */ | ||||
| 
 | ||||
| /* BIST Control and Status Register1(for the retry buffer of PCI Express) */ | ||||
| #define REG_BIST1_CTRL              0x1420 | ||||
| #define     BIST1_NOW                   0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */ | ||||
| /* BIST process and reset to zero when BIST is done */ | ||||
| #define     BIST1_SRAM_FAIL             0x2 /* 1: The SRAM failure is un-repairable because it has address */ | ||||
| /* decoder failure or more than 1 cell stuck-to-x failure.*/ | ||||
| #define     BIST1_FUSE_FLAG             0x4 | ||||
| 
 | ||||
| /* SerDes Lock Detect Control and Status Register */ | ||||
| #define REG_SERDES_LOCK             0x1424 | ||||
| #define     SERDES_LOCK_DETECT          1  /* 1: SerDes lock detected . This signal comes from Analog SerDes */ | ||||
| #define     SERDES_LOCK_DETECT_EN       2  /* 1: Enable SerDes Lock detect function */ | ||||
| 
 | ||||
| /* MAC Control Register  */ | ||||
| #define REG_MAC_CTRL                0x1480 | ||||
| #define     MAC_CTRL_TX_EN              1  /* 1: Transmit Enable */ | ||||
| #define     MAC_CTRL_RX_EN              2  /* 1: Receive Enable */ | ||||
| #define     MAC_CTRL_TX_FLOW            4  /* 1: Transmit Flow Control Enable */ | ||||
| #define     MAC_CTRL_RX_FLOW            8  /* 1: Receive Flow Control Enable */ | ||||
| #define     MAC_CTRL_LOOPBACK           0x10      /* 1: Loop back at G/MII Interface */ | ||||
| #define     MAC_CTRL_DUPLX              0x20      /* 1: Full-duplex mode  0: Half-duplex mode */ | ||||
| #define     MAC_CTRL_ADD_CRC            0x40      /* 1: Instruct MAC to attach CRC on all egress Ethernet frames */ | ||||
| #define     MAC_CTRL_PAD                0x80      /* 1: Instruct MAC to pad short frames to 60-bytes, and then attach CRC. This bit has higher priority over CRC_EN */ | ||||
| #define     MAC_CTRL_LENCHK             0x100     /* 1: Instruct MAC to check if length field matches the real packet length */ | ||||
| #define     MAC_CTRL_HUGE_EN            0x200     /* 1: receive Jumbo frame enable */ | ||||
| #define     MAC_CTRL_PRMLEN_SHIFT       10        /* Preamble length */ | ||||
| #define     MAC_CTRL_PRMLEN_MASK        0xf | ||||
| #define     MAC_CTRL_RMV_VLAN           0x4000    /* 1: to remove VLAN Tag automatically from all receive packets */ | ||||
| #define     MAC_CTRL_PROMIS_EN          0x8000    /* 1: Promiscuous Mode Enable */ | ||||
| #define     MAC_CTRL_TX_PAUSE           0x10000   /* 1: transmit test pause */ | ||||
| #define     MAC_CTRL_SCNT               0x20000   /* 1: shortcut slot time counter */ | ||||
| #define     MAC_CTRL_SRST_TX            0x40000   /* 1: synchronized reset Transmit MAC module */ | ||||
| #define     MAC_CTRL_TX_SIMURST         0x80000   /* 1: transmit simulation reset */ | ||||
| #define     MAC_CTRL_SPEED_SHIFT        20        /* 10: gigabit 01:10M/100M */ | ||||
| #define     MAC_CTRL_SPEED_MASK         0x300000 | ||||
| #define     MAC_CTRL_SPEED_1000         2 | ||||
| #define     MAC_CTRL_SPEED_10_100       1 | ||||
| #define     MAC_CTRL_DBG_TX_BKPRESURE   0x400000  /* 1: transmit maximum backoff (half-duplex test bit) */ | ||||
| #define     MAC_CTRL_TX_HUGE            0x800000  /* 1: transmit huge enable */ | ||||
| #define     MAC_CTRL_RX_CHKSUM_EN       0x1000000 /* 1: RX checksum enable */ | ||||
| #define     MAC_CTRL_MC_ALL_EN          0x2000000 /* 1: upload all multicast frame without error to system */ | ||||
| #define     MAC_CTRL_BC_EN              0x4000000 /* 1: upload all broadcast frame without error to system */ | ||||
| #define     MAC_CTRL_DBG                0x8000000 /* 1: upload all received frame to system (Debug Mode) */ | ||||
| 
 | ||||
| /* MAC IPG/IFG Control Register  */ | ||||
| #define REG_MAC_IPG_IFG             0x1484 | ||||
| #define     MAC_IPG_IFG_IPGT_SHIFT      0     /* Desired back to back inter-packet gap. The default is 96-bit time */ | ||||
| #define     MAC_IPG_IFG_IPGT_MASK       0x7f | ||||
| #define     MAC_IPG_IFG_MIFG_SHIFT      8     /* Minimum number of IFG to enforce in between RX frames */ | ||||
| #define     MAC_IPG_IFG_MIFG_MASK       0xff  /* Frame gap below such IFP is dropped */ | ||||
| #define     MAC_IPG_IFG_IPGR1_SHIFT     16    /* 64bit Carrier-Sense window */ | ||||
| #define     MAC_IPG_IFG_IPGR1_MASK      0x7f | ||||
| #define     MAC_IPG_IFG_IPGR2_SHIFT     24    /* 96-bit IPG window */ | ||||
| #define     MAC_IPG_IFG_IPGR2_MASK      0x7f | ||||
| 
 | ||||
| /* MAC STATION ADDRESS  */ | ||||
| #define REG_MAC_STA_ADDR            0x1488 | ||||
| 
 | ||||
| /* Hash table for multicast address */ | ||||
| #define REG_RX_HASH_TABLE           0x1490 | ||||
| 
 | ||||
| 
 | ||||
| /* MAC Half-Duplex Control Register */ | ||||
| #define REG_MAC_HALF_DUPLX_CTRL     0x1498 | ||||
| #define     MAC_HALF_DUPLX_CTRL_LCOL_SHIFT   0      /* Collision Window */ | ||||
| #define     MAC_HALF_DUPLX_CTRL_LCOL_MASK    0x3ff | ||||
| #define     MAC_HALF_DUPLX_CTRL_RETRY_SHIFT  12     /* Retransmission maximum, afterwards the packet will be discarded */ | ||||
| #define     MAC_HALF_DUPLX_CTRL_RETRY_MASK   0xf | ||||
| #define     MAC_HALF_DUPLX_CTRL_EXC_DEF_EN   0x10000 /* 1: Allow the transmission of a packet which has been excessively deferred */ | ||||
| #define     MAC_HALF_DUPLX_CTRL_NO_BACK_C    0x20000 /* 1: No back-off on collision, immediately start the retransmission */ | ||||
| #define     MAC_HALF_DUPLX_CTRL_NO_BACK_P    0x40000 /* 1: No back-off on backpressure, immediately start the transmission after back pressure */ | ||||
| #define     MAC_HALF_DUPLX_CTRL_ABEBE        0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */ | ||||
| #define     MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT  20      /* Maximum binary exponential number */ | ||||
| #define     MAC_HALF_DUPLX_CTRL_ABEBT_MASK   0xf | ||||
| #define     MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24      /* IPG to start JAM for collision based flow control in half-duplex */ | ||||
| #define     MAC_HALF_DUPLX_CTRL_JAMIPG_MASK  0xf     /* mode. In unit of 8-bit time */ | ||||
| 
 | ||||
| /* Maximum Frame Length Control Register   */ | ||||
| #define REG_MTU                     0x149c | ||||
| 
 | ||||
| /* Wake-On-Lan control register */ | ||||
| #define REG_WOL_CTRL                0x14a0 | ||||
| #define     WOL_PATTERN_EN                  0x00000001 | ||||
| #define     WOL_PATTERN_PME_EN              0x00000002 | ||||
| #define     WOL_MAGIC_EN                    0x00000004 | ||||
| #define     WOL_MAGIC_PME_EN                0x00000008 | ||||
| #define     WOL_LINK_CHG_EN                 0x00000010 | ||||
| #define     WOL_LINK_CHG_PME_EN             0x00000020 | ||||
| #define     WOL_PATTERN_ST                  0x00000100 | ||||
| #define     WOL_MAGIC_ST                    0x00000200 | ||||
| #define     WOL_LINKCHG_ST                  0x00000400 | ||||
| #define     WOL_CLK_SWITCH_EN               0x00008000 | ||||
| #define     WOL_PT0_EN                      0x00010000 | ||||
| #define     WOL_PT1_EN                      0x00020000 | ||||
| #define     WOL_PT2_EN                      0x00040000 | ||||
| #define     WOL_PT3_EN                      0x00080000 | ||||
| #define     WOL_PT4_EN                      0x00100000 | ||||
| #define     WOL_PT5_EN                      0x00200000 | ||||
| #define     WOL_PT6_EN                      0x00400000 | ||||
| /* WOL Length ( 2 DWORD ) */ | ||||
| #define REG_WOL_PATTERN_LEN         0x14a4 | ||||
| #define     WOL_PT_LEN_MASK                 0x7f | ||||
| #define     WOL_PT0_LEN_SHIFT               0 | ||||
| #define     WOL_PT1_LEN_SHIFT               8 | ||||
| #define     WOL_PT2_LEN_SHIFT               16 | ||||
| #define     WOL_PT3_LEN_SHIFT               24 | ||||
| #define     WOL_PT4_LEN_SHIFT               0 | ||||
| #define     WOL_PT5_LEN_SHIFT               8 | ||||
| #define     WOL_PT6_LEN_SHIFT               16 | ||||
| 
 | ||||
| /* Internal SRAM Partition Register */ | ||||
| #define REG_SRAM_TRD_ADDR           0x1518 | ||||
| #define REG_SRAM_TRD_LEN            0x151C | ||||
| #define REG_SRAM_RXF_ADDR           0x1520 | ||||
| #define REG_SRAM_RXF_LEN            0x1524 | ||||
| #define REG_SRAM_TXF_ADDR           0x1528 | ||||
| #define REG_SRAM_TXF_LEN            0x152C | ||||
| #define REG_SRAM_TCPH_ADDR          0x1530 | ||||
| #define REG_SRAM_PKTH_ADDR          0x1532 | ||||
| 
 | ||||
| /* Load Ptr Register */ | ||||
| #define REG_LOAD_PTR                0x1534  /* Software sets this bit after the initialization of the head and tail */ | ||||
| 
 | ||||
| /*
 | ||||
|  * addresses of all descriptors, as well as the following descriptor | ||||
|  * control register, which triggers each function block to load the head | ||||
|  * pointer to prepare for the operation. This bit is then self-cleared | ||||
|  * after one cycle. | ||||
|  */ | ||||
| 
 | ||||
| /* Descriptor Control register  */ | ||||
| #define REG_RXF3_BASE_ADDR_HI           0x153C | ||||
| #define REG_DESC_BASE_ADDR_HI           0x1540 | ||||
| #define REG_RXF0_BASE_ADDR_HI           0x1540 /* share with DESC BASE ADDR HI */ | ||||
| #define REG_HOST_RXF0_PAGE0_LO          0x1544 | ||||
| #define REG_HOST_RXF0_PAGE1_LO          0x1548 | ||||
| #define REG_TPD_BASE_ADDR_LO            0x154C | ||||
| #define REG_RXF1_BASE_ADDR_HI           0x1550 | ||||
| #define REG_RXF2_BASE_ADDR_HI           0x1554 | ||||
| #define REG_HOST_RXFPAGE_SIZE           0x1558 | ||||
| #define REG_TPD_RING_SIZE               0x155C | ||||
| /* RSS about */ | ||||
| #define REG_RSS_KEY0                    0x14B0 | ||||
| #define REG_RSS_KEY1                    0x14B4 | ||||
| #define REG_RSS_KEY2                    0x14B8 | ||||
| #define REG_RSS_KEY3                    0x14BC | ||||
| #define REG_RSS_KEY4                    0x14C0 | ||||
| #define REG_RSS_KEY5                    0x14C4 | ||||
| #define REG_RSS_KEY6                    0x14C8 | ||||
| #define REG_RSS_KEY7                    0x14CC | ||||
| #define REG_RSS_KEY8                    0x14D0 | ||||
| #define REG_RSS_KEY9                    0x14D4 | ||||
| #define REG_IDT_TABLE4                  0x14E0 | ||||
| #define REG_IDT_TABLE5                  0x14E4 | ||||
| #define REG_IDT_TABLE6                  0x14E8 | ||||
| #define REG_IDT_TABLE7                  0x14EC | ||||
| #define REG_IDT_TABLE0                  0x1560 | ||||
| #define REG_IDT_TABLE1                  0x1564 | ||||
| #define REG_IDT_TABLE2                  0x1568 | ||||
| #define REG_IDT_TABLE3                  0x156C | ||||
| #define REG_IDT_TABLE                   REG_IDT_TABLE0 | ||||
| #define REG_RSS_HASH_VALUE              0x1570 | ||||
| #define REG_RSS_HASH_FLAG               0x1574 | ||||
| #define REG_BASE_CPU_NUMBER             0x157C | ||||
| 
 | ||||
| 
 | ||||
| /* TXQ Control Register */ | ||||
| #define REG_TXQ_CTRL                0x1580 | ||||
| #define     TXQ_CTRL_NUM_TPD_BURST_MASK     0xF | ||||
| #define     TXQ_CTRL_NUM_TPD_BURST_SHIFT    0 | ||||
| #define     TXQ_CTRL_EN                     0x20  /* 1: Enable TXQ */ | ||||
| #define     TXQ_CTRL_ENH_MODE               0x40  /* Performance enhancement mode, in which up to two back-to-back DMA read commands might be dispatched. */ | ||||
| #define     TXQ_CTRL_TXF_BURST_NUM_SHIFT    16    /* Number of data byte to read in a cache-aligned burst. Each SRAM entry is 8-byte in length. */ | ||||
| #define     TXQ_CTRL_TXF_BURST_NUM_MASK     0xffff | ||||
| 
 | ||||
| /* Jumbo packet Threshold for task offload */ | ||||
| #define REG_TX_EARLY_TH                     0x1584 /* Jumbo frame threshold in QWORD unit. Packet greater than */ | ||||
| /* JUMBO_TASK_OFFLOAD_THRESHOLD will not be task offloaded. */ | ||||
| #define     TX_TX_EARLY_TH_MASK             0x7ff | ||||
| #define     TX_TX_EARLY_TH_SHIFT            0 | ||||
| 
 | ||||
| 
 | ||||
| /* RXQ Control Register */ | ||||
| #define REG_RXQ_CTRL                0x15A0 | ||||
| #define         RXQ_CTRL_PBA_ALIGN_32                   0   /* rx-packet alignment */ | ||||
| #define         RXQ_CTRL_PBA_ALIGN_64                   1 | ||||
| #define         RXQ_CTRL_PBA_ALIGN_128                  2 | ||||
| #define         RXQ_CTRL_PBA_ALIGN_256                  3 | ||||
| #define         RXQ_CTRL_Q1_EN				0x10 | ||||
| #define         RXQ_CTRL_Q2_EN				0x20 | ||||
| #define         RXQ_CTRL_Q3_EN				0x40 | ||||
| #define         RXQ_CTRL_IPV6_XSUM_VERIFY_EN		0x80 | ||||
| #define         RXQ_CTRL_HASH_TLEN_SHIFT                8 | ||||
| #define         RXQ_CTRL_HASH_TLEN_MASK                 0xFF | ||||
| #define         RXQ_CTRL_HASH_TYPE_IPV4                 0x10000 | ||||
| #define         RXQ_CTRL_HASH_TYPE_IPV4_TCP             0x20000 | ||||
| #define         RXQ_CTRL_HASH_TYPE_IPV6                 0x40000 | ||||
| #define         RXQ_CTRL_HASH_TYPE_IPV6_TCP             0x80000 | ||||
| #define         RXQ_CTRL_RSS_MODE_DISABLE               0 | ||||
| #define         RXQ_CTRL_RSS_MODE_SQSINT                0x4000000 | ||||
| #define         RXQ_CTRL_RSS_MODE_MQUESINT              0x8000000 | ||||
| #define         RXQ_CTRL_RSS_MODE_MQUEMINT              0xC000000 | ||||
| #define         RXQ_CTRL_NIP_QUEUE_SEL_TBL              0x10000000 | ||||
| #define         RXQ_CTRL_HASH_ENABLE                    0x20000000 | ||||
| #define         RXQ_CTRL_CUT_THRU_EN                    0x40000000 | ||||
| #define         RXQ_CTRL_EN                             0x80000000 | ||||
| 
 | ||||
| /* Rx jumbo packet threshold and rrd  retirement timer  */ | ||||
| #define REG_RXQ_JMBOSZ_RRDTIM       0x15A4 | ||||
| /*
 | ||||
|  * Jumbo packet threshold for non-VLAN packet, in QWORD (64-bit) unit. | ||||
|  * When the packet length greater than or equal to this value, RXQ | ||||
|  * shall start cut-through forwarding of the received packet. | ||||
|  */ | ||||
| #define         RXQ_JMBOSZ_TH_MASK      0x7ff | ||||
| #define         RXQ_JMBOSZ_TH_SHIFT         0  /* RRD retirement timer. Decrement by 1 after every 512ns passes*/ | ||||
| #define         RXQ_JMBO_LKAH_MASK          0xf | ||||
| #define         RXQ_JMBO_LKAH_SHIFT         11 | ||||
| 
 | ||||
| /* RXF flow control register */ | ||||
| #define REG_RXQ_RXF_PAUSE_THRESH    0x15A8 | ||||
| #define     RXQ_RXF_PAUSE_TH_HI_SHIFT       0 | ||||
| #define     RXQ_RXF_PAUSE_TH_HI_MASK        0xfff | ||||
| #define     RXQ_RXF_PAUSE_TH_LO_SHIFT       16 | ||||
| #define     RXQ_RXF_PAUSE_TH_LO_MASK        0xfff | ||||
| 
 | ||||
| 
 | ||||
| /* DMA Engine Control Register */ | ||||
| #define REG_DMA_CTRL                0x15C0 | ||||
| #define     DMA_CTRL_DMAR_IN_ORDER          0x1 | ||||
| #define     DMA_CTRL_DMAR_ENH_ORDER         0x2 | ||||
| #define     DMA_CTRL_DMAR_OUT_ORDER         0x4 | ||||
| #define     DMA_CTRL_RCB_VALUE              0x8 | ||||
| #define     DMA_CTRL_DMAR_BURST_LEN_SHIFT   4 | ||||
| #define     DMA_CTRL_DMAR_BURST_LEN_MASK    7 | ||||
| #define     DMA_CTRL_DMAW_BURST_LEN_SHIFT   7 | ||||
| #define     DMA_CTRL_DMAW_BURST_LEN_MASK    7 | ||||
| #define     DMA_CTRL_DMAR_REQ_PRI           0x400 | ||||
| #define     DMA_CTRL_DMAR_DLY_CNT_MASK      0x1F | ||||
| #define     DMA_CTRL_DMAR_DLY_CNT_SHIFT     11 | ||||
| #define     DMA_CTRL_DMAW_DLY_CNT_MASK      0xF | ||||
| #define     DMA_CTRL_DMAW_DLY_CNT_SHIFT     16 | ||||
| #define     DMA_CTRL_TXCMB_EN               0x100000 | ||||
| #define     DMA_CTRL_RXCMB_EN				0x200000 | ||||
| 
 | ||||
| 
 | ||||
| /* CMB/SMB Control Register */ | ||||
| #define REG_SMB_STAT_TIMER                      0x15C4 | ||||
| #define REG_TRIG_RRD_THRESH                     0x15CA | ||||
| #define REG_TRIG_TPD_THRESH                     0x15C8 | ||||
| #define REG_TRIG_TXTIMER                        0x15CC | ||||
| #define REG_TRIG_RXTIMER                        0x15CE | ||||
| 
 | ||||
| /* HOST RXF Page 1,2,3 address */ | ||||
| #define REG_HOST_RXF1_PAGE0_LO                  0x15D0 | ||||
| #define REG_HOST_RXF1_PAGE1_LO                  0x15D4 | ||||
| #define REG_HOST_RXF2_PAGE0_LO                  0x15D8 | ||||
| #define REG_HOST_RXF2_PAGE1_LO                  0x15DC | ||||
| #define REG_HOST_RXF3_PAGE0_LO                  0x15E0 | ||||
| #define REG_HOST_RXF3_PAGE1_LO                  0x15E4 | ||||
| 
 | ||||
| /* Mail box */ | ||||
| #define REG_MB_RXF1_RADDR                       0x15B4 | ||||
| #define REG_MB_RXF2_RADDR                       0x15B8 | ||||
| #define REG_MB_RXF3_RADDR                       0x15BC | ||||
| #define REG_MB_TPD_PROD_IDX                     0x15F0 | ||||
| 
 | ||||
| /* RXF-Page 0-3  PageNo & Valid bit */ | ||||
| #define REG_HOST_RXF0_PAGE0_VLD     0x15F4 | ||||
| #define     HOST_RXF_VALID              1 | ||||
| #define     HOST_RXF_PAGENO_SHIFT       1 | ||||
| #define     HOST_RXF_PAGENO_MASK        0x7F | ||||
| #define REG_HOST_RXF0_PAGE1_VLD     0x15F5 | ||||
| #define REG_HOST_RXF1_PAGE0_VLD     0x15F6 | ||||
| #define REG_HOST_RXF1_PAGE1_VLD     0x15F7 | ||||
| #define REG_HOST_RXF2_PAGE0_VLD     0x15F8 | ||||
| #define REG_HOST_RXF2_PAGE1_VLD     0x15F9 | ||||
| #define REG_HOST_RXF3_PAGE0_VLD     0x15FA | ||||
| #define REG_HOST_RXF3_PAGE1_VLD     0x15FB | ||||
| 
 | ||||
| /* Interrupt Status Register */ | ||||
| #define REG_ISR    0x1600 | ||||
| #define  ISR_SMB   		1 | ||||
| #define  ISR_TIMER		2       /* Interrupt when Timer is counted down to zero */ | ||||
| /*
 | ||||
|  * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set | ||||
|  * in Table 51 Selene Master Control Register (Offset 0x1400). | ||||
|  */ | ||||
| #define  ISR_MANUAL         	4 | ||||
| #define  ISR_HW_RXF_OV          8        /* RXF overflow interrupt */ | ||||
| #define  ISR_HOST_RXF0_OV       0x10 | ||||
| #define  ISR_HOST_RXF1_OV       0x20 | ||||
| #define  ISR_HOST_RXF2_OV       0x40 | ||||
| #define  ISR_HOST_RXF3_OV       0x80 | ||||
| #define  ISR_TXF_UN             0x100 | ||||
| #define  ISR_RX0_PAGE_FULL      0x200 | ||||
| #define  ISR_DMAR_TO_RST        0x400 | ||||
| #define  ISR_DMAW_TO_RST        0x800 | ||||
| #define  ISR_GPHY               0x1000 | ||||
| #define  ISR_TX_CREDIT          0x2000 | ||||
| #define  ISR_GPHY_LPW           0x4000    /* GPHY low power state interrupt */ | ||||
| #define  ISR_RX_PKT             0x10000   /* One packet received, triggered by RFD */ | ||||
| #define  ISR_TX_PKT             0x20000   /* One packet transmitted, triggered by TPD */ | ||||
| #define  ISR_TX_DMA             0x40000 | ||||
| #define  ISR_RX_PKT_1           0x80000 | ||||
| #define  ISR_RX_PKT_2           0x100000 | ||||
| #define  ISR_RX_PKT_3           0x200000 | ||||
| #define  ISR_MAC_RX             0x400000 | ||||
| #define  ISR_MAC_TX             0x800000 | ||||
| #define  ISR_UR_DETECTED        0x1000000 | ||||
| #define  ISR_FERR_DETECTED      0x2000000 | ||||
| #define  ISR_NFERR_DETECTED     0x4000000 | ||||
| #define  ISR_CERR_DETECTED      0x8000000 | ||||
| #define  ISR_PHY_LINKDOWN       0x10000000 | ||||
| #define  ISR_DIS_INT            0x80000000 | ||||
| 
 | ||||
| 
 | ||||
| /* Interrupt Mask Register */ | ||||
| #define REG_IMR 0x1604 | ||||
| 
 | ||||
| 
 | ||||
| #define IMR_NORMAL_MASK (\ | ||||
| 		ISR_SMB	        |\ | ||||
| 		ISR_TXF_UN      |\ | ||||
| 		ISR_HW_RXF_OV   |\ | ||||
| 		ISR_HOST_RXF0_OV|\ | ||||
| 		ISR_MANUAL      |\ | ||||
| 		ISR_GPHY        |\ | ||||
| 		ISR_GPHY_LPW    |\ | ||||
| 		ISR_DMAR_TO_RST |\ | ||||
| 		ISR_DMAW_TO_RST |\ | ||||
| 		ISR_PHY_LINKDOWN|\ | ||||
| 		ISR_RX_PKT      |\ | ||||
| 		ISR_TX_PKT) | ||||
| 
 | ||||
| #define ISR_TX_EVENT (ISR_TXF_UN | ISR_TX_PKT) | ||||
| #define ISR_RX_EVENT (ISR_HOST_RXF0_OV | ISR_HW_RXF_OV | ISR_RX_PKT) | ||||
| 
 | ||||
| #define REG_MAC_RX_STATUS_BIN 0x1700 | ||||
| #define REG_MAC_RX_STATUS_END 0x175c | ||||
| #define REG_MAC_TX_STATUS_BIN 0x1760 | ||||
| #define REG_MAC_TX_STATUS_END 0x17c0 | ||||
| 
 | ||||
| /* Hardware Offset Register */ | ||||
| #define REG_HOST_RXF0_PAGEOFF 0x1800 | ||||
| #define REG_TPD_CONS_IDX      0x1804 | ||||
| #define REG_HOST_RXF1_PAGEOFF 0x1808 | ||||
| #define REG_HOST_RXF2_PAGEOFF 0x180C | ||||
| #define REG_HOST_RXF3_PAGEOFF 0x1810 | ||||
| 
 | ||||
| /* RXF-Page 0-3 Offset DMA Address */ | ||||
| #define REG_HOST_RXF0_MB0_LO  0x1820 | ||||
| #define REG_HOST_RXF0_MB1_LO  0x1824 | ||||
| #define REG_HOST_RXF1_MB0_LO  0x1828 | ||||
| #define REG_HOST_RXF1_MB1_LO  0x182C | ||||
| #define REG_HOST_RXF2_MB0_LO  0x1830 | ||||
| #define REG_HOST_RXF2_MB1_LO  0x1834 | ||||
| #define REG_HOST_RXF3_MB0_LO  0x1838 | ||||
| #define REG_HOST_RXF3_MB1_LO  0x183C | ||||
| 
 | ||||
| /* Tpd CMB DMA Address */ | ||||
| #define REG_HOST_TX_CMB_LO    0x1840 | ||||
| #define REG_HOST_SMB_ADDR_LO  0x1844 | ||||
| 
 | ||||
| /* DEBUG ADDR */ | ||||
| #define REG_DEBUG_DATA0 0x1900 | ||||
| #define REG_DEBUG_DATA1 0x1904 | ||||
| 
 | ||||
| /***************************** MII definition ***************************************/ | ||||
| /* PHY Common Register */ | ||||
| #define MII_AT001_PSCR                  0x10 | ||||
| #define MII_AT001_PSSR                  0x11 | ||||
| #define MII_INT_CTRL                    0x12 | ||||
| #define MII_INT_STATUS                  0x13 | ||||
| #define MII_SMARTSPEED                  0x14 | ||||
| #define MII_LBRERROR                    0x18 | ||||
| #define MII_RESV2                       0x1a | ||||
| 
 | ||||
| #define MII_DBG_ADDR			0x1D | ||||
| #define MII_DBG_DATA			0x1E | ||||
| 
 | ||||
| /* Autoneg Advertisement Register */ | ||||
| #define MII_AR_DEFAULT_CAP_MASK                 0 | ||||
| 
 | ||||
| /* 1000BASE-T Control Register */ | ||||
| #define MII_AT001_CR_1000T_SPEED_MASK \ | ||||
| 	(ADVERTISE_1000FULL | ADVERTISE_1000HALF) | ||||
| #define MII_AT001_CR_1000T_DEFAULT_CAP_MASK	MII_AT001_CR_1000T_SPEED_MASK | ||||
| 
 | ||||
| /* AT001 PHY Specific Control Register */ | ||||
| #define MII_AT001_PSCR_JABBER_DISABLE           0x0001  /* 1=Jabber Function disabled */ | ||||
| #define MII_AT001_PSCR_POLARITY_REVERSAL        0x0002  /* 1=Polarity Reversal enabled */ | ||||
| #define MII_AT001_PSCR_SQE_TEST                 0x0004  /* 1=SQE Test enabled */ | ||||
| #define MII_AT001_PSCR_MAC_POWERDOWN            0x0008 | ||||
| #define MII_AT001_PSCR_CLK125_DISABLE           0x0010  /* 1=CLK125 low, | ||||
| 							 * 0=CLK125 toggling | ||||
| 							 */ | ||||
| #define MII_AT001_PSCR_MDI_MANUAL_MODE          0x0000  /* MDI Crossover Mode bits 6:5 */ | ||||
| /* Manual MDI configuration */ | ||||
| #define MII_AT001_PSCR_MDIX_MANUAL_MODE         0x0020  /* Manual MDIX configuration */ | ||||
| #define MII_AT001_PSCR_AUTO_X_1000T             0x0040  /* 1000BASE-T: Auto crossover, | ||||
| 							 *  100BASE-TX/10BASE-T: | ||||
| 							 *  MDI Mode | ||||
| 							 */ | ||||
| #define MII_AT001_PSCR_AUTO_X_MODE              0x0060  /* Auto crossover enabled | ||||
| 							 * all speeds. | ||||
| 							 */ | ||||
| #define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE     0x0080 | ||||
| /* 1=Enable Extended 10BASE-T distance
 | ||||
|  * (Lower 10BASE-T RX Threshold) | ||||
|  * 0=Normal 10BASE-T RX Threshold */ | ||||
| #define MII_AT001_PSCR_MII_5BIT_ENABLE          0x0100 | ||||
| /* 1=5-Bit interface in 100BASE-TX
 | ||||
|  * 0=MII interface in 100BASE-TX */ | ||||
| #define MII_AT001_PSCR_SCRAMBLER_DISABLE        0x0200  /* 1=Scrambler disable */ | ||||
| #define MII_AT001_PSCR_FORCE_LINK_GOOD          0x0400  /* 1=Force link good */ | ||||
| #define MII_AT001_PSCR_ASSERT_CRS_ON_TX         0x0800  /* 1=Assert CRS on Transmit */ | ||||
| #define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT    1 | ||||
| #define MII_AT001_PSCR_AUTO_X_MODE_SHIFT          5 | ||||
| #define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7 | ||||
| /* AT001 PHY Specific Status Register */ | ||||
| #define MII_AT001_PSSR_SPD_DPLX_RESOLVED        0x0800  /* 1=Speed & Duplex resolved */ | ||||
| #define MII_AT001_PSSR_DPLX                     0x2000  /* 1=Duplex 0=Half Duplex */ | ||||
| #define MII_AT001_PSSR_SPEED                    0xC000  /* Speed, bits 14:15 */ | ||||
| #define MII_AT001_PSSR_10MBS                    0x0000  /* 00=10Mbs */ | ||||
| #define MII_AT001_PSSR_100MBS                   0x4000  /* 01=100Mbs */ | ||||
| #define MII_AT001_PSSR_1000MBS                  0x8000  /* 10=1000Mbs */ | ||||
| 
 | ||||
| #endif /*_ATHL1E_HW_H_*/ | ||||
							
								
								
									
										2579
									
								
								drivers/net/ethernet/atheros/atl1e/atl1e_main.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2579
									
								
								drivers/net/ethernet/atheros/atl1e/atl1e_main.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										269
									
								
								drivers/net/ethernet/atheros/atl1e/atl1e_param.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										269
									
								
								drivers/net/ethernet/atheros/atl1e/atl1e_param.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,269 @@ | |||
| /*
 | ||||
|  * Copyright(c) 2007 Atheros Corporation. All rights reserved. | ||||
|  * | ||||
|  * Derived from Intel e1000 driver | ||||
|  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the Free | ||||
|  * Software Foundation; either version 2 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., 59 | ||||
|  * Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/netdevice.h> | ||||
| 
 | ||||
| #include "atl1e.h" | ||||
| 
 | ||||
| /* This is the only thing that needs to be changed to adjust the
 | ||||
|  * maximum number of ports that the driver can manage. | ||||
|  */ | ||||
| 
 | ||||
| #define ATL1E_MAX_NIC 32 | ||||
| 
 | ||||
| #define OPTION_UNSET    -1 | ||||
| #define OPTION_DISABLED 0 | ||||
| #define OPTION_ENABLED  1 | ||||
| 
 | ||||
| /* All parameters are treated the same, as an integer array of values.
 | ||||
|  * This macro just reduces the need to repeat the same declaration code | ||||
|  * over and over (plus this helps to avoid typo bugs). | ||||
|  */ | ||||
| #define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET } | ||||
| 
 | ||||
| #define ATL1E_PARAM(x, desc) \ | ||||
| 	static int x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \ | ||||
| 	static unsigned int num_##x; \ | ||||
| 	module_param_array_named(x, x, int, &num_##x, 0); \ | ||||
| 	MODULE_PARM_DESC(x, desc); | ||||
| 
 | ||||
| /* Transmit Memory count
 | ||||
|  * | ||||
|  * Valid Range: 64-2048 | ||||
|  * | ||||
|  * Default Value: 128 | ||||
|  */ | ||||
| #define ATL1E_MIN_TX_DESC_CNT		32 | ||||
| #define ATL1E_MAX_TX_DESC_CNT		1020 | ||||
| #define ATL1E_DEFAULT_TX_DESC_CNT	128 | ||||
| ATL1E_PARAM(tx_desc_cnt, "Transmit description count"); | ||||
| 
 | ||||
| /* Receive Memory Block Count
 | ||||
|  * | ||||
|  * Valid Range: 16-512 | ||||
|  * | ||||
|  * Default Value: 128 | ||||
|  */ | ||||
| #define ATL1E_MIN_RX_MEM_SIZE		8    /* 8KB   */ | ||||
| #define ATL1E_MAX_RX_MEM_SIZE		1024 /* 1MB   */ | ||||
| #define ATL1E_DEFAULT_RX_MEM_SIZE	256  /* 128KB */ | ||||
| ATL1E_PARAM(rx_mem_size, "memory size of rx buffer(KB)"); | ||||
| 
 | ||||
| /* User Specified MediaType Override
 | ||||
|  * | ||||
|  * Valid Range: 0-5 | ||||
|  *  - 0    - auto-negotiate at all supported speeds | ||||
|  *  - 1    - only link at 100Mbps Full Duplex | ||||
|  *  - 2    - only link at 100Mbps Half Duplex | ||||
|  *  - 3    - only link at 10Mbps Full Duplex | ||||
|  *  - 4    - only link at 10Mbps Half Duplex | ||||
|  * Default Value: 0 | ||||
|  */ | ||||
| 
 | ||||
| ATL1E_PARAM(media_type, "MediaType Select"); | ||||
| 
 | ||||
| /* Interrupt Moderate Timer in units of 2 us
 | ||||
|  * | ||||
|  * Valid Range: 10-65535 | ||||
|  * | ||||
|  * Default Value: 45000(90ms) | ||||
|  */ | ||||
| #define INT_MOD_DEFAULT_CNT             100 /* 200us */ | ||||
| #define INT_MOD_MAX_CNT                 65000 | ||||
| #define INT_MOD_MIN_CNT                 50 | ||||
| ATL1E_PARAM(int_mod_timer, "Interrupt Moderator Timer"); | ||||
| 
 | ||||
| #define AUTONEG_ADV_DEFAULT  0x2F | ||||
| #define AUTONEG_ADV_MASK     0x2F | ||||
| #define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL | ||||
| 
 | ||||
| #define FLASH_VENDOR_DEFAULT    0 | ||||
| #define FLASH_VENDOR_MIN        0 | ||||
| #define FLASH_VENDOR_MAX        2 | ||||
| 
 | ||||
| struct atl1e_option { | ||||
| 	enum { enable_option, range_option, list_option } type; | ||||
| 	char *name; | ||||
| 	char *err; | ||||
| 	int  def; | ||||
| 	union { | ||||
| 		struct { /* range_option info */ | ||||
| 			int min; | ||||
| 			int max; | ||||
| 		} r; | ||||
| 		struct { /* list_option info */ | ||||
| 			int nr; | ||||
| 			struct atl1e_opt_list { int i; char *str; } *p; | ||||
| 		} l; | ||||
| 	} arg; | ||||
| }; | ||||
| 
 | ||||
| static int atl1e_validate_option(int *value, struct atl1e_option *opt, | ||||
| 				 struct atl1e_adapter *adapter) | ||||
| { | ||||
| 	if (*value == OPTION_UNSET) { | ||||
| 		*value = opt->def; | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	switch (opt->type) { | ||||
| 	case enable_option: | ||||
| 		switch (*value) { | ||||
| 		case OPTION_ENABLED: | ||||
| 			netdev_info(adapter->netdev, | ||||
| 				    "%s Enabled\n", opt->name); | ||||
| 			return 0; | ||||
| 		case OPTION_DISABLED: | ||||
| 			netdev_info(adapter->netdev, | ||||
| 				    "%s Disabled\n", opt->name); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		break; | ||||
| 	case range_option: | ||||
| 		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { | ||||
| 			netdev_info(adapter->netdev, "%s set to %i\n", | ||||
| 				    opt->name, *value); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		break; | ||||
| 	case list_option:{ | ||||
| 			int i; | ||||
| 			struct atl1e_opt_list *ent; | ||||
| 
 | ||||
| 			for (i = 0; i < opt->arg.l.nr; i++) { | ||||
| 				ent = &opt->arg.l.p[i]; | ||||
| 				if (*value == ent->i) { | ||||
| 					if (ent->str[0] != '\0') | ||||
| 						netdev_info(adapter->netdev, | ||||
| 							    "%s\n", ent->str); | ||||
| 					return 0; | ||||
| 				} | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	default: | ||||
| 		BUG(); | ||||
| 	} | ||||
| 
 | ||||
| 	netdev_info(adapter->netdev, "Invalid %s specified (%i) %s\n", | ||||
| 		    opt->name, *value, opt->err); | ||||
| 	*value = opt->def; | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * atl1e_check_options - Range Checking for Command Line Parameters | ||||
|  * @adapter: board private structure | ||||
|  * | ||||
|  * This routine checks all command line parameters for valid user | ||||
|  * input.  If an invalid value is given, or if no user specified | ||||
|  * value exists, a default value is used.  The final value is stored | ||||
|  * in a variable in the adapter structure. | ||||
|  */ | ||||
| void atl1e_check_options(struct atl1e_adapter *adapter) | ||||
| { | ||||
| 	int bd = adapter->bd_number; | ||||
| 
 | ||||
| 	if (bd >= ATL1E_MAX_NIC) { | ||||
| 		netdev_notice(adapter->netdev, | ||||
| 			      "no configuration for board #%i\n", bd); | ||||
| 		netdev_notice(adapter->netdev, | ||||
| 			      "Using defaults for all values\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	{ 		/* Transmit Ring Size */ | ||||
| 		struct atl1e_option opt = { | ||||
| 			.type = range_option, | ||||
| 			.name = "Transmit Ddescription Count", | ||||
| 			.err  = "using default of " | ||||
| 				__MODULE_STRING(ATL1E_DEFAULT_TX_DESC_CNT), | ||||
| 			.def  = ATL1E_DEFAULT_TX_DESC_CNT, | ||||
| 			.arg  = { .r = { .min = ATL1E_MIN_TX_DESC_CNT, | ||||
| 					 .max = ATL1E_MAX_TX_DESC_CNT} } | ||||
| 		}; | ||||
| 		int val; | ||||
| 		if (num_tx_desc_cnt > bd) { | ||||
| 			val = tx_desc_cnt[bd]; | ||||
| 			atl1e_validate_option(&val, &opt, adapter); | ||||
| 			adapter->tx_ring.count = (u16) val & 0xFFFC; | ||||
| 		} else | ||||
| 			adapter->tx_ring.count = (u16)opt.def; | ||||
| 	} | ||||
| 
 | ||||
| 	{ 		/* Receive Memory Block Count */ | ||||
| 		struct atl1e_option opt = { | ||||
| 			.type = range_option, | ||||
| 			.name = "Memory size of rx buffer(KB)", | ||||
| 			.err  = "using default of " | ||||
| 				__MODULE_STRING(ATL1E_DEFAULT_RX_MEM_SIZE), | ||||
| 			.def  = ATL1E_DEFAULT_RX_MEM_SIZE, | ||||
| 			.arg  = { .r = { .min = ATL1E_MIN_RX_MEM_SIZE, | ||||
| 					 .max = ATL1E_MAX_RX_MEM_SIZE} } | ||||
| 		}; | ||||
| 		int val; | ||||
| 		if (num_rx_mem_size > bd) { | ||||
| 			val = rx_mem_size[bd]; | ||||
| 			atl1e_validate_option(&val, &opt, adapter); | ||||
| 			adapter->rx_ring.page_size = (u32)val * 1024; | ||||
| 		} else { | ||||
| 			adapter->rx_ring.page_size = (u32)opt.def * 1024; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	{ 		/* Interrupt Moderate Timer */ | ||||
| 		struct atl1e_option opt = { | ||||
| 			.type = range_option, | ||||
| 			.name = "Interrupt Moderate Timer", | ||||
| 			.err  = "using default of " | ||||
| 				__MODULE_STRING(INT_MOD_DEFAULT_CNT), | ||||
| 			.def  = INT_MOD_DEFAULT_CNT, | ||||
| 			.arg  = { .r = { .min = INT_MOD_MIN_CNT, | ||||
| 					 .max = INT_MOD_MAX_CNT} } | ||||
| 		} ; | ||||
| 		int val; | ||||
| 		if (num_int_mod_timer > bd) { | ||||
| 			val = int_mod_timer[bd]; | ||||
| 			atl1e_validate_option(&val, &opt, adapter); | ||||
| 			adapter->hw.imt = (u16) val; | ||||
| 		} else | ||||
| 			adapter->hw.imt = (u16)(opt.def); | ||||
| 	} | ||||
| 
 | ||||
| 	{ 		/* MediaType */ | ||||
| 		struct atl1e_option opt = { | ||||
| 			.type = range_option, | ||||
| 			.name = "Speed/Duplex Selection", | ||||
| 			.err  = "using default of " | ||||
| 				__MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR), | ||||
| 			.def  = MEDIA_TYPE_AUTO_SENSOR, | ||||
| 			.arg  = { .r = { .min = MEDIA_TYPE_AUTO_SENSOR, | ||||
| 					 .max = MEDIA_TYPE_10M_HALF} } | ||||
| 		} ; | ||||
| 		int val; | ||||
| 		if (num_media_type > bd) { | ||||
| 			val = media_type[bd]; | ||||
| 			atl1e_validate_option(&val, &opt, adapter); | ||||
| 			adapter->hw.media_type = (u16) val; | ||||
| 		} else | ||||
| 			adapter->hw.media_type = (u16)(opt.def); | ||||
| 
 | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										3
									
								
								drivers/net/ethernet/atheros/atlx/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								drivers/net/ethernet/atheros/atlx/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| obj-$(CONFIG_ATL1)	+= atl1.o | ||||
| obj-$(CONFIG_ATL2)	+= atl2.o | ||||
| 
 | ||||
							
								
								
									
										3690
									
								
								drivers/net/ethernet/atheros/atlx/atl1.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3690
									
								
								drivers/net/ethernet/atheros/atlx/atl1.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										803
									
								
								drivers/net/ethernet/atheros/atlx/atl1.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										803
									
								
								drivers/net/ethernet/atheros/atlx/atl1.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,803 @@ | |||
| /*
 | ||||
|  * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. | ||||
|  * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com> | ||||
|  * Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com> | ||||
|  * | ||||
|  * Derived from Intel e1000 driver | ||||
|  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the Free | ||||
|  * Software Foundation; either version 2 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., 59 | ||||
|  * Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef ATL1_H | ||||
| #define ATL1_H | ||||
| 
 | ||||
| #include <linux/compiler.h> | ||||
| #include <linux/ethtool.h> | ||||
| #include <linux/if_vlan.h> | ||||
| #include <linux/mii.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/skbuff.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/timer.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/workqueue.h> | ||||
| 
 | ||||
| #include "atlx.h" | ||||
| 
 | ||||
| #define ATLX_DRIVER_NAME "atl1" | ||||
| 
 | ||||
| MODULE_DESCRIPTION("Atheros L1 Gigabit Ethernet Driver"); | ||||
| 
 | ||||
| #define atlx_adapter		atl1_adapter | ||||
| #define atlx_check_for_link	atl1_check_for_link | ||||
| #define atlx_check_link		atl1_check_link | ||||
| #define atlx_hash_mc_addr	atl1_hash_mc_addr | ||||
| #define atlx_hash_set		atl1_hash_set | ||||
| #define atlx_hw			atl1_hw | ||||
| #define atlx_mii_ioctl		atl1_mii_ioctl | ||||
| #define atlx_read_phy_reg	atl1_read_phy_reg | ||||
| #define atlx_set_mac		atl1_set_mac | ||||
| #define atlx_set_mac_addr	atl1_set_mac_addr | ||||
| 
 | ||||
| struct atl1_adapter; | ||||
| struct atl1_hw; | ||||
| 
 | ||||
| /* function prototypes needed by multiple files */ | ||||
| static u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr); | ||||
| static void atl1_hash_set(struct atl1_hw *hw, u32 hash_value); | ||||
| static void atl1_set_mac_addr(struct atl1_hw *hw); | ||||
| static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, | ||||
| 	int cmd); | ||||
| static u32 atl1_check_link(struct atl1_adapter *adapter); | ||||
| 
 | ||||
| /* hardware definitions specific to L1 */ | ||||
| 
 | ||||
| /* Block IDLE Status Register */ | ||||
| #define IDLE_STATUS_RXMAC			0x1 | ||||
| #define IDLE_STATUS_TXMAC			0x2 | ||||
| #define IDLE_STATUS_RXQ				0x4 | ||||
| #define IDLE_STATUS_TXQ				0x8 | ||||
| #define IDLE_STATUS_DMAR			0x10 | ||||
| #define IDLE_STATUS_DMAW			0x20 | ||||
| #define IDLE_STATUS_SMB				0x40 | ||||
| #define IDLE_STATUS_CMB				0x80 | ||||
| 
 | ||||
| /* MDIO Control Register */ | ||||
| #define MDIO_WAIT_TIMES				30 | ||||
| 
 | ||||
| /* MAC Control Register */ | ||||
| #define MAC_CTRL_TX_PAUSE			0x10000 | ||||
| #define MAC_CTRL_SCNT				0x20000 | ||||
| #define MAC_CTRL_SRST_TX			0x40000 | ||||
| #define MAC_CTRL_TX_SIMURST			0x80000 | ||||
| #define MAC_CTRL_SPEED_SHIFT			20 | ||||
| #define MAC_CTRL_SPEED_MASK			0x300000 | ||||
| #define MAC_CTRL_SPEED_1000			0x2 | ||||
| #define MAC_CTRL_SPEED_10_100			0x1 | ||||
| #define MAC_CTRL_DBG_TX_BKPRESURE		0x400000 | ||||
| #define MAC_CTRL_TX_HUGE			0x800000 | ||||
| #define MAC_CTRL_RX_CHKSUM_EN			0x1000000 | ||||
| #define MAC_CTRL_DBG				0x8000000 | ||||
| 
 | ||||
| /* Wake-On-Lan control register */ | ||||
| #define WOL_CLK_SWITCH_EN			0x8000 | ||||
| #define WOL_PT5_EN				0x200000 | ||||
| #define WOL_PT6_EN				0x400000 | ||||
| #define WOL_PT5_MATCH				0x8000000 | ||||
| #define WOL_PT6_MATCH				0x10000000 | ||||
| 
 | ||||
| /* WOL Length ( 2 DWORD ) */ | ||||
| #define REG_WOL_PATTERN_LEN			0x14A4 | ||||
| #define WOL_PT_LEN_MASK				0x7F | ||||
| #define WOL_PT0_LEN_SHIFT			0 | ||||
| #define WOL_PT1_LEN_SHIFT			8 | ||||
| #define WOL_PT2_LEN_SHIFT			16 | ||||
| #define WOL_PT3_LEN_SHIFT			24 | ||||
| #define WOL_PT4_LEN_SHIFT			0 | ||||
| #define WOL_PT5_LEN_SHIFT			8 | ||||
| #define WOL_PT6_LEN_SHIFT			16 | ||||
| 
 | ||||
| /* Internal SRAM Partition Registers, low 32 bits */ | ||||
| #define REG_SRAM_RFD_LEN			0x1504 | ||||
| #define REG_SRAM_RRD_ADDR			0x1508 | ||||
| #define REG_SRAM_RRD_LEN			0x150C | ||||
| #define REG_SRAM_TPD_ADDR			0x1510 | ||||
| #define REG_SRAM_TPD_LEN			0x1514 | ||||
| #define REG_SRAM_TRD_ADDR			0x1518 | ||||
| #define REG_SRAM_TRD_LEN			0x151C | ||||
| #define REG_SRAM_RXF_ADDR			0x1520 | ||||
| #define REG_SRAM_RXF_LEN			0x1524 | ||||
| #define REG_SRAM_TXF_ADDR			0x1528 | ||||
| #define REG_SRAM_TXF_LEN			0x152C | ||||
| #define REG_SRAM_TCPH_PATH_ADDR			0x1530 | ||||
| #define SRAM_TCPH_ADDR_MASK			0xFFF | ||||
| #define SRAM_TCPH_ADDR_SHIFT			0 | ||||
| #define SRAM_PATH_ADDR_MASK			0xFFF | ||||
| #define SRAM_PATH_ADDR_SHIFT			16 | ||||
| 
 | ||||
| /* Load Ptr Register */ | ||||
| #define REG_LOAD_PTR				0x1534 | ||||
| 
 | ||||
| /* Descriptor Control registers, low 32 bits */ | ||||
| #define REG_DESC_RFD_ADDR_LO			0x1544 | ||||
| #define REG_DESC_RRD_ADDR_LO			0x1548 | ||||
| #define REG_DESC_TPD_ADDR_LO			0x154C | ||||
| #define REG_DESC_CMB_ADDR_LO			0x1550 | ||||
| #define REG_DESC_SMB_ADDR_LO			0x1554 | ||||
| #define REG_DESC_RFD_RRD_RING_SIZE		0x1558 | ||||
| #define DESC_RFD_RING_SIZE_MASK			0x7FF | ||||
| #define DESC_RFD_RING_SIZE_SHIFT		0 | ||||
| #define DESC_RRD_RING_SIZE_MASK			0x7FF | ||||
| #define DESC_RRD_RING_SIZE_SHIFT		16 | ||||
| #define REG_DESC_TPD_RING_SIZE			0x155C | ||||
| #define DESC_TPD_RING_SIZE_MASK			0x3FF | ||||
| #define DESC_TPD_RING_SIZE_SHIFT		0 | ||||
| 
 | ||||
| /* TXQ Control Register */ | ||||
| #define REG_TXQ_CTRL				0x1580 | ||||
| #define TXQ_CTRL_TPD_BURST_NUM_SHIFT		0 | ||||
| #define TXQ_CTRL_TPD_BURST_NUM_MASK		0x1F | ||||
| #define TXQ_CTRL_EN				0x20 | ||||
| #define TXQ_CTRL_ENH_MODE			0x40 | ||||
| #define TXQ_CTRL_TPD_FETCH_TH_SHIFT		8 | ||||
| #define TXQ_CTRL_TPD_FETCH_TH_MASK		0x3F | ||||
| #define TXQ_CTRL_TXF_BURST_NUM_SHIFT		16 | ||||
| #define TXQ_CTRL_TXF_BURST_NUM_MASK		0xFFFF | ||||
| 
 | ||||
| /* Jumbo packet Threshold for task offload */ | ||||
| #define REG_TX_JUMBO_TASK_TH_TPD_IPG		0x1584 | ||||
| #define TX_JUMBO_TASK_TH_MASK			0x7FF | ||||
| #define TX_JUMBO_TASK_TH_SHIFT			0 | ||||
| #define TX_TPD_MIN_IPG_MASK			0x1F | ||||
| #define TX_TPD_MIN_IPG_SHIFT			16 | ||||
| 
 | ||||
| /* RXQ Control Register */ | ||||
| #define REG_RXQ_CTRL				0x15A0 | ||||
| #define RXQ_CTRL_RFD_BURST_NUM_SHIFT		0 | ||||
| #define RXQ_CTRL_RFD_BURST_NUM_MASK		0xFF | ||||
| #define RXQ_CTRL_RRD_BURST_THRESH_SHIFT		8 | ||||
| #define RXQ_CTRL_RRD_BURST_THRESH_MASK		0xFF | ||||
| #define RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT		16 | ||||
| #define RXQ_CTRL_RFD_PREF_MIN_IPG_MASK		0x1F | ||||
| #define RXQ_CTRL_CUT_THRU_EN			0x40000000 | ||||
| #define RXQ_CTRL_EN				0x80000000 | ||||
| 
 | ||||
| /* Rx jumbo packet threshold and rrd  retirement timer */ | ||||
| #define REG_RXQ_JMBOSZ_RRDTIM			0x15A4 | ||||
| #define RXQ_JMBOSZ_TH_MASK			0x7FF | ||||
| #define RXQ_JMBOSZ_TH_SHIFT			0 | ||||
| #define RXQ_JMBO_LKAH_MASK			0xF | ||||
| #define RXQ_JMBO_LKAH_SHIFT			11 | ||||
| #define RXQ_RRD_TIMER_MASK			0xFFFF | ||||
| #define RXQ_RRD_TIMER_SHIFT			16 | ||||
| 
 | ||||
| /* RFD flow control register */ | ||||
| #define REG_RXQ_RXF_PAUSE_THRESH		0x15A8 | ||||
| #define RXQ_RXF_PAUSE_TH_HI_SHIFT		16 | ||||
| #define RXQ_RXF_PAUSE_TH_HI_MASK		0xFFF | ||||
| #define RXQ_RXF_PAUSE_TH_LO_SHIFT		0 | ||||
| #define RXQ_RXF_PAUSE_TH_LO_MASK		0xFFF | ||||
| 
 | ||||
| /* RRD flow control register */ | ||||
| #define REG_RXQ_RRD_PAUSE_THRESH		0x15AC | ||||
| #define RXQ_RRD_PAUSE_TH_HI_SHIFT		0 | ||||
| #define RXQ_RRD_PAUSE_TH_HI_MASK		0xFFF | ||||
| #define RXQ_RRD_PAUSE_TH_LO_SHIFT		16 | ||||
| #define RXQ_RRD_PAUSE_TH_LO_MASK		0xFFF | ||||
| 
 | ||||
| /* DMA Engine Control Register */ | ||||
| #define REG_DMA_CTRL				0x15C0 | ||||
| #define DMA_CTRL_DMAR_IN_ORDER			0x1 | ||||
| #define DMA_CTRL_DMAR_ENH_ORDER			0x2 | ||||
| #define DMA_CTRL_DMAR_OUT_ORDER			0x4 | ||||
| #define DMA_CTRL_RCB_VALUE			0x8 | ||||
| #define DMA_CTRL_DMAR_BURST_LEN_SHIFT		4 | ||||
| #define DMA_CTRL_DMAR_BURST_LEN_MASK		7 | ||||
| #define DMA_CTRL_DMAW_BURST_LEN_SHIFT		7 | ||||
| #define DMA_CTRL_DMAW_BURST_LEN_MASK		7 | ||||
| #define DMA_CTRL_DMAR_EN			0x400 | ||||
| #define DMA_CTRL_DMAW_EN			0x800 | ||||
| 
 | ||||
| /* CMB/SMB Control Register */ | ||||
| #define REG_CSMB_CTRL				0x15D0 | ||||
| #define CSMB_CTRL_CMB_NOW			1 | ||||
| #define CSMB_CTRL_SMB_NOW			2 | ||||
| #define CSMB_CTRL_CMB_EN			4 | ||||
| #define CSMB_CTRL_SMB_EN			8 | ||||
| 
 | ||||
| /* CMB DMA Write Threshold Register */ | ||||
| #define REG_CMB_WRITE_TH			0x15D4 | ||||
| #define CMB_RRD_TH_SHIFT			0 | ||||
| #define CMB_RRD_TH_MASK				0x7FF | ||||
| #define CMB_TPD_TH_SHIFT			16 | ||||
| #define CMB_TPD_TH_MASK				0x7FF | ||||
| 
 | ||||
| /* RX/TX count-down timer to trigger CMB-write. 2us resolution. */ | ||||
| #define REG_CMB_WRITE_TIMER			0x15D8 | ||||
| #define CMB_RX_TM_SHIFT				0 | ||||
| #define CMB_RX_TM_MASK				0xFFFF | ||||
| #define CMB_TX_TM_SHIFT				16 | ||||
| #define CMB_TX_TM_MASK				0xFFFF | ||||
| 
 | ||||
| /* Number of packet received since last CMB write */ | ||||
| #define REG_CMB_RX_PKT_CNT			0x15DC | ||||
| 
 | ||||
| /* Number of packet transmitted since last CMB write */ | ||||
| #define REG_CMB_TX_PKT_CNT			0x15E0 | ||||
| 
 | ||||
| /* SMB auto DMA timer register */ | ||||
| #define REG_SMB_TIMER				0x15E4 | ||||
| 
 | ||||
| /* Mailbox Register */ | ||||
| #define REG_MAILBOX				0x15F0 | ||||
| #define MB_RFD_PROD_INDX_SHIFT			0 | ||||
| #define MB_RFD_PROD_INDX_MASK			0x7FF | ||||
| #define MB_RRD_CONS_INDX_SHIFT			11 | ||||
| #define MB_RRD_CONS_INDX_MASK			0x7FF | ||||
| #define MB_TPD_PROD_INDX_SHIFT			22 | ||||
| #define MB_TPD_PROD_INDX_MASK			0x3FF | ||||
| 
 | ||||
| /* Interrupt Status Register */ | ||||
| #define ISR_SMB					0x1 | ||||
| #define ISR_TIMER				0x2 | ||||
| #define ISR_MANUAL				0x4 | ||||
| #define ISR_RXF_OV				0x8 | ||||
| #define ISR_RFD_UNRUN				0x10 | ||||
| #define ISR_RRD_OV				0x20 | ||||
| #define ISR_TXF_UNRUN				0x40 | ||||
| #define ISR_LINK				0x80 | ||||
| #define ISR_HOST_RFD_UNRUN			0x100 | ||||
| #define ISR_HOST_RRD_OV				0x200 | ||||
| #define ISR_DMAR_TO_RST				0x400 | ||||
| #define ISR_DMAW_TO_RST				0x800 | ||||
| #define ISR_GPHY				0x1000 | ||||
| #define ISR_RX_PKT				0x10000 | ||||
| #define ISR_TX_PKT				0x20000 | ||||
| #define ISR_TX_DMA				0x40000 | ||||
| #define ISR_RX_DMA				0x80000 | ||||
| #define ISR_CMB_RX				0x100000 | ||||
| #define ISR_CMB_TX				0x200000 | ||||
| #define ISR_MAC_RX				0x400000 | ||||
| #define ISR_MAC_TX				0x800000 | ||||
| #define ISR_DIS_SMB				0x20000000 | ||||
| #define ISR_DIS_DMA				0x40000000 | ||||
| 
 | ||||
| /* Normal Interrupt mask without RX/TX enabled */ | ||||
| #define IMR_NORXTX_MASK	(\ | ||||
| 	ISR_SMB		|\ | ||||
| 	ISR_GPHY	|\ | ||||
| 	ISR_PHY_LINKDOWN|\ | ||||
| 	ISR_DMAR_TO_RST	|\ | ||||
| 	ISR_DMAW_TO_RST) | ||||
| 
 | ||||
| /* Normal Interrupt mask  */ | ||||
| #define IMR_NORMAL_MASK	(\ | ||||
| 	IMR_NORXTX_MASK	|\ | ||||
| 	ISR_CMB_TX	|\ | ||||
| 	ISR_CMB_RX) | ||||
| 
 | ||||
| /* Debug Interrupt Mask  (enable all interrupt) */ | ||||
| #define IMR_DEBUG_MASK	(\ | ||||
| 	ISR_SMB		|\ | ||||
| 	ISR_TIMER	|\ | ||||
| 	ISR_MANUAL	|\ | ||||
| 	ISR_RXF_OV	|\ | ||||
| 	ISR_RFD_UNRUN	|\ | ||||
| 	ISR_RRD_OV	|\ | ||||
| 	ISR_TXF_UNRUN	|\ | ||||
| 	ISR_LINK	|\ | ||||
| 	ISR_CMB_TX	|\ | ||||
| 	ISR_CMB_RX	|\ | ||||
| 	ISR_RX_PKT	|\ | ||||
| 	ISR_TX_PKT	|\ | ||||
| 	ISR_MAC_RX	|\ | ||||
| 	ISR_MAC_TX) | ||||
| 
 | ||||
| #define MEDIA_TYPE_1000M_FULL			1 | ||||
| #define MEDIA_TYPE_100M_FULL			2 | ||||
| #define MEDIA_TYPE_100M_HALF			3 | ||||
| #define MEDIA_TYPE_10M_FULL			4 | ||||
| #define MEDIA_TYPE_10M_HALF			5 | ||||
| 
 | ||||
| #define AUTONEG_ADVERTISE_SPEED_DEFAULT		0x002F	/* All but 1000-Half */ | ||||
| 
 | ||||
| #define MAX_JUMBO_FRAME_SIZE			10240 | ||||
| 
 | ||||
| #define ATL1_EEDUMP_LEN				48 | ||||
| 
 | ||||
| /* Statistics counters collected by the MAC */ | ||||
| struct stats_msg_block { | ||||
| 	/* rx */ | ||||
| 	u32 rx_ok;		/* good RX packets */ | ||||
| 	u32 rx_bcast;		/* good RX broadcast packets */ | ||||
| 	u32 rx_mcast;		/* good RX multicast packets */ | ||||
| 	u32 rx_pause;		/* RX pause frames */ | ||||
| 	u32 rx_ctrl;		/* RX control packets other than pause frames */ | ||||
| 	u32 rx_fcs_err;		/* RX packets with bad FCS */ | ||||
| 	u32 rx_len_err;		/* RX packets with length != actual size */ | ||||
| 	u32 rx_byte_cnt;	/* good bytes received. FCS is NOT included */ | ||||
| 	u32 rx_runt;		/* RX packets < 64 bytes with good FCS */ | ||||
| 	u32 rx_frag;		/* RX packets < 64 bytes with bad FCS */ | ||||
| 	u32 rx_sz_64;		/* 64 byte RX packets */ | ||||
| 	u32 rx_sz_65_127; | ||||
| 	u32 rx_sz_128_255; | ||||
| 	u32 rx_sz_256_511; | ||||
| 	u32 rx_sz_512_1023; | ||||
| 	u32 rx_sz_1024_1518; | ||||
| 	u32 rx_sz_1519_max;	/* 1519 byte to MTU RX packets */ | ||||
| 	u32 rx_sz_ov;		/* truncated RX packets > MTU */ | ||||
| 	u32 rx_rxf_ov;		/* frames dropped due to RX FIFO overflow */ | ||||
| 	u32 rx_rrd_ov;		/* frames dropped due to RRD overflow */ | ||||
| 	u32 rx_align_err;	/* alignment errors */ | ||||
| 	u32 rx_bcast_byte_cnt;	/* RX broadcast bytes, excluding FCS */ | ||||
| 	u32 rx_mcast_byte_cnt;	/* RX multicast bytes, excluding FCS */ | ||||
| 	u32 rx_err_addr;	/* packets dropped due to address filtering */ | ||||
| 
 | ||||
| 	/* tx */ | ||||
| 	u32 tx_ok;		/* good TX packets */ | ||||
| 	u32 tx_bcast;		/* good TX broadcast packets */ | ||||
| 	u32 tx_mcast;		/* good TX multicast packets */ | ||||
| 	u32 tx_pause;		/* TX pause frames */ | ||||
| 	u32 tx_exc_defer;	/* TX packets deferred excessively */ | ||||
| 	u32 tx_ctrl;		/* TX control frames, excluding pause frames */ | ||||
| 	u32 tx_defer;		/* TX packets deferred */ | ||||
| 	u32 tx_byte_cnt;	/* bytes transmitted, FCS is NOT included */ | ||||
| 	u32 tx_sz_64;		/* 64 byte TX packets */ | ||||
| 	u32 tx_sz_65_127; | ||||
| 	u32 tx_sz_128_255; | ||||
| 	u32 tx_sz_256_511; | ||||
| 	u32 tx_sz_512_1023; | ||||
| 	u32 tx_sz_1024_1518; | ||||
| 	u32 tx_sz_1519_max;	/* 1519 byte to MTU TX packets */ | ||||
| 	u32 tx_1_col;		/* packets TX after a single collision */ | ||||
| 	u32 tx_2_col;		/* packets TX after multiple collisions */ | ||||
| 	u32 tx_late_col;	/* TX packets with late collisions */ | ||||
| 	u32 tx_abort_col;	/* TX packets aborted w/excessive collisions */ | ||||
| 	u32 tx_underrun;	/* TX packets aborted due to TX FIFO underrun
 | ||||
| 				 * or TRD FIFO underrun */ | ||||
| 	u32 tx_rd_eop;		/* reads beyond the EOP into the next frame
 | ||||
| 				 * when TRD was not written timely */ | ||||
| 	u32 tx_len_err;		/* TX packets where length != actual size */ | ||||
| 	u32 tx_trunc;		/* TX packets truncated due to size > MTU */ | ||||
| 	u32 tx_bcast_byte;	/* broadcast bytes transmitted, excluding FCS */ | ||||
| 	u32 tx_mcast_byte;	/* multicast bytes transmitted, excluding FCS */ | ||||
| 	u32 smb_updated;	/* 1: SMB Updated. This is used by software to
 | ||||
| 				 * indicate the statistics update. Software | ||||
| 				 * should clear this bit after retrieving the | ||||
| 				 * statistics information. */ | ||||
| }; | ||||
| 
 | ||||
| /* Coalescing Message Block */ | ||||
| struct coals_msg_block { | ||||
| 	u32 int_stats;		/* interrupt status */ | ||||
| 	u16 rrd_prod_idx;	/* TRD Producer Index. */ | ||||
| 	u16 rfd_cons_idx;	/* RFD Consumer Index. */ | ||||
| 	u16 update;		/* Selene sets this bit every time it DMAs the
 | ||||
| 				 * CMB to host memory. Software should clear | ||||
| 				 * this bit when CMB info is processed. */ | ||||
| 	u16 tpd_cons_idx;	/* TPD Consumer Index. */ | ||||
| }; | ||||
| 
 | ||||
| /* RRD descriptor */ | ||||
| struct rx_return_desc { | ||||
| 	u8 num_buf;	/* Number of RFD buffers used by the received packet */ | ||||
| 	u8 resved; | ||||
| 	u16 buf_indx;	/* RFD Index of the first buffer */ | ||||
| 	union { | ||||
| 		u32 valid; | ||||
| 		struct { | ||||
| 			u16 rx_chksum; | ||||
| 			u16 pkt_size; | ||||
| 		} xsum_sz; | ||||
| 	} xsz; | ||||
| 
 | ||||
| 	u16 pkt_flg;	/* Packet flags */ | ||||
| 	u16 err_flg;	/* Error flags */ | ||||
| 	u16 resved2; | ||||
| 	u16 vlan_tag;	/* VLAN TAG */ | ||||
| }; | ||||
| 
 | ||||
| #define PACKET_FLAG_ETH_TYPE	0x0080 | ||||
| #define PACKET_FLAG_VLAN_INS	0x0100 | ||||
| #define PACKET_FLAG_ERR		0x0200 | ||||
| #define PACKET_FLAG_IPV4	0x0400 | ||||
| #define PACKET_FLAG_UDP		0x0800 | ||||
| #define PACKET_FLAG_TCP		0x1000 | ||||
| #define PACKET_FLAG_BCAST	0x2000 | ||||
| #define PACKET_FLAG_MCAST	0x4000 | ||||
| #define PACKET_FLAG_PAUSE	0x8000 | ||||
| 
 | ||||
| #define ERR_FLAG_CRC		0x0001 | ||||
| #define ERR_FLAG_CODE		0x0002 | ||||
| #define ERR_FLAG_DRIBBLE	0x0004 | ||||
| #define ERR_FLAG_RUNT		0x0008 | ||||
| #define ERR_FLAG_OV		0x0010 | ||||
| #define ERR_FLAG_TRUNC		0x0020 | ||||
| #define ERR_FLAG_IP_CHKSUM	0x0040 | ||||
| #define ERR_FLAG_L4_CHKSUM	0x0080 | ||||
| #define ERR_FLAG_LEN		0x0100 | ||||
| #define ERR_FLAG_DES_ADDR	0x0200 | ||||
| 
 | ||||
| /* RFD descriptor */ | ||||
| struct rx_free_desc { | ||||
| 	__le64 buffer_addr;	/* Address of the descriptor's data buffer */ | ||||
| 	__le16 buf_len;		/* Size of the receive buffer in host memory */ | ||||
| 	u16 coalese;		/* Update consumer index to host after the
 | ||||
| 				 * reception of this frame */ | ||||
| 	/* __packed is required */ | ||||
| } __packed; | ||||
| 
 | ||||
| /*
 | ||||
|  * The L1 transmit packet descriptor is comprised of four 32-bit words. | ||||
|  * | ||||
|  *	31					0 | ||||
|  *	+---------------------------------------+ | ||||
|  *      |	Word 0: Buffer addr lo 		| | ||||
|  *      +---------------------------------------+ | ||||
|  *      |	Word 1: Buffer addr hi		| | ||||
|  *      +---------------------------------------+ | ||||
|  *      |		Word 2			| | ||||
|  *      +---------------------------------------+ | ||||
|  *      |		Word 3			| | ||||
|  *      +---------------------------------------+ | ||||
|  * | ||||
|  * Words 0 and 1 combine to form a 64-bit buffer address. | ||||
|  * | ||||
|  * Word 2 is self explanatory in the #define block below. | ||||
|  * | ||||
|  * Word 3 has two forms, depending upon the state of bits 3 and 4. | ||||
|  * If bits 3 and 4 are both zero, then bits 14:31 are unused by the | ||||
|  * hardware.  Otherwise, if either bit 3 or 4 is set, the definition | ||||
|  * of bits 14:31 vary according to the following depiction. | ||||
|  * | ||||
|  *	0	End of packet			0	End of packet | ||||
|  *	1	Coalesce			1	Coalesce | ||||
|  *	2	Insert VLAN tag			2	Insert VLAN tag | ||||
|  *	3	Custom csum enable = 0		3	Custom csum enable = 1 | ||||
|  *	4	Segment enable = 1		4	Segment enable = 0 | ||||
|  *	5	Generate IP checksum		5	Generate IP checksum | ||||
|  *	6	Generate TCP checksum		6	Generate TCP checksum | ||||
|  *	7	Generate UDP checksum		7	Generate UDP checksum | ||||
|  *	8	VLAN tagged			8	VLAN tagged | ||||
|  *	9	Ethernet frame type		9	Ethernet frame type | ||||
|  *	10-+ 					10-+ | ||||
|  *	11 |	IP hdr length (10:13)		11 |	IP hdr length (10:13) | ||||
|  *	12 |	(num 32-bit words)		12 |	(num 32-bit words) | ||||
|  *	13-+					13-+ | ||||
|  *	14-+					14	Unused | ||||
|  *	15 |	TCP hdr length (14:17)		15	Unused | ||||
|  *	16 |	(num 32-bit words)		16-+ | ||||
|  *	17-+					17 | | ||||
|  *	18	Header TPD flag			18 | | ||||
|  *	19-+					19 |	Payload offset | ||||
|  *	20 |					20 |	    (16:23) | ||||
|  *	21 |					21 | | ||||
|  *	22 |					22 | | ||||
|  *	23 |					23-+ | ||||
|  *	24 |					24-+ | ||||
|  *	25 |	MSS (19:31)			25 | | ||||
|  *	26 |					26 | | ||||
|  *	27 |					27 |	Custom csum offset | ||||
|  *	28 |					28 |	     (24:31) | ||||
|  *	29 |					29 | | ||||
|  *	30 |					30 | | ||||
|  *	31-+					31-+ | ||||
|  */ | ||||
| 
 | ||||
| /* tpd word 2 */ | ||||
| #define TPD_BUFLEN_MASK		0x3FFF | ||||
| #define TPD_BUFLEN_SHIFT	0 | ||||
| #define TPD_DMAINT_MASK		0x0001 | ||||
| #define TPD_DMAINT_SHIFT	14 | ||||
| #define TPD_PKTNT_MASK		0x0001 | ||||
| #define TPD_PKTINT_SHIFT	15 | ||||
| #define TPD_VLANTAG_MASK	0xFFFF | ||||
| #define TPD_VLANTAG_SHIFT	16 | ||||
| 
 | ||||
| /* tpd word 3 bits 0:13 */ | ||||
| #define TPD_EOP_MASK		0x0001 | ||||
| #define TPD_EOP_SHIFT		0 | ||||
| #define TPD_COALESCE_MASK	0x0001 | ||||
| #define TPD_COALESCE_SHIFT	1 | ||||
| #define TPD_INS_VL_TAG_MASK	0x0001 | ||||
| #define TPD_INS_VL_TAG_SHIFT	2 | ||||
| #define TPD_CUST_CSUM_EN_MASK	0x0001 | ||||
| #define TPD_CUST_CSUM_EN_SHIFT	3 | ||||
| #define TPD_SEGMENT_EN_MASK	0x0001 | ||||
| #define TPD_SEGMENT_EN_SHIFT	4 | ||||
| #define TPD_IP_CSUM_MASK	0x0001 | ||||
| #define TPD_IP_CSUM_SHIFT	5 | ||||
| #define TPD_TCP_CSUM_MASK	0x0001 | ||||
| #define TPD_TCP_CSUM_SHIFT	6 | ||||
| #define TPD_UDP_CSUM_MASK	0x0001 | ||||
| #define TPD_UDP_CSUM_SHIFT	7 | ||||
| #define TPD_VL_TAGGED_MASK	0x0001 | ||||
| #define TPD_VL_TAGGED_SHIFT	8 | ||||
| #define TPD_ETHTYPE_MASK	0x0001 | ||||
| #define TPD_ETHTYPE_SHIFT	9 | ||||
| #define TPD_IPHL_MASK		0x000F | ||||
| #define TPD_IPHL_SHIFT		10 | ||||
| 
 | ||||
| /* tpd word 3 bits 14:31 if segment enabled */ | ||||
| #define TPD_TCPHDRLEN_MASK	0x000F | ||||
| #define TPD_TCPHDRLEN_SHIFT	14 | ||||
| #define TPD_HDRFLAG_MASK	0x0001 | ||||
| #define TPD_HDRFLAG_SHIFT	18 | ||||
| #define TPD_MSS_MASK		0x1FFF | ||||
| #define TPD_MSS_SHIFT		19 | ||||
| 
 | ||||
| /* tpd word 3 bits 16:31 if custom csum enabled */ | ||||
| #define TPD_PLOADOFFSET_MASK	0x00FF | ||||
| #define TPD_PLOADOFFSET_SHIFT	16 | ||||
| #define TPD_CCSUMOFFSET_MASK	0x00FF | ||||
| #define TPD_CCSUMOFFSET_SHIFT	24 | ||||
| 
 | ||||
| struct tx_packet_desc { | ||||
| 	__le64 buffer_addr; | ||||
| 	__le32 word2; | ||||
| 	__le32 word3; | ||||
| }; | ||||
| 
 | ||||
| /* DMA Order Settings */ | ||||
| enum atl1_dma_order { | ||||
| 	atl1_dma_ord_in = 1, | ||||
| 	atl1_dma_ord_enh = 2, | ||||
| 	atl1_dma_ord_out = 4 | ||||
| }; | ||||
| 
 | ||||
| enum atl1_dma_rcb { | ||||
| 	atl1_rcb_64 = 0, | ||||
| 	atl1_rcb_128 = 1 | ||||
| }; | ||||
| 
 | ||||
| enum atl1_dma_req_block { | ||||
| 	atl1_dma_req_128 = 0, | ||||
| 	atl1_dma_req_256 = 1, | ||||
| 	atl1_dma_req_512 = 2, | ||||
| 	atl1_dma_req_1024 = 3, | ||||
| 	atl1_dma_req_2048 = 4, | ||||
| 	atl1_dma_req_4096 = 5 | ||||
| }; | ||||
| 
 | ||||
| #define ATL1_MAX_INTR		3 | ||||
| #define ATL1_MAX_TX_BUF_LEN	0x3000	/* 12288 bytes */ | ||||
| 
 | ||||
| #define ATL1_DEFAULT_TPD	256 | ||||
| #define ATL1_MAX_TPD		1024 | ||||
| #define ATL1_MIN_TPD		64 | ||||
| #define ATL1_DEFAULT_RFD	512 | ||||
| #define ATL1_MIN_RFD		128 | ||||
| #define ATL1_MAX_RFD		2048 | ||||
| #define ATL1_REG_COUNT		1538 | ||||
| 
 | ||||
| #define ATL1_GET_DESC(R, i, type)	(&(((type *)((R)->desc))[i])) | ||||
| #define ATL1_RFD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_free_desc) | ||||
| #define ATL1_TPD_DESC(R, i)	ATL1_GET_DESC(R, i, struct tx_packet_desc) | ||||
| #define ATL1_RRD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_return_desc) | ||||
| 
 | ||||
| /*
 | ||||
|  * atl1_ring_header represents a single, contiguous block of DMA space | ||||
|  * mapped for the three descriptor rings (tpd, rfd, rrd) and the two | ||||
|  * message blocks (cmb, smb) described below | ||||
|  */ | ||||
| struct atl1_ring_header { | ||||
| 	void *desc;		/* virtual address */ | ||||
| 	dma_addr_t dma;		/* physical address*/ | ||||
| 	unsigned int size;	/* length in bytes */ | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * atl1_buffer is wrapper around a pointer to a socket buffer | ||||
|  * so a DMA handle can be stored along with the skb | ||||
|  */ | ||||
| struct atl1_buffer { | ||||
| 	struct sk_buff *skb;	/* socket buffer */ | ||||
| 	u16 length;		/* rx buffer length */ | ||||
| 	u16 alloced;		/* 1 if skb allocated */ | ||||
| 	dma_addr_t dma; | ||||
| }; | ||||
| 
 | ||||
| /* transmit packet descriptor (tpd) ring */ | ||||
| struct atl1_tpd_ring { | ||||
| 	void *desc;		/* descriptor ring virtual address */ | ||||
| 	dma_addr_t dma;		/* descriptor ring physical address */ | ||||
| 	u16 size;		/* descriptor ring length in bytes */ | ||||
| 	u16 count;		/* number of descriptors in the ring */ | ||||
| 	u16 hw_idx;		/* hardware index */ | ||||
| 	atomic_t next_to_clean; | ||||
| 	atomic_t next_to_use; | ||||
| 	struct atl1_buffer *buffer_info; | ||||
| }; | ||||
| 
 | ||||
| /* receive free descriptor (rfd) ring */ | ||||
| struct atl1_rfd_ring { | ||||
| 	void *desc;		/* descriptor ring virtual address */ | ||||
| 	dma_addr_t dma;		/* descriptor ring physical address */ | ||||
| 	u16 size;		/* descriptor ring length in bytes */ | ||||
| 	u16 count;		/* number of descriptors in the ring */ | ||||
| 	atomic_t next_to_use; | ||||
| 	u16 next_to_clean; | ||||
| 	struct atl1_buffer *buffer_info; | ||||
| }; | ||||
| 
 | ||||
| /* receive return descriptor (rrd) ring */ | ||||
| struct atl1_rrd_ring { | ||||
| 	void *desc;		/* descriptor ring virtual address */ | ||||
| 	dma_addr_t dma;		/* descriptor ring physical address */ | ||||
| 	unsigned int size;	/* descriptor ring length in bytes */ | ||||
| 	u16 count;		/* number of descriptors in the ring */ | ||||
| 	u16 next_to_use; | ||||
| 	atomic_t next_to_clean; | ||||
| }; | ||||
| 
 | ||||
| /* coalescing message block (cmb) */ | ||||
| struct atl1_cmb { | ||||
| 	struct coals_msg_block *cmb; | ||||
| 	dma_addr_t dma; | ||||
| }; | ||||
| 
 | ||||
| /* statistics message block (smb) */ | ||||
| struct atl1_smb { | ||||
| 	struct stats_msg_block *smb; | ||||
| 	dma_addr_t dma; | ||||
| }; | ||||
| 
 | ||||
| /* Statistics counters */ | ||||
| struct atl1_sft_stats { | ||||
| 	u64 rx_packets; | ||||
| 	u64 tx_packets; | ||||
| 	u64 rx_bytes; | ||||
| 	u64 tx_bytes; | ||||
| 	u64 multicast; | ||||
| 	u64 collisions; | ||||
| 	u64 rx_errors; | ||||
| 	u64 rx_length_errors; | ||||
| 	u64 rx_crc_errors; | ||||
| 	u64 rx_dropped; | ||||
| 	u64 rx_frame_errors; | ||||
| 	u64 rx_fifo_errors; | ||||
| 	u64 rx_missed_errors; | ||||
| 	u64 tx_errors; | ||||
| 	u64 tx_fifo_errors; | ||||
| 	u64 tx_aborted_errors; | ||||
| 	u64 tx_window_errors; | ||||
| 	u64 tx_carrier_errors; | ||||
| 	u64 tx_pause;		/* TX pause frames */ | ||||
| 	u64 excecol;		/* TX packets w/ excessive collisions */ | ||||
| 	u64 deffer;		/* TX packets deferred */ | ||||
| 	u64 scc;		/* packets TX after a single collision */ | ||||
| 	u64 mcc;		/* packets TX after multiple collisions */ | ||||
| 	u64 latecol;		/* TX packets w/ late collisions */ | ||||
| 	u64 tx_underun;		/* TX packets aborted due to TX FIFO underrun
 | ||||
| 				 * or TRD FIFO underrun */ | ||||
| 	u64 tx_trunc;		/* TX packets truncated due to size > MTU */ | ||||
| 	u64 rx_pause;		/* num Pause packets received. */ | ||||
| 	u64 rx_rrd_ov; | ||||
| 	u64 rx_trunc; | ||||
| }; | ||||
| 
 | ||||
| /* hardware structure */ | ||||
| struct atl1_hw { | ||||
| 	u8 __iomem *hw_addr; | ||||
| 	struct atl1_adapter *back; | ||||
| 	enum atl1_dma_order dma_ord; | ||||
| 	enum atl1_dma_rcb rcb_value; | ||||
| 	enum atl1_dma_req_block dmar_block; | ||||
| 	enum atl1_dma_req_block dmaw_block; | ||||
| 	u8 preamble_len; | ||||
| 	u8 max_retry; | ||||
| 	u8 jam_ipg;		/* IPG to start JAM for collision based flow
 | ||||
| 				 * control in half-duplex mode. In units of | ||||
| 				 * 8-bit time */ | ||||
| 	u8 ipgt;		/* Desired back to back inter-packet gap.
 | ||||
| 				 * The default is 96-bit time */ | ||||
| 	u8 min_ifg;		/* Minimum number of IFG to enforce in between
 | ||||
| 				 * receive frames. Frame gap below such IFP | ||||
| 				 * is dropped */ | ||||
| 	u8 ipgr1;		/* 64bit Carrier-Sense window */ | ||||
| 	u8 ipgr2;		/* 96-bit IPG window */ | ||||
| 	u8 tpd_burst;		/* Number of TPD to prefetch in cache-aligned
 | ||||
| 				 * burst. Each TPD is 16 bytes long */ | ||||
| 	u8 rfd_burst;		/* Number of RFD to prefetch in cache-aligned
 | ||||
| 				 * burst. Each RFD is 12 bytes long */ | ||||
| 	u8 rfd_fetch_gap; | ||||
| 	u8 rrd_burst;		/* Threshold number of RRDs that can be retired
 | ||||
| 				 * in a burst. Each RRD is 16 bytes long */ | ||||
| 	u8 tpd_fetch_th; | ||||
| 	u8 tpd_fetch_gap; | ||||
| 	u16 tx_jumbo_task_th; | ||||
| 	u16 txf_burst;		/* Number of data bytes to read in a cache-
 | ||||
| 				 * aligned burst. Each SRAM entry is 8 bytes */ | ||||
| 	u16 rx_jumbo_th;	/* Jumbo packet size for non-VLAN packet. VLAN
 | ||||
| 				 * packets should add 4 bytes */ | ||||
| 	u16 rx_jumbo_lkah; | ||||
| 	u16 rrd_ret_timer;	/* RRD retirement timer. Decrement by 1 after
 | ||||
| 				 * every 512ns passes. */ | ||||
| 	u16 lcol;		/* Collision Window */ | ||||
| 
 | ||||
| 	u16 cmb_tpd; | ||||
| 	u16 cmb_rrd; | ||||
| 	u16 cmb_rx_timer; | ||||
| 	u16 cmb_tx_timer; | ||||
| 	u32 smb_timer; | ||||
| 	u16 media_type; | ||||
| 	u16 autoneg_advertised; | ||||
| 
 | ||||
| 	u16 mii_autoneg_adv_reg; | ||||
| 	u16 mii_1000t_ctrl_reg; | ||||
| 
 | ||||
| 	u32 max_frame_size; | ||||
| 	u32 min_frame_size; | ||||
| 
 | ||||
| 	u16 dev_rev; | ||||
| 
 | ||||
| 	/* spi flash */ | ||||
| 	u8 flash_vendor; | ||||
| 
 | ||||
| 	u8 mac_addr[ETH_ALEN]; | ||||
| 	u8 perm_mac_addr[ETH_ALEN]; | ||||
| 
 | ||||
| 	bool phy_configured; | ||||
| }; | ||||
| 
 | ||||
| struct atl1_adapter { | ||||
| 	struct net_device *netdev; | ||||
| 	struct pci_dev *pdev; | ||||
| 
 | ||||
| 	struct atl1_sft_stats soft_stats; | ||||
| 	u32 rx_buffer_len; | ||||
| 	u32 wol; | ||||
| 	u16 link_speed; | ||||
| 	u16 link_duplex; | ||||
| 	spinlock_t lock; | ||||
| 	struct napi_struct napi; | ||||
| 	struct work_struct reset_dev_task; | ||||
| 	struct work_struct link_chg_task; | ||||
| 
 | ||||
| 	struct timer_list phy_config_timer; | ||||
| 	bool phy_timer_pending; | ||||
| 
 | ||||
| 	/* all descriptor rings' memory */ | ||||
| 	struct atl1_ring_header ring_header; | ||||
| 
 | ||||
| 	/* TX */ | ||||
| 	struct atl1_tpd_ring tpd_ring; | ||||
| 	spinlock_t mb_lock; | ||||
| 
 | ||||
| 	/* RX */ | ||||
| 	struct atl1_rfd_ring rfd_ring; | ||||
| 	struct atl1_rrd_ring rrd_ring; | ||||
| 	u64 hw_csum_err; | ||||
| 	u64 hw_csum_good; | ||||
| 	u32 msg_enable; | ||||
| 	u16 imt;		/* interrupt moderator timer (2us resolution) */ | ||||
| 	u16 ict;		/* interrupt clear timer (2us resolution */ | ||||
| 	struct mii_if_info mii;	/* MII interface info */ | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Use this value to check is napi handler allowed to | ||||
| 	 * enable ints or not | ||||
| 	 */ | ||||
| 	bool int_enabled; | ||||
| 
 | ||||
| 	u32 bd_number;		/* board number */ | ||||
| 	bool pci_using_64; | ||||
| 	struct atl1_hw hw; | ||||
| 	struct atl1_smb smb; | ||||
| 	struct atl1_cmb cmb; | ||||
| }; | ||||
| 
 | ||||
| #endif /* ATL1_H */ | ||||
							
								
								
									
										3087
									
								
								drivers/net/ethernet/atheros/atlx/atl2.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3087
									
								
								drivers/net/ethernet/atheros/atlx/atl2.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										524
									
								
								drivers/net/ethernet/atheros/atlx/atl2.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										524
									
								
								drivers/net/ethernet/atheros/atlx/atl2.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,524 @@ | |||
| /* atl2.h -- atl2 driver definitions
 | ||||
|  * | ||||
|  * Copyright(c) 2007 Atheros Corporation. All rights reserved. | ||||
|  * Copyright(c) 2006 xiong huang <xiong.huang@atheros.com> | ||||
|  * Copyright(c) 2007 Chris Snook <csnook@redhat.com> | ||||
|  * | ||||
|  * Derived from Intel e1000 driver | ||||
|  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the Free | ||||
|  * Software Foundation; either version 2 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., 59 | ||||
|  * Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _ATL2_H_ | ||||
| #define _ATL2_H_ | ||||
| 
 | ||||
| #include <linux/atomic.h> | ||||
| #include <linux/netdevice.h> | ||||
| 
 | ||||
| #ifndef _ATL2_HW_H_ | ||||
| #define _ATL2_HW_H_ | ||||
| 
 | ||||
| #ifndef _ATL2_OSDEP_H_ | ||||
| #define _ATL2_OSDEP_H_ | ||||
| 
 | ||||
| #include <linux/pci.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/if_ether.h> | ||||
| 
 | ||||
| #include "atlx.h" | ||||
| 
 | ||||
| #ifdef ETHTOOL_OPS_COMPAT | ||||
| int ethtool_ioctl(struct ifreq *ifr); | ||||
| #endif | ||||
| 
 | ||||
| #define PCI_COMMAND_REGISTER	PCI_COMMAND | ||||
| #define CMD_MEM_WRT_INVALIDATE	PCI_COMMAND_INVALIDATE | ||||
| 
 | ||||
| #define ATL2_WRITE_REG(a, reg, value) (iowrite32((value), \ | ||||
| 	((a)->hw_addr + (reg)))) | ||||
| 
 | ||||
| #define ATL2_WRITE_FLUSH(a) (ioread32((a)->hw_addr)) | ||||
| 
 | ||||
| #define ATL2_READ_REG(a, reg) (ioread32((a)->hw_addr + (reg))) | ||||
| 
 | ||||
| #define ATL2_WRITE_REGB(a, reg, value) (iowrite8((value), \ | ||||
| 	((a)->hw_addr + (reg)))) | ||||
| 
 | ||||
| #define ATL2_READ_REGB(a, reg) (ioread8((a)->hw_addr + (reg))) | ||||
| 
 | ||||
| #define ATL2_WRITE_REGW(a, reg, value) (iowrite16((value), \ | ||||
| 	((a)->hw_addr + (reg)))) | ||||
| 
 | ||||
| #define ATL2_READ_REGW(a, reg) (ioread16((a)->hw_addr + (reg))) | ||||
| 
 | ||||
| #define ATL2_WRITE_REG_ARRAY(a, reg, offset, value) \ | ||||
| 	(iowrite32((value), (((a)->hw_addr + (reg)) + ((offset) << 2)))) | ||||
| 
 | ||||
| #define ATL2_READ_REG_ARRAY(a, reg, offset) \ | ||||
| 	(ioread32(((a)->hw_addr + (reg)) + ((offset) << 2))) | ||||
| 
 | ||||
| #endif /* _ATL2_OSDEP_H_ */ | ||||
| 
 | ||||
| struct atl2_adapter; | ||||
| struct atl2_hw; | ||||
| 
 | ||||
| /* function prototype */ | ||||
| static s32 atl2_reset_hw(struct atl2_hw *hw); | ||||
| static s32 atl2_read_mac_addr(struct atl2_hw *hw); | ||||
| static s32 atl2_init_hw(struct atl2_hw *hw); | ||||
| static s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed, | ||||
| 	u16 *duplex); | ||||
| static u32 atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr); | ||||
| static void atl2_hash_set(struct atl2_hw *hw, u32 hash_value); | ||||
| static s32 atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data); | ||||
| static s32 atl2_write_phy_reg(struct atl2_hw *hw, u32 reg_addr, u16 phy_data); | ||||
| static void atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value); | ||||
| static void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value); | ||||
| static void atl2_set_mac_addr(struct atl2_hw *hw); | ||||
| static bool atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue); | ||||
| static bool atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value); | ||||
| static s32 atl2_phy_init(struct atl2_hw *hw); | ||||
| static int atl2_check_eeprom_exist(struct atl2_hw *hw); | ||||
| static void atl2_force_ps(struct atl2_hw *hw); | ||||
| 
 | ||||
| /* register definition */ | ||||
| 
 | ||||
| /* Block IDLE Status Register */ | ||||
| #define IDLE_STATUS_RXMAC	1	/* 1: RXMAC is non-IDLE */ | ||||
| #define IDLE_STATUS_TXMAC	2	/* 1: TXMAC is non-IDLE */ | ||||
| #define IDLE_STATUS_DMAR	8	/* 1: DMAR is non-IDLE */ | ||||
| #define IDLE_STATUS_DMAW	4	/* 1: DMAW is non-IDLE */ | ||||
| 
 | ||||
| /* MDIO Control Register */ | ||||
| #define MDIO_WAIT_TIMES		10 | ||||
| 
 | ||||
| /* MAC Control Register */ | ||||
| #define MAC_CTRL_DBG_TX_BKPRESURE	0x100000	/* 1: TX max backoff */ | ||||
| #define MAC_CTRL_MACLP_CLK_PHY		0x8000000	/* 1: 25MHz from phy */ | ||||
| #define MAC_CTRL_HALF_LEFT_BUF_SHIFT	28 | ||||
| #define MAC_CTRL_HALF_LEFT_BUF_MASK	0xF		/* MAC retry buf x32B */ | ||||
| 
 | ||||
| /* Internal SRAM Partition Register */ | ||||
| #define REG_SRAM_TXRAM_END	0x1500	/* Internal tail address of TXRAM | ||||
| 					 * default: 2byte*1024 */ | ||||
| #define REG_SRAM_RXRAM_END	0x1502	/* Internal tail address of RXRAM | ||||
| 					 * default: 2byte*1024 */ | ||||
| 
 | ||||
| /* Descriptor Control register */ | ||||
| #define REG_TXD_BASE_ADDR_LO	0x1544	/* The base address of the Transmit | ||||
| 					 * Data Mem low 32-bit(dword align) */ | ||||
| #define REG_TXD_MEM_SIZE	0x1548	/* Transmit Data Memory size(by | ||||
| 					 * double word , max 256KB) */ | ||||
| #define REG_TXS_BASE_ADDR_LO	0x154C	/* The base address of the Transmit | ||||
| 					 * Status Memory low 32-bit(dword word | ||||
| 					 * align) */ | ||||
| #define REG_TXS_MEM_SIZE	0x1550	/* double word unit, max 4*2047 | ||||
| 					 * bytes. */ | ||||
| #define REG_RXD_BASE_ADDR_LO	0x1554	/* The base address of the Transmit | ||||
| 					 * Status Memory low 32-bit(unit 8 | ||||
| 					 * bytes) */ | ||||
| #define REG_RXD_BUF_NUM		0x1558	/* Receive Data & Status Memory buffer | ||||
| 					 * number (unit 1536bytes, max | ||||
| 					 * 1536*2047) */ | ||||
| 
 | ||||
| /* DMAR Control Register */ | ||||
| #define REG_DMAR	0x1580 | ||||
| #define     DMAR_EN	0x1	/* 1: Enable DMAR */ | ||||
| 
 | ||||
| /* TX Cur-Through (early tx threshold) Control Register */ | ||||
| #define REG_TX_CUT_THRESH	0x1590	/* TxMac begin transmit packet | ||||
| 					 * threshold(unit word) */ | ||||
| 
 | ||||
| /* DMAW Control Register */ | ||||
| #define REG_DMAW	0x15A0 | ||||
| #define     DMAW_EN	0x1 | ||||
| 
 | ||||
| /* Flow control register */ | ||||
| #define REG_PAUSE_ON_TH		0x15A8	/* RXD high watermark of overflow | ||||
| 					 * threshold configuration register */ | ||||
| #define REG_PAUSE_OFF_TH	0x15AA	/* RXD lower watermark of overflow | ||||
| 					 * threshold configuration register */ | ||||
| 
 | ||||
| /* Mailbox Register */ | ||||
| #define REG_MB_TXD_WR_IDX	0x15f0	/* double word align */ | ||||
| #define REG_MB_RXD_RD_IDX	0x15F4	/* RXD Read index (unit: 1536byets) */ | ||||
| 
 | ||||
| /* Interrupt Status Register */ | ||||
| #define ISR_TIMER	1	/* Interrupt when Timer counts down to zero */ | ||||
| #define ISR_MANUAL	2	/* Software manual interrupt, for debug. Set | ||||
| 				 * when SW_MAN_INT_EN is set in Table 51 | ||||
| 				 * Selene Master Control Register | ||||
| 				 * (Offset 0x1400). */ | ||||
| #define ISR_RXF_OV	4	/* RXF overflow interrupt */ | ||||
| #define ISR_TXF_UR	8	/* TXF underrun interrupt */ | ||||
| #define ISR_TXS_OV	0x10	/* Internal transmit status buffer full | ||||
| 				 * interrupt */ | ||||
| #define ISR_RXS_OV	0x20	/* Internal receive status buffer full | ||||
| 				 * interrupt */ | ||||
| #define ISR_LINK_CHG	0x40	/* Link Status Change Interrupt */ | ||||
| #define ISR_HOST_TXD_UR	0x80 | ||||
| #define ISR_HOST_RXD_OV	0x100	/* Host rx data memory full , one pulse */ | ||||
| #define ISR_DMAR_TO_RST	0x200	/* DMAR op timeout interrupt. SW should | ||||
| 				 * do Reset */ | ||||
| #define ISR_DMAW_TO_RST	0x400 | ||||
| #define ISR_PHY		0x800	/* phy interrupt */ | ||||
| #define ISR_TS_UPDATE	0x10000	/* interrupt after new tx pkt status written | ||||
| 				 * to host */ | ||||
| #define ISR_RS_UPDATE	0x20000	/* interrupt ater new rx pkt status written | ||||
| 				 * to host. */ | ||||
| #define ISR_TX_EARLY	0x40000	/* interrupt when txmac begin transmit one | ||||
| 				 * packet */ | ||||
| 
 | ||||
| #define ISR_TX_EVENT (ISR_TXF_UR | ISR_TXS_OV | ISR_HOST_TXD_UR |\ | ||||
| 	ISR_TS_UPDATE | ISR_TX_EARLY) | ||||
| #define ISR_RX_EVENT (ISR_RXF_OV | ISR_RXS_OV | ISR_HOST_RXD_OV |\ | ||||
| 	 ISR_RS_UPDATE) | ||||
| 
 | ||||
| #define IMR_NORMAL_MASK		(\ | ||||
| 	/*ISR_LINK_CHG		|*/\ | ||||
| 	ISR_MANUAL		|\ | ||||
| 	ISR_DMAR_TO_RST		|\ | ||||
| 	ISR_DMAW_TO_RST		|\ | ||||
| 	ISR_PHY			|\ | ||||
| 	ISR_PHY_LINKDOWN	|\ | ||||
| 	ISR_TS_UPDATE		|\ | ||||
| 	ISR_RS_UPDATE) | ||||
| 
 | ||||
| /* Receive MAC Statistics Registers */ | ||||
| #define REG_STS_RX_PAUSE	0x1700	/* Num pause packets received */ | ||||
| #define REG_STS_RXD_OV		0x1704	/* Num frames dropped due to RX | ||||
| 					 * FIFO overflow */ | ||||
| #define REG_STS_RXS_OV		0x1708	/* Num frames dropped due to RX | ||||
| 					 * Status Buffer Overflow */ | ||||
| #define REG_STS_RX_FILTER	0x170C	/* Num packets dropped due to | ||||
| 					 * address filtering */ | ||||
| 
 | ||||
| /* MII definitions */ | ||||
| 
 | ||||
| /* PHY Common Register */ | ||||
| #define MII_SMARTSPEED	0x14 | ||||
| #define MII_DBG_ADDR	0x1D | ||||
| #define MII_DBG_DATA	0x1E | ||||
| 
 | ||||
| /* PCI Command Register Bit Definitions */ | ||||
| #define PCI_REG_COMMAND		0x04 | ||||
| #define CMD_IO_SPACE		0x0001 | ||||
| #define CMD_MEMORY_SPACE	0x0002 | ||||
| #define CMD_BUS_MASTER		0x0004 | ||||
| 
 | ||||
| #define MEDIA_TYPE_100M_FULL	1 | ||||
| #define MEDIA_TYPE_100M_HALF	2 | ||||
| #define MEDIA_TYPE_10M_FULL	3 | ||||
| #define MEDIA_TYPE_10M_HALF	4 | ||||
| 
 | ||||
| #define AUTONEG_ADVERTISE_SPEED_DEFAULT	0x000F	/* Everything */ | ||||
| 
 | ||||
| /* The size (in bytes) of a ethernet packet */ | ||||
| #define ENET_HEADER_SIZE		14 | ||||
| #define MAXIMUM_ETHERNET_FRAME_SIZE	1518	/* with FCS */ | ||||
| #define MINIMUM_ETHERNET_FRAME_SIZE	64	/* with FCS */ | ||||
| #define ETHERNET_FCS_SIZE		4 | ||||
| #define MAX_JUMBO_FRAME_SIZE		0x2000 | ||||
| #define VLAN_SIZE                                               4 | ||||
| 
 | ||||
| struct tx_pkt_header { | ||||
| 	unsigned pkt_size:11; | ||||
| 	unsigned:4;			/* reserved */ | ||||
| 	unsigned ins_vlan:1;		/* txmac should insert vlan */ | ||||
| 	unsigned short vlan;		/* vlan tag */ | ||||
| }; | ||||
| /* FIXME: replace above bitfields with MASK/SHIFT defines below */ | ||||
| #define TX_PKT_HEADER_SIZE_MASK		0x7FF | ||||
| #define TX_PKT_HEADER_SIZE_SHIFT	0 | ||||
| #define TX_PKT_HEADER_INS_VLAN_MASK	0x1 | ||||
| #define TX_PKT_HEADER_INS_VLAN_SHIFT	15 | ||||
| #define TX_PKT_HEADER_VLAN_TAG_MASK	0xFFFF | ||||
| #define TX_PKT_HEADER_VLAN_TAG_SHIFT	16 | ||||
| 
 | ||||
| struct tx_pkt_status { | ||||
| 	unsigned pkt_size:11; | ||||
| 	unsigned:5;		/* reserved */ | ||||
| 	unsigned ok:1;		/* current packet transmitted without error */ | ||||
| 	unsigned bcast:1;	/* broadcast packet */ | ||||
| 	unsigned mcast:1;	/* multicast packet */ | ||||
| 	unsigned pause:1;	/* transmiited a pause frame */ | ||||
| 	unsigned ctrl:1; | ||||
| 	unsigned defer:1;    	/* current packet is xmitted with defer */ | ||||
| 	unsigned exc_defer:1; | ||||
| 	unsigned single_col:1; | ||||
| 	unsigned multi_col:1; | ||||
| 	unsigned late_col:1; | ||||
| 	unsigned abort_col:1; | ||||
| 	unsigned underun:1;	/* current packet is aborted
 | ||||
| 				 * due to txram underrun */ | ||||
| 	unsigned:3;		/* reserved */ | ||||
| 	unsigned update:1;	/* always 1'b1 in tx_status_buf */ | ||||
| }; | ||||
| /* FIXME: replace above bitfields with MASK/SHIFT defines below */ | ||||
| #define TX_PKT_STATUS_SIZE_MASK		0x7FF | ||||
| #define TX_PKT_STATUS_SIZE_SHIFT	0 | ||||
| #define TX_PKT_STATUS_OK_MASK		0x1 | ||||
| #define TX_PKT_STATUS_OK_SHIFT		16 | ||||
| #define TX_PKT_STATUS_BCAST_MASK	0x1 | ||||
| #define TX_PKT_STATUS_BCAST_SHIFT	17 | ||||
| #define TX_PKT_STATUS_MCAST_MASK	0x1 | ||||
| #define TX_PKT_STATUS_MCAST_SHIFT	18 | ||||
| #define TX_PKT_STATUS_PAUSE_MASK	0x1 | ||||
| #define TX_PKT_STATUS_PAUSE_SHIFT	19 | ||||
| #define TX_PKT_STATUS_CTRL_MASK		0x1 | ||||
| #define TX_PKT_STATUS_CTRL_SHIFT	20 | ||||
| #define TX_PKT_STATUS_DEFER_MASK	0x1 | ||||
| #define TX_PKT_STATUS_DEFER_SHIFT	21 | ||||
| #define TX_PKT_STATUS_EXC_DEFER_MASK	0x1 | ||||
| #define TX_PKT_STATUS_EXC_DEFER_SHIFT	22 | ||||
| #define TX_PKT_STATUS_SINGLE_COL_MASK	0x1 | ||||
| #define TX_PKT_STATUS_SINGLE_COL_SHIFT	23 | ||||
| #define TX_PKT_STATUS_MULTI_COL_MASK	0x1 | ||||
| #define TX_PKT_STATUS_MULTI_COL_SHIFT	24 | ||||
| #define TX_PKT_STATUS_LATE_COL_MASK	0x1 | ||||
| #define TX_PKT_STATUS_LATE_COL_SHIFT	25 | ||||
| #define TX_PKT_STATUS_ABORT_COL_MASK	0x1 | ||||
| #define TX_PKT_STATUS_ABORT_COL_SHIFT	26 | ||||
| #define TX_PKT_STATUS_UNDERRUN_MASK	0x1 | ||||
| #define TX_PKT_STATUS_UNDERRUN_SHIFT	27 | ||||
| #define TX_PKT_STATUS_UPDATE_MASK	0x1 | ||||
| #define TX_PKT_STATUS_UPDATE_SHIFT	31 | ||||
| 
 | ||||
| struct rx_pkt_status { | ||||
| 	unsigned pkt_size:11;	/* packet size, max 2047 bytes */ | ||||
| 	unsigned:5;		/* reserved */ | ||||
| 	unsigned ok:1;		/* current packet received ok without error */ | ||||
| 	unsigned bcast:1;	/* current packet is broadcast */ | ||||
| 	unsigned mcast:1;	/* current packet is multicast */ | ||||
| 	unsigned pause:1; | ||||
| 	unsigned ctrl:1; | ||||
| 	unsigned crc:1;		/* received a packet with crc error */ | ||||
| 	unsigned code:1;	/* received a packet with code error */ | ||||
| 	unsigned runt:1;	/* received a packet less than 64 bytes
 | ||||
| 				 * with good crc */ | ||||
| 	unsigned frag:1;	/* received a packet less than 64 bytes
 | ||||
| 				 * with bad crc */ | ||||
| 	unsigned trunc:1;	/* current frame truncated due to rxram full */ | ||||
| 	unsigned align:1;	/* this packet is alignment error */ | ||||
| 	unsigned vlan:1;	/* this packet has vlan */ | ||||
| 	unsigned:3;		/* reserved */ | ||||
| 	unsigned update:1; | ||||
| 	unsigned short vtag;	/* vlan tag */ | ||||
| 	unsigned:16; | ||||
| }; | ||||
| /* FIXME: replace above bitfields with MASK/SHIFT defines below */ | ||||
| #define RX_PKT_STATUS_SIZE_MASK		0x7FF | ||||
| #define RX_PKT_STATUS_SIZE_SHIFT	0 | ||||
| #define RX_PKT_STATUS_OK_MASK		0x1 | ||||
| #define RX_PKT_STATUS_OK_SHIFT		16 | ||||
| #define RX_PKT_STATUS_BCAST_MASK	0x1 | ||||
| #define RX_PKT_STATUS_BCAST_SHIFT	17 | ||||
| #define RX_PKT_STATUS_MCAST_MASK	0x1 | ||||
| #define RX_PKT_STATUS_MCAST_SHIFT	18 | ||||
| #define RX_PKT_STATUS_PAUSE_MASK	0x1 | ||||
| #define RX_PKT_STATUS_PAUSE_SHIFT	19 | ||||
| #define RX_PKT_STATUS_CTRL_MASK		0x1 | ||||
| #define RX_PKT_STATUS_CTRL_SHIFT	20 | ||||
| #define RX_PKT_STATUS_CRC_MASK		0x1 | ||||
| #define RX_PKT_STATUS_CRC_SHIFT		21 | ||||
| #define RX_PKT_STATUS_CODE_MASK		0x1 | ||||
| #define RX_PKT_STATUS_CODE_SHIFT	22 | ||||
| #define RX_PKT_STATUS_RUNT_MASK		0x1 | ||||
| #define RX_PKT_STATUS_RUNT_SHIFT	23 | ||||
| #define RX_PKT_STATUS_FRAG_MASK		0x1 | ||||
| #define RX_PKT_STATUS_FRAG_SHIFT	24 | ||||
| #define RX_PKT_STATUS_TRUNK_MASK	0x1 | ||||
| #define RX_PKT_STATUS_TRUNK_SHIFT	25 | ||||
| #define RX_PKT_STATUS_ALIGN_MASK	0x1 | ||||
| #define RX_PKT_STATUS_ALIGN_SHIFT	26 | ||||
| #define RX_PKT_STATUS_VLAN_MASK		0x1 | ||||
| #define RX_PKT_STATUS_VLAN_SHIFT	27 | ||||
| #define RX_PKT_STATUS_UPDATE_MASK	0x1 | ||||
| #define RX_PKT_STATUS_UPDATE_SHIFT	31 | ||||
| #define RX_PKT_STATUS_VLAN_TAG_MASK	0xFFFF | ||||
| #define RX_PKT_STATUS_VLAN_TAG_SHIFT	32 | ||||
| 
 | ||||
| struct rx_desc { | ||||
| 	struct rx_pkt_status	status; | ||||
| 	unsigned char     	packet[1536-sizeof(struct rx_pkt_status)]; | ||||
| }; | ||||
| 
 | ||||
| enum atl2_speed_duplex { | ||||
| 	atl2_10_half = 0, | ||||
| 	atl2_10_full = 1, | ||||
| 	atl2_100_half = 2, | ||||
| 	atl2_100_full = 3 | ||||
| }; | ||||
| 
 | ||||
| struct atl2_spi_flash_dev { | ||||
| 	const char *manu_name;	/* manufacturer id */ | ||||
| 	/* op-code */ | ||||
| 	u8 cmdWRSR; | ||||
| 	u8 cmdREAD; | ||||
| 	u8 cmdPROGRAM; | ||||
| 	u8 cmdWREN; | ||||
| 	u8 cmdWRDI; | ||||
| 	u8 cmdRDSR; | ||||
| 	u8 cmdRDID; | ||||
| 	u8 cmdSECTOR_ERASE; | ||||
| 	u8 cmdCHIP_ERASE; | ||||
| }; | ||||
| 
 | ||||
| /* Structure containing variables used by the shared code (atl2_hw.c) */ | ||||
| struct atl2_hw { | ||||
| 	u8 __iomem *hw_addr; | ||||
| 	void *back; | ||||
| 
 | ||||
| 	u8 preamble_len; | ||||
| 	u8 max_retry;          /* Retransmission maximum, afterwards the
 | ||||
| 				* packet will be discarded. */ | ||||
| 	u8 jam_ipg;            /* IPG to start JAM for collision based flow
 | ||||
| 				* control in half-duplex mode. In unit of | ||||
| 				* 8-bit time. */ | ||||
| 	u8 ipgt;               /* Desired back to back inter-packet gap. The
 | ||||
| 				* default is 96-bit time. */ | ||||
| 	u8 min_ifg;            /* Minimum number of IFG to enforce in between
 | ||||
| 				* RX frames. Frame gap below such IFP is | ||||
| 				* dropped. */ | ||||
| 	u8 ipgr1;              /* 64bit Carrier-Sense window */ | ||||
| 	u8 ipgr2;              /* 96-bit IPG window */ | ||||
| 	u8 retry_buf;          /* When half-duplex mode, should hold some
 | ||||
| 				* bytes for mac retry . (8*4bytes unit) */ | ||||
| 
 | ||||
| 	u16 fc_rxd_hi; | ||||
| 	u16 fc_rxd_lo; | ||||
| 	u16 lcol;              /* Collision Window */ | ||||
| 	u16 max_frame_size; | ||||
| 
 | ||||
| 	u16 MediaType; | ||||
| 	u16 autoneg_advertised; | ||||
| 	u16 pci_cmd_word; | ||||
| 
 | ||||
| 	u16 mii_autoneg_adv_reg; | ||||
| 
 | ||||
| 	u32 mem_rang; | ||||
| 	u32 txcw; | ||||
| 	u32 mc_filter_type; | ||||
| 	u32 num_mc_addrs; | ||||
| 	u32 collision_delta; | ||||
| 	u32 tx_packet_delta; | ||||
| 	u16 phy_spd_default; | ||||
| 
 | ||||
| 	u16 device_id; | ||||
| 	u16 vendor_id; | ||||
| 	u16 subsystem_id; | ||||
| 	u16 subsystem_vendor_id; | ||||
| 	u8 revision_id; | ||||
| 
 | ||||
| 	/* spi flash */ | ||||
| 	u8 flash_vendor; | ||||
| 
 | ||||
| 	u8 dma_fairness; | ||||
| 	u8 mac_addr[ETH_ALEN]; | ||||
| 	u8 perm_mac_addr[ETH_ALEN]; | ||||
| 
 | ||||
| 	/* FIXME */ | ||||
| 	/* bool phy_preamble_sup; */ | ||||
| 	bool phy_configured; | ||||
| }; | ||||
| 
 | ||||
| #endif /* _ATL2_HW_H_ */ | ||||
| 
 | ||||
| struct atl2_ring_header { | ||||
|     /* pointer to the descriptor ring memory */ | ||||
|     void *desc; | ||||
|     /* physical address of the descriptor ring */ | ||||
|     dma_addr_t dma; | ||||
|     /* length of descriptor ring in bytes */ | ||||
|     unsigned int size; | ||||
| }; | ||||
| 
 | ||||
| /* board specific private data structure */ | ||||
| struct atl2_adapter { | ||||
| 	/* OS defined structs */ | ||||
| 	struct net_device *netdev; | ||||
| 	struct pci_dev *pdev; | ||||
| 	u32 wol; | ||||
| 	u16 link_speed; | ||||
| 	u16 link_duplex; | ||||
| 
 | ||||
| 	spinlock_t stats_lock; | ||||
| 
 | ||||
| 	struct work_struct reset_task; | ||||
| 	struct work_struct link_chg_task; | ||||
| 	struct timer_list watchdog_timer; | ||||
| 	struct timer_list phy_config_timer; | ||||
| 
 | ||||
| 	unsigned long cfg_phy; | ||||
| 	bool mac_disabled; | ||||
| 
 | ||||
| 	/* All Descriptor memory */ | ||||
| 	dma_addr_t	ring_dma; | ||||
| 	void		*ring_vir_addr; | ||||
| 	int		ring_size; | ||||
| 
 | ||||
| 	struct tx_pkt_header	*txd_ring; | ||||
| 	dma_addr_t	txd_dma; | ||||
| 
 | ||||
| 	struct tx_pkt_status	*txs_ring; | ||||
| 	dma_addr_t	txs_dma; | ||||
| 
 | ||||
| 	struct rx_desc	*rxd_ring; | ||||
| 	dma_addr_t	rxd_dma; | ||||
| 
 | ||||
| 	u32 txd_ring_size;         /* bytes per unit */ | ||||
| 	u32 txs_ring_size;         /* dwords per unit */ | ||||
| 	u32 rxd_ring_size;         /* 1536 bytes per unit */ | ||||
| 
 | ||||
| 	/* read /write ptr: */ | ||||
| 	/* host */ | ||||
| 	u32 txd_write_ptr; | ||||
| 	u32 txs_next_clear; | ||||
| 	u32 rxd_read_ptr; | ||||
| 
 | ||||
| 	/* nic */ | ||||
| 	atomic_t txd_read_ptr; | ||||
| 	atomic_t txs_write_ptr; | ||||
| 	u32 rxd_write_ptr; | ||||
| 
 | ||||
| 	/* Interrupt Moderator timer ( 2us resolution) */ | ||||
| 	u16 imt; | ||||
| 	/* Interrupt Clear timer (2us resolution) */ | ||||
| 	u16 ict; | ||||
| 
 | ||||
| 	unsigned long flags; | ||||
| 	/* structs defined in atl2_hw.h */ | ||||
| 	u32 bd_number;     /* board number */ | ||||
| 	bool pci_using_64; | ||||
| 	bool have_msi; | ||||
| 	struct atl2_hw hw; | ||||
| 
 | ||||
| 	u32 usr_cmd; | ||||
| 	/* FIXME */ | ||||
| 	/* u32 regs_buff[ATL2_REGS_LEN]; */ | ||||
| 	u32 pci_state[16]; | ||||
| 
 | ||||
| 	u32 *config_space; | ||||
| }; | ||||
| 
 | ||||
| enum atl2_state_t { | ||||
| 	__ATL2_TESTING, | ||||
| 	__ATL2_RESETTING, | ||||
| 	__ATL2_DOWN | ||||
| }; | ||||
| 
 | ||||
| #endif /* _ATL2_H_ */ | ||||
							
								
								
									
										279
									
								
								drivers/net/ethernet/atheros/atlx/atlx.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										279
									
								
								drivers/net/ethernet/atheros/atlx/atlx.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,279 @@ | |||
| /* atlx.c -- common functions for Attansic network drivers
 | ||||
|  * | ||||
|  * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. | ||||
|  * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com> | ||||
|  * Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com> | ||||
|  * Copyright(c) 2007 Atheros Corporation. All rights reserved. | ||||
|  * | ||||
|  * Derived from Intel e1000 driver | ||||
|  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the Free | ||||
|  * Software Foundation; either version 2 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., 59 | ||||
|  * Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||
|  */ | ||||
| 
 | ||||
| /* Including this file like a header is a temporary hack, I promise. -- CHS */ | ||||
| #ifndef ATLX_C | ||||
| #define ATLX_C | ||||
| 
 | ||||
| #include <linux/device.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/etherdevice.h> | ||||
| #include <linux/if.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/socket.h> | ||||
| #include <linux/sockios.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/string.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/workqueue.h> | ||||
| 
 | ||||
| #include "atlx.h" | ||||
| 
 | ||||
| static s32 atlx_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data); | ||||
| static u32 atlx_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr); | ||||
| static void atlx_set_mac_addr(struct atl1_hw *hw); | ||||
| 
 | ||||
| static struct atlx_spi_flash_dev flash_table[] = { | ||||
| /*	MFR_NAME  WRSR  READ  PRGM  WREN  WRDI  RDSR  RDID  SEC_ERS CHIP_ERS */ | ||||
| 	{"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52,   0x62}, | ||||
| 	{"SST",   0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20,   0x60}, | ||||
| 	{"ST",    0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8,   0xC7}, | ||||
| }; | ||||
| 
 | ||||
| static int atlx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | ||||
| { | ||||
| 	switch (cmd) { | ||||
| 	case SIOCGMIIPHY: | ||||
| 	case SIOCGMIIREG: | ||||
| 	case SIOCSMIIREG: | ||||
| 		return atlx_mii_ioctl(netdev, ifr, cmd); | ||||
| 	default: | ||||
| 		return -EOPNOTSUPP; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * atlx_set_mac - Change the Ethernet Address of the NIC | ||||
|  * @netdev: network interface device structure | ||||
|  * @p: pointer to an address structure | ||||
|  * | ||||
|  * Returns 0 on success, negative on failure | ||||
|  */ | ||||
| static int atlx_set_mac(struct net_device *netdev, void *p) | ||||
| { | ||||
| 	struct atlx_adapter *adapter = netdev_priv(netdev); | ||||
| 	struct sockaddr *addr = p; | ||||
| 
 | ||||
| 	if (netif_running(netdev)) | ||||
| 		return -EBUSY; | ||||
| 
 | ||||
| 	if (!is_valid_ether_addr(addr->sa_data)) | ||||
| 		return -EADDRNOTAVAIL; | ||||
| 
 | ||||
| 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); | ||||
| 	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); | ||||
| 
 | ||||
| 	atlx_set_mac_addr(&adapter->hw); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void atlx_check_for_link(struct atlx_adapter *adapter) | ||||
| { | ||||
| 	struct net_device *netdev = adapter->netdev; | ||||
| 	u16 phy_data = 0; | ||||
| 
 | ||||
| 	spin_lock(&adapter->lock); | ||||
| 	adapter->phy_timer_pending = false; | ||||
| 	atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); | ||||
| 	atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); | ||||
| 	spin_unlock(&adapter->lock); | ||||
| 
 | ||||
| 	/* notify upper layer link down ASAP */ | ||||
| 	if (!(phy_data & BMSR_LSTATUS)) { | ||||
| 		/* Link Down */ | ||||
| 		if (netif_carrier_ok(netdev)) { | ||||
| 			/* old link state: Up */ | ||||
| 			dev_info(&adapter->pdev->dev, "%s link is down\n", | ||||
| 				netdev->name); | ||||
| 			adapter->link_speed = SPEED_0; | ||||
| 			netif_carrier_off(netdev); | ||||
| 		} | ||||
| 	} | ||||
| 	schedule_work(&adapter->link_chg_task); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * atlx_set_multi - Multicast and Promiscuous mode set | ||||
|  * @netdev: network interface device structure | ||||
|  * | ||||
|  * The set_multi entry point is called whenever the multicast address | ||||
|  * list or the network interface flags are updated.  This routine is | ||||
|  * responsible for configuring the hardware for proper multicast, | ||||
|  * promiscuous mode, and all-multi behavior. | ||||
|  */ | ||||
| static void atlx_set_multi(struct net_device *netdev) | ||||
| { | ||||
| 	struct atlx_adapter *adapter = netdev_priv(netdev); | ||||
| 	struct atlx_hw *hw = &adapter->hw; | ||||
| 	struct netdev_hw_addr *ha; | ||||
| 	u32 rctl; | ||||
| 	u32 hash_value; | ||||
| 
 | ||||
| 	/* Check for Promiscuous and All Multicast modes */ | ||||
| 	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL); | ||||
| 	if (netdev->flags & IFF_PROMISC) | ||||
| 		rctl |= MAC_CTRL_PROMIS_EN; | ||||
| 	else if (netdev->flags & IFF_ALLMULTI) { | ||||
| 		rctl |= MAC_CTRL_MC_ALL_EN; | ||||
| 		rctl &= ~MAC_CTRL_PROMIS_EN; | ||||
| 	} else | ||||
| 		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); | ||||
| 
 | ||||
| 	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL); | ||||
| 
 | ||||
| 	/* clear the old settings from the multicast hash table */ | ||||
| 	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE); | ||||
| 	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2)); | ||||
| 
 | ||||
| 	/* compute mc addresses' hash value ,and put it into hash table */ | ||||
| 	netdev_for_each_mc_addr(ha, netdev) { | ||||
| 		hash_value = atlx_hash_mc_addr(hw, ha->addr); | ||||
| 		atlx_hash_set(hw, hash_value); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static inline void atlx_imr_set(struct atlx_adapter *adapter, | ||||
| 				unsigned int imr) | ||||
| { | ||||
| 	iowrite32(imr, adapter->hw.hw_addr + REG_IMR); | ||||
| 	ioread32(adapter->hw.hw_addr + REG_IMR); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * atlx_irq_enable - Enable default interrupt generation settings | ||||
|  * @adapter: board private structure | ||||
|  */ | ||||
| static void atlx_irq_enable(struct atlx_adapter *adapter) | ||||
| { | ||||
| 	atlx_imr_set(adapter, IMR_NORMAL_MASK); | ||||
| 	adapter->int_enabled = true; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * atlx_irq_disable - Mask off interrupt generation on the NIC | ||||
|  * @adapter: board private structure | ||||
|  */ | ||||
| static void atlx_irq_disable(struct atlx_adapter *adapter) | ||||
| { | ||||
| 	adapter->int_enabled = false; | ||||
| 	atlx_imr_set(adapter, 0); | ||||
| 	synchronize_irq(adapter->pdev->irq); | ||||
| } | ||||
| 
 | ||||
| static void atlx_clear_phy_int(struct atlx_adapter *adapter) | ||||
| { | ||||
| 	u16 phy_data; | ||||
| 	unsigned long flags; | ||||
| 
 | ||||
| 	spin_lock_irqsave(&adapter->lock, flags); | ||||
| 	atlx_read_phy_reg(&adapter->hw, 19, &phy_data); | ||||
| 	spin_unlock_irqrestore(&adapter->lock, flags); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * atlx_tx_timeout - Respond to a Tx Hang | ||||
|  * @netdev: network interface device structure | ||||
|  */ | ||||
| static void atlx_tx_timeout(struct net_device *netdev) | ||||
| { | ||||
| 	struct atlx_adapter *adapter = netdev_priv(netdev); | ||||
| 	/* Do the reset outside of interrupt context */ | ||||
| 	schedule_work(&adapter->reset_dev_task); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * atlx_link_chg_task - deal with link change event Out of interrupt context | ||||
|  */ | ||||
| static void atlx_link_chg_task(struct work_struct *work) | ||||
| { | ||||
| 	struct atlx_adapter *adapter; | ||||
| 	unsigned long flags; | ||||
| 
 | ||||
| 	adapter = container_of(work, struct atlx_adapter, link_chg_task); | ||||
| 
 | ||||
| 	spin_lock_irqsave(&adapter->lock, flags); | ||||
| 	atlx_check_link(adapter); | ||||
| 	spin_unlock_irqrestore(&adapter->lock, flags); | ||||
| } | ||||
| 
 | ||||
| static void __atlx_vlan_mode(netdev_features_t features, u32 *ctrl) | ||||
| { | ||||
| 	if (features & NETIF_F_HW_VLAN_CTAG_RX) { | ||||
| 		/* enable VLAN tag insert/strip */ | ||||
| 		*ctrl |= MAC_CTRL_RMV_VLAN; | ||||
| 	} else { | ||||
| 		/* disable VLAN tag insert/strip */ | ||||
| 		*ctrl &= ~MAC_CTRL_RMV_VLAN; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void atlx_vlan_mode(struct net_device *netdev, | ||||
| 	netdev_features_t features) | ||||
| { | ||||
| 	struct atlx_adapter *adapter = netdev_priv(netdev); | ||||
| 	unsigned long flags; | ||||
| 	u32 ctrl; | ||||
| 
 | ||||
| 	spin_lock_irqsave(&adapter->lock, flags); | ||||
| 	/* atlx_irq_disable(adapter); FIXME: confirm/remove */ | ||||
| 	ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL); | ||||
| 	__atlx_vlan_mode(features, &ctrl); | ||||
| 	iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL); | ||||
| 	/* atlx_irq_enable(adapter); FIXME */ | ||||
| 	spin_unlock_irqrestore(&adapter->lock, flags); | ||||
| } | ||||
| 
 | ||||
| static void atlx_restore_vlan(struct atlx_adapter *adapter) | ||||
| { | ||||
| 	atlx_vlan_mode(adapter->netdev, adapter->netdev->features); | ||||
| } | ||||
| 
 | ||||
| static netdev_features_t atlx_fix_features(struct net_device *netdev, | ||||
| 	netdev_features_t features) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * Since there is no support for separate rx/tx vlan accel | ||||
| 	 * enable/disable make sure tx flag is always in same state as rx. | ||||
| 	 */ | ||||
| 	if (features & NETIF_F_HW_VLAN_CTAG_RX) | ||||
| 		features |= NETIF_F_HW_VLAN_CTAG_TX; | ||||
| 	else | ||||
| 		features &= ~NETIF_F_HW_VLAN_CTAG_TX; | ||||
| 
 | ||||
| 	return features; | ||||
| } | ||||
| 
 | ||||
| static int atlx_set_features(struct net_device *netdev, | ||||
| 	netdev_features_t features) | ||||
| { | ||||
| 	netdev_features_t changed = netdev->features ^ features; | ||||
| 
 | ||||
| 	if (changed & NETIF_F_HW_VLAN_CTAG_RX) | ||||
| 		atlx_vlan_mode(netdev, features); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #endif /* ATLX_C */ | ||||
							
								
								
									
										502
									
								
								drivers/net/ethernet/atheros/atlx/atlx.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										502
									
								
								drivers/net/ethernet/atheros/atlx/atlx.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,502 @@ | |||
| /* atlx_hw.h -- common hardware definitions for Attansic network drivers
 | ||||
|  * | ||||
|  * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. | ||||
|  * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com> | ||||
|  * Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com> | ||||
|  * Copyright(c) 2007 Atheros Corporation. All rights reserved. | ||||
|  * | ||||
|  * Derived from Intel e1000 driver | ||||
|  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the Free | ||||
|  * Software Foundation; either version 2 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., 59 | ||||
|  * Temple Place - Suite 330, Boston, MA  02111-1307, USA. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef ATLX_H | ||||
| #define ATLX_H | ||||
| 
 | ||||
| #include <linux/module.h> | ||||
| #include <linux/types.h> | ||||
| 
 | ||||
| #define ATLX_ERR_PHY			2 | ||||
| #define ATLX_ERR_PHY_SPEED		7 | ||||
| #define ATLX_ERR_PHY_RES		8 | ||||
| 
 | ||||
| #define SPEED_0				0xffff | ||||
| #define SPEED_10			10 | ||||
| #define SPEED_100			100 | ||||
| #define SPEED_1000			1000 | ||||
| #define HALF_DUPLEX			1 | ||||
| #define FULL_DUPLEX			2 | ||||
| 
 | ||||
| #define MEDIA_TYPE_AUTO_SENSOR		0 | ||||
| 
 | ||||
| /* register definitions */ | ||||
| #define REG_PM_CTRLSTAT			0x44 | ||||
| 
 | ||||
| #define REG_PCIE_CAP_LIST		0x58 | ||||
| 
 | ||||
| #define REG_VPD_CAP			0x6C | ||||
| #define VPD_CAP_ID_MASK			0xFF | ||||
| #define VPD_CAP_ID_SHIFT		0 | ||||
| #define VPD_CAP_NEXT_PTR_MASK		0xFF | ||||
| #define VPD_CAP_NEXT_PTR_SHIFT		8 | ||||
| #define VPD_CAP_VPD_ADDR_MASK		0x7FFF | ||||
| #define VPD_CAP_VPD_ADDR_SHIFT		16 | ||||
| #define VPD_CAP_VPD_FLAG		0x80000000 | ||||
| 
 | ||||
| #define REG_VPD_DATA			0x70 | ||||
| 
 | ||||
| #define REG_SPI_FLASH_CTRL		0x200 | ||||
| #define SPI_FLASH_CTRL_STS_NON_RDY	0x1 | ||||
| #define SPI_FLASH_CTRL_STS_WEN		0x2 | ||||
| #define SPI_FLASH_CTRL_STS_WPEN		0x80 | ||||
| #define SPI_FLASH_CTRL_DEV_STS_MASK	0xFF | ||||
| #define SPI_FLASH_CTRL_DEV_STS_SHIFT	0 | ||||
| #define SPI_FLASH_CTRL_INS_MASK		0x7 | ||||
| #define SPI_FLASH_CTRL_INS_SHIFT	8 | ||||
| #define SPI_FLASH_CTRL_START		0x800 | ||||
| #define SPI_FLASH_CTRL_EN_VPD		0x2000 | ||||
| #define SPI_FLASH_CTRL_LDSTART		0x8000 | ||||
| #define SPI_FLASH_CTRL_CS_HI_MASK	0x3 | ||||
| #define SPI_FLASH_CTRL_CS_HI_SHIFT	16 | ||||
| #define SPI_FLASH_CTRL_CS_HOLD_MASK	0x3 | ||||
| #define SPI_FLASH_CTRL_CS_HOLD_SHIFT	18 | ||||
| #define SPI_FLASH_CTRL_CLK_LO_MASK	0x3 | ||||
| #define SPI_FLASH_CTRL_CLK_LO_SHIFT	20 | ||||
| #define SPI_FLASH_CTRL_CLK_HI_MASK	0x3 | ||||
| #define SPI_FLASH_CTRL_CLK_HI_SHIFT	22 | ||||
| #define SPI_FLASH_CTRL_CS_SETUP_MASK	0x3 | ||||
| #define SPI_FLASH_CTRL_CS_SETUP_SHIFT	24 | ||||
| #define SPI_FLASH_CTRL_EROM_PGSZ_MASK	0x3 | ||||
| #define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT	26 | ||||
| #define SPI_FLASH_CTRL_WAIT_READY	0x10000000 | ||||
| 
 | ||||
| #define REG_SPI_ADDR			0x204 | ||||
| 
 | ||||
| #define REG_SPI_DATA			0x208 | ||||
| 
 | ||||
| #define REG_SPI_FLASH_CONFIG		0x20C | ||||
| #define SPI_FLASH_CONFIG_LD_ADDR_MASK	0xFFFFFF | ||||
| #define SPI_FLASH_CONFIG_LD_ADDR_SHIFT	0 | ||||
| #define SPI_FLASH_CONFIG_VPD_ADDR_MASK	0x3 | ||||
| #define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT	24 | ||||
| #define SPI_FLASH_CONFIG_LD_EXIST	0x4000000 | ||||
| 
 | ||||
| #define REG_SPI_FLASH_OP_PROGRAM	0x210 | ||||
| #define REG_SPI_FLASH_OP_SC_ERASE	0x211 | ||||
| #define REG_SPI_FLASH_OP_CHIP_ERASE	0x212 | ||||
| #define REG_SPI_FLASH_OP_RDID		0x213 | ||||
| #define REG_SPI_FLASH_OP_WREN		0x214 | ||||
| #define REG_SPI_FLASH_OP_RDSR		0x215 | ||||
| #define REG_SPI_FLASH_OP_WRSR		0x216 | ||||
| #define REG_SPI_FLASH_OP_READ		0x217 | ||||
| 
 | ||||
| #define REG_TWSI_CTRL			0x218 | ||||
| #define TWSI_CTRL_LD_OFFSET_MASK	0xFF | ||||
| #define TWSI_CTRL_LD_OFFSET_SHIFT	0 | ||||
| #define TWSI_CTRL_LD_SLV_ADDR_MASK	0x7 | ||||
| #define TWSI_CTRL_LD_SLV_ADDR_SHIFT	8 | ||||
| #define TWSI_CTRL_SW_LDSTART		0x800 | ||||
| #define TWSI_CTRL_HW_LDSTART		0x1000 | ||||
| #define TWSI_CTRL_SMB_SLV_ADDR_MASK	0x7F | ||||
| #define TWSI_CTRL_SMB_SLV_ADDR_SHIFT	15 | ||||
| #define TWSI_CTRL_LD_EXIST		0x400000 | ||||
| #define TWSI_CTRL_READ_FREQ_SEL_MASK	0x3 | ||||
| #define TWSI_CTRL_READ_FREQ_SEL_SHIFT	23 | ||||
| #define TWSI_CTRL_FREQ_SEL_100K		0 | ||||
| #define TWSI_CTRL_FREQ_SEL_200K		1 | ||||
| #define TWSI_CTRL_FREQ_SEL_300K		2 | ||||
| #define TWSI_CTRL_FREQ_SEL_400K		3 | ||||
| #define TWSI_CTRL_SMB_SLV_ADDR		/* FIXME: define or remove */ | ||||
| #define TWSI_CTRL_WRITE_FREQ_SEL_MASK	0x3 | ||||
| #define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT	24 | ||||
| 
 | ||||
| #define REG_PCIE_DEV_MISC_CTRL			0x21C | ||||
| #define PCIE_DEV_MISC_CTRL_EXT_PIPE		0x2 | ||||
| #define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS		0x1 | ||||
| #define PCIE_DEV_MISC_CTRL_SPIROM_EXIST		0x4 | ||||
| #define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN	0x8 | ||||
| #define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN	0x10 | ||||
| 
 | ||||
| #define REG_PCIE_PHYMISC		0x1000 | ||||
| #define PCIE_PHYMISC_FORCE_RCV_DET	0x4 | ||||
| 
 | ||||
| #define REG_PCIE_DLL_TX_CTRL1		0x1104 | ||||
| #define PCIE_DLL_TX_CTRL1_SEL_NOR_CLK	0x400 | ||||
| #define PCIE_DLL_TX_CTRL1_DEF		0x568 | ||||
| 
 | ||||
| #define REG_LTSSM_TEST_MODE		0x12FC | ||||
| #define LTSSM_TEST_MODE_DEF		0x6500 | ||||
| 
 | ||||
| /* Master Control Register */ | ||||
| #define REG_MASTER_CTRL			0x1400 | ||||
| #define MASTER_CTRL_SOFT_RST		0x1 | ||||
| #define MASTER_CTRL_MTIMER_EN		0x2 | ||||
| #define MASTER_CTRL_ITIMER_EN		0x4 | ||||
| #define MASTER_CTRL_MANUAL_INT		0x8 | ||||
| #define MASTER_CTRL_REV_NUM_SHIFT	16 | ||||
| #define MASTER_CTRL_REV_NUM_MASK	0xFF | ||||
| #define MASTER_CTRL_DEV_ID_SHIFT	24 | ||||
| #define MASTER_CTRL_DEV_ID_MASK		0xFF | ||||
| 
 | ||||
| /* Timer Initial Value Register */ | ||||
| #define REG_MANUAL_TIMER_INIT		0x1404 | ||||
| 
 | ||||
| /* IRQ Moderator Timer Initial Value Register */ | ||||
| #define REG_IRQ_MODU_TIMER_INIT		0x1408 | ||||
| 
 | ||||
| #define REG_PHY_ENABLE			0x140C | ||||
| 
 | ||||
| /* IRQ Anti-Lost Timer Initial Value Register */ | ||||
| #define REG_CMBDISDMA_TIMER		0x140E | ||||
| 
 | ||||
| /* Block IDLE Status Register */ | ||||
| #define REG_IDLE_STATUS			0x1410 | ||||
| 
 | ||||
| /* MDIO Control Register */ | ||||
| #define REG_MDIO_CTRL			0x1414 | ||||
| #define MDIO_DATA_MASK			0xFFFF | ||||
| #define MDIO_DATA_SHIFT			0 | ||||
| #define MDIO_REG_ADDR_MASK		0x1F | ||||
| #define MDIO_REG_ADDR_SHIFT		16 | ||||
| #define MDIO_RW				0x200000 | ||||
| #define MDIO_SUP_PREAMBLE		0x400000 | ||||
| #define MDIO_START			0x800000 | ||||
| #define MDIO_CLK_SEL_SHIFT		24 | ||||
| #define MDIO_CLK_25_4			0 | ||||
| #define MDIO_CLK_25_6			2 | ||||
| #define MDIO_CLK_25_8			3 | ||||
| #define MDIO_CLK_25_10			4 | ||||
| #define MDIO_CLK_25_14			5 | ||||
| #define MDIO_CLK_25_20			6 | ||||
| #define MDIO_CLK_25_28			7 | ||||
| #define MDIO_BUSY			0x8000000 | ||||
| 
 | ||||
| /* MII PHY Status Register */ | ||||
| #define REG_PHY_STATUS			0x1418 | ||||
| 
 | ||||
| /* BIST Control and Status Register0 (for the Packet Memory) */ | ||||
| #define REG_BIST0_CTRL			0x141C | ||||
| #define BIST0_NOW			0x1 | ||||
| #define BIST0_SRAM_FAIL			0x2 | ||||
| #define BIST0_FUSE_FLAG			0x4 | ||||
| #define REG_BIST1_CTRL			0x1420 | ||||
| #define BIST1_NOW			0x1 | ||||
| #define BIST1_SRAM_FAIL			0x2 | ||||
| #define BIST1_FUSE_FLAG			0x4 | ||||
| 
 | ||||
| /* SerDes Lock Detect Control and Status Register */ | ||||
| #define REG_SERDES_LOCK			0x1424 | ||||
| #define SERDES_LOCK_DETECT		1 | ||||
| #define SERDES_LOCK_DETECT_EN		2 | ||||
| 
 | ||||
| /* MAC Control Register */ | ||||
| #define REG_MAC_CTRL			0x1480 | ||||
| #define MAC_CTRL_TX_EN			1 | ||||
| #define MAC_CTRL_RX_EN			2 | ||||
| #define MAC_CTRL_TX_FLOW		4 | ||||
| #define MAC_CTRL_RX_FLOW		8 | ||||
| #define MAC_CTRL_LOOPBACK		0x10 | ||||
| #define MAC_CTRL_DUPLX			0x20 | ||||
| #define MAC_CTRL_ADD_CRC		0x40 | ||||
| #define MAC_CTRL_PAD			0x80 | ||||
| #define MAC_CTRL_LENCHK			0x100 | ||||
| #define MAC_CTRL_HUGE_EN		0x200 | ||||
| #define MAC_CTRL_PRMLEN_SHIFT		10 | ||||
| #define MAC_CTRL_PRMLEN_MASK		0xF | ||||
| #define MAC_CTRL_RMV_VLAN		0x4000 | ||||
| #define MAC_CTRL_PROMIS_EN		0x8000 | ||||
| #define MAC_CTRL_MC_ALL_EN		0x2000000 | ||||
| #define MAC_CTRL_BC_EN			0x4000000 | ||||
| 
 | ||||
| /* MAC IPG/IFG Control Register */ | ||||
| #define REG_MAC_IPG_IFG			0x1484 | ||||
| #define MAC_IPG_IFG_IPGT_SHIFT		0 | ||||
| #define MAC_IPG_IFG_IPGT_MASK		0x7F | ||||
| #define MAC_IPG_IFG_MIFG_SHIFT		8 | ||||
| #define MAC_IPG_IFG_MIFG_MASK		0xFF | ||||
| #define MAC_IPG_IFG_IPGR1_SHIFT		16 | ||||
| #define MAC_IPG_IFG_IPGR1_MASK		0x7F | ||||
| #define MAC_IPG_IFG_IPGR2_SHIFT		24 | ||||
| #define MAC_IPG_IFG_IPGR2_MASK		0x7F | ||||
| 
 | ||||
| /* MAC STATION ADDRESS */ | ||||
| #define REG_MAC_STA_ADDR		0x1488 | ||||
| 
 | ||||
| /* Hash table for multicast address */ | ||||
| #define REG_RX_HASH_TABLE		0x1490 | ||||
| 
 | ||||
| /* MAC Half-Duplex Control Register */ | ||||
| #define REG_MAC_HALF_DUPLX_CTRL			0x1498 | ||||
| #define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT		0 | ||||
| #define MAC_HALF_DUPLX_CTRL_LCOL_MASK		0x3FF | ||||
| #define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT		12 | ||||
| #define MAC_HALF_DUPLX_CTRL_RETRY_MASK		0xF | ||||
| #define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN		0x10000 | ||||
| #define MAC_HALF_DUPLX_CTRL_NO_BACK_C		0x20000 | ||||
| #define MAC_HALF_DUPLX_CTRL_NO_BACK_P		0x40000 | ||||
| #define MAC_HALF_DUPLX_CTRL_ABEBE		0x80000 | ||||
| #define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT		20 | ||||
| #define MAC_HALF_DUPLX_CTRL_ABEBT_MASK		0xF | ||||
| #define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT	24 | ||||
| #define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK		0xF | ||||
| 
 | ||||
| /* Maximum Frame Length Control Register */ | ||||
| #define REG_MTU				0x149C | ||||
| 
 | ||||
| /* Wake-On-Lan control register */ | ||||
| #define REG_WOL_CTRL			0x14A0 | ||||
| #define WOL_PATTERN_EN			0x1 | ||||
| #define WOL_PATTERN_PME_EN		0x2 | ||||
| #define WOL_MAGIC_EN			0x4 | ||||
| #define WOL_MAGIC_PME_EN		0x8 | ||||
| #define WOL_LINK_CHG_EN			0x10 | ||||
| #define WOL_LINK_CHG_PME_EN		0x20 | ||||
| #define WOL_PATTERN_ST			0x100 | ||||
| #define WOL_MAGIC_ST			0x200 | ||||
| #define WOL_LINKCHG_ST			0x400 | ||||
| #define WOL_PT0_EN			0x10000 | ||||
| #define WOL_PT1_EN			0x20000 | ||||
| #define WOL_PT2_EN			0x40000 | ||||
| #define WOL_PT3_EN			0x80000 | ||||
| #define WOL_PT4_EN			0x100000 | ||||
| #define WOL_PT0_MATCH			0x1000000 | ||||
| #define WOL_PT1_MATCH			0x2000000 | ||||
| #define WOL_PT2_MATCH			0x4000000 | ||||
| #define WOL_PT3_MATCH			0x8000000 | ||||
| #define WOL_PT4_MATCH			0x10000000 | ||||
| 
 | ||||
| /* Internal SRAM Partition Register, high 32 bits */ | ||||
| #define REG_SRAM_RFD_ADDR		0x1500 | ||||
| 
 | ||||
| /* Descriptor Control register, high 32 bits */ | ||||
| #define REG_DESC_BASE_ADDR_HI		0x1540 | ||||
| 
 | ||||
| /* Interrupt Status Register */ | ||||
| #define REG_ISR				0x1600 | ||||
| #define ISR_UR_DETECTED			0x1000000 | ||||
| #define ISR_FERR_DETECTED		0x2000000 | ||||
| #define ISR_NFERR_DETECTED		0x4000000 | ||||
| #define ISR_CERR_DETECTED		0x8000000 | ||||
| #define ISR_PHY_LINKDOWN		0x10000000 | ||||
| #define ISR_DIS_INT			0x80000000 | ||||
| 
 | ||||
| /* Interrupt Mask Register */ | ||||
| #define REG_IMR				0x1604 | ||||
| 
 | ||||
| #define REG_RFD_RRD_IDX			0x1800 | ||||
| #define REG_TPD_IDX			0x1804 | ||||
| 
 | ||||
| /* MII definitions */ | ||||
| 
 | ||||
| /* PHY Common Register */ | ||||
| #define MII_ATLX_CR			0x09 | ||||
| #define MII_ATLX_SR			0x0A | ||||
| #define MII_ATLX_ESR			0x0F | ||||
| #define MII_ATLX_PSCR			0x10 | ||||
| #define MII_ATLX_PSSR			0x11 | ||||
| 
 | ||||
| /* PHY Control Register */ | ||||
| #define MII_CR_SPEED_SELECT_MSB		0x0040	/* bits 6,13: 10=1000, 01=100, | ||||
| 						 * 00=10 | ||||
| 						 */ | ||||
| #define MII_CR_COLL_TEST_ENABLE		0x0080	/* Collision test enable */ | ||||
| #define MII_CR_FULL_DUPLEX		0x0100	/* FDX =1, half duplex =0 */ | ||||
| #define MII_CR_RESTART_AUTO_NEG		0x0200	/* Restart auto negotiation */ | ||||
| #define MII_CR_ISOLATE			0x0400	/* Isolate PHY from MII */ | ||||
| #define MII_CR_POWER_DOWN		0x0800	/* Power down */ | ||||
| #define MII_CR_AUTO_NEG_EN		0x1000	/* Auto Neg Enable */ | ||||
| #define MII_CR_SPEED_SELECT_LSB		0x2000	/* bits 6,13: 10=1000, 01=100, | ||||
| 						 * 00=10 | ||||
| 						 */ | ||||
| #define MII_CR_LOOPBACK			0x4000	/* 0 = normal, 1 = loopback */ | ||||
| #define MII_CR_RESET			0x8000	/* 0 = normal, 1 = PHY reset */ | ||||
| #define MII_CR_SPEED_MASK		0x2040 | ||||
| #define MII_CR_SPEED_1000		0x0040 | ||||
| #define MII_CR_SPEED_100		0x2000 | ||||
| #define MII_CR_SPEED_10			0x0000 | ||||
| 
 | ||||
| /* PHY Status Register */ | ||||
| #define MII_SR_EXTENDED_CAPS		0x0001	/* Ext register capabilities */ | ||||
| #define MII_SR_JABBER_DETECT		0x0002	/* Jabber Detected */ | ||||
| #define MII_SR_LINK_STATUS		0x0004	/* Link Status 1 = link */ | ||||
| #define MII_SR_AUTONEG_CAPS		0x0008	/* Auto Neg Capable */ | ||||
| #define MII_SR_REMOTE_FAULT		0x0010	/* Remote Fault Detect */ | ||||
| #define MII_SR_AUTONEG_COMPLETE		0x0020	/* Auto Neg Complete */ | ||||
| #define MII_SR_PREAMBLE_SUPPRESS	0x0040	/* Preamble may be suppressed */ | ||||
| #define MII_SR_EXTENDED_STATUS		0x0100	/* Ext stat info in Reg 0x0F */ | ||||
| #define MII_SR_100T2_HD_CAPS		0x0200	/* 100T2 Half Duplex Capable */ | ||||
| #define MII_SR_100T2_FD_CAPS		0x0400	/* 100T2 Full Duplex Capable */ | ||||
| #define MII_SR_10T_HD_CAPS		0x0800	/* 10T   Half Duplex Capable */ | ||||
| #define MII_SR_10T_FD_CAPS		0x1000	/* 10T   Full Duplex Capable */ | ||||
| #define MII_SR_100X_HD_CAPS		0x2000	/* 100X  Half Duplex Capable */ | ||||
| #define MII_SR_100X_FD_CAPS		0x4000	/* 100X  Full Duplex Capable */ | ||||
| #define MII_SR_100T4_CAPS		0x8000	/* 100T4 Capable */ | ||||
| 
 | ||||
| /* Link partner ability register */ | ||||
| #define MII_LPA_SLCT			0x001f	/* Same as advertise selector */ | ||||
| #define MII_LPA_10HALF			0x0020	/* Can do 10mbps half-duplex */ | ||||
| #define MII_LPA_10FULL			0x0040	/* Can do 10mbps full-duplex */ | ||||
| #define MII_LPA_100HALF			0x0080	/* Can do 100mbps half-duplex */ | ||||
| #define MII_LPA_100FULL			0x0100	/* Can do 100mbps full-duplex */ | ||||
| #define MII_LPA_100BASE4		0x0200	/* 100BASE-T4 */ | ||||
| #define MII_LPA_PAUSE			0x0400	/* PAUSE */ | ||||
| #define MII_LPA_ASYPAUSE		0x0800	/* Asymmetrical PAUSE */ | ||||
| #define MII_LPA_RFAULT			0x2000	/* Link partner faulted */ | ||||
| #define MII_LPA_LPACK			0x4000	/* Link partner acked us */ | ||||
| #define MII_LPA_NPAGE			0x8000	/* Next page bit */ | ||||
| 
 | ||||
| /* Autoneg Advertisement Register */ | ||||
| #define MII_AR_SELECTOR_FIELD		0x0001	/* IEEE 802.3 CSMA/CD */ | ||||
| #define MII_AR_10T_HD_CAPS		0x0020	/* 10T   Half Duplex Capable */ | ||||
| #define MII_AR_10T_FD_CAPS		0x0040	/* 10T   Full Duplex Capable */ | ||||
| #define MII_AR_100TX_HD_CAPS		0x0080	/* 100TX Half Duplex Capable */ | ||||
| #define MII_AR_100TX_FD_CAPS		0x0100	/* 100TX Full Duplex Capable */ | ||||
| #define MII_AR_100T4_CAPS		0x0200	/* 100T4 Capable */ | ||||
| #define MII_AR_PAUSE			0x0400	/* Pause operation desired */ | ||||
| #define MII_AR_ASM_DIR			0x0800	/* Asymmetric Pause Dir bit */ | ||||
| #define MII_AR_REMOTE_FAULT		0x2000	/* Remote Fault detected */ | ||||
| #define MII_AR_NEXT_PAGE		0x8000	/* Next Page ability support */ | ||||
| #define MII_AR_SPEED_MASK		0x01E0 | ||||
| #define MII_AR_DEFAULT_CAP_MASK		0x0DE0 | ||||
| 
 | ||||
| /* 1000BASE-T Control Register */ | ||||
| #define MII_ATLX_CR_1000T_HD_CAPS	0x0100	/* Adv 1000T HD cap */ | ||||
| #define MII_ATLX_CR_1000T_FD_CAPS	0x0200	/* Adv 1000T FD cap */ | ||||
| #define MII_ATLX_CR_1000T_REPEATER_DTE	0x0400	/* 1=Repeater/switch device, | ||||
| 						 * 0=DTE device */ | ||||
| #define MII_ATLX_CR_1000T_MS_VALUE	0x0800	/* 1=Config PHY as Master, | ||||
| 						 * 0=Configure PHY as Slave */ | ||||
| #define MII_ATLX_CR_1000T_MS_ENABLE	0x1000	/* 1=Man Master/Slave config, | ||||
| 						 * 0=Auto Master/Slave config | ||||
| 						 */ | ||||
| #define MII_ATLX_CR_1000T_TEST_MODE_NORMAL	0x0000	/* Normal Operation */ | ||||
| #define MII_ATLX_CR_1000T_TEST_MODE_1	0x2000	/* Transmit Waveform test */ | ||||
| #define MII_ATLX_CR_1000T_TEST_MODE_2	0x4000	/* Master Xmit Jitter test */ | ||||
| #define MII_ATLX_CR_1000T_TEST_MODE_3	0x6000	/* Slave Xmit Jitter test */ | ||||
| #define MII_ATLX_CR_1000T_TEST_MODE_4	0x8000	/* Xmitter Distortion test */ | ||||
| #define MII_ATLX_CR_1000T_SPEED_MASK	0x0300 | ||||
| #define MII_ATLX_CR_1000T_DEFAULT_CAP_MASK	0x0300 | ||||
| 
 | ||||
| /* 1000BASE-T Status Register */ | ||||
| #define MII_ATLX_SR_1000T_LP_HD_CAPS	0x0400	/* LP is 1000T HD capable */ | ||||
| #define MII_ATLX_SR_1000T_LP_FD_CAPS	0x0800	/* LP is 1000T FD capable */ | ||||
| #define MII_ATLX_SR_1000T_REMOTE_RX_STATUS	0x1000	/* Remote receiver OK */ | ||||
| #define MII_ATLX_SR_1000T_LOCAL_RX_STATUS	0x2000	/* Local receiver OK */ | ||||
| #define MII_ATLX_SR_1000T_MS_CONFIG_RES		0x4000	/* 1=Local TX is Master | ||||
| 							 * 0=Slave | ||||
| 							 */ | ||||
| #define MII_ATLX_SR_1000T_MS_CONFIG_FAULT	0x8000	/* Master/Slave config | ||||
| 							 * fault */ | ||||
| #define MII_ATLX_SR_1000T_REMOTE_RX_STATUS_SHIFT	12 | ||||
| #define MII_ATLX_SR_1000T_LOCAL_RX_STATUS_SHIFT		13 | ||||
| 
 | ||||
| /* Extended Status Register */ | ||||
| #define MII_ATLX_ESR_1000T_HD_CAPS	0x1000	/* 1000T HD capable */ | ||||
| #define MII_ATLX_ESR_1000T_FD_CAPS	0x2000	/* 1000T FD capable */ | ||||
| #define MII_ATLX_ESR_1000X_HD_CAPS	0x4000	/* 1000X HD capable */ | ||||
| #define MII_ATLX_ESR_1000X_FD_CAPS	0x8000	/* 1000X FD capable */ | ||||
| 
 | ||||
| /* ATLX PHY Specific Control Register */ | ||||
| #define MII_ATLX_PSCR_JABBER_DISABLE	0x0001	/* 1=Jabber Func disabled */ | ||||
| #define MII_ATLX_PSCR_POLARITY_REVERSAL	0x0002	/* 1=Polarity Reversal enbld */ | ||||
| #define MII_ATLX_PSCR_SQE_TEST		0x0004	/* 1=SQE Test enabled */ | ||||
| #define MII_ATLX_PSCR_MAC_POWERDOWN	0x0008 | ||||
| #define MII_ATLX_PSCR_CLK125_DISABLE	0x0010	/* 1=CLK125 low | ||||
| 						 * 0=CLK125 toggling | ||||
| 						 */ | ||||
| #define MII_ATLX_PSCR_MDI_MANUAL_MODE	0x0000	/* MDI Crossover Mode bits 6:5, | ||||
| 						 * Manual MDI configuration | ||||
| 						 */ | ||||
| #define MII_ATLX_PSCR_MDIX_MANUAL_MODE	0x0020	/* Manual MDIX configuration */ | ||||
| #define MII_ATLX_PSCR_AUTO_X_1000T	0x0040	/* 1000BASE-T: Auto crossover | ||||
| 						 * 100BASE-TX/10BASE-T: MDI | ||||
| 						 * Mode */ | ||||
| #define MII_ATLX_PSCR_AUTO_X_MODE	0x0060	/* Auto crossover enabled | ||||
| 						 * all speeds. | ||||
| 						 */ | ||||
| #define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE	0x0080	/* 1=Enable Extended | ||||
| 							 * 10BASE-T distance | ||||
| 							 * (Lower 10BASE-T RX | ||||
| 							 * Threshold) | ||||
| 							 * 0=Normal 10BASE-T RX | ||||
| 							 * Threshold | ||||
| 							 */ | ||||
| #define MII_ATLX_PSCR_MII_5BIT_ENABLE	0x0100	/* 1=5-Bit interface in | ||||
| 						 * 100BASE-TX | ||||
| 						 * 0=MII interface in | ||||
| 						 * 100BASE-TX | ||||
| 						 */ | ||||
| #define MII_ATLX_PSCR_SCRAMBLER_DISABLE	0x0200	/* 1=Scrambler dsbl */ | ||||
| #define MII_ATLX_PSCR_FORCE_LINK_GOOD	0x0400	/* 1=Force link good */ | ||||
| #define MII_ATLX_PSCR_ASSERT_CRS_ON_TX	0x0800	/* 1=Assert CRS on Transmit */ | ||||
| #define MII_ATLX_PSCR_POLARITY_REVERSAL_SHIFT		1 | ||||
| #define MII_ATLX_PSCR_AUTO_X_MODE_SHIFT			5 | ||||
| #define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE_SHIFT	7 | ||||
| 
 | ||||
| /* ATLX PHY Specific Status Register */ | ||||
| #define MII_ATLX_PSSR_SPD_DPLX_RESOLVED	0x0800	/* 1=Speed & Duplex resolved */ | ||||
| #define MII_ATLX_PSSR_DPLX		0x2000	/* 1=Duplex 0=Half Duplex */ | ||||
| #define MII_ATLX_PSSR_SPEED		0xC000	/* Speed, bits 14:15 */ | ||||
| #define MII_ATLX_PSSR_10MBS		0x0000	/* 00=10Mbs */ | ||||
| #define MII_ATLX_PSSR_100MBS		0x4000	/* 01=100Mbs */ | ||||
| #define MII_ATLX_PSSR_1000MBS		0x8000	/* 10=1000Mbs */ | ||||
| 
 | ||||
| #define MII_DBG_ADDR			0x1D | ||||
| #define MII_DBG_DATA			0x1E | ||||
| 
 | ||||
| /* PCI Command Register Bit Definitions */ | ||||
| #define PCI_REG_COMMAND			0x04	/* PCI Command Register */ | ||||
| #define CMD_IO_SPACE			0x0001 | ||||
| #define CMD_MEMORY_SPACE		0x0002 | ||||
| #define CMD_BUS_MASTER			0x0004 | ||||
| 
 | ||||
| /* Wake Up Filter Control */ | ||||
| #define ATLX_WUFC_LNKC	0x00000001	/* Link Status Change Wakeup Enable */ | ||||
| #define ATLX_WUFC_MAG	0x00000002	/* Magic Packet Wakeup Enable */ | ||||
| #define ATLX_WUFC_EX	0x00000004	/* Directed Exact Wakeup Enable */ | ||||
| #define ATLX_WUFC_MC	0x00000008	/* Multicast Wakeup Enable */ | ||||
| #define ATLX_WUFC_BC	0x00000010	/* Broadcast Wakeup Enable */ | ||||
| 
 | ||||
| #define ADVERTISE_10_HALF		0x0001 | ||||
| #define ADVERTISE_10_FULL		0x0002 | ||||
| #define ADVERTISE_100_HALF		0x0004 | ||||
| #define ADVERTISE_100_FULL		0x0008 | ||||
| #define ADVERTISE_1000_HALF		0x0010 | ||||
| #define ADVERTISE_1000_FULL		0x0020 | ||||
| #define AUTONEG_ADVERTISE_10_100_ALL	0x000F	/* All 10/100 speeds */ | ||||
| #define AUTONEG_ADVERTISE_10_ALL	0x0003	/* 10Mbps Full & Half speeds */ | ||||
| 
 | ||||
| #define PHY_AUTO_NEG_TIME		45	/* 4.5 Seconds */ | ||||
| #define PHY_FORCE_TIME			20	/* 2.0 Seconds */ | ||||
| 
 | ||||
| /* For checksumming, the sum of all words in the EEPROM should equal 0xBABA */ | ||||
| #define EEPROM_SUM			0xBABA | ||||
| 
 | ||||
| struct atlx_spi_flash_dev { | ||||
| 	const char *manu_name;	/* manufacturer id */ | ||||
| 	/* op-code */ | ||||
| 	u8 cmd_wrsr; | ||||
| 	u8 cmd_read; | ||||
| 	u8 cmd_program; | ||||
| 	u8 cmd_wren; | ||||
| 	u8 cmd_wrdi; | ||||
| 	u8 cmd_rdsr; | ||||
| 	u8 cmd_rdid; | ||||
| 	u8 cmd_sector_erase; | ||||
| 	u8 cmd_chip_erase; | ||||
| }; | ||||
| 
 | ||||
| #endif /* ATLX_H */ | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 awab228
						awab228