Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

alc(4) support for Atheros AR815x

12 views
Skip to first unread message

Kevin Lo

unread,
Jan 25, 2011, 5:24:28 AM1/25/11
to
Hi,

The following diff adds support for Atheros AR8151/AR8152 chipsets;
mostly from FreeBSD. It also fixes an issue i386/6311.
Tested on Acer AOD255E.

Index: share/man/man4/alc.4
===================================================================
RCS file: /cvs/src/share/man/man4/alc.4,v
retrieving revision 1.2
diff -u -p -r1.2 alc.4
--- share/man/man4/alc.4 8 Aug 2009 14:12:41 -0000 1.2
+++ share/man/man4/alc.4 25 Jan 2011 10:19:48 -0000
@@ -19,7 +19,7 @@
.Os
.Sh NAME
.Nm alc
-.Nd Atheros AR8131/AR8132 10/100/Gigabit Ethernet device
+.Nd Atheros AR813x/AR815x 10/100/Gigabit Ethernet device
.Sh SYNOPSIS
.Cd "alc* at pci?"
.Cd "atphy* at mii?"
@@ -27,8 +27,7 @@
The
.Nm
driver provides support for Ethernet interfaces based on the
-Atheros AR8131/AR8132 Ethernet chipset, also known as
-the Attansic L1C/L2C respectively.
+Atheros AR813x/AR815x Ethernet chipset.
.Pp
The
.Nm
Index: sys/arch/amd64/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v
retrieving revision 1.312
diff -u -p -r1.312 GENERIC
--- sys/arch/amd64/conf/GENERIC 8 Jan 2011 11:56:30 -0000 1.312
+++ sys/arch/amd64/conf/GENERIC 25 Jan 2011 10:19:49 -0000
@@ -473,7 +473,7 @@ gem* at pci? # Sun 'gem' ethernet
vic* at pci? # VMware VMXnet virtual interface
et* at pci? # Agere/LSI ET1310
age* at pci? # Attansic L1 Ethernet
-alc* at pci? # Attansic L1C/L2C Ethernet
+alc* at pci? # Attansic L1C/L1D/L2C Ethernet
ale* at pci? # Attansic L1E Ethernet
lii* at pci? # Attansic L2 Ethernet
jme* at pci? # JMicron JMC250/JMC260 Ethernet
Index: sys/arch/amd64/conf/RAMDISK_CD
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/RAMDISK_CD,v
retrieving revision 1.115
diff -u -p -r1.115 RAMDISK_CD
--- sys/arch/amd64/conf/RAMDISK_CD 4 Aug 2010 21:44:41 -0000 1.115
+++ sys/arch/amd64/conf/RAMDISK_CD 25 Jan 2011 10:19:49 -0000
@@ -291,7 +291,7 @@ xge* at pci? # Neterion Xframe-I/II 10
vic* at pci? # VMware VMXnet virtual interface
et* at pci? # Agere/LSI ET1310
age* at pci? # Attansic L1 Ethernet
-alc* at pci? # Attansic L1C/L2C Ethernet
+alc* at pci? # Attansic L1C/L1D/L2C Ethernet
ale* at pci? # Attansic L1E Ethernet
lii* at pci? # Attansic L2 Ethernet
jme* at pci? # JMicron JMC250/JMC260 Ethernet
Index: sys/arch/i386/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/i386/conf/GENERIC,v
retrieving revision 1.708
diff -u -p -r1.708 GENERIC
--- sys/arch/i386/conf/GENERIC 15 Jan 2011 04:39:27 -0000 1.708
+++ sys/arch/i386/conf/GENERIC 25 Jan 2011 10:19:50 -0000
@@ -634,7 +634,7 @@ gem* at pci? # Sun 'gem' ethernet
vic* at pci? # VMware VMXnet virtual interface
et* at pci? # Agere/LSI ET1310
age* at pci? # Attansic L1 Ethernet
-alc* at pci? # Attansic L1C/L2C Ethernet
+alc* at pci? # Attansic L1C/L1D/L2C Ethernet
ale* at pci? # Attansic L1E Ethernet
lii* at pci? # Attansic L2 Ethernet
jme* at pci? # JMicron JMC250/JMC260 Ethernet
Index: sys/arch/i386/conf/RAMDISK_CD
===================================================================
RCS file: /cvs/src/sys/arch/i386/conf/RAMDISK_CD,v
retrieving revision 1.183
diff -u -p -r1.183 RAMDISK_CD
--- sys/arch/i386/conf/RAMDISK_CD 15 Jan 2011 04:39:27 -0000 1.183
+++ sys/arch/i386/conf/RAMDISK_CD 25 Jan 2011 10:19:51 -0000
@@ -372,7 +372,7 @@ xge* at pci? # Neterion Xframe-I/II 1
vic* at pci? # VMware VMXnet virtual interface
et* at pci? # Agere/LSI ET1310
age* at pci? # Attansic L1 Ethernet
-alc* at pci? # Attansic L1C/L2C Ethernet
+alc* at pci? # Attansic L1C/L1D/L2C Ethernet
ale* at pci? # Attansic L1E Ethernet
lii* at pci? # Attansic L2 Ethernet
jme* at pci? # JMicron JMC250/JMC260 Ethernet
Index: sys/dev/pci/files.pci
===================================================================
RCS file: /cvs/src/sys/dev/pci/files.pci,v
retrieving revision 1.277
diff -u -p -r1.277 files.pci
--- sys/dev/pci/files.pci 15 Jan 2011 04:35:34 -0000 1.277
+++ sys/dev/pci/files.pci 25 Jan 2011 10:19:54 -0000
@@ -643,7 +643,7 @@ device age: ether, ifnet, mii, ifmedia,
attach age at pci
file dev/pci/if_age.c age

-# Attansic/Atheros L1C/L2C Gigabit Ethernet
+# Attansic/Atheros L1C/L1D/L2C Gigabit Ethernet
device alc: ether, ifnet, mii, ifmedia, mii_phy
attach alc at pci
file dev/pci/if_alc.c alc
Index: sys/dev/pci/if_alc.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_alc.c,v
retrieving revision 1.8
diff -u -p -r1.8 if_alc.c
--- sys/dev/pci/if_alc.c 31 Aug 2010 17:13:44 -0000 1.8
+++ sys/dev/pci/if_alc.c 25 Jan 2011 10:19:55 -0000
@@ -88,7 +88,7 @@ void alc_watchdog(struct ifnet *);
int alc_mediachange(struct ifnet *);
void alc_mediastatus(struct ifnet *, struct ifmediareq *);

-void alc_aspm(struct alc_softc *);
+void alc_aspm(struct alc_softc *, int);
void alc_disable_l0s_l1(struct alc_softc *);
int alc_dma_alloc(struct alc_softc *);
void alc_dma_free(struct alc_softc *);
@@ -109,7 +109,7 @@ void alc_phy_down(struct alc_softc *);
void alc_phy_reset(struct alc_softc *);
void alc_reset(struct alc_softc *);
void alc_rxeof(struct alc_softc *, struct rx_rdesc *);
-int alc_rxintr(struct alc_softc *);
+void alc_rxintr(struct alc_softc *);
void alc_iff(struct alc_softc *);
void alc_rxvlan(struct alc_softc *);
void alc_start_queue(struct alc_softc *);
@@ -125,7 +125,11 @@ uint32_t alc_dma_burst[] = { 128, 256, 5

const struct pci_matchid alc_devices[] = {
{ PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L1C },
- { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2C }
+ { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2C },
+ { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L1D },
+ { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L1D_1 },
+ { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2C_1 },
+ { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2C_2 }
};

struct cfattach alc_ca = {
@@ -236,8 +240,8 @@ alc_miibus_statchg(struct device *dev)
reg = CSR_READ_4(sc, ALC_MAC_CFG);
reg |= MAC_CFG_TX_ENB | MAC_CFG_RX_ENB;
CSR_WRITE_4(sc, ALC_MAC_CFG, reg);
+ alc_aspm(sc, IFM_SUBTYPE(mii->mii_media_active));
}
- alc_aspm(sc);
}

void
@@ -280,20 +284,53 @@ void
alc_get_macaddr(struct alc_softc *sc)
{
uint32_t ea[2], opt;
- int i;
+ uint16_t val;
+ int eeprom, i;

+ eeprom = 0;
opt = CSR_READ_4(sc, ALC_OPT_CFG);
- if ((CSR_READ_4(sc, ALC_TWSI_DEBUG) & TWSI_DEBUG_DEV_EXIST) != 0) {
+ if ((CSR_READ_4(sc, ALC_MASTER_CFG) & MASTER_OTP_SEL) != 0 &&
+ (CSR_READ_4(sc, ALC_TWSI_DEBUG) & TWSI_DEBUG_DEV_EXIST) != 0) {
/*
* EEPROM found, let TWSI reload EEPROM configuration.
* This will set ethernet address of controller.
*/
- if ((opt & OPT_CFG_CLK_ENB) == 0) {
- opt |= OPT_CFG_CLK_ENB;
- CSR_WRITE_4(sc, ALC_OPT_CFG, opt);
- CSR_READ_4(sc, ALC_OPT_CFG);
- DELAY(1000);
+ eeprom++;
+ switch (sc->sc_product) {
+ case PCI_PRODUCT_ATTANSIC_L1C:
+ case PCI_PRODUCT_ATTANSIC_L2C:
+ if ((opt & OPT_CFG_CLK_ENB) == 0) {
+ opt |= OPT_CFG_CLK_ENB;
+ CSR_WRITE_4(sc, ALC_OPT_CFG, opt);
+ CSR_READ_4(sc, ALC_OPT_CFG);
+ DELAY(1000);
+ }
+ break;
+ case PCI_PRODUCT_ATTANSIC_L1D:
+ case PCI_PRODUCT_ATTANSIC_L1D_1:
+ case PCI_PRODUCT_ATTANSIC_L2C_1:
+ case PCI_PRODUCT_ATTANSIC_L2C_2:
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_ADDR, 0x00);
+ val = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA);
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA, val & 0xFF7F);
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_ADDR, 0x3B);
+ val = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA);
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA, val | 0x0008);
+ DELAY(20);
+ break;
}
+
+ CSR_WRITE_4(sc, ALC_LTSSM_ID_CFG,
+ CSR_READ_4(sc, ALC_LTSSM_ID_CFG) & ~LTSSM_ID_WRO_ENB);
+ CSR_WRITE_4(sc, ALC_WOL_CFG, 0);
+ CSR_READ_4(sc, ALC_WOL_CFG);
+
CSR_WRITE_4(sc, ALC_TWSI_CFG, CSR_READ_4(sc, ALC_TWSI_CFG) |
TWSI_CFG_SW_LD_START);
for (i = 100; i > 0; i--) {
@@ -309,11 +346,36 @@ alc_get_macaddr(struct alc_softc *sc)
if (alcdebug)
printf("%s: EEPROM not found!\n", sc->sc_dev.dv_xname);
}
- if ((opt & OPT_CFG_CLK_ENB) != 0) {
- opt &= ~OPT_CFG_CLK_ENB;
- CSR_WRITE_4(sc, ALC_OPT_CFG, opt);
- CSR_READ_4(sc, ALC_OPT_CFG);
- DELAY(1000);
+ if (eeprom != 0) {
+ switch (sc->sc_product) {
+ case PCI_PRODUCT_ATTANSIC_L1C:
+ case PCI_PRODUCT_ATTANSIC_L2C:
+ if ((opt & OPT_CFG_CLK_ENB) != 0) {
+ opt &= ~OPT_CFG_CLK_ENB;
+ CSR_WRITE_4(sc, ALC_OPT_CFG, opt);
+ CSR_READ_4(sc, ALC_OPT_CFG);
+ DELAY(1000);
+ }
+ break;
+ case PCI_PRODUCT_ATTANSIC_L1D:
+ case PCI_PRODUCT_ATTANSIC_L1D_1:
+ case PCI_PRODUCT_ATTANSIC_L2C_1:
+ case PCI_PRODUCT_ATTANSIC_L2C_2:
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_ADDR, 0x00);
+ val = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA);
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA, val | 0x0080);
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_ADDR, 0x3B);
+ val = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA);
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA, val & 0xFFF7);
+ DELAY(20);
+ break;
+ }
}

ea[0] = CSR_READ_4(sc, ALC_PAR0);
@@ -358,6 +420,43 @@ alc_phy_reset(struct alc_softc *sc)
CSR_READ_2(sc, ALC_GPHY_CFG);
DELAY(10 * 1000);

+ /* DSP fixup, Vendor magic. */
+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1) {
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_ADDR, 0x000A);
+ data = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA);
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA, data & 0xDFFF);
+ }
+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2) {
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_ADDR, 0x003B);
+ data = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA);
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA, data & 0xFFF7);
+ DELAY(20 * 1000);
+ }
+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D) {
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_ADDR, 0x0029);
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA, 0x929D);
+ }
+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1C ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2) {
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_ADDR, 0x0029);
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA, 0xB6DD);
+ }
+
/* Load DSP codes, vendor magic. */
data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
((1 << ANA_INTERVAL_SEL_TIMER_SHIFT) &
ANA_INTERVAL_SEL_TIMER_MASK);
@@ -406,35 +505,114 @@ alc_phy_reset(struct alc_softc *sc)
void
alc_phy_down(struct alc_softc *sc)
{
-
- /* Force PHY down. */
- CSR_WRITE_2(sc, ALC_GPHY_CFG,
- GPHY_CFG_EXT_RESET | GPHY_CFG_HIB_EN | GPHY_CFG_HIB_PULSE |
- GPHY_CFG_SEL_ANA_RESET | GPHY_CFG_PHY_IDDQ | GPHY_CFG_PWDOWN_HW);
- DELAY(1000);
+ switch (sc->sc_product) {
+ case PCI_PRODUCT_ATTANSIC_L1D:
+ case PCI_PRODUCT_ATTANSIC_L1D_1:
+ /*
+ * GPHY power down caused more problems on AR8151 v2.0.
+ * When driver is reloaded after GPHY power down,
+ * accesses to PHY/MAC registers hung the system. Only
+ * cold boot recovered from it. I'm not sure whether
+ * AR8151 v1.0 also requires this one though. I don't
+ * have AR8151 v1.0 controller in hand.
+ * The only option left is to isolate the PHY and
+ * initiates power down the PHY which in turn saves
+ * more power when driver is unloaded.
+ */
+ alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
+ MII_BMCR, BMCR_ISO | BMCR_PDOWN);
+ break;
+ default:
+ /* Force PHY down. */
+ CSR_WRITE_2(sc, ALC_GPHY_CFG,
+ GPHY_CFG_EXT_RESET | GPHY_CFG_HIB_EN | GPHY_CFG_HIB_PULSE |
+ GPHY_CFG_SEL_ANA_RESET | GPHY_CFG_PHY_IDDQ |
+ GPHY_CFG_PWDOWN_HW);
+ DELAY(1000);
+ break;
+ }
}

void
-alc_aspm(struct alc_softc *sc)
+alc_aspm(struct alc_softc *sc, int media)
{
uint32_t pmcfg;
+ uint16_t linkcfg;

pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
+ if ((sc->alc_flags & (ALC_FLAG_APS | ALC_FLAG_PCIE)) ==
+ (ALC_FLAG_APS | ALC_FLAG_PCIE))
+ linkcfg = CSR_READ_2(sc, sc->alc_expcap +
+ PCI_PCIE_LCSR);
+ else
+ linkcfg = 0;
pmcfg &= ~PM_CFG_SERDES_PD_EX_L1;
- pmcfg |= PM_CFG_SERDES_BUDS_RX_L1_ENB;
- pmcfg |= PM_CFG_SERDES_L1_ENB;
- pmcfg &= ~PM_CFG_L1_ENTRY_TIMER_MASK;
+ pmcfg &= ~(PM_CFG_L1_ENTRY_TIMER_MASK | PM_CFG_LCKDET_TIMER_MASK);
pmcfg |= PM_CFG_MAC_ASPM_CHK;
+ pmcfg |= (PM_CFG_LCKDET_TIMER_DEFAULT << PM_CFG_LCKDET_TIMER_SHIFT);
+ pmcfg &= ~(PM_CFG_ASPM_L1_ENB | PM_CFG_ASPM_L0S_ENB);
+
+ if ((sc->alc_flags & ALC_FLAG_APS) != 0) {
+ /* Disable extended sync except AR8152 B v1.0 */
+ linkcfg &= ~0x80;
+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 &&
+ sc->alc_rev == ATHEROS_AR8152_B_V10)
+ linkcfg |= 0x80;
+ CSR_WRITE_2(sc, sc->alc_expcap + PCI_PCIE_LCSR,
+ linkcfg);
+ pmcfg &= ~(PM_CFG_EN_BUFS_RX_L0S | PM_CFG_SA_DLY_ENB |
+ PM_CFG_HOTRST);
+ pmcfg |= (PM_CFG_L1_ENTRY_TIMER_DEFAULT <<
+ PM_CFG_L1_ENTRY_TIMER_SHIFT);
+ pmcfg &= ~PM_CFG_PM_REQ_TIMER_MASK;
+ pmcfg |= (PM_CFG_PM_REQ_TIMER_DEFAULT <<
+ PM_CFG_PM_REQ_TIMER_SHIFT);
+ pmcfg |= PM_CFG_SERDES_PD_EX_L1 | PM_CFG_PCIE_RECV;
+ }
+
if ((sc->alc_flags & ALC_FLAG_LINK) != 0) {
- pmcfg |= PM_CFG_SERDES_PLL_L1_ENB;
- pmcfg &= ~PM_CFG_CLK_SWH_L1;
- pmcfg &= ~PM_CFG_ASPM_L1_ENB;
- pmcfg &= ~PM_CFG_ASPM_L0S_ENB;
+ if ((sc->alc_flags & ALC_FLAG_L0S) != 0)
+ pmcfg |= PM_CFG_ASPM_L0S_ENB;
+ if ((sc->alc_flags & ALC_FLAG_L1S) != 0)
+ pmcfg |= PM_CFG_ASPM_L1_ENB;
+ if ((sc->alc_flags & ALC_FLAG_APS) != 0) {
+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1)
+ pmcfg &= ~PM_CFG_ASPM_L0S_ENB;
+ pmcfg &= ~(PM_CFG_SERDES_L1_ENB |
+ PM_CFG_SERDES_PLL_L1_ENB |
+ PM_CFG_SERDES_BUDS_RX_L1_ENB);
+ pmcfg |= PM_CFG_CLK_SWH_L1;
+ if (media == IFM_100_TX || media == IFM_1000_T) {
+ pmcfg &= ~PM_CFG_L1_ENTRY_TIMER_MASK;
+ switch (sc->sc_product) {
+ case PCI_PRODUCT_ATTANSIC_L2C_1:
+ pmcfg |= (7 <<
+ PM_CFG_L1_ENTRY_TIMER_SHIFT);
+ break;
+ case PCI_PRODUCT_ATTANSIC_L1D_1:
+ case PCI_PRODUCT_ATTANSIC_L2C_2:
+ pmcfg |= (4 <<
+ PM_CFG_L1_ENTRY_TIMER_SHIFT);
+ break;
+ default:
+ pmcfg |= (15 <<
+ PM_CFG_L1_ENTRY_TIMER_SHIFT);
+ break;
+ }
+ }
+ } else {
+ pmcfg |= PM_CFG_SERDES_L1_ENB |
+ PM_CFG_SERDES_PLL_L1_ENB |
+ PM_CFG_SERDES_BUDS_RX_L1_ENB;
+ pmcfg &= ~(PM_CFG_CLK_SWH_L1 |
+ PM_CFG_ASPM_L1_ENB | PM_CFG_ASPM_L0S_ENB);
+ }
} else {
- pmcfg &= ~PM_CFG_SERDES_PLL_L1_ENB;
+ pmcfg &= ~(PM_CFG_SERDES_BUDS_RX_L1_ENB | PM_CFG_SERDES_L1_ENB |
+ PM_CFG_SERDES_PLL_L1_ENB);
pmcfg |= PM_CFG_CLK_SWH_L1;
- pmcfg &= ~PM_CFG_ASPM_L1_ENB;
- pmcfg &= ~PM_CFG_ASPM_L0S_ENB;
+ if ((sc->alc_flags & ALC_FLAG_L1S) != 0)
+ pmcfg |= PM_CFG_ASPM_L1_ENB;
}
CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
}
@@ -450,9 +628,9 @@ alc_attach(struct device *parent, struct
const char *intrstr;
struct ifnet *ifp;
pcireg_t memtype;
- char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/l1" };
+ char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/L1" };
uint16_t burst;
- int base, mii_flags, state, error = 0;
+ int base, state, error = 0;
uint32_t cap, ctl, val;

/*
@@ -499,6 +677,7 @@ alc_attach(struct device *parent, struct
if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PCIEXPRESS,
&base, NULL)) {
sc->alc_flags |= ALC_FLAG_PCIE;
+ sc->alc_expcap = base;
burst = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
base + PCI_PCIE_DCSR) >> 16;
sc->alc_dma_rd_burst = (burst & 0x7000) >> 12;
@@ -515,6 +694,20 @@ alc_attach(struct device *parent, struct
val = CSR_READ_4(sc, ALC_PEX_UNC_ERR_SEV);
val &= ~(PEX_UNC_ERR_SEV_DLP | PEX_UNC_ERR_SEV_FCP);
CSR_WRITE_4(sc, ALC_PEX_UNC_ERR_SEV, val);
+ CSR_WRITE_4(sc, ALC_LTSSM_ID_CFG,
+ CSR_READ_4(sc, ALC_LTSSM_ID_CFG) & ~LTSSM_ID_WRO_ENB);
+ CSR_WRITE_4(sc, ALC_PCIE_PHYMISC,
+ CSR_READ_4(sc, ALC_PCIE_PHYMISC) |
+ PCIE_PHYMISC_FORCE_RCV_DET);
+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 &&
+ sc->alc_rev == ATHEROS_AR8152_B_V10) {
+ val = CSR_READ_4(sc, ALC_PCIE_PHYMISC2);
+ val &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK |
+ PCIE_PHYMISC2_SERDES_TH_MASK);
+ val |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT;
+ val |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT;
+ CSR_WRITE_4(sc, ALC_PCIE_PHYMISC2, val);
+ }
/* Disable ASPM L0S and L1. */
cap = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
base + PCI_PCIE_LCAP) >> 16;
@@ -528,13 +721,16 @@ alc_attach(struct device *parent, struct
sc->sc_dev.dv_xname,
sc->alc_rcb == DMA_CFG_RCB_64 ? 64 : 128);
state = ctl & 0x03;
+ if (state & 0x01)
+ sc->alc_flags |= ALC_FLAG_L0S;
+ if (state & 0x02)
+ sc->alc_flags |= ALC_FLAG_L1S;
if (alcdebug)
printf("%s: ASPM %s %s\n",
sc->sc_dev.dv_xname,
aspm_state[state],
state == 0 ? "disabled" : "enabled");
- if (state != 0)
- alc_disable_l0s_l1(sc);
+ alc_disable_l0s_l1(sc);
}
}

@@ -551,12 +747,39 @@ alc_attach(struct device *parent, struct
* used in AR8132 can't establish gigabit link even if it
* shows the same PHY model/revision number of AR8131.
*/
- if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATTANSIC_L2C)
- sc->alc_flags |= ALC_FLAG_FASTETHER | ALC_FLAG_JUMBO;
- else
- sc->alc_flags |= ALC_FLAG_JUMBO | ALC_FLAG_ASPM_MON;
+ sc->sc_product = PCI_PRODUCT(pa->pa_id);
+ switch (sc->sc_product) {
+ case PCI_PRODUCT_ATTANSIC_L2C_1:
+ case PCI_PRODUCT_ATTANSIC_L2C_2:
+ sc->alc_flags |= ALC_FLAG_APS;
+ /* FALLTHROUGH */
+ case PCI_PRODUCT_ATTANSIC_L2C:
+ sc->alc_flags |= ALC_FLAG_FASTETHER;
+ break;
+ case PCI_PRODUCT_ATTANSIC_L1D:
+ case PCI_PRODUCT_ATTANSIC_L1D_1:
+ sc->alc_flags |= ALC_FLAG_APS;
+ /* FALLTHROUGH */
+ default:
+ break;
+ }
+ sc->alc_flags |= ALC_FLAG_ASPM_MON | ALC_FLAG_JUMBO;
+
+ switch (sc->sc_product) {
+ case PCI_PRODUCT_ATTANSIC_L1C:
+ case PCI_PRODUCT_ATTANSIC_L2C:
+ sc->alc_max_framelen = 9 * 1024;
+ break;
+ case PCI_PRODUCT_ATTANSIC_L1D:
+ case PCI_PRODUCT_ATTANSIC_L1D_1:
+ case PCI_PRODUCT_ATTANSIC_L2C_1:
+ case PCI_PRODUCT_ATTANSIC_L2C_2:
+ sc->alc_max_framelen = 6 * 1024;
+ break;
+ }
+
/*
- * It seems that AR8131/AR8132 has silicon bug for SMB. In
+ * It seems that AR813x/AR815x has silicon bug for SMB. In
* addition, Atheros said that enabling SMB wouldn't improve
* performance. However I think it's bad to access lots of
* registers to extract MAC statistics.
@@ -619,11 +842,8 @@ alc_attach(struct device *parent, struct

ifmedia_init(&sc->sc_miibus.mii_media, 0, alc_mediachange,
alc_mediastatus);
- mii_flags = 0;
- if ((sc->alc_flags & ALC_FLAG_JUMBO) != 0)
- mii_flags |= MIIF_DOPAUSE;
mii_attach(self, &sc->sc_miibus, 0xffffffff, MII_PHY_ANY,
- MII_OFFSET_ANY, mii_flags);
+ MII_OFFSET_ANY, MIIF_DOPAUSE);

if (LIST_FIRST(&sc->sc_miibus.mii_phys) == NULL) {
printf("%s: no PHY found!\n", sc->sc_dev.dv_xname);
@@ -1136,16 +1356,15 @@ alc_start(struct ifnet *ifp)
{
struct alc_softc *sc = ifp->if_softc;
struct mbuf *m_head;
- int enq;
-
- if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
- return;
+ int enq = 0;

/* Reclaim transmitted frames. */
if (sc->alc_cdata.alc_tx_cnt >= ALC_TX_DESC_HIWAT)
alc_txeof(sc);

- enq = 0;
+ if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
+ return;
+
for (;;) {
IFQ_DEQUEUE(&ifp->if_snd, m_head);
if (m_head == NULL)
@@ -1162,7 +1381,7 @@ alc_start(struct ifnet *ifp)
ifp->if_flags |= IFF_OACTIVE;
break;
}
- enq = 1;
+ enq++;

#if NBPFILTER > 0
/*
@@ -1174,7 +1393,7 @@ alc_start(struct ifnet *ifp)
#endif
}

- if (enq) {
+ if (enq > 0) {
/* Sync descriptors. */
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_tx_ring_map, 0,
sc->alc_cdata.alc_tx_ring_map->dm_mapsize,
@@ -1274,6 +1493,10 @@ alc_mac_config(struct alc_softc *sc)
reg = CSR_READ_4(sc, ALC_MAC_CFG);
reg &= ~(MAC_CFG_FULL_DUPLEX | MAC_CFG_TX_FC | MAC_CFG_RX_FC |
MAC_CFG_SPEED_MASK);
+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2)
+ reg |= MAC_CFG_HASH_ALG_CRC32 | MAC_CFG_SPEED_MODE_SW;
/* Reprogram MAC with resolved speed/duplex. */
switch (IFM_SUBTYPE(mii->mii_media_active)) {
case IFM_10_T:
@@ -1451,24 +1674,25 @@ alc_intr(void *arg)
struct alc_softc *sc = arg;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
uint32_t status;
+ int claimed = 0;

status = CSR_READ_4(sc, ALC_INTR_STATUS);
if ((status & ALC_INTRS) == 0)
return (0);

+ /* Disable interrupts. */
+ CSR_WRITE_4(sc, ALC_INTR_STATUS, INTR_DIS_INT);
+
+ status = CSR_READ_4(sc, ALC_INTR_STATUS);
+ if ((status & ALC_INTRS) == 0)
+ goto back;
+
/* Acknowledge and disable interrupts. */
CSR_WRITE_4(sc, ALC_INTR_STATUS, status | INTR_DIS_INT);

if (ifp->if_flags & IFF_RUNNING) {
- if (status & INTR_RX_PKT) {
- int error;
-
- error = alc_rxintr(sc);
- if (error) {
- alc_init(ifp);
- return (0);
- }
- }
+ if (status & INTR_RX_PKT)
+ alc_rxintr(sc);

if (status & (INTR_DMA_RD_TO_RST | INTR_DMA_WR_TO_RST |
INTR_TXQ_TO_RST)) {
@@ -1485,14 +1709,17 @@ alc_intr(void *arg)
return (0);
}

- alc_txeof(sc);
- if (!IFQ_IS_EMPTY(&ifp->if_snd))
+ if (status & INTR_TX_PKT) {
+ alc_txeof(sc);
+ if (!IFQ_IS_EMPTY(&ifp->if_snd))
alc_start(ifp);
+ }
}
-
+ claimed = 1;
+back:
/* Re-enable interrupts. */
CSR_WRITE_4(sc, ALC_INTR_STATUS, 0x7FFFFFFF);
- return (1);
+ return (claimed);
}

void
@@ -1507,7 +1734,7 @@ alc_txeof(struct alc_softc *sc)
return;
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_tx_ring_map, 0,
sc->alc_cdata.alc_tx_ring_map->dm_mapsize,
- BUS_DMASYNC_POSTREAD);
+ BUS_DMASYNC_POSTWRITE);
if ((sc->alc_flags & ALC_FLAG_CMB_BUG) == 0) {
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_cmb_map, 0,
sc->alc_cdata.alc_cmb_map->dm_mapsize,
@@ -1601,7 +1828,7 @@ alc_newbuf(struct alc_softc *sc, struct
return (0);
}

-int
+void
alc_rxintr(struct alc_softc *sc)
{
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
@@ -1625,7 +1852,7 @@ alc_rxintr(struct alc_softc *sc)
if (alcdebug)
printf("%s: unexpected segment count -- "
"resetting\n", sc->sc_dev.dv_xname);
- return (EIO);
+ break;
}
alc_rxeof(sc, rrd);
/* Clear Rx return status. */
@@ -1663,8 +1890,6 @@ alc_rxintr(struct alc_softc *sc)
CSR_WRITE_4(sc, ALC_MBOX_RD0_PROD_IDX,
sc->alc_cdata.alc_rx_cons);
}
-
- return (0);
}

/* Receive a frame. */
@@ -1696,9 +1921,8 @@ alc_rxeof(struct alc_softc *sc, struct r
* Force network stack compute checksum for
* errored frames.
*/
- status |= RRD_TCP_UDPCSUM_NOK | RRD_IPCSUM_NOK;
- if ((RRD_ERR_CRC | RRD_ERR_ALIGN | RRD_ERR_TRUNC |
- RRD_ERR_RUNT) != 0)
+ if ((status & (RRD_ERR_CRC | RRD_ERR_ALIGN |
+ RRD_ERR_TRUNC | RRD_ERR_RUNT)) != 0)
return;
}

@@ -1811,7 +2035,9 @@ alc_reset(struct alc_softc *sc)
uint32_t reg;
int i;

- CSR_WRITE_4(sc, ALC_MASTER_CFG, MASTER_RESET);
+ reg = CSR_READ_4(sc, ALC_MASTER_CFG) & 0xFFFF;
+ reg |= MASTER_OOB_DIS_OFF | MASTER_RESET;
+ CSR_WRITE_4(sc, ALC_MASTER_CFG, reg);
for (i = ALC_RESET_TIMEOUT; i > 0; i--) {
DELAY(10);
if ((CSR_READ_4(sc, ALC_MASTER_CFG) & MASTER_RESET) == 0)
@@ -1862,6 +2088,9 @@ alc_init(struct ifnet *ifp)
alc_init_cmb(sc);
alc_init_smb(sc);

+ /* Enable all clocks. */
+ CSR_WRITE_4(sc, ALC_CLK_GATING_CFG, 0);
+
/* Reprogram the station address. */
bcopy(LLADDR(ifp->if_sadl), eaddr, ETHER_ADDR_LEN);
CSR_WRITE_4(sc, ALC_PAR0,
@@ -1923,6 +2152,18 @@ alc_init(struct ifnet *ifp)
CSR_WRITE_4(sc, ALC_SMB_BASE_ADDR_HI, ALC_ADDR_HI(paddr));
CSR_WRITE_4(sc, ALC_SMB_BASE_ADDR_LO, ALC_ADDR_LO(paddr));

+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1) {
+ /* Reconfigure SRAM - Vendor magic. */
+ CSR_WRITE_4(sc, ALC_SRAM_RX_FIFO_LEN, 0x000002A0);
+ CSR_WRITE_4(sc, ALC_SRAM_TX_FIFO_LEN, 0x00000100);
+ CSR_WRITE_4(sc, ALC_SRAM_RX_FIFO_ADDR, 0x029F0000);
+ CSR_WRITE_4(sc, ALC_SRAM_RD0_ADDR, 0x02BF02A0);
+ CSR_WRITE_4(sc, ALC_SRAM_TX_FIFO_ADDR, 0x03BF02C0);
+ CSR_WRITE_4(sc, ALC_SRAM_TD_ADDR, 0x03DF03C0);
+ CSR_WRITE_4(sc, ALC_TXF_WATER_MARK, 0x00000000);
+ CSR_WRITE_4(sc, ALC_RD_DMA_CFG, 0x00000000);
+ }
+
/* Tell hardware that we're ready to load DMA blocks. */
CSR_WRITE_4(sc, ALC_DMA_BLOCK, DMA_BLOCK_LOAD);

@@ -1932,14 +2173,11 @@ alc_init(struct ifnet *ifp)
reg = ALC_USECS(sc->alc_int_rx_mod) << IM_TIMER_RX_SHIFT;
reg |= ALC_USECS(sc->alc_int_tx_mod) << IM_TIMER_TX_SHIFT;
CSR_WRITE_4(sc, ALC_IM_TIMER, reg);
- reg = CSR_READ_4(sc, ALC_MASTER_CFG);
- reg &= ~(MASTER_CHIP_REV_MASK | MASTER_CHIP_ID_MASK);
/*
* We don't want to automatic interrupt clear as task queue
* for the interrupt should know interrupt status.
*/
- reg &= ~MASTER_INTR_RD_CLR;
- reg &= ~(MASTER_IM_RX_TIMER_ENB | MASTER_IM_TX_TIMER_ENB);
+ reg = MASTER_SA_TIMER_ENB;
if (ALC_USECS(sc->alc_int_rx_mod) != 0)
reg |= MASTER_IM_RX_TIMER_ENB;
if (ALC_USECS(sc->alc_int_tx_mod) != 0)
@@ -1980,7 +2218,7 @@ alc_init(struct ifnet *ifp)
* Be conservative in what you do, be liberal in what you
* accept from others - RFC 793.
*/
- CSR_WRITE_4(sc, ALC_FRAME_SIZE, ALC_JUMBO_FRAMELEN);
+ CSR_WRITE_4(sc, ALC_FRAME_SIZE, sc->alc_max_framelen);

/* Disable header split(?) */
CSR_WRITE_4(sc, ALC_HDS_CFG, 0);
@@ -2007,11 +2245,14 @@ alc_init(struct ifnet *ifp)
* TSO/checksum offloading.
*/
CSR_WRITE_4(sc, ALC_TSO_OFFLOAD_THRESH,
- (ALC_JUMBO_FRAMELEN >> TSO_OFFLOAD_THRESH_UNIT_SHIFT) &
+ (sc->alc_max_framelen >> TSO_OFFLOAD_THRESH_UNIT_SHIFT) &
TSO_OFFLOAD_THRESH_MASK);
/* Configure TxQ. */
reg = (alc_dma_burst[sc->alc_dma_rd_burst] <<
TXQ_CFG_TX_FIFO_BURST_SHIFT) & TXQ_CFG_TX_FIFO_BURST_MASK;
+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2)
+ reg >>= 1;
reg |= (TXQ_CFG_TD_BURST_DEFAULT << TXQ_CFG_TD_BURST_SHIFT) &
TXQ_CFG_TD_BURST_MASK;
CSR_WRITE_4(sc, ALC_TXQ_CFG, reg | TXQ_CFG_ENHANCED_MODE);
@@ -2028,14 +2269,22 @@ alc_init(struct ifnet *ifp)
* XON : 80% of Rx FIFO
* XOFF : 30% of Rx FIFO
*/
- reg = CSR_READ_4(sc, ALC_SRAM_RX_FIFO_LEN);
- rxf_hi = (reg * 8) / 10;
- rxf_lo = (reg * 3)/ 10;
- CSR_WRITE_4(sc, ALC_RX_FIFO_PAUSE_THRESH,
- ((rxf_lo << RX_FIFO_PAUSE_THRESH_LO_SHIFT) &
- RX_FIFO_PAUSE_THRESH_LO_MASK) |
- ((rxf_hi << RX_FIFO_PAUSE_THRESH_HI_SHIFT) &
- RX_FIFO_PAUSE_THRESH_HI_MASK));
+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1C ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C) {
+ reg = CSR_READ_4(sc, ALC_SRAM_RX_FIFO_LEN);
+ rxf_hi = (reg * 8) / 10;
+ rxf_lo = (reg * 3) / 10;
+ CSR_WRITE_4(sc, ALC_RX_FIFO_PAUSE_THRESH,
+ ((rxf_lo << RX_FIFO_PAUSE_THRESH_LO_SHIFT) &
+ RX_FIFO_PAUSE_THRESH_LO_MASK) |
+ ((rxf_hi << RX_FIFO_PAUSE_THRESH_HI_SHIFT) &
+ RX_FIFO_PAUSE_THRESH_HI_MASK));
+ }
+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1)
+ CSR_WRITE_4(sc, ALC_SERDES_LOCK,
+ CSR_READ_4(sc, ALC_SERDES_LOCK) | SERDES_MAC_CLK_SLOWDOWN |
+ SERDES_PHY_CLK_SLOWDOWN);

/* Disable RSS until I understand L1C/L2C's RSS logic. */
CSR_WRITE_4(sc, ALC_RSS_IDT_TABLE0, 0);
@@ -2046,15 +2295,9 @@ alc_init(struct ifnet *ifp)
RXQ_CFG_RD_BURST_MASK;
reg |= RXQ_CFG_RSS_MODE_DIS;
if ((sc->alc_flags & ALC_FLAG_ASPM_MON) != 0)
- reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_100M;
+ reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_1M;
CSR_WRITE_4(sc, ALC_RXQ_CFG, reg);

- /* Configure Rx DMAW request thresold. */
- CSR_WRITE_4(sc, ALC_RD_DMA_CFG,
- ((RD_DMA_CFG_THRESH_DEFAULT << RD_DMA_CFG_THRESH_SHIFT) &
- RD_DMA_CFG_THRESH_MASK) |
- ((ALC_RD_DMA_CFG_USECS(0) << RD_DMA_CFG_TIMER_SHIFT) &
- RD_DMA_CFG_TIMER_MASK));
/* Configure DMA parameters. */
reg = DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI;
reg |= sc->alc_rcb;
@@ -2080,7 +2323,7 @@ alc_init(struct ifnet *ifp)
* - Enable CRC generation.
* Actual reconfiguration of MAC for resolved speed/duplex
* is followed after detection of link establishment.
- * AR8131/AR8132 always does checksum computation regardless
+ * AR813x/AR815x always does checksum computation regardless
* of MAC_CFG_RXCSUM_ENB bit. Also the controller is known to
* have bug in protocol field in Rx return structure so
* these controllers can't handle fragmented frames. Disable
@@ -2090,6 +2333,10 @@ alc_init(struct ifnet *ifp)
reg = MAC_CFG_TX_CRC_ENB | MAC_CFG_TX_AUTO_PAD | MAC_CFG_FULL_DUPLEX |
((MAC_CFG_PREAMBLE_DEFAULT << MAC_CFG_PREAMBLE_SHIFT) &
MAC_CFG_PREAMBLE_MASK);
+ if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
+ sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2)
+ reg |= MAC_CFG_HASH_ALG_CRC32 | MAC_CFG_SPEED_MODE_SW;
if ((sc->alc_flags & ALC_FLAG_FASTETHER) != 0)
reg |= MAC_CFG_SPEED_10_100;
else
@@ -2191,7 +2438,7 @@ alc_stop_mac(struct alc_softc *sc)
/* Disable Rx/Tx MAC. */
reg = CSR_READ_4(sc, ALC_MAC_CFG);
if ((reg & (MAC_CFG_TX_ENB | MAC_CFG_RX_ENB)) != 0) {
- reg &= ~MAC_CFG_TX_ENB | MAC_CFG_RX_ENB;
+ reg &= ~(MAC_CFG_TX_ENB | MAC_CFG_RX_ENB);
CSR_WRITE_4(sc, ALC_MAC_CFG, reg);
}
for (i = ALC_TIMEOUT; i > 0; i--) {
Index: sys/dev/pci/if_alcreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_alcreg.h,v
retrieving revision 1.1
diff -u -p -r1.1 if_alcreg.h
--- sys/dev/pci/if_alcreg.h 8 Aug 2009 09:31:13 -0000 1.1
+++ sys/dev/pci/if_alcreg.h 25 Jan 2011 10:19:56 -0000
@@ -31,7 +31,10 @@
#ifndef _IF_ALCREG_H
#define _IF_ALCREG_H

-#define ALC_PCIR_BAR 0x10
+#define ALC_PCIR_BAR 0x10
+
+#define ATHEROS_AR8152_B_V10 0xC0
+#define ATHEROS_AR8152_B_V11 0xC1

/* 0x0000 - 0x02FF : PCIe configuration space */

@@ -56,6 +59,12 @@
#define ALC_PCIE_PHYMISC 0x1000
#define PCIE_PHYMISC_FORCE_RCV_DET 0x00000004

+#define ALC_PCIE_PHYMISC2 0x1004
+#define PCIE_PHYMISC2_SERDES_CDR_MASK 0x00030000
+#define PCIE_PHYMISC2_SERDES_TH_MASK 0x000C0000
+#define PCIE_PHYMISC2_SERDES_CDR_SHIFT 16
+#define PCIE_PHYMISC2_SERDES_TH_SHIFT 18
+
#define ALC_TWSI_DEBUG 0x1108
#define TWSI_DEBUG_DEV_EXIST 0x20000000

@@ -88,7 +97,9 @@
#define PM_CFG_PCIE_RECV 0x00008000
#define PM_CFG_L1_ENTRY_TIMER_MASK 0x000F0000
#define PM_CFG_PM_REQ_TIMER_MASK 0x00F00000
-#define PM_CFG_LCKDET_TIMER_MASK 0x3F000000
+#define PM_CFG_LCKDET_TIMER_MASK 0x0F000000
+#define PM_CFG_EN_BUFS_RX_L0S 0x10000000
+#define PM_CFG_SA_DLY_ENB 0x20000000
#define PM_CFG_MAC_ASPM_CHK 0x40000000
#define PM_CFG_HOTRST 0x80000000
#define PM_CFG_L0S_ENTRY_TIMER_SHIFT 8
@@ -96,10 +107,20 @@
#define PM_CFG_PM_REQ_TIMER_SHIFT 20
#define PM_CFG_LCKDET_TIMER_SHIFT 24

+#define PM_CFG_L0S_ENTRY_TIMER_DEFAULT 6
+#define PM_CFG_L1_ENTRY_TIMER_DEFAULT 1
+#define PM_CFG_LCKDET_TIMER_DEFAULT 12
+#define PM_CFG_PM_REQ_TIMER_DEFAULT 12
+
+#define ALC_LTSSM_ID_CFG 0x12FC
+#define LTSSM_ID_WRO_ENB 0x00001000
+
#define ALC_MASTER_CFG 0x1400
#define MASTER_RESET 0x00000001
+#define MASTER_TEST_MODE_MASK 0x0000000C
#define MASTER_BERT_START 0x00000010
-#define MASTER_TEST_MODE_MASK 0x000000C0
+#define MASTER_OOB_DIS_OFF 0x00000040
+#define MASTER_SA_TIMER_ENB 0x00000080
#define MASTER_MTIMER_ENB 0x00000100
#define MASTER_MANUAL_INTR_ENB 0x00000200
#define MASTER_IM_TX_TIMER_ENB 0x00000400
@@ -114,7 +135,7 @@
#define MASTER_CHIP_REV_SHIFT 16
#define MASTER_CHIP_ID_SHIFT 24

-/* Number of ticks per usec for AR8131/AR8132. */
+/* Number of ticks per usec for AR813x/AR815x. */
#define ALC_TICK_USECS 2
#define ALC_USECS(x) ((x) / ALC_TICK_USECS)

@@ -136,7 +157,7 @@
* alc(4) does not rely on Tx completion interrupts, so set it
* somewhat large value to reduce Tx completion interrupts.
*/
-#define ALC_IM_TX_TIMER_DEFAULT 50000 /* 50ms */
+#define ALC_IM_TX_TIMER_DEFAULT 1000 /* 1ms */

#define ALC_GPHY_CFG 0x140C /* 16bits */
#define GPHY_CFG_EXT_RESET 0x0001
@@ -212,6 +233,8 @@
#define ALC_SERDES_LOCK 0x1424
#define SERDES_LOCK_DET 0x00000001
#define SERDES_LOCK_DET_ENB 0x00000002
+#define SERDES_MAC_CLK_SLOWDOWN 0x00020000
+#define SERDES_PHY_CLK_SLOWDOWN 0x00040000

#define ALC_MAC_CFG 0x1480
#define MAC_CFG_TX_ENB 0x00000001
@@ -241,6 +264,8 @@
#define MAC_CFG_BCAST 0x04000000
#define MAC_CFG_DBG 0x08000000
#define MAC_CFG_SINGLE_PAUSE_ENB 0x10000000
+#define MAC_CFG_HASH_ALG_CRC32 0x20000000
+#define MAC_CFG_SPEED_MODE_SW 0x40000000
#define MAC_CFG_PREAMBLE_SHIFT 10
#define MAC_CFG_PREAMBLE_DEFAULT 7

@@ -683,11 +708,19 @@
#define HDS_CFG_BACKFILLSIZE_SHIFT 8
#define HDS_CFG_MAX_HDRSIZE_SHIFT 20

-/* AR8131/AR8132 registers for MAC statistics */
+/* AR813x/AR815x registers for MAC statistics */
#define ALC_RX_MIB_BASE 0x1700

#define ALC_TX_MIB_BASE 0x1760

+#define ALC_CLK_GATING_CFG 0x1814
+#define CLK_GATING_DMAW_ENB 0x0001
+#define CLK_GATING_DMAR_ENB 0x0002
+#define CLK_GATING_TXQ_ENB 0x0004
+#define CLK_GATING_RXQ_ENB 0x0008
+#define CLK_GATING_TXMAC_ENB 0x0010
+#define CLK_GATING_RXMAC_ENB 0x0020
+
#define ALC_DEBUG_DATA0 0x1900

#define ALC_DEBUG_DATA1 0x1904
@@ -1112,6 +1145,7 @@ struct alc_softc {
bus_dma_tag_t sc_dmat;
pci_chipset_tag_t sc_pct;
pcitag_t sc_pcitag;
+ pci_vendor_id_t sc_product;

void *sc_irq_handle;

@@ -1120,19 +1154,23 @@ struct alc_softc {
int alc_chip_rev;
int alc_phyaddr;
uint8_t alc_eaddr[ETHER_ADDR_LEN];
+ uint32_t alc_max_framelen;
uint32_t alc_dma_rd_burst;
uint32_t alc_dma_wr_burst;
uint32_t alc_rcb;
+ int alc_expcap;
int alc_flags;
#define ALC_FLAG_PCIE 0x0001
#define ALC_FLAG_PCIX 0x0002
-#define ALC_FLAG_MSI 0x0004
-#define ALC_FLAG_MSIX 0x0008
+#define ALC_FLAG_PM 0x0010
#define ALC_FLAG_FASTETHER 0x0020
#define ALC_FLAG_JUMBO 0x0040
#define ALC_FLAG_ASPM_MON 0x0080
#define ALC_FLAG_CMB_BUG 0x0100
#define ALC_FLAG_SMB_BUG 0x0200
+#define ALC_FLAG_L0S 0x0400
+#define ALC_FLAG_L1S 0x0800
+#define ALC_FLAG_APS 0x1000
#define ALC_FLAG_DETACH 0x4000
#define ALC_FLAG_LINK 0x8000

Index: sys/dev/pci/pcidevs
===================================================================
RCS file: /cvs/src/sys/dev/pci/pcidevs,v
retrieving revision 1.1588
diff -u -p -r1.1588 pcidevs
--- sys/dev/pci/pcidevs 19 Jan 2011 10:56:37 -0000 1.1588
+++ sys/dev/pci/pcidevs 25 Jan 2011 10:19:59 -0000
@@ -1429,6 +1429,10 @@ product ATTANSIC L1 0x1048 L1
product ATTANSIC L2C 0x1062 L2C
product ATTANSIC L1C 0x1063 L1C
product ATTANSIC L2 0x2048 L2
+product ATTANSIC L1D 0x1073 L1D
+product ATTANSIC L1D_1 0x1083 L1D
+product ATTANSIC L2C_1 0x2060 L2C
+product ATTANSIC L2C_2 0x2062 L2C

/* Aureal products */
product AUREAL AU8820 0x0001 Vortex 1

Damien Bergamini

unread,
Jan 25, 2011, 6:02:40 AM1/25/11
to
See my comments inline.

Damien

| void
| -alc_aspm(struct alc_softc *sc)
| +alc_aspm(struct alc_softc *sc, int media)
| {
| uint32_t pmcfg;
| + uint16_t linkcfg;
|
| pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
| + if ((sc->alc_flags & (ALC_FLAG_APS | ALC_FLAG_PCIE)) ==
| + (ALC_FLAG_APS | ALC_FLAG_PCIE))
| + linkcfg = CSR_READ_2(sc, sc->alc_expcap +
| + PCI_PCIE_LCSR);

You should probably use pci_conf_read() here.
Just turn linkcfg into a pcireg_t.


| + else
| + linkcfg = 0;
| pmcfg &= ~PM_CFG_SERDES_PD_EX_L1;
| - pmcfg |= PM_CFG_SERDES_BUDS_RX_L1_ENB;
| - pmcfg |= PM_CFG_SERDES_L1_ENB;
| - pmcfg &= ~PM_CFG_L1_ENTRY_TIMER_MASK;
| + pmcfg &= ~(PM_CFG_L1_ENTRY_TIMER_MASK | PM_CFG_LCKDET_TIMER_MASK);
| pmcfg |= PM_CFG_MAC_ASPM_CHK;
| + pmcfg |= (PM_CFG_LCKDET_TIMER_DEFAULT <<
| PM_CFG_LCKDET_TIMER_SHIFT);
| + pmcfg &= ~(PM_CFG_ASPM_L1_ENB | PM_CFG_ASPM_L0S_ENB);
| +
| + if ((sc->alc_flags & ALC_FLAG_APS) != 0) {
| + /* Disable extended sync except AR8152 B v1.0 */
| + linkcfg &= ~0x80;
| + if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 &&
| + sc->alc_rev == ATHEROS_AR8152_B_V10)
| + linkcfg |= 0x80;

I recently added the definition of the "Extended Synch" bit to pcireg.h
so you could use PCI_PCIE_LCSR_ES instead of 0x80 here.


| + CSR_WRITE_2(sc, sc->alc_expcap + PCI_PCIE_LCSR,
| + linkcfg);

and use pci_conf_write() here.

Gabriel Linder

unread,
Feb 15, 2011, 6:35:18 AM2/15/11
to
On 01/25/11 11:24, Kevin Lo wrote:
> Hi,
>
> The following diff adds support for Atheros AR8151/AR8152 chipsets;
> mostly from FreeBSD. It also fixes an issue i386/6311.
> Tested on Acer AOD255E.

Tried yesterday on EeePC 1005PX, some comments inline.

> @@ -515,6 +694,20 @@ alc_attach(struct device *parent, struct
> val = CSR_READ_4(sc, ALC_PEX_UNC_ERR_SEV);

> val&= ~(PEX_UNC_ERR_SEV_DLP | PEX_UNC_ERR_SEV_FCP);


> CSR_WRITE_4(sc, ALC_PEX_UNC_ERR_SEV, val);
> + CSR_WRITE_4(sc, ALC_LTSSM_ID_CFG,

> + CSR_READ_4(sc, ALC_LTSSM_ID_CFG)& ~LTSSM_ID_WRO_ENB);


> + CSR_WRITE_4(sc, ALC_PCIE_PHYMISC,
> + CSR_READ_4(sc, ALC_PCIE_PHYMISC) |
> + PCIE_PHYMISC_FORCE_RCV_DET);

> + if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1&&

> + sc->alc_rev == ATHEROS_AR8152_B_V10) {

Using sc->sc_product and sc->alc_rev, but they are initialized later.

> @@ -551,12 +747,39 @@ alc_attach(struct device *parent, struct
> * used in AR8132 can't establish gigabit link even if it
> * shows the same PHY model/revision number of AR8131.
> */
> - if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATTANSIC_L2C)
> - sc->alc_flags |= ALC_FLAG_FASTETHER | ALC_FLAG_JUMBO;
> - else
> - sc->alc_flags |= ALC_FLAG_JUMBO | ALC_FLAG_ASPM_MON;
> + sc->sc_product = PCI_PRODUCT(pa->pa_id);

Here is sc->sc_product, sc->alc_rev initialized line 569 of if_alc.c r1.9

alc_newbuf should always use M_DONTWAIT (get rid of init), see
http://marc.info/?l=openbsd-tech&m=129639859909043&w=2

Jonathan Gray

unread,
Apr 27, 2011, 5:21:16 PM4/27/11
to
On Tue, Jan 25, 2011 at 06:24:28PM +0800, Kevin Lo wrote:
> Hi,
>
> The following diff adds support for Atheros AR8151/AR8152 chipsets;
> mostly from FreeBSD. It also fixes an issue i386/6311.
> Tested on Acer AOD255E.

Is there an updated diff for this? It seems this never made it
into the tree.

0 new messages