Add in the platform specific quirks to get the AR934x SoC ethernet

up and running.

* The MAC FIFO configurations needed updating;
* Reset the MDIO block at the same time the MAC block is reset;
* The default divisor needs changing as the DB120 runs at a higher
  base MDIO bus clock compared to other chips.

The long-term fix is to allow the system to have a target MDIO bus
clock rate and then calculate the most suitable divider to meet
that.  This will likely need implementing before stable external
PHY or switch support can be committed.

Tested:

* AR9344 (mips74k)
* AR9331 (mips24k)
This commit is contained in:
adrian 2013-10-16 03:11:18 +00:00
parent 06167610a0
commit 6a6acca2aa

View File

@ -90,6 +90,7 @@ MODULE_VERSION(arge, 1);
#include "miibus_if.h"
#include <mips/atheros/ar71xxreg.h>
#include <mips/atheros/ar934xreg.h> /* XXX tsk! */
#include <mips/atheros/if_argevar.h>
#include <mips/atheros/ar71xx_setup.h>
#include <mips/atheros/ar71xx_cpudef.h>
@ -298,17 +299,38 @@ static void
arge_reset_mac(struct arge_softc *sc)
{
uint32_t reg;
uint32_t reset_reg;
/* Step 1. Soft-reset MAC */
ARGE_SET_BITS(sc, AR71XX_MAC_CFG1, MAC_CFG1_SOFT_RESET);
DELAY(20);
/* Step 2. Punt the MAC core from the central reset register */
ar71xx_device_stop(sc->arge_mac_unit == 0 ? RST_RESET_GE0_MAC :
RST_RESET_GE1_MAC);
/*
* XXX TODO: migrate this (and other) chip specific stuff into
* a chipdef method.
*/
if (sc->arge_mac_unit == 0) {
reset_reg = RST_RESET_GE0_MAC;
} else {
reset_reg = RST_RESET_GE1_MAC;
}
/*
* AR934x (and later) also needs the MDIO block reset.
*/
if (ar71xx_soc == AR71XX_SOC_AR9341 ||
ar71xx_soc == AR71XX_SOC_AR9342 ||
ar71xx_soc == AR71XX_SOC_AR9344) {
if (sc->arge_mac_unit == 0) {
reset_reg |= AR934X_RESET_GE0_MDIO;
} else {
reset_reg |= AR934X_RESET_GE1_MDIO;
}
}
ar71xx_device_stop(reset_reg);
DELAY(100);
ar71xx_device_start(sc->arge_mac_unit == 0 ? RST_RESET_GE0_MAC :
RST_RESET_GE1_MAC);
ar71xx_device_start(reset_reg);
/* Step 3. Reconfigure MAC block */
ARGE_WRITE(sc, AR71XX_MAC_CFG1,
@ -322,14 +344,46 @@ arge_reset_mac(struct arge_softc *sc)
ARGE_WRITE(sc, AR71XX_MAC_MAX_FRAME_LEN, 1536);
}
/*
* Fetch the MDIO bus clock rate.
*
* For now, the default is DIV_28 for everything
* bar AR934x, which will be DIV_42.
*
* It will definitely need updating to take into account
* the MDIO bus core clock rate and the target clock
* rate for the chip.
*/
static uint32_t
arge_fetch_mdiobus_clock_rate(struct arge_softc *sc)
{
switch (ar71xx_soc) {
case AR71XX_SOC_AR9341:
case AR71XX_SOC_AR9342:
case AR71XX_SOC_AR9344:
return (MAC_MII_CFG_CLOCK_DIV_42);
default:
return (MAC_MII_CFG_CLOCK_DIV_28);
}
}
static void
arge_reset_miibus(struct arge_softc *sc)
{
uint32_t mdio_div;
/* Reset MII bus */
ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, MAC_MII_CFG_RESET);
mdio_div = arge_fetch_mdiobus_clock_rate(sc);
/*
* XXX AR934x and later; should we be also resetting the
* MDIO block(s) using the reset register block?
*/
/* Reset MII bus; program in the default divisor */
ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, MAC_MII_CFG_RESET | mdio_div);
DELAY(100);
ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, MAC_MII_CFG_CLOCK_DIV_28);
ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, mdio_div);
DELAY(100);
}
@ -588,9 +642,13 @@ arge_attach(device_t dev)
case AR71XX_SOC_AR7242:
case AR71XX_SOC_AR9330:
case AR71XX_SOC_AR9331:
case AR71XX_SOC_AR9341:
case AR71XX_SOC_AR9342:
case AR71XX_SOC_AR9344:
ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG1, 0x0010ffff);
ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG2, 0x015500aa);
break;
/* AR71xx, AR913x */
default:
ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG1, 0x0fff0000);
ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG2, 0x00001fff);
@ -917,12 +975,16 @@ arge_set_pll(struct arge_softc *sc, int media, int duplex)
case AR71XX_SOC_AR7242:
case AR71XX_SOC_AR9330:
case AR71XX_SOC_AR9331:
case AR71XX_SOC_AR9341:
case AR71XX_SOC_AR9342:
case AR71XX_SOC_AR9344:
fifo_tx = 0x01f00140;
break;
case AR71XX_SOC_AR9130:
case AR71XX_SOC_AR9132:
fifo_tx = 0x00780fff;
break;
/* AR71xx */
default:
fifo_tx = 0x008001ff;
}