summaryrefslogtreecommitdiffstats
path: root/sys/mips
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2012-05-02 07:43:11 +0000
committeradrian <adrian@FreeBSD.org>2012-05-02 07:43:11 +0000
commit65b39d0c149e6210ac1f2aab9d128a9849789c29 (patch)
treeff2d03e865c2f20671643d8ae58fce63505c8d5b /sys/mips
parent5d7eac9221d06f08437ea65fcfd1e3f11b537718 (diff)
downloadFreeBSD-src-65b39d0c149e6210ac1f2aab9d128a9849789c29.zip
FreeBSD-src-65b39d0c149e6210ac1f2aab9d128a9849789c29.tar.gz
Implement PLL configuration override support, similar to what openwrt
implements.
Diffstat (limited to 'sys/mips')
-rw-r--r--sys/mips/atheros/if_arge.c50
-rw-r--r--sys/mips/atheros/if_argevar.h10
2 files changed, 57 insertions, 3 deletions
diff --git a/sys/mips/atheros/if_arge.c b/sys/mips/atheros/if_arge.c
index d5f67d1..c463e1e 100644
--- a/sys/mips/atheros/if_arge.c
+++ b/sys/mips/atheros/if_arge.c
@@ -101,6 +101,7 @@ typedef enum {
ARGE_DBG_RX = 0x00000008,
ARGE_DBG_ERR = 0x00000010,
ARGE_DBG_RESET = 0x00000020,
+ ARGE_DBG_PLL = 0x00000040,
} arge_debug_flags;
static const char * arge_miicfg_str[] = {
@@ -331,6 +332,34 @@ arge_reset_miibus(struct arge_softc *sc)
DELAY(100);
}
+static void
+arge_fetch_pll_config(struct arge_softc *sc)
+{
+ long int val;
+
+ if (resource_long_value(device_get_name(sc->arge_dev),
+ device_get_unit(sc->arge_dev),
+ "pll_10", &val) == 0) {
+ sc->arge_pllcfg.pll_10 = val;
+ device_printf(sc->arge_dev, "%s: pll_10 = 0x%x\n",
+ __func__, (int) val);
+ }
+ if (resource_long_value(device_get_name(sc->arge_dev),
+ device_get_unit(sc->arge_dev),
+ "pll_100", &val) == 0) {
+ sc->arge_pllcfg.pll_100 = val;
+ device_printf(sc->arge_dev, "%s: pll_100 = 0x%x\n",
+ __func__, (int) val);
+ }
+ if (resource_long_value(device_get_name(sc->arge_dev),
+ device_get_unit(sc->arge_dev),
+ "pll_1000", &val) == 0) {
+ sc->arge_pllcfg.pll_1000 = val;
+ device_printf(sc->arge_dev, "%s: pll_1000 = 0x%x\n",
+ __func__, (int) val);
+ }
+}
+
static int
arge_attach(device_t dev)
{
@@ -372,6 +401,11 @@ arge_attach(device_t dev)
("if_arge: Only MAC0 and MAC1 supported"));
/*
+ * Fetch the PLL configuration.
+ */
+ arge_fetch_pll_config(sc);
+
+ /*
* Get the MII configuration, if applicable.
*/
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
@@ -821,7 +855,7 @@ arge_set_pll(struct arge_softc *sc, int media, int duplex)
uint32_t fifo_tx, pll;
int if_speed;
- ARGEDEBUG(sc, ARGE_DBG_MII, "set_pll(%04x, %s)\n", media,
+ ARGEDEBUG(sc, ARGE_DBG_PLL, "set_pll(%04x, %s)\n", media,
duplex == IFM_FDX ? "full" : "half");
cfg = ARGE_READ(sc, AR71XX_MAC_CFG2);
cfg &= ~(MAC_CFG2_IFACE_MODE_1000
@@ -859,7 +893,7 @@ arge_set_pll(struct arge_softc *sc, int media, int duplex)
"Unknown media %d\n", media);
}
- ARGEDEBUG(sc, ARGE_DBG_MII, "%s: if_speed=%d\n", __func__, if_speed);
+ ARGEDEBUG(sc, ARGE_DBG_PLL, "%s: if_speed=%d\n", __func__, if_speed);
switch (ar71xx_soc) {
case AR71XX_SOC_AR7240:
@@ -881,8 +915,18 @@ arge_set_pll(struct arge_softc *sc, int media, int duplex)
rx_filtmask);
ARGE_WRITE(sc, AR71XX_MAC_FIFO_TX_THRESHOLD, fifo_tx);
- /* set PLL registers */
+ /* fetch PLL registers */
pll = ar71xx_device_get_eth_pll(sc->arge_mac_unit, if_speed);
+ ARGEDEBUG(sc, ARGE_DBG_PLL, "%s: pll=0x%x\n", __func__, pll);
+
+ /* Override if required by platform data */
+ if (if_speed == 10 && sc->arge_pllcfg.pll_10 != 0)
+ pll = sc->arge_pllcfg.pll_10;
+ else if (if_speed == 100 && sc->arge_pllcfg.pll_100 != 0)
+ pll = sc->arge_pllcfg.pll_100;
+ else if (if_speed == 1000 && sc->arge_pllcfg.pll_1000 != 0)
+ pll = sc->arge_pllcfg.pll_1000;
+ ARGEDEBUG(sc, ARGE_DBG_PLL, "%s: final pll=0x%x\n", __func__, pll);
/* XXX ensure pll != 0 */
ar71xx_device_set_pll_ge(sc->arge_mac_unit, if_speed, pll);
diff --git a/sys/mips/atheros/if_argevar.h b/sys/mips/atheros/if_argevar.h
index f592d85..9add674 100644
--- a/sys/mips/atheros/if_argevar.h
+++ b/sys/mips/atheros/if_argevar.h
@@ -118,6 +118,15 @@ struct arge_ring_data {
bus_addr_t arge_tx_ring_paddr;
};
+/*
+ * Allow PLL values to be overridden.
+ */
+struct arge_pll_data {
+ uint32_t pll_10;
+ uint32_t pll_100;
+ uint32_t pll_1000;
+};
+
struct arge_softc {
struct ifnet *arge_ifp; /* interface info */
device_t arge_dev;
@@ -136,6 +145,7 @@ struct arge_softc {
device_t arge_miibus;
device_t arge_miiproxy;
ar71xx_mii_mode arge_miicfg;
+ struct arge_pll_data arge_pllcfg;
bus_dma_tag_t arge_parent_tag;
bus_dma_tag_t arge_tag;
struct mtx arge_mtx;
OpenPOWER on IntegriCloud