linux.kernel

[patch net-next]alx: Atheros AR8131/AR8151/AR8152/AR8161 Ethernet driver


alx: Atheros AR8131/AR8151/AR8152/AR8161 Ethernet driver
It is able to support Atheros AR8131/AR8151/AR8152/AR8161 ethernet adapter.
Signed-off-by: cloud ren <cloud.ren_at_atheros.com>
---
diff --git a/drivers/net/ethernet/atheros/Kconfig b/drivers/net/ethernet/atheros/Kconfig
index 1ed886d..24976ea 100644
--- a/drivers/net/ethernet/atheros/Kconfig
+++ b/drivers/net/ethernet/atheros/Kconfig
_at__at_ -67,4 +67,17 _at__at_ config ATL1C
To compile this driver as a module, choose M here. The module
will be called atl1c.

+config ALX
+ tristate "Atheros ALX Gigabit Ethernet support (EXPERIMENTAL)"
+ depends on PCI && EXPERIMENTAL
+ select CRC32
+ select NET_CORE
+ select MII
+ ---help---
+ This driver supports the Atheros L1C/L1D/L1F gigabit ethernet
+ adapter.
+
+ To compile this driver as a module, choose M here. The module
+ will be called atl1c.
+
endif # NET_VENDOR_ATHEROS
diff --git a/drivers/net/ethernet/atheros/Makefile b/drivers/net/ethernet/atheros/Makefile
index e7e76fb..5cf1c65 100644
--- a/drivers/net/ethernet/atheros/Makefile
+++ b/drivers/net/ethernet/atheros/Makefile
_at__at_ -6,3 +6,4 _at__at_ obj-$(CONFIG_ATL1) += atlx/
obj-$(CONFIG_ATL2) += atlx/
obj-$(CONFIG_ATL1E) += atl1e/
obj-$(CONFIG_ATL1C) += atl1c/
+obj-$(CONFIG_ALX) += alx/
diff --git a/drivers/net/ethernet/atheros/alx/Makefile b/drivers/net/ethernet/atheros/alx/Makefile
new file mode 100755
index 0000000..62b054e
--- /dev/null
+++ b/drivers/net/ethernet/atheros/alx/Makefile
_at__at_ -0,0 +1,2 _at__at_
+obj-$(CONFIG_ALX) += alx.o
+alx-objs := alx_main.o alx_ethtool.o alc_cb.o alc_hw.o alf_cb.o alf_hw.o
diff --git a/drivers/net/ethernet/atheros/alx/alc_cb.c b/drivers/net/ethernet/atheros/alx/alc_cb.c
new file mode 100755
index 0000000..77f9005
--- /dev/null
+++ b/drivers/net/ethernet/atheros/alx/alc_cb.c
_at__at_ -0,0 +1,1006 _at__at_
+/*
+ * Copyright (c) 2010 - 2011 Atheros Communications 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 "alc_hw.h"
+
+
+/* NIC */
+int alc_identify_nic(struct alx_hw *hw)
+{
+ return 0;
+}
+
+/* PHY */
+int alc_read_phy_reg(struct alx_hw *hw, u32 device_type,
+ u16 reg_addr, u16 *phy_data)
+{
+ bool fast = false;
+ bool ext = false;
+ u16 error;
+ int retval = 0;
+
+ ALX_MDIO_LOCK(&hw->mdio_lock);
+
+ if (device_type != ALX_MDIO_NORM_DEV)
+ ext = true;
+
+ error = l1c_read_phy(hw, ext, device_type, fast,
+ reg_addr, phy_data);
+ if (error) {
+ ALX_HW_ERR("Error when reading phy reg (%d).", error);
+ retval = ALX_ERR_PHY_READ_REG;
+ }
+
+ ALX_MDIO_UNLOCK(&hw->mdio_lock);
+
+ return retval;
+}
+
+int alc_write_phy_reg(struct alx_hw *hw, u32 device_type,
+ u16 reg_addr, u16 phy_data)
+{
+ bool fast = false;
+ bool ext = false;
+ u16 error;
+ int retval = 0;
+
+ ALX_MDIO_LOCK(&hw->mdio_lock);
+
+ if (device_type != ALX_MDIO_NORM_DEV)
+ ext = true;
+
+ error = l1c_write_phy(hw, ext, device_type, fast, reg_addr, phy_data);
+ if (error) {
+ ALX_HW_ERR("Error when writting phy reg (%d).", error);
+ retval = ALX_ERR_PHY_WRITE_REG;
+ }
+
+ ALX_MDIO_UNLOCK(&hw->mdio_lock);
+
+ return retval;
+}
+
+
+int alc_init_phy(struct alx_hw *hw)
+{
+ u16 phy_id[2];
+ int retval;
+
+ ALX_HW_DBG("ENTER\n");
+
+ /* 1. init mdio spin lock */
+ ALX_MDIO_LOCK_INIT(&hw->mdio_lock);
+
+ /* 2. read phy id */
+ retval = alc_read_phy_reg(hw, ALX_MDIO_NORM_DEV,
+ L1C_MII_PHYSID1, &phy_id[0]);
+ if (retval)
+ return retval;
+ retval = alc_read_phy_reg(hw, ALX_MDIO_NORM_DEV,
+ L1C_MII_PHYSID1, &phy_id[1]);
+ if (retval)
+ return retval;
+
+ memcpy(&hw->phy_id, phy_id, sizeof(hw->phy_id));
+
+ hw->autoneg_advertised = ALX_LINK_SPEED_1GB_FULL |
+ ALX_LINK_SPEED_10_HALF |
+ ALX_LINK_SPEED_10_FULL |
+ ALX_LINK_SPEED_100_HALF |
+ ALX_LINK_SPEED_100_FULL;
+ return retval;
+}
+
+
+int alc_reset_phy(struct alx_hw *hw)
+{
+ int retval = 0;
+ bool pws_en, az_en, ptp_en;
+
+ ALX_HW_DBG("ENTER\n");
+
+ pws_en = az_en = ptp_en = false;
+ CLI_HW_FLAG(PWSAVE_EN);
+ CLI_HW_FLAG(AZ_EN);
+ CLI_HW_FLAG(PTP_EN);
+
+ if (CHK_HW_FLAG(PWSAVE_CAP)) {
+ pws_en = true;
+ SET_HW_FLAG(PWSAVE_EN);
+ }
+
+ if (CHK_HW_FLAG(AZ_CAP)) {
+ az_en = true;
+ SET_HW_FLAG(AZ_EN);
+ }
+
+ if (CHK_HW_FLAG(PTP_CAP)) {
+ ptp_en = true;
+ SET_HW_FLAG(PTP_EN);
+ }
+
+ ALX_HW_INFO("reset PHY, pws = %d, az = %d, ptp = %d\n",
+ pws_en, az_en, ptp_en);
+
+ if (l1c_reset_phy(hw, pws_en, az_en, ptp_en))
+ retval = ALX_ERR_PHY_RESET;
+
+ return retval;
+}
+
+/* LINK */
+int alc_setup_phy_link(struct alx_hw *hw, u32 speed, bool autoneg, bool fc)
+{
+ u8 link_cap = 0;
+ int retval = 0;
+
+ ALX_HW_DBG("ENTER\n");
+
+ ALX_HW_INFO("speed = 0x%x, autoneg = %d\n", speed, autoneg);
+ if (speed & ALX_LINK_SPEED_1GB_FULL)
+ link_cap |= LX_LC_1000F;
+
+ if (speed & ALX_LINK_SPEED_100_FULL)
+ link_cap |= LX_LC_100F;
+
+ if (speed & ALX_LINK_SPEED_100_HALF)
+ link_cap |= LX_LC_100H;
+
+ if (speed & ALX_LINK_SPEED_10_FULL)
+ link_cap |= LX_LC_10F;
+
+ if (speed & ALX_LINK_SPEED_10_HALF)
+ link_cap |= LX_LC_10H;
+
+ if (l1c_init_phy_spdfc(hw, autoneg, link_cap, fc))
+ retval = ALX_ERR_PHY_SETUP_LNK;
+
+ return retval;
+}
+
+
+
+int alc_setup_phy_link_speed(struct alx_hw *hw, u32 speed,
+ bool autoneg, bool fc)
+{
+ int retval = 0;
+
+ ALX_HW_DBG("ENTER\n");
+
+ /*
+ * Clear autoneg_advertised and set new values based on input link
+ * speed.
+ */
+ hw->autoneg_advertised = 0;
+
+ if (speed & ALX_LINK_SPEED_1GB_FULL)
+ hw->autoneg_advertised |= ALX_LINK_SPEED_1GB_FULL;
+
+ if (speed & ALX_LINK_SPEED_100_FULL)
+ hw->autoneg_advertised |= ALX_LINK_SPEED_100_FULL;
+
+ if (speed & ALX_LINK_SPEED_100_HALF)
+ hw->autoneg_advertised |= ALX_LINK_SPEED_100_HALF;
+
+ if (speed & ALX_LINK_SPEED_10_FULL)
+ hw->autoneg_advertised |= ALX_LINK_SPEED_10_FULL;
+
+ if (speed & ALX_LINK_SPEED_10_HALF)
+ hw->autoneg_advertised |= ALX_LINK_SPEED_10_HALF;
+
+ retval = alc_setup_phy_link(hw, hw->autoneg_advertised,
+ autoneg, fc);
+ return retval;
+
+
+}
+
+
+
+int alc_check_phy_link(struct alx_hw *hw, u32 *speed, bool *link_up)
+{



Written by 20/10/2011 8.50.01
Check some pics on this site!
25/05/2012 5.14.57