Modify the if_arge code to use a /fixed/ media mode when it's configured.

Otherwise, the initial media speed would change if a PHY is hooked up,
sending PHY speed notifications.  For the AP135 at least, the RGMII
PHY has a static speed/duplex configured and if the PHY plumbing
attaches the PHY to the if_arge interface, the first link speed change
from 1000/full will set the MAC to something that isn't useful.

This shouldn't affect any other platforms - everything I looked at is
using hard-coded speed/duplex as static, as they're facing a switch
with no PHY attached.
This commit is contained in:
Adrian Chadd 2015-03-08 22:03:54 +00:00
parent 749cac133f
commit bbe493ec23

View File

@ -304,6 +304,8 @@ arge_reset_mac(struct arge_softc *sc)
uint32_t reg;
uint32_t reset_reg;
ARGEDEBUG(sc, ARGE_DBG_RESET, "%s called\n", __func__);
/* Step 1. Soft-reset MAC */
ARGE_SET_BITS(sc, AR71XX_MAC_CFG1, MAC_CFG1_SOFT_RESET);
DELAY(20);
@ -649,8 +651,7 @@ arge_attach(device_t dev)
}
/*
* Get default media & duplex mode, by default its Base100T
* and full duplex
* Get default/hard-coded media & duplex mode.
*/
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"media", &hint) != 0)
@ -658,8 +659,12 @@ arge_attach(device_t dev)
if (hint == 1000)
sc->arge_media_type = IFM_1000_T;
else
else if (hint == 100)
sc->arge_media_type = IFM_100_TX;
else if (hint == 10)
sc->arge_media_type = IFM_10_T;
else
sc->arge_media_type = 0;
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"fduplex", &hint) != 0)
@ -847,9 +852,10 @@ arge_attach(device_t dev)
}
}
}
if (sc->arge_miibus == NULL) {
/* no PHY, so use hard-coded values */
ifmedia_init(&sc->arge_ifmedia, 0,
ifmedia_init(&sc->arge_ifmedia, 0,
arge_multiphy_mediachange,
arge_multiphy_mediastatus);
ifmedia_add(&sc->arge_ifmedia,
@ -1071,6 +1077,25 @@ arge_update_link_locked(struct arge_softc *sc)
return;
}
/*
* If we have a static media type configured, then
* use that. Some PHY configurations (eg QCA955x -> AR8327)
* use a static speed/duplex between the SoC and switch,
* even though the front-facing PHY speed changes.
*/
if (sc->arge_media_type != 0) {
ARGEDEBUG(sc, ARGE_DBG_MII, "%s: fixed; media=%d, duplex=%d\n",
__func__,
sc->arge_media_type,
sc->arge_duplex_mode);
if (mii->mii_media_status & IFM_ACTIVE) {
sc->arge_link_status = 1;
} else {
sc->arge_link_status = 0;
}
arge_set_pll(sc, sc->arge_media_type, sc->arge_duplex_mode);
}
if (mii->mii_media_status & IFM_ACTIVE) {
media = IFM_SUBTYPE(mii->mii_media_active);
@ -1095,6 +1120,12 @@ arge_set_pll(struct arge_softc *sc, int media, int duplex)
uint32_t fifo_tx, pll;
int if_speed;
/*
* XXX Verify - is this valid for all chips?
* QCA955x (and likely some of the earlier chips!) define
* this as nibble mode and byte mode, and those have to do
* with the interface type (MII/SMII versus GMII/RGMII.)
*/
ARGEDEBUG(sc, ARGE_DBG_PLL, "set_pll(%04x, %s)\n", media,
duplex == IFM_FDX ? "full" : "half");
cfg = ARGE_READ(sc, AR71XX_MAC_CFG2);
@ -1199,6 +1230,9 @@ arge_set_pll(struct arge_softc *sc, int media, int duplex)
static void
arge_reset_dma(struct arge_softc *sc)
{
ARGEDEBUG(sc, ARGE_DBG_RESET, "%s: called\n", __func__);
ARGE_WRITE(sc, AR71XX_DMA_RX_CONTROL, 0);
ARGE_WRITE(sc, AR71XX_DMA_TX_CONTROL, 0);
@ -1230,8 +1264,6 @@ arge_reset_dma(struct arge_softc *sc)
arge_flush_ddr(sc);
}
static void
arge_init(void *xsc)
{